Exemplo n.º 1
0
        public override void ChannelInactive(IChannelHandlerContext ctx)
        {
            ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();

            try
            {
                if (this.cumulation != null)
                {
                    this.CallDecode(ctx, this.cumulation, output);
                    this.DecodeLast(ctx, this.cumulation, output);
                }
                else
                {
                    this.DecodeLast(ctx, Unpooled.Empty, output);
                }
            }
            catch (DecoderException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new DecoderException(e);
            }
            finally
            {
                try
                {
                    if (this.cumulation != null)
                    {
                        this.cumulation.Release();
                        this.cumulation = null;
                    }
                    int size = output.Count;
                    for (int i = 0; i < size; i++)
                    {
                        ctx.FireChannelRead(output[i]);
                    }
                    if (size > 0)
                    {
                        // Something was read, call fireChannelReadComplete()
                        ctx.FireChannelReadComplete();
                    }
                    ctx.FireChannelInactive();
                }
                finally
                {
                    // recycle in all cases
                    output.Return();
                }
            }
        }
Exemplo n.º 2
0
        /// <inheritdoc />
        public override void ChannelRead(IChannelHandlerContext context, object message)
        {
            if (message is IByteBuffer data)
            {
                ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();
                try
                {
                    _first      = _cumulation is null;
                    _cumulation = _cumulator.Cumulate(context.Allocator, _first ? Unpooled.Empty : _cumulation, data);
                    CallDecode(context, _cumulation, output);
                }
                catch (DecoderException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    CThrowHelper.ThrowDecoderException(ex);
                }
                finally
                {
                    try
                    {
                        if (_cumulation is object && !_cumulation.IsReadable())
                        {
                            _numReads   = 0;
                            _           = _cumulation.Release();
                            _cumulation = null;
                        }
                        else if (++_numReads >= _discardAfterReads)
                        {
                            // We did enough reads already try to discard some bytes so we not risk to see a OOME.
                            // See https://github.com/netty/netty/issues/4275
                            _numReads = 0;
                            DiscardSomeReadBytes();
                        }

                        int size = output.Count;
                        _firedChannelRead |= (uint)size > 0u;
                        FireChannelRead(context, output, size);
                    }
                    finally
                    {
                        output.Return();
                    }
                }
            }
            else
            {
                _ = context.FireChannelRead(message);
            }
        }
Exemplo n.º 3
0
        public override void ChannelRead(IChannelHandlerContext context, object message)
        {
            var data = message as IByteBuffer;

            if (data != null)
            {
                ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();
                try
                {
                    this.first = this.cumulation == null;
                    if (this.first)
                    {
                        this.cumulation = data;
                    }
                    else
                    {
                        this.cumulation = this.cumulator(context.Allocator, this.cumulation, data);
                    }
                    this.CallDecode(context, this.cumulation, output);
                }
                catch (DecoderException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    throw new DecoderException(ex);
                }
                finally
                {
                    if (this.cumulation != null && !this.cumulation.IsReadable())
                    {
                        this.cumulation.Release();
                        this.cumulation = null;
                    }
                    int size = output.Count;
                    this.decodeWasNull = size == 0;

                    for (int i = 0; i < size; i++)
                    {
                        context.FireChannelRead(output[i]);
                    }
                    output.Return();
                }
            }
            else
            {
                context.FireChannelRead(message);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        ///     Write messages to the outbound of this <see cref="IChannel" />.
        /// </summary>
        /// <param name="msgs">The messages to be written.</param>
        /// <returns><c>true</c> if the write operation did add something to the inbound buffer</returns>
        public bool WriteOutbound(params object[] msgs)
        {
            this.EnsureOpen();
            if (msgs.Length == 0)
            {
                return(IsNotEmpty(this.outboundMessages));
            }

            ThreadLocalObjectList futures = ThreadLocalObjectList.NewInstance(msgs.Length);

            foreach (object m in msgs)
            {
                if (m == null)
                {
                    break;
                }
                futures.Add(this.WriteAsync(m));
            }
            // We need to call RunPendingTasks first as a IChannelHandler may have used IEventLoop.Execute(...) to
            // delay the write on the next event loop run.
            this.RunPendingTasks();
            this.Flush();

            int size = futures.Count;

            for (int i = 0; i < size; i++)
            {
                var future = (Task)futures[i];
                if (future.IsCompleted)
                {
                    this.RecordException(future);
                }
                else
                {
                    // The write may be delayed to run later by runPendingTasks()
                    future.ContinueWith(t => this.RecordException(t));
                }
                Debug.Assert(future.IsCompleted);
                if (future.Exception != null)
                {
                    this.RecordException(future.Exception);
                }
            }

            this.RunPendingTasks();
            this.CheckException();
            return(IsNotEmpty(this.outboundMessages));
        }
Exemplo n.º 5
0
        /// <inheritdoc />
        public override void ChannelRead(IChannelHandlerContext context, object message)
        {
            ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();

            try
            {
                if (this.AcceptInboundMessage(message))
                {
                    var cast = (T)message;
                    try
                    {
                        this.Decode(context, cast, output);
                    }
                    finally
                    {
                        _ = ReferenceCountUtil.Release(cast);
                    }
                }
                else
                {
                    output.Add(message);
                }
            }
            catch (DecoderException)
            {
                throw;
            }
            catch (Exception e)
            {
                CThrowHelper.ThrowDecoderException(e);
            }
            finally
            {
                try
                {
                    int size = output.Count;
                    for (int i = 0; i < size; i++)
                    {
                        _ = context.FireChannelRead(output[i]);
                    }
                }
                finally
                {
                    output.Return();
                }
            }
        }
Exemplo n.º 6
0
        /// <inheritdoc />
        public override void ChannelRead(IChannelHandlerContext context, object message)
        {
            ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();

            try
            {
                if (message is IByteBuffer byteBuffer)
                {
                    try
                    {
                        var reader = new ByteBufferReader(byteBuffer);
                        Decode(context, ref reader, output);
                    }
                    finally
                    {
                        _ = ReferenceCountUtil.Release(message);
                    }
                }
                else
                {
                    output.Add(message);
                }
            }
            catch (DecoderException)
            {
                throw;
            }
            catch (Exception e)
            {
                CThrowHelper.ThrowDecoderException(e);
            }
            finally
            {
                try
                {
                    int size = output.Count;
                    for (int i = 0; i < size; i++)
                    {
                        _ = context.FireChannelRead(output[i]);
                    }
                }
                finally
                {
                    output.Return();
                }
            }
        }
Exemplo n.º 7
0
        /// <summary>
        ///     Write messages to the outbound of this <see cref="IChannel" />.
        /// </summary>
        /// <param name="msgs">The messages to be written.</param>
        /// <returns><c>true</c> if the write operation did add something to the inbound buffer</returns>
        public bool WriteOutbound(params object[] msgs)
        {
            EnsureOpen();
            if (0u >= (uint)msgs.Length)
            {
                return(_outboundMessages.NonEmpty);
            }

            ThreadLocalObjectList futures = ThreadLocalObjectList.NewInstance(msgs.Length);

            try
            {
                for (int i = 0; i < msgs.Length; i++)
                {
                    object m = msgs[i];
                    if (m is null)
                    {
                        break;
                    }
                    futures.Add(WriteAsync(m));
                }

                FlushOutbound0();

                int size = futures.Count;
                for (int i = 0; i < size; i++)
                {
                    var future = (Task)futures[i];
                    if (future.IsCompleted)
                    {
                        RecordException(future);
                    }
                    else
                    {
                        // The write may be delayed to run later by RunPendingTasks()
                        future.ContinueWith(t => RecordException(t), TaskContinuationOptions.ExecuteSynchronously);
                    }
                }

                CheckException();
                return(_outboundMessages.NonEmpty);
            }
            finally
            {
                futures.Return();
            }
        }
Exemplo n.º 8
0
        static void EncodeSubscribeMessage(IByteBufferAllocator bufferAllocator, SubscribePacket packet, List <object> output)
        {
            const int VariableHeaderSize = PacketIdLength;
            int       payloadBufferSize  = 0;

            ThreadLocalObjectList encodedTopicFilters = ThreadLocalObjectList.NewInstance();

            IByteBuffer buf = null;

            try
            {
                foreach (SubscriptionRequest topic in packet.Requests)
                {
                    byte[] topicFilterBytes = EncodeStringInUtf8(topic.TopicFilter);
                    payloadBufferSize += StringSizeLength + topicFilterBytes.Length + 1; // length, value, QoS
                    encodedTopicFilters.Add(topicFilterBytes);
                }

                int variablePartSize      = VariableHeaderSize + payloadBufferSize;
                int fixedHeaderBufferSize = 1 + MaxVariableLength;

                buf = bufferAllocator.Buffer(fixedHeaderBufferSize + variablePartSize);
                buf.WriteByte(CalculateFirstByteOfFixedHeader(packet));
                WriteVariableLengthInt(buf, variablePartSize);

                // Variable Header
                buf.WriteShort(packet.PacketId); // todo: review: validate?

                // Payload
                for (int i = 0; i < encodedTopicFilters.Count; i++)
                {
                    var topicFilterBytes = (byte[])encodedTopicFilters[i];
                    buf.WriteShort(topicFilterBytes.Length);
                    buf.WriteBytes(topicFilterBytes, 0, topicFilterBytes.Length);
                    buf.WriteByte((int)packet.Requests[i].QualityOfService);
                }

                output.Add(buf);
                buf = null;
            }
            finally
            {
                buf?.SafeRelease();
                encodedTopicFilters.Return();
            }
        }
Exemplo n.º 9
0
        static void EncodeUnsubscribeMessage(IByteBufferAllocator bufferAllocator, UnsubscribePacket packet, List <Object> output)
        {
            const Int32 VariableHeaderSize = 2;
            var         payloadBufferSize  = 0;

            ThreadLocalObjectList encodedTopicFilters = ThreadLocalObjectList.NewInstance();

            Packet buf = null;

            try
            {
                foreach (var topic in packet.TopicFilters)
                {
                    var topicFilterBytes = EncodeStringInUtf8(topic);
                    payloadBufferSize += StringSizeLength + topicFilterBytes.Length; // length, value
                    encodedTopicFilters.Add(topicFilterBytes);
                }

                var variablePartSize      = VariableHeaderSize + payloadBufferSize;
                var fixedHeaderBufferSize = 1 + MaxVariableLength;

                buf = bufferAllocator.Buffer(fixedHeaderBufferSize + variablePartSize);
                buf.WriteByte(CalculateFirstByteOfFixedHeader(packet));
                WriteVariableLengthInt(buf, variablePartSize);

                // Variable Header
                buf.WriteShort(packet.PacketId); // todo: review: validate?

                // Payload
                for (var i = 0; i < encodedTopicFilters.Count; i++)
                {
                    var topicFilterBytes = (Byte[])encodedTopicFilters[i];
                    buf.WriteShort(topicFilterBytes.Length);
                    buf.WriteBytes(topicFilterBytes, 0, topicFilterBytes.Length);
                }

                output.Add(buf);
                buf = null;
            }
            finally
            {
                buf?.SafeRelease();
                encodedTopicFilters.Return();
            }
        }
Exemplo n.º 10
0
        private void ChannelInputClosed(IChannelHandlerContext ctx, bool callChannelInactive)
        {
            ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance();

            try
            {
                ChannelInputClosed(ctx, output);
            }
            catch (DecoderException)
            {
                throw;
            }
            catch (Exception e)
            {
                CThrowHelper.ThrowDecoderException(e);
            }
            finally
            {
                try
                {
                    if (_cumulation is object)
                    {
                        _           = _cumulation.Release();
                        _cumulation = null;
                    }
                    int size = output.Count;
                    if ((uint)size > 0u)
                    {
                        FireChannelRead(ctx, output, size);
                        // Something was read, call fireChannelReadComplete()
                        _ = ctx.FireChannelReadComplete();
                    }
                    if (callChannelInactive)
                    {
                        _ = ctx.FireChannelInactive();
                    }
                }
                finally
                {
                    // Recycle in all cases
                    output.Return();
                }
            }
        }
        public override Task WriteAsync(IChannelHandlerContext ctx, object msg)
        {
            Task result;
            ThreadLocalObjectList output = null;

            try
            {
                if (this.AcceptOutboundMessage(msg))
                {
                    output = ThreadLocalObjectList.NewInstance();
                    var cast = (T)msg;
                    try
                    {
                        this.Encode(ctx, cast, output);
                    }
                    finally
                    {
                        ReferenceCountUtil.Release(cast);
                    }

                    if (output.Count == 0)
                    {
                        output.Return();
                        output = null;

                        throw new EncoderException(this.GetType().Name + " must produce at least one message.");
                    }
                }
                else
                {
                    return(ctx.WriteAsync(msg));
                }
            }
            catch (EncoderException e)
            {
                return(TaskEx.FromException(e));
            }
            catch (Exception ex)
            {
                return(TaskEx.FromException(new EncoderException(ex))); // todo: we don't have a stack on EncoderException but it's present on inner exception.
            }
            finally
            {
                if (output != null)
                {
                    int lastItemIndex = output.Count - 1;
                    if (lastItemIndex == 0)
                    {
                        result = ctx.WriteAsync(output[0]);
                    }
                    else if (lastItemIndex > 0)
                    {
                        for (int i = 0; i < lastItemIndex; i++)
                        {
                            // we don't care about output from these messages as failure while sending one of these messages will fail all messages up to the last message - which will be observed by the caller in Task result.
                            ctx.WriteAsync(output[i]); // todo: optimize: once IChannelHandlerContext allows, pass "not interested in task" flag
                        }
                        result = ctx.WriteAsync(output[lastItemIndex]);
                    }
                    else
                    {
                        // 0 items in output - must never get here
                        result = null;
                    }
                    output.Return();
                }
                else
                {
                    // output was reset during exception handling - must never get here
                    result = null;
                }
            }
            return(result);
        }
Exemplo n.º 12
0
        /// <inheritdoc />
        public override void Write(IChannelHandlerContext ctx, object msg, IPromise promise)
        {
            ThreadLocalObjectList output = null;

            try
            {
                if (AcceptOutboundMessage(msg))
                {
                    output = ThreadLocalObjectList.NewInstance();
                    var cast = (T)msg;
                    try
                    {
                        Encode(ctx, cast, output);
                    }
                    finally
                    {
                        _ = ReferenceCountUtil.Release(cast);
                    }

                    if (0u >= (uint)output.Count)
                    {
                        CThrowHelper.ThrowEncoderException_MustProduceAtLeastOneMsg(GetType());
                    }
                }
                else
                {
                    _ = ctx.WriteAsync(msg, promise);
                }
            }
            catch (EncoderException)
            {
                throw;
            }
            catch (Exception ex)
            {
                CThrowHelper.ThrowEncoderException(ex); // todo: we don't have a stack on EncoderException but it's present on inner exception.
            }
            finally
            {
                if (output is object)
                {
                    try
                    {
                        int lastItemIndex = output.Count - 1;
                        if (0u >= (uint)lastItemIndex)
                        {
                            _ = ctx.WriteAsync(output[0], promise);
                        }
                        else if (lastItemIndex > 0)
                        {
                            // Check if we can use a voidPromise for our extra writes to reduce GC-Pressure
                            // See https://github.com/netty/netty/issues/2525
                            if (promise == ctx.VoidPromise())
                            {
                                WriteVoidPromise(ctx, output);
                            }
                            else
                            {
                                WritePromiseCombiner(ctx, output, promise);
                            }
                        }
                    }
                    finally
                    {
                        output.Return();
                    }
                }
            }
        }
Exemplo n.º 13
0
 private ApplicationProtocolNegotiationHandler()
 {
     _bufferedMessages = ThreadLocalObjectList.NewInstance();
 }
Exemplo n.º 14
0
        public override Task WriteAsync(IChannelHandlerContext ctx, object msg)
        {
            Task result;
            ThreadLocalObjectList output = null;

            try
            {
                if (base.AcceptOutboundMessage(msg))
                {
                    output = ThreadLocalObjectList.NewInstance();
                    var cast = (PacketInfo)msg;
                    try
                    {
                        base.Encode(ctx, cast, output);
                    }
                    finally
                    {
                        ReferenceCountUtil.Release(cast);
                    }

                    if (output.Count == 0)
                    {
                        output.Return();
                        output = null;

                        throw new EncoderException(this.GetType().Name + " must produce at least one message.");
                    }
                }
                else
                {
                    return(ctx.WriteAsync(msg));
                }
            }
            catch (EncoderException e)
            {
                throw new EncoderException(e);
            }
            catch (Exception ex)
            {
                throw new EncoderException(ex);
            }
            finally
            {
                if (output != null)
                {
                    if (output.Count > 0)
                    {
                        IByteBuffer byteBuffer = Unpooled.CopiedBuffer(output.ConvertAll(v => v as IByteBuffer).ToArray());
                        result = ctx.WriteAsync(new BinaryWebSocketFrame(byteBuffer));
                    }
                    else
                    {
                        // 0 items in output - must never get here
                        result = null;
                    }
                    output.Return();
                }
                else
                {
                    // output was reset during exception handling - must never get here
                    result = null;
                }
            }

            return(result);
        }