Package org.apache.directory.server.dns.io.encoder

Source Code of org.apache.directory.server.dns.io.encoder.DnsMessageEncoder

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF 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 org.apache.directory.server.dns.io.encoder;


import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.directory.server.dns.messages.DnsMessage;
import org.apache.directory.server.dns.messages.MessageType;
import org.apache.directory.server.dns.messages.OpCode;
import org.apache.directory.server.dns.messages.QuestionRecord;
import org.apache.directory.server.dns.messages.RecordType;
import org.apache.directory.server.dns.messages.ResourceRecord;
import org.apache.directory.server.dns.messages.ResponseCode;
import org.apache.directory.server.i18n.I18n;
import org.apache.mina.core.buffer.IoBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* An encoder for DNS messages.  The primary usage of the DnsMessageEncoder is
* to call the <code>encode(ByteBuffer, DnsMessage)</code> method which will
* write the message to the outgoing ByteBuffer according to the DnsMessage
* encoding in RFC-1035.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class DnsMessageEncoder
{
    /** the log for this class */
    private static final Logger log = LoggerFactory.getLogger( DnsMessageEncoder.class );

    /**
     * A Hashed Adapter mapping record types to their encoders.
     */
    private static final Map<RecordType, RecordEncoder> DEFAULT_ENCODERS;

    static
    {
        Map<RecordType, RecordEncoder> map = new HashMap<RecordType, RecordEncoder>();

        map.put( RecordType.SOA, new StartOfAuthorityRecordEncoder() );
        map.put( RecordType.A, new AddressRecordEncoder() );
        map.put( RecordType.NS, new NameServerRecordEncoder() );
        map.put( RecordType.CNAME, new CanonicalNameRecordEncoder() );
        map.put( RecordType.PTR, new PointerRecordEncoder() );
        map.put( RecordType.MX, new MailExchangeRecordEncoder() );
        map.put( RecordType.SRV, new ServerSelectionRecordEncoder() );
        map.put( RecordType.TXT, new TextRecordEncoder() );

        DEFAULT_ENCODERS = Collections.unmodifiableMap( map );
    }


    /**
     * Encodes the {@link DnsMessage} into the {@link IoBuffer}.
     *
     * @param byteBuffer
     * @param message
     */
    public void encode( IoBuffer byteBuffer, DnsMessage message )
    {
        byteBuffer.putShort( ( short ) message.getTransactionId() );

        byte header = ( byte ) 0x00;
        header |= encodeMessageType( message.getMessageType() );
        header |= encodeOpCode( message.getOpCode() );
        header |= encodeAuthoritativeAnswer( message.isAuthoritativeAnswer() );
        header |= encodeTruncated( message.isTruncated() );
        header |= encodeRecursionDesired( message.isRecursionDesired() );
        byteBuffer.put( header );

        header = ( byte ) 0x00;
        header |= encodeRecursionAvailable( message.isRecursionAvailable() );
        header |= encodeResponseCode( message.getResponseCode() );
        byteBuffer.put( header );

        byteBuffer
            .putShort( ( short ) ( message.getQuestionRecords() != null ? message.getQuestionRecords().size() : 0 ) );
        byteBuffer.putShort( ( short ) ( message.getAnswerRecords() != null ? message.getAnswerRecords().size() : 0 ) );
        byteBuffer.putShort( ( short ) ( message.getAuthorityRecords() != null ? message.getAuthorityRecords().size()
            : 0 ) );
        byteBuffer.putShort( ( short ) ( message.getAdditionalRecords() != null ? message.getAdditionalRecords().size()
            : 0 ) );

        putQuestionRecords( byteBuffer, message.getQuestionRecords() );
        putResourceRecords( byteBuffer, message.getAnswerRecords() );
        putResourceRecords( byteBuffer, message.getAuthorityRecords() );
        putResourceRecords( byteBuffer, message.getAdditionalRecords() );
    }


    private void putQuestionRecords( IoBuffer byteBuffer, List<QuestionRecord> questions )
    {
        if ( questions == null )
        {
            return;
        }

        QuestionRecordEncoder encoder = new QuestionRecordEncoder();

        Iterator<QuestionRecord> it = questions.iterator();

        while ( it.hasNext() )
        {
            QuestionRecord question = it.next();
            encoder.put( byteBuffer, question );
        }
    }


    private void putResourceRecords( IoBuffer byteBuffer, List<ResourceRecord> records )
    {
        if ( records == null )
        {
            return;
        }

        Iterator<ResourceRecord> it = records.iterator();

        while ( it.hasNext() )
        {
            ResourceRecord record = it.next();

            try
            {
                put( byteBuffer, record );
            }
            catch ( IOException ioe )
            {
                log.error( ioe.getLocalizedMessage(), ioe );
            }
        }
    }


    private void put( IoBuffer byteBuffer, ResourceRecord record ) throws IOException
    {
        RecordType type = record.getRecordType();

        RecordEncoder encoder = DEFAULT_ENCODERS.get( type );

        if ( encoder == null )
        {
            throw new IOException( I18n.err( I18n.ERR_597, type ) );
        }

        encoder.put( byteBuffer, record );
    }


    private byte encodeMessageType( MessageType messageType )
    {
        byte oneBit = ( byte ) ( messageType.convert() & 0x01 );
        return ( byte ) ( oneBit << 7 );
    }


    private byte encodeOpCode( OpCode opCode )
    {
        byte fourBits = ( byte ) ( opCode.convert() & 0x0F );
        return ( byte ) ( fourBits << 3 );
    }


    private byte encodeAuthoritativeAnswer( boolean authoritative )
    {
        if ( authoritative )
        {
            return ( byte ) ( ( byte ) 0x01 << 2 );
        }
        return ( byte ) 0;
    }


    private byte encodeTruncated( boolean truncated )
    {
        if ( truncated )
        {
            return ( byte ) ( ( byte ) 0x01 << 1 );
        }
        return 0;
    }


    private byte encodeRecursionDesired( boolean recursionDesired )
    {
        if ( recursionDesired )
        {
            return ( byte ) 0x01;
        }
        return 0;
    }


    private byte encodeRecursionAvailable( boolean recursionAvailable )
    {
        if ( recursionAvailable )
        {
            return ( byte ) ( ( byte ) 0x01 << 7 );
        }
        return 0;
    }


    private byte encodeResponseCode( ResponseCode responseCode )
    {
        return ( byte ) ( responseCode.convert() & 0x0F );
    }
}
TOP

Related Classes of org.apache.directory.server.dns.io.encoder.DnsMessageEncoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.