/// <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)); }
/// <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(); } } }
/// <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(); } } }
/// <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(); } }
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(); } }
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(); } }
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); }