示例#1
0
        // 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);
            }
        }
示例#2
0
        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;
                }
            }
        }
示例#5
0
        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();
        }
示例#6
0
        public static void AssertNotReadFrameThread(string msg)
        {
#if ASSERT
            if (ThreadUtils.IsReadFrameThread())
            {
                LogAdapter.LogError("Asserts", msg + " - Details: Assert failed: AssertNotReadFrameThread at " + new StackTrace());
            }
#endif
        }
示例#7
0
        // 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();
            }
        }
示例#8
0
        public Task Read_GenericMessageCount(Func <uint, Task> continuation)
        {
            uint messageCount = _amqpReader.ReadLong();

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogError(LogSource, "< GenericMessageCount : " + messageCount);
            }

            return(continuation(messageCount));
        }
示例#9
0
        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));
        }
示例#10
0
        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);
        }
示例#11
0
        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;
            }
        }
示例#12
0
        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);
        }
示例#13
0
        // 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");
            }
        }
示例#15
0
        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;
                }
            }
        }
示例#16
0
        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));
            }
        }
示例#17
0
        // 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;
        }
示例#18
0
        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);
            }
        }
示例#19
0
        // 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);
            }
        }
示例#20
0
        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();
        }
示例#21
0
        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");
            }
        }
示例#22
0
        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");
                }
            }
        }
示例#23
0
        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;
            }
        }
示例#24
0
        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);
            }
        }
示例#25
0
        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);
            }
        }