// Run on its own thread, and invokes user code from it private void ReadFramesLoop() { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogDebug("ConnectionIO", "ReadFramesLoop starting"); } try { var token = _threadCancelToken; while (!token.IsCancellationRequested) { _frameReader.ReadAndDispatch(); } LogAdapter.LogError("ConnectionIO", "ReadFramesLoop exiting"); } catch (ThreadAbortException) { // no-op } catch (Exception ex) { LogAdapter.LogError("ConnectionIO", "ReadFramesLoop error", ex); this.InitiateAbruptClose(ex); } }
private void ReadSocketIntoRingBuffer() { try { while (!_cancellationToken.IsCancellationRequested) { _ringBuffer.WriteBufferFromSocketRecv(_socket); } } catch (SocketException ex) { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogError("SocketProducer", "Socket error", ex); } FireClosed(ex); } catch (Exception ex) { LogAdapter.LogError("SocketProducer", "Error", ex); FireClosed(ex); } }
public override void Write(byte[] buffer, int offset, int count) { try { var totalSent = 0; while (totalSent < count) { var sent = _socket.Send(buffer, offset + totalSent, count - totalSent, SocketFlags.None); totalSent += sent; } } catch (SocketException ex) { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogError("SocketStreamWriterAdapter", "Socket error", ex); } FireClosed(ex); } catch (Exception ex) { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogError("SocketStreamWriterAdapter", "Error", ex); } FireClosed(ex); } }
private async Task Recover() { RecoveryEnabledChannel[] channelsToRecover; lock (_channelRecoveries) channelsToRecover = _channelRecoveries.ToArray(); foreach (var recoveryEnabledChannel in channelsToRecover) { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogWarn(LogSource, "Recover: recovering channel " + recoveryEnabledChannel.ChannelNumber); } try { await recoveryEnabledChannel.DoRecover(_connection).ConfigureAwait(false); } catch (Exception ex) { if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "Recover: error recovering channel " + recoveryEnabledChannel.ChannelNumber, ex); } throw; } } }
public void Start() { _reply.Bind(_endpoint); var t = new Thread((_) => { try { while (true) { var data = _reply.Recv(); if (data != null) { OnRequestReceived(data, _reply); } } } catch (Exception e) { LogAdapter.LogError("Listener", e.ToString()); } }) { IsBackground = true }; t.Start(); }
public static void AssertNotReadFrameThread(string msg) { #if ASSERT if (ThreadUtils.IsReadFrameThread()) { LogAdapter.LogError("Asserts", msg + " - Details: Assert failed: AssertNotReadFrameThread at " + new StackTrace()); } #endif }
// Run on its own thread, and invokes user code from it (task continuations) private void WriteFramesLoop() { if (LogAdapter.IsDebugEnabled) { LogAdapter.LogDebug(LogSource, "WriteFramesLoop starting"); } CommandToSend cmdToSend = null; _writeThreadRunning = true; try { var token = _threadCancelToken; while (!token.IsCancellationRequested) { _commandOutboxEvent.WaitOne(1000); // maybe it's better to _cancellationToken.Register(action) ? if (token.IsCancellationRequested) { break; // perf hit? } while (_commandOutbox.TryDequeue(out cmdToSend)) { FlushCommand(cmdToSend); } } if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "WriteFramesLoop exiting"); } } catch (ThreadAbortException) { // no-op } catch (Exception ex) { if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "WriteFramesLoop error. Last command " + cmdToSend.ToDebugInfo(), ex); } this.InitiateAbruptClose(ex).IntentionallyNotAwaited(); } finally { _writeThreadRunning = false; TryTriggerClean(); } }
public Task Read_GenericMessageCount(Func <uint, Task> continuation) { uint messageCount = _amqpReader.ReadLong(); if (LogAdapter.ProtocolLevelLogEnabled) { LogAdapter.LogError(LogSource, "< GenericMessageCount : " + messageCount); } return(continuation(messageCount)); }
public Task Read_BasicCancel(Func <string, byte, Task> continuation) { string consumerTag = _amqpReader.ReadShortStr(); var noWait = _amqpReader.ReadBits(); if (LogAdapter.ProtocolLevelLogEnabled) { LogAdapter.LogError(LogSource, "< BasicCancel : " + consumerTag + " bits " + noWait); } return(continuation(consumerTag, noWait)); }
public void Read_BasicAck(Action <ulong, bool> continuation) { ulong deliveryTags = _amqpReader.ReadULong(); bool multiple = _amqpReader.ReadBits() != 0; if (LogAdapter.ProtocolLevelLogEnabled) { LogAdapter.LogError(LogSource, "< BasicAck : " + deliveryTags + " multiple " + multiple); } continuation(deliveryTags, multiple); }
internal async Task DoRecover(Connection connection) { try { var maxUnconfirmed = this._channel._confirmationKeeper != null ? (int)this._channel._confirmationKeeper.Max : 0; var replacementChannel = (Channel)await connection.InternalCreateChannel(_channel._options, this.ChannelNumber, maxUnconfirmed, this.IsConfirmationEnabled).ConfigureAwait(false); var specialNamesMapping = new Dictionary <string, string>(StringComparer.Ordinal); // _channel.Dispose(); need to dispose in a way that consumers do not receive the cancellation signal, but drain any pending task // copy delegate pointers from old to new _channel.CopyDelegates(replacementChannel); _channel.ComputeOffsets(replacementChannel); // 0. QoS await RecoverQos(replacementChannel).ConfigureAwait(false); // 1. Recover exchanges await RecoverExchanges(replacementChannel).ConfigureAwait(false); // 2. Recover queues await RecoverQueues(replacementChannel, specialNamesMapping).ConfigureAwait(false); // 3. Recover bindings (queue and exchanges) await RecoverBindings(replacementChannel, specialNamesMapping).ConfigureAwait(false); // 4. Recover consumers await RecoverConsumers(replacementChannel, specialNamesMapping).ConfigureAwait(false); // (+ rpc lifecycle) foreach (var helper in _rpcHelpers) { await helper.SignalRecovered(specialNamesMapping).ConfigureAwait(false); } _channel = replacementChannel; Interlocked.Exchange(ref _isRecovering, 0); } catch (Exception ex) { if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "Recovery error", ex); } throw; } }
public void Read_BasicNAck(Action <ulong, bool, bool> continuation) { ulong deliveryTags = _amqpReader.ReadULong(); byte bits = _amqpReader.ReadBits(); bool multiple = (bits & 1) != 0; bool requeue = (bits & 2) != 0; if (LogAdapter.ProtocolLevelLogEnabled) { LogAdapter.LogError(LogSource, "< BasicNAck from server for " + deliveryTags + " multiple: " + multiple + " requeue " + requeue); } continuation(deliveryTags, multiple, requeue); }
// Run on its own thread, and invokes user code from it private void ReadFramesLoop() { if (LogAdapter.IsDebugEnabled) { LogAdapter.LogDebug(LogSource, "ReadFramesLoop starting"); } _readThreadRunning = true; try { var token = _threadCancelToken; while (!token.IsCancellationRequested) { _frameReader.ReadAndDispatch(); } LogAdapter.LogError(LogSource, "ReadFramesLoop exiting"); } catch (ThreadAbortException) { // no-op } catch (Exception ex) { LogAdapter.LogError(LogSource, "ReadFramesLoop error", ex); this.InitiateAbruptClose(ex).IntentionallyNotAwaited(); } finally { _readThreadRunning = false; TryTriggerClean(); } }
protected override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (!IsAuthenticated()) { return(Task.FromResult(request.CreateResponse(HttpStatusCode.Unauthorized))); } stopWatch.Start(); try { var swaggerProvider = _config.GetSwaggerProvider(request); var rootUrl = _config.GetRootUrl(request); var apiVersion = request.GetRouteData().Values["apiVersion"].ToString(); var swaggerDoc = swaggerProvider.GetSwagger(rootUrl, apiVersion); var content = ContentFor(request, swaggerDoc); return(cancellationToken.IsCancellationRequested ? Task.FromResult(default(HttpResponseMessage)) : Task.FromResult(new HttpResponseMessage { Content = content })); } catch (UnknownApiVersion ex) { return(Task.FromResult(request.CreateErrorResponse(HttpStatusCode.NotFound, ex))); } catch (Exception ex) { LogAdapter.LogError("Could not create swagger specification file", ex); return(Task.FromResult(default(HttpResponseMessage))); } finally { stopWatch.Stop(); LogAdapter.LogInfo($"Swagger specification generation took: {stopWatch.ElapsedMilliseconds} ms"); } }
private void WorkerProc(object state) { try { using (var socket = this._ctx.CreateSocket(SocketType.Rep)) { socket.Connect(this._backendEndpoint); var polling = new Polling(PollingEvents.RecvReady, socket); // once data is ready, we pass it along to the actual worker polling.RecvReady += _ => { var msg = socket.Recv(); this._proc(msg, socket); }; while (_running) { polling.PollForever(); } } } catch (ZmqException e) { if (LogAdapter.LogEnabled) { LogAdapter.LogError(this.GetType().FullName, e.ToString()); } if (e.ZmqErrorCode != ZmqErrorCode.ETERM) { throw; } } }
internal static void SetException <T>(TaskCompletionSource <T> tcs, AmqpError error, int classMethodId) { if (tcs == null) { return; } if (error != null) { tcs.TrySetException(new Exception("Error: " + error.ToErrorString())); } else if (classMethodId == 0) { tcs.TrySetException(new Exception("The server closed the connection")); } else { var classId = classMethodId >> 16; var methodId = classMethodId & 0x0000FFFF; LogAdapter.LogError(LogSource, "Unexpected situation: classId " + classId + " method " + methodId + " and error = null"); tcs.TrySetException(new Exception("Unexpected reply from the server: classId = " + classId + " method " + methodId)); } }
// invoked from the read frame thread only. continuations need to be executed async public void Confirm(ulong deliveryTag, bool multiple, bool requeue, bool isAck) { if (LogAdapter.IsDebugEnabled) { LogAdapter.LogDebug(LogSource, string.Format("Confirming delivery {0} lastConfirmed {4} M: {1} Reque: {2} isAck: {3}", deliveryTag, multiple, requeue, isAck, _lastConfirmed)); } var startPos = multiple ? _lastConfirmed + 1 : deliveryTag; for (var i = startPos; i <= deliveryTag; i++) { var index = i % _max; var tcs = Interlocked.Exchange(ref _tasks[index], null); _semaphoreSlim.Release(); if (tcs == null) { LogAdapter.LogError(LogSource, "Unexpected tcs null at " + index); } else { if (isAck) { tcs.TrySetResult(true); } else { tcs.TrySetException(new Exception("Server said it rejected this message. Sorry")); } } } _lastConfirmed = deliveryTag; }
public void Read_BasicReturn(Channel channelImpl, // Func<ushort, string, string, string, int, BasicProperties, BaseLightStream, Task> continuation, BasicProperties properties) { ushort replyCode = _amqpReader.ReadShort(); string replyText = _amqpReader.ReadShortStr(); string exchange = _amqpReader.ReadShortStr(internIt: true); string routingKey = _amqpReader.ReadShortStr(internIt: true); byte frameEndMarker = _amqpReader.ReadOctet(); if (frameEndMarker != AmqpConstants.FrameEnd) { LogAdapter.LogError(LogSource, "Expecting FrameEnd but got " + frameEndMarker); throw new Exception("Expecting frameend!"); } // Frame Header / Content header byte frameHeaderStart = _amqpReader.ReadOctet(); if (frameHeaderStart != AmqpConstants.FrameHeader) { LogAdapter.LogError(LogSource, "Expecting FrameHeader but got " + frameHeaderStart); throw new Exception("Expecting Frame Header"); } // await _reader.SkipBy(4 + 2 + 2 + 2); ushort channel = _reader.ReadUInt16(); int payloadLength = _reader.ReadInt32(); ushort classId = _reader.ReadUInt16(); ushort weight = _reader.ReadUInt16(); var bodySize = (long)_reader.ReadUInt64(); // BasicProperties properties = ReadRestOfContentHeader(); ReadRestOfContentHeader(properties, bodySize == 0); // Frame Body(s) if (bodySize != 0) { frameHeaderStart = _reader.ReadByte(); if (frameHeaderStart != AmqpConstants.FrameBody) { LogAdapter.LogError(LogSource, "Expecting FrameBody but got " + frameHeaderStart); throw new Exception("Expecting Frame Body"); } // await _reader.SkipBy(2).ConfigureAwait(false); // channel = _reader.ReadUInt16(); _reader.SkipBy(2); // channel = _reader.ReadUInt16(); uint length = _reader.ReadUInt32(); // must leave pending Frame end if (length == bodySize) { // TODO: Experimenting in making sure the body is available ... // TODO: ... before invoking the callback so we block this IO thread only // _reader._ringBufferStream.EnsureAvailableToRead(bodySize); channelImpl.DispatchBasicReturn(replyCode, replyText, exchange, routingKey, (int)length, properties, _reader._ringBufferStream); } else { channelImpl.DispatchBasicReturn(replyCode, replyText, exchange, routingKey, (int)bodySize, properties, new MultiBodyStreamWrapper(_reader._ringBufferStream, (int)length, bodySize)); } } else { // no body channelImpl.DispatchBasicReturn(replyCode, replyText, exchange, routingKey, 0, properties, null); } }
// Run on its own thread, and invokes user code from it (task continuations) private void WriteFramesLoop() { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogDebug("ConnectionIO", "WriteFramesLoop starting"); } CommandToSend cmdToSend = null; try { var token = _threadCancelToken; while (!token.IsCancellationRequested) { _commandOutboxEvent.WaitOne(1000); // maybe it's better to _cancellationToken.Register(action) ? while (_commandOutbox.TryDequeue(out cmdToSend)) { _waitingServerReply.Wait(token); // Contention sadly required by the server/amqp // The command will signal that we can send more commands... cmdToSend.Prepare(cmdToSend.ExpectsReply ? _waitingServerReply : null); if (cmdToSend.ExpectsReply) // enqueues as awaiting a reply from the server { _waitingServerReply.Reset(); // cannot send anything else var queue = cmdToSend.Channel == 0 ? _awaitingReplyQueue : _conn.ResolveChannel(cmdToSend.Channel)._awaitingReplyQueue; queue.Enqueue(cmdToSend); } // writes to socket var frameWriter = cmdToSend.OptionalArg as IFrameContentWriter; if (frameWriter != null) { frameWriter.Write(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg); } else { cmdToSend.commandGenerator(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg); } // if writing to socket is enough, set as complete if (!cmdToSend.ExpectsReply) { cmdToSend.RunReplyAction(0, 0, null).IntentionallyNotAwaited(); } } } LogAdapter.LogError("ConnectionIO", "WriteFramesLoop exiting"); } catch (ThreadAbortException) { // no-op } catch (Exception ex) { LogAdapter.LogError("ConnectionIO", "WriteFramesLoop error. Last command " + cmdToSend.ToDebugInfo(), ex); this.InitiateAbruptClose(ex); } }
public virtual void Start() { EnsureNotDisposed(); if (!this._ownSockets) { if (!(this.Frontend is Socket)) { throw new InvalidOperationException("Frontend instance is not a Socket"); } if (!(this.Backend is Socket)) { throw new InvalidOperationException("Backend instance is not a Socket"); } } var thread = new Thread(() => { if (this._ownSockets) { this.Frontend = _ctx.CreateSocket(this._frontendType); this.Backend = _ctx.CreateSocket(this._backendType); } var front = (Socket)this.Frontend; var back = (Socket)this.Backend; StartFrontEnd(); StartBackEnd(); IZmqSocket capReceiver; IZmqSocket captureSink = capReceiver = null; if (this._enableCapture) { var rnd = new Random((int)DateTime.Now.Ticks); var captureendpoint = "inproc://capture" + rnd.Next(0, Int32.MaxValue); captureSink = _ctx.Pair(); captureSink.Bind(captureendpoint); capReceiver = _ctx.Pair(); capReceiver.Connect(captureendpoint); var captureThread = new Thread(() => { try { while (true) { var data = capReceiver.Recv(); if (data == null) { continue; } var ev = this.Captured; if (ev != null) { ev(data); } } } catch (Exception e) { if (LogAdapter.LogEnabled) { LogAdapter.LogError("DeviceCapture", e.ToString()); } } }) { IsBackground = true, Name = "Capture thread for " + captureendpoint }; captureThread.Start(); } var captureHandle = _enableCapture ? captureSink.Handle() : IntPtr.Zero; restart: // this will block forever, hence it's running in a separate thread var res = Native.Device.zmq_proxy(front.Handle(), back.Handle(), captureHandle); if (res == Native.ErrorCode) { if (Native.LastError() == ZmqErrorCode.EINTR) // unix interruption { goto restart; } // force disposal since these sockets were eterm'ed or worse this.Dispose(); if (captureSink != null) { captureSink.Dispose(); } if (capReceiver != null) { capReceiver.Dispose(); } // this is expected if (Native.LastError() == ZmqErrorCode.ETERM) { return; } // not expected var msg = "Error on zmq_proxy: " + Native.LastErrorString(); System.Diagnostics.Trace.TraceError(msg); System.Diagnostics.Debug.WriteLine(msg); if (LogAdapter.LogEnabled) { LogAdapter.LogError(this.GetType().FullName, msg); } } }) { IsBackground = true }; thread.Start(); }
private void TryInitiateRecovery() { if (Interlocked.CompareExchange(ref _inRecovery, 1, 0) == 0) { LogAdapter.LogDebug(LogSource, "TryInitiateRecovery starting recovery process"); // block all channels lock (_channelRecoveries) foreach (var recoveryEnabledChannel in _channelRecoveries) { recoveryEnabledChannel.Disconnected(); } // from this point on, no api calls are allowed on the channel decorators ThreadFactory.BackgroundThread(async(pthis) => { try { LogAdapter.LogDebug(LogSource, "Starting Recovery"); pthis.FireWillRecover(); pthis.ResetConnection(); var didConnect = await pthis.CycleReconnect().ConfigureAwait(false); if (!didConnect) { // Cancelled pthis.FireRecoveryFailed(); return; } LogAdapter.LogDebug(LogSource, "Reconnected"); await pthis.Recover().ConfigureAwait(false); pthis.FireRecoveryCompleted(); LogAdapter.LogDebug(LogSource, "Completed"); } catch (Exception ex) { LogAdapter.LogError(LogSource, "TryInitiateRecovery error", ex); pthis.HandleRecoveryFatalError(ex); pthis.FireRecoveryFailed(); } finally { Interlocked.Exchange(ref pthis._inRecovery, 0); } }, "RecoveryProc", this); } else { LogAdapter.LogDebug(LogSource, "TryInitiateRecovery: recovery in progress. skipping"); } }
private void ReadRestOfContentHeader(BasicProperties properties, bool skipFrameEnd) { var presence = _reader.ReadUInt16(); // BasicProperties properties; if (presence != 0) // no header content { // properties = new BasicProperties {_presenceSWord = presence}; properties._presenceSWord = presence; if (properties.IsContentTypePresent) { properties.ContentType = _amqpReader.ReadShortStr(); } if (properties.IsContentEncodingPresent) { properties.ContentEncoding = _amqpReader.ReadShortStr(); } if (properties.IsHeadersPresent) { _amqpReader.ReadTable(properties.Headers); } if (properties.IsDeliveryModePresent) { properties.DeliveryMode = _amqpReader.ReadOctet(); } if (properties.IsPriorityPresent) { properties.Priority = _amqpReader.ReadOctet(); } if (properties.IsCorrelationIdPresent) { properties.CorrelationId = _amqpReader.ReadShortStr(); } if (properties.IsReplyToPresent) { properties.ReplyTo = _amqpReader.ReadShortStr(); } if (properties.IsExpirationPresent) { properties.Expiration = _amqpReader.ReadShortStr(); } if (properties.IsMessageIdPresent) { properties.MessageId = _amqpReader.ReadShortStr(); } if (properties.IsTimestampPresent) { properties.Timestamp = _amqpReader.ReadTimestamp(); } if (properties.IsTypePresent) { properties.Type = _amqpReader.ReadShortStr(); } if (properties.IsUserIdPresent) { properties.UserId = _amqpReader.ReadShortStr(); } if (properties.IsAppIdPresent) { properties.AppId = _amqpReader.ReadShortStr(); } if (properties.IsClusterIdPresent) { properties.ClusterId = _amqpReader.ReadShortStr(); } } if (!skipFrameEnd) { byte frameEndMarker = _reader.ReadByte(); if (frameEndMarker != AmqpConstants.FrameEnd) { LogAdapter.LogError(LogSource, "Expecting FrameEnd but got " + frameEndMarker); throw new Exception("Expecting frameend"); } } }
public void ReadAndDispatch() { try { byte frameType = _reader.ReadByte(); if (frameType == 'A') { var msg = "Invalid frame received " + frameType; LogAdapter.LogError(LogSource, msg); throw new Exception(msg); } ushort channel = _reader.ReadUInt16(); int payloadLength = _reader.ReadInt32(); // needs special case for heartbeat, flow, etc.. // since they are not replies to methods we sent and alter the client's behavior ushort classId, methodId; classId = methodId = 0; if (frameType == AmqpConstants.FrameMethod) { classId = _reader.ReadUInt16(); methodId = _reader.ReadUInt16(); var classMethodId = classId << 16 | methodId; if (LogAdapter.ProtocolLevelLogEnabled) { LogAdapter.LogDebug(LogSource, "> Incoming Frame (" + frameType + ") for channel [" + channel + "] class (" + classId + ") method (" + methodId + ") payload size: " + payloadLength); } _frameProcessor.DispatchMethod(channel, classMethodId); } else if (frameType == AmqpConstants.FrameHeartbeat) { if (LogAdapter.ProtocolLevelLogEnabled) { LogAdapter.LogDebug(LogSource, "Received FrameHeartbeat"); } _frameProcessor.DispatchHeartbeat(); } byte frameEndMarker = _reader.ReadByte(); if (frameEndMarker != AmqpConstants.FrameEnd) { var msg = "Expecting frame end, but found " + frameEndMarker + ". The original class and method: " + classId + " " + methodId; LogAdapter.LogError(LogSource, msg); throw new Exception(msg); } } catch (ThreadAbortException) { // no-op } catch (Exception ex) { if (LogAdapter.IsErrorEnabled) { LogAdapter.LogError(LogSource, "Frame Reader error", ex); } throw; } }
public async Task Read_BasicDelivery( Func <string, ulong, bool, string, string, int, BasicProperties, BaseLightStream, Task> continuation, BasicProperties properties) { string consumerTag = _amqpReader.ReadShortStr(); ulong deliveryTag = _amqpReader.ReadULong(); bool redelivered = _amqpReader.ReadBits() != 0; string exchange = _amqpReader.ReadShortStr(); string routingKey = _amqpReader.ReadShortStr(); byte frameEndMarker = _amqpReader.ReadOctet(); if (frameEndMarker != AmqpConstants.FrameEnd) { throw new Exception("Expecting frameend!"); } // Frame Header / Content header byte frameHeaderStart = _amqpReader.ReadOctet(); if (frameHeaderStart != AmqpConstants.FrameHeader) { throw new Exception("Expecting Frame Header"); } // await _reader.SkipBy(4 + 2 + 2 + 2); ushort channel = _reader.ReadUInt16(); int payloadLength = _reader.ReadInt32(); ushort classId = _reader.ReadUInt16(); ushort weight = _reader.ReadUInt16(); long bodySize = (long)_reader.ReadUInt64(); // BasicProperties properties = ReadRestOfContentHeader(); ReadRestOfContentHeader(properties, bodySize == 0); // Frame Body(s) if (bodySize != 0) { // Support just single body at this moment. frameHeaderStart = _reader.ReadByte(); if (frameHeaderStart != AmqpConstants.FrameBody) { LogAdapter.LogError(LogSource, "Expecting FrameBody but got " + frameHeaderStart); throw new Exception("Expecting Frame Body"); } // await _reader.SkipBy(2); channel = _reader.ReadUInt16(); uint length = _reader.ReadUInt32(); // Pending Frame end if (length == bodySize) { // TODO: Experimenting in making sure the body is available ... // TODO: ... before invoking the callback so we block this IO thread only // _reader._ringBufferStream.EnsureAvailableToRead(bodySize); await continuation(consumerTag, deliveryTag, redelivered, exchange, routingKey, (int)length, properties, _reader._ringBufferStream).ConfigureAwait(false); } else { await continuation(consumerTag, deliveryTag, redelivered, exchange, routingKey, (int)bodySize, properties, new MultiBodyStreamWrapper(_reader._ringBufferStream, (int)length, bodySize)).ConfigureAwait(false); } } else { // Empty body size await continuation(consumerTag, deliveryTag, redelivered, exchange, routingKey, 0, properties, null).ConfigureAwait(false); } }
public async Task Read_BasicReturn(Func <ushort, string, string, string, int, BasicProperties, BaseLightStream, Task> continuation, BasicProperties properties) { ushort replyCode = _amqpReader.ReadShort(); string replyText = _amqpReader.ReadShortStr(); string exchange = _amqpReader.ReadShortStr(); string routingKey = _amqpReader.ReadShortStr(); byte frameEndMarker = _amqpReader.ReadOctet(); if (frameEndMarker != AmqpConstants.FrameEnd) { LogAdapter.LogError(LogSource, "Expecting FrameEnd but got " + frameEndMarker); throw new Exception("Expecting frameend!"); } // Frame Header / Content header byte frameHeaderStart = _amqpReader.ReadOctet(); if (frameHeaderStart != AmqpConstants.FrameHeader) { LogAdapter.LogError(LogSource, "Expecting FrameHeader but got " + frameHeaderStart); throw new Exception("Expecting Frame Header"); } // await _reader.SkipBy(4 + 2 + 2 + 2); ushort channel = _reader.ReadUInt16(); int payloadLength = _reader.ReadInt32(); ushort classId = _reader.ReadUInt16(); ushort weight = _reader.ReadUInt16(); var bodySize = (long)_reader.ReadUInt64(); // BasicProperties properties = ReadRestOfContentHeader(); ReadRestOfContentHeader(properties, bodySize == 0); // Frame Body(s) if (bodySize != 0) { frameHeaderStart = _reader.ReadByte(); if (frameHeaderStart != AmqpConstants.FrameBody) { LogAdapter.LogError(LogSource, "Expecting FrameBody but got " + frameHeaderStart); throw new Exception("Expecting Frame Body"); } await _reader.SkipBy(2).ConfigureAwait(false); // channel = _reader.ReadUInt16(); uint length = _reader.ReadUInt32(); // must leave pending Frame end if (length == bodySize) { await continuation(replyCode, replyText, exchange, routingKey, (int)length, properties, _reader._ringBufferStream).ConfigureAwait(false); } else { throw new NotSupportedException("Multi body not supported yet. Total body size is " + bodySize + " and first body is " + length + " bytes"); } } else { // no body await continuation(replyCode, replyText, exchange, routingKey, 0, properties, null).ConfigureAwait(false); } }