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 );
+       }
+}
+

Reply via email to