/// <summary> /// Called once data should be decoded from the given <see cref="IByteBuffer"/>. This method will call /// <see cref="Decode(IChannelHandlerContext, IByteBuffer, List{object})"/> as long as decoding should take place. /// </summary> /// <param name="context"></param> /// <param name="input"></param> /// <param name="output"></param> protected virtual void CallDecode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { if (context is null) { CThrowHelper.ThrowArgumentNullException(CExceptionArgument.context); } if (input is null) { CThrowHelper.ThrowArgumentNullException(CExceptionArgument.input); } if (output is null) { CThrowHelper.ThrowArgumentNullException(CExceptionArgument.output); } try { while (input.IsReadable()) { int initialOutputCount = output.Count; if ((uint)initialOutputCount > 0u) { FireChannelRead(context, output, initialOutputCount); output.Clear(); // Check if this handler was removed before continuing with decoding. // If it was removed, it is not safe to continue to operate on the buffer. // // See: // - https://github.com/netty/netty/issues/4635 if (context.IsRemoved) { break; } initialOutputCount = 0; } int oldInputLength = input.ReadableBytes; DecodeRemovalReentryProtection(context, input, output); // Check if this handler was removed before continuing the loop. // If it was removed, it is not safe to continue to operate on the buffer. // // See https://github.com/netty/netty/issues/1664 if (context.IsRemoved) { break; } bool noOutgoingMessages = 0u >= (uint)(oldInputLength - input.ReadableBytes); if (0u >= (uint)(initialOutputCount - output.Count)) { // no outgoing messages have been produced if (noOutgoingMessages) { break; } else { continue; } } if (noOutgoingMessages) { CThrowHelper.ThrowDecoderException_ByteToMessageDecoder(GetType()); } if (SingleDecode) { break; } } } catch (DecoderException) { throw; } catch (Exception cause) { CThrowHelper.ThrowDecoderException(cause); } }