private final class DnsResponseHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
final DnsResponse res = (DnsResponse) msg;
final int queryId = res.header().id();
if (logger.isDebugEnabled()) {
logger.debug("{} RECEIVED: [{}: {}], {}", ch, queryId, res.sender(), res);
}
final DnsQueryContext qCtx = promises.get(queryId);
if (qCtx == null) {
if (logger.isWarnEnabled()) {
logger.warn("Received a DNS response with an unknown ID: {}", queryId);
}
return;
}
final List<DnsQuestion> questions = res.questions();
if (questions.size() != 1) {
logger.warn("Received a DNS response with invalid number of questions: {}", res);
return;
}
final DnsQuestion q = qCtx.question();
if (!q.equals(questions.get(0))) {
logger.warn("Received a mismatching DNS response: {}", res);
return;
}
// Cancel the timeout task.
final ScheduledFuture<?> timeoutFuture = qCtx.timeoutFuture();
if (timeoutFuture != null) {
timeoutFuture.cancel(false);
}
if (res.header().responseCode() == DnsResponseCode.NOERROR) {
cache(q, res);
promises.set(queryId, null);
Promise<DnsResponse> qPromise = qCtx.promise();
if (qPromise.setUncancellable()) {
qPromise.setSuccess(res.retain());
}
} else {
qCtx.retry(res.sender(),
"response code: " + res.header().responseCode() +
" with " + res.answers().size() + " answer(s) and " +
res.authorityResources().size() + " authority resource(s)");
}
} finally {
ReferenceCountUtil.safeRelease(msg);
}
}