public override void ChannelInactive(IChannelHandlerContext ctx) { ThreadLocalObjectList output = ThreadLocalObjectList.Take(); 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(); } } }
public override void ChannelRead(IChannelHandlerContext context, object message) { var data = message as IByteBuffer; if (data != null) { ThreadLocalObjectList output = ThreadLocalObjectList.Take(); 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); } }
static void EncodeSubscribeMessage(IByteBufferAllocator bufferAllocator, SubscribePacket packet, List <object> output) { const int VariableHeaderSize = PacketIdLength; int payloadBufferSize = 0; ThreadLocalObjectList encodedTopicFilters = ThreadLocalObjectList.Take(); 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; IByteBuffer 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); } finally { encodedTopicFilters.Return(); } }
public override void ChannelRead(IChannelHandlerContext context, object message) { ThreadLocalObjectList output = ThreadLocalObjectList.Take(); try { if (this.AcceptInboundMessage(message)) { T cast = (T)message; try { this.Decode(context, cast, output); } finally { ReferenceCountUtil.Release(cast); } } else { output.Add(message); } } catch (DecoderException e) { throw; } catch (Exception e) { throw new DecoderException(e); } finally { int size = output.Count; for (int i = 0; i < size; i++) { context.FireChannelRead(output[i]); } output.Return(); } base.ChannelRead(context, message); }
public override Task WriteAsync(IChannelHandlerContext ctx, object msg) { Task result; ThreadLocalObjectList output = null; try { if (this.AcceptOutboundMessage(msg)) { output = ThreadLocalObjectList.Take(); 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); }