You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2005/01/11 02:14:35 UTC
svn commit: r124859 - /incubator/directory/dns/trunk/core/src/java/org/apache/dns/io/DnsMessageDecoder.java
Author: erodriguez
Date: Mon Jan 10 17:14:34 2005
New Revision: 124859
URL: http://svn.apache.org/viewcvs?view=rev&rev=124859
Log:
Basic DNS message decoder.
Added:
incubator/directory/dns/trunk/core/src/java/org/apache/dns/io/DnsMessageDecoder.java
Added: incubator/directory/dns/trunk/core/src/java/org/apache/dns/io/DnsMessageDecoder.java
Url: http://svn.apache.org/viewcvs/incubator/directory/dns/trunk/core/src/java/org/apache/dns/io/DnsMessageDecoder.java?view=auto&rev=124859
==============================================================================
--- (empty file)
+++ incubator/directory/dns/trunk/core/src/java/org/apache/dns/io/DnsMessageDecoder.java Mon Jan 10 17:14:34 2005
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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 org.apache.dns.io;
+
+import java.nio.ByteBuffer;
+
+import org.apache.dns.messages.DnsMessage;
+import org.apache.dns.messages.DnsMessageModifier;
+import org.apache.dns.messages.MessageType;
+import org.apache.dns.messages.OpCode;
+import org.apache.dns.messages.ResponseCode;
+import org.apache.dns.records.QuestionRecord;
+import org.apache.dns.records.RecordClass;
+import org.apache.dns.records.RecordType;
+import org.apache.dns.records.ResourceRecord;
+
+
+public class DnsMessageDecoder
+{
+ public DnsMessage decode( ByteBuffer byteBuffer )
+ {
+ DnsMessageModifier modifier = new DnsMessageModifier();
+
+ modifier.setTransactionId( byteBuffer.getShort() );
+
+ byte header = byteBuffer.get();
+ modifier.setMessageType( parseMessageType( header ) );
+ modifier.setOpCode( parseOpCode( header ) );
+ modifier.setAuthoritativeAnswer( parseAuthoritativeAnswer( header ) );
+ modifier.setTruncated( parseTruncated( header ) );
+ modifier.setRecursionDesired( parseRecursionDesired( header ) );
+
+ header = byteBuffer.get();
+ modifier.setRecursionAvailable( parseRecursionAvailable( header ) );
+ modifier.setResponseCode( parseResponseCode( header ) );
+
+ short questionCount = byteBuffer.getShort();
+ short answerCount = byteBuffer.getShort();
+ short authorityCount = byteBuffer.getShort();
+ short additionalCount = byteBuffer.getShort();
+
+ modifier.setQuestionRecords( parseQuestions( questionCount, byteBuffer ) );
+ modifier.setAnswerRecords( parseRecords( answerCount, byteBuffer ) );
+ modifier.setAuthorityRecords( parseRecords( authorityCount, byteBuffer ) );
+ modifier.setAdditionalRecords( parseRecords( additionalCount, byteBuffer ) );
+
+ return modifier.getDnsMessage();
+ }
+
+ private ResourceRecord[] parseRecords( short recordCount, ByteBuffer byteBuffer )
+ {
+ ResourceRecord[] questions = new ResourceRecord[ recordCount ];
+
+ for ( int ii = 0; ii < recordCount; ii++ )
+ {
+ String domainName = parseDomainName( byteBuffer );
+
+ RecordType recordType = RecordType.getTypeByOrdinal( byteBuffer.getShort() );
+ RecordClass recordClass = RecordClass.getTypeByOrdinal( byteBuffer.getShort() );
+
+ int timeToLive = byteBuffer.getInt();
+ short dataLength = byteBuffer.getShort();
+
+ byte[] data = new byte[ dataLength ];
+ byteBuffer.get( data );
+
+ questions[ ii ] = new ResourceRecord( domainName, recordType,
+ recordClass, timeToLive, data );
+ }
+
+ return questions;
+ }
+
+ private QuestionRecord[] parseQuestions( short questionCount, ByteBuffer byteBuffer )
+ {
+ QuestionRecord[] questions = new QuestionRecord[ questionCount ];
+
+ for ( int ii = 0; ii < questionCount; ii++ )
+ {
+ String domainName = parseDomainName( byteBuffer );
+
+ RecordType recordType = RecordType.getTypeByOrdinal( byteBuffer.getShort() );
+ RecordClass recordClass = RecordClass.getTypeByOrdinal( byteBuffer.getShort() );
+
+ questions[ ii ] = new QuestionRecord( domainName, recordType, recordClass );
+ }
+
+ return questions;
+ }
+
+ private String parseDomainName( ByteBuffer byteBuffer )
+ {
+ StringBuffer domainName = new StringBuffer();
+ recurseDomainName( domainName, byteBuffer );
+
+ return domainName.toString();
+ }
+
+ private void recurseDomainName( StringBuffer domainName, ByteBuffer byteBuffer )
+ {
+ byte currentByte = byteBuffer.get();
+
+ boolean isCompressed = ( ( currentByte & (byte)0xc0 ) == (byte)0xc0 );
+ boolean isLabelLength = ( ( currentByte != 0 ) && !isCompressed );
+
+ if ( isCompressed )
+ {
+ int position = byteBuffer.get();
+ int originalPosition = byteBuffer.position();
+ byteBuffer.position( position );
+
+ int labelLength = byteBuffer.get();
+ getLabel( labelLength, byteBuffer, domainName );
+ recurseDomainName( domainName, byteBuffer );
+
+ byteBuffer.position( originalPosition );
+ }
+
+ if ( isLabelLength )
+ {
+ int labelLength = currentByte;
+ getLabel( labelLength, byteBuffer, domainName );
+ recurseDomainName( domainName, byteBuffer );
+ }
+ }
+
+ private void getLabel( int labelLength, ByteBuffer byteBuffer, StringBuffer domainName )
+ {
+ for ( int jj = 0; jj < labelLength; jj++ )
+ {
+ char character = (char)byteBuffer.get();
+ domainName.append( character );
+ }
+
+ if ( byteBuffer.get( byteBuffer.position() ) != 0 )
+ {
+ domainName.append( "." );
+ }
+ }
+
+ private MessageType parseMessageType( byte header )
+ {
+ return MessageType.getTypeByOrdinal( ( header & 0x80 ) >>> 7 );
+ }
+
+ private OpCode parseOpCode( byte header )
+ {
+ return OpCode.getTypeByOrdinal( ( header & 0x78 ) >>> 3 );
+ }
+
+ private boolean parseAuthoritativeAnswer( byte header )
+ {
+ return ( ( header & 0x04 ) >>> 2 ) == 1;
+ }
+
+ private boolean parseTruncated( byte header )
+ {
+ return ( ( header & 0x02 ) >>> 1 ) == 1;
+ }
+
+ private boolean parseRecursionDesired( byte header )
+ {
+ return ( ( header & 0x01 ) ) == 1;
+ }
+
+ private boolean parseRecursionAvailable( byte header )
+ {
+ return ( ( header & 0x80 ) >>> 7 ) == 1;
+ }
+
+ private ResponseCode parseResponseCode( byte header )
+ {
+ return ResponseCode.getTypeByOrdinal( header & 0x0F );
+ }
+}
+