}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
Channel ch = ctx.channel();
try {
if (!firstPass) {
readHeader(buf);
} else {
firstPass = false;
}
byte[] bytes = readBytes(buf);
byte[] challenge = server.evaluateResponse(bytes);
if (!server.isComplete()) {
ch.writeAndFlush(newContinueMessage(ctx, Unpooled.wrappedBuffer(challenge)));
} else {
ch.writeAndFlush(newSuccessMessage(ctx, Unpooled.wrappedBuffer(challenge)));
ChannelPipeline pipeline = ctx.pipeline();
String qop = (String) server.getNegotiatedProperty(Sasl.QOP);
if (qop != null
&& (qop.equalsIgnoreCase(AUTH_INT)
|| qop.equalsIgnoreCase(AUTO_CONF))) {
SaslServer server = this.server;
this.server = null;
// Replace this handler now with the QopHandler
// This is mainly done as the QopHandler itself will not block at all and so we can
// get rid of the usage of the EventExecutorGroup after the negation took place.
pipeline.replace(this, ctx.name(), new QopHandler(server));
} else {
// there is no need for any QOP handling so we are done now and can just remove ourself from the
// pipeline
pipeline.remove(this);
}
}
} catch (SaslException e) {
Object errorMsg = newErrorMessage(ctx, e);
if (errorMsg != null) {
ch.writeAndFlush(errorMsg).addListener(ChannelFutureListener.CLOSE);
}
}
}