예제 #1
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));
        }
예제 #2
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();
                }
            }
        }
예제 #3
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();
                }
            }
        }
예제 #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)
        {
            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();
            }
        }
예제 #5
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();
            }
        }
예제 #6
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();
            }
        }
예제 #7
0
 public override void ChannelRead(IChannelHandlerContext ctx, object msg)
 {
     // Let's buffer all data until this handler will be removed from the pipeline.
     _bufferedMessages.Add(msg);
 }