/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.dns;
import io.netty.channel.AddressedEnvelope;
import io.netty.util.internal.StringUtil;
import java.net.SocketAddress;
/**
* Provides some utility methods for DNS message implementations.
*/
final class DnsMessageUtil {
static StringBuilder appendQuery(StringBuilder buf, DnsQuery query) {
appendQueryHeader(buf, query);
appendAllRecords(buf, query);
return buf;
}
static StringBuilder appendResponse(StringBuilder buf, DnsResponse response) {
appendResponseHeader(buf, response);
appendAllRecords(buf, response);
return buf;
}
static StringBuilder appendRecordClass(StringBuilder buf, int dnsClass) {
final String name;
switch (dnsClass &= 0xFFFF) {
case DnsRecord.CLASS_IN:
name = "IN";
break;
case DnsRecord.CLASS_CSNET:
name = "CSNET";
break;
case DnsRecord.CLASS_CHAOS:
name = "CHAOS";
break;
case DnsRecord.CLASS_HESIOD:
name = "HESIOD";
break;
case DnsRecord.CLASS_NONE:
name = "NONE";
break;
case DnsRecord.CLASS_ANY:
name = "ANY";
break;
default:
name = null;
break;
}
if (name != null) {
buf.append(name);
} else {
buf.append("UNKNOWN(").append(dnsClass).append(')');
}
return buf;
}
private static void appendQueryHeader(StringBuilder buf, DnsQuery msg) {
buf.append(StringUtil.simpleClassName(msg))
.append('(');
appendAddresses(buf, msg)
.append(msg.id())
.append(", ")
.append(msg.opCode());
if (msg.isRecursionDesired()) {
buf.append(", RD");
}
if (msg.z() != 0) {
buf.append(", Z: ")
.append(msg.z());
}
buf.append(')');
}
private static void appendResponseHeader(StringBuilder buf, DnsResponse msg) {
buf.append(StringUtil.simpleClassName(msg))
.append('(');
appendAddresses(buf, msg)
.append(msg.id())
.append(", ")
.append(msg.opCode())
.append(", ")
.append(msg.code())
.append(',');
boolean hasComma = true;
if (msg.isRecursionDesired()) {
hasComma = false;
buf.append(" RD");
}
if (msg.isAuthoritativeAnswer()) {
hasComma = false;
buf.append(" AA");
}
if (msg.isTruncated()) {
hasComma = false;
buf.append(" TC");
}
if (msg.isRecursionAvailable()) {
hasComma = false;
buf.append(" RA");
}
if (msg.z() != 0) {
if (!hasComma) {
buf.append(',');
}
buf.append(" Z: ")
.append(msg.z());
}
if (hasComma) {
buf.setCharAt(buf.length() - 1, ')');
} else {
buf.append(')');
}
}
private static StringBuilder appendAddresses(StringBuilder buf, DnsMessage msg) {
if (!(msg instanceof AddressedEnvelope)) {
return buf;
}
@SuppressWarnings("unchecked")
AddressedEnvelope<?, SocketAddress> envelope = (AddressedEnvelope<?, SocketAddress>) msg;
SocketAddress addr = envelope.sender();
if (addr != null) {
buf.append("from: ")
.append(addr)
.append(", ");
}
addr = envelope.recipient();
if (addr != null) {
buf.append("to: ")
.append(addr)
.append(", ");
}
return buf;
}
private static void appendAllRecords(StringBuilder buf, DnsMessage msg) {
appendRecords(buf, msg, DnsSection.QUESTION);
appendRecords(buf, msg, DnsSection.ANSWER);
appendRecords(buf, msg, DnsSection.AUTHORITY);
appendRecords(buf, msg, DnsSection.ADDITIONAL);
}
private static void appendRecords(StringBuilder buf, DnsMessage message, DnsSection section) {
final int count = message.count(section);
for (int i = 0; i < count; i ++) {
buf.append(StringUtil.NEWLINE)
.append(StringUtil.TAB)
.append(message.<DnsRecord>recordAt(section, i));
}
}
private DnsMessageUtil() { }
}