Hola @jzyong,
ProtocolDecoderImpl.doDecode() realiza cuatro validaciones distintas (longitud mínima, longitud máxima, control de flujo/anti-flood y verificación de buffer completo) en un único método secuencial con múltiples returns y manejo manual del cursor del buffer.
Situación actual:
Agregar una nueva regla de validación (por ejemplo, una lista negra de IP) obliga a modificar este método ya complejo, con riesgo de introducir regresiones en el framing del protocolo.
Solución propuesta:
Aplicar el patrón Chain of Responsibility, extrayendo cada validación a una clase DecodeValidator independiente, encadenadas en una secuencia configurable (MinLengthValidator -> MaxLengthValidator -> FloodControlValidator -> ...).
Esto permite agregar o reordenar validaciones sin tocar la lógica de lectura del buffer existente. Quedamos atentos a sus comentarios.
1. Contexto y Contrato
// Clase para compartir estado entre validadores
public class DecodeContext {
private int length;
private int maxReadSize;
private Predicate<IoSession> overMaxReadSizeHandler;
public int getLength() { return length; }
public void setLength(int length) { this.length = length; }
public int getMaxReadSize() { return maxReadSize; }
public void setMaxReadSize(int maxReadSize) { this.maxReadSize = maxReadSize; }
public Predicate<IoSession> getOverMaxReadSizeHandler() { return overMaxReadSizeHandler; }
public void setOverMaxReadSizeHandler(Predicate<IoSession> h) { this.overMaxReadSizeHandler = h; }
}
// Interfaz para los eslabones de la cadena
public interface DecodeValidator {
/** true = continua la cadena, false = detiene el procesamiento del mensaje. */
boolean validate(IoSession session, IoBuffer ib, ProtocolDecoderOutput out, DecodeContext ctx);
}
2. Implementación de la Cadena en ProtocolDecoderImpl
public class ProtocolDecoderImpl extends CumulativeProtocolDecoder {
private final List<DecodeValidator> chain = Arrays.asList(
new MinLengthValidator(),
new MaxLengthValidator(),
new FloodControlValidator(),
new BufferCompletenessValidator()
);
@Override
protected boolean doDecode(IoSession session, IoBuffer ib, ProtocolDecoderOutput out) throws Exception {
ib.mark();
DecodeContext ctx = new DecodeContext();
ctx.setMaxReadSize(maxReadSize);
ctx.setOverMaxReadSizeHandler(overMaxReadSizeHandler);
// Ejecución de la cadena de responsabilidad
for (DecodeValidator validator : chain) {
if (!validator.validate(session, ib, out, ctx)) {
ib.reset();
return false;
}
}
// ... continuación de la lógica de decodificación ...
}
}
3. Eslabones Concretos (Validadores)
class MinLengthValidator implements DecodeValidator {
@Override
public boolean validate(IoSession s, IoBuffer ib, ProtocolDecoderOutput out, DecodeContext ctx) {
return ib.remaining() >= 4;
}
}
class MaxLengthValidator implements DecodeValidator {
@Override
public boolean validate(IoSession s, IoBuffer ib, ProtocolDecoderOutput out, DecodeContext ctx) {
return ctx.getLength() > 0 && ctx.getLength() <= ctx.getMaxReadSize();
}
}
class FloodControlValidator implements DecodeValidator {
@Override
public boolean validate(IoSession s, IoBuffer ib, ProtocolDecoderOutput out, DecodeContext ctx) {
return ctx.getOverMaxReadSizeHandler() == null || !ctx.getOverMaxReadSizeHandler().test(s);
}
}
class BufferCompletenessValidator implements DecodeValidator {
@Override
public boolean validate(IoSession s, IoBuffer ib, ProtocolDecoderOutput out, DecodeContext ctx) {
return ib.remaining() >= ctx.getLength();
}
}

Hola @jzyong,
ProtocolDecoderImpl.doDecode() realiza cuatro validaciones distintas (longitud mínima, longitud máxima, control de flujo/anti-flood y verificación de buffer completo) en un único método secuencial con múltiples returns y manejo manual del cursor del buffer.
Situación actual:
Agregar una nueva regla de validación (por ejemplo, una lista negra de IP) obliga a modificar este método ya complejo, con riesgo de introducir regresiones en el framing del protocolo.
Solución propuesta:
Aplicar el patrón Chain of Responsibility, extrayendo cada validación a una clase DecodeValidator independiente, encadenadas en una secuencia configurable (MinLengthValidator -> MaxLengthValidator -> FloodControlValidator -> ...).
Esto permite agregar o reordenar validaciones sin tocar la lógica de lectura del buffer existente. Quedamos atentos a sus comentarios.
1. Contexto y Contrato
// Clase para compartir estado entre validadores
public class DecodeContext {
}
// Interfaz para los eslabones de la cadena
public interface DecodeValidator {
}
2. Implementación de la Cadena en ProtocolDecoderImpl
public class ProtocolDecoderImpl extends CumulativeProtocolDecoder {
}
3. Eslabones Concretos (Validadores)
class MinLengthValidator implements DecodeValidator {
}
class MaxLengthValidator implements DecodeValidator {
}
class FloodControlValidator implements DecodeValidator {
}
class BufferCompletenessValidator implements DecodeValidator {
}