001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    
021    package org.apache.directory.server.dns.protocol;
022    
023    
024    import java.util.ArrayList;
025    
026    import org.apache.directory.server.dns.DnsServer;
027    import org.apache.directory.server.dns.DnsException;
028    import org.apache.directory.server.dns.messages.DnsMessage;
029    import org.apache.directory.server.dns.messages.DnsMessageModifier;
030    import org.apache.directory.server.dns.messages.MessageType;
031    import org.apache.directory.server.dns.messages.OpCode;
032    import org.apache.directory.server.dns.messages.ResourceRecord;
033    import org.apache.directory.server.dns.messages.ResponseCode;
034    import org.apache.directory.server.dns.service.DnsContext;
035    import org.apache.directory.server.dns.service.DomainNameService;
036    import org.apache.directory.server.dns.store.RecordStore;
037    import org.apache.mina.core.service.IoHandler;
038    import org.apache.mina.core.session.IdleStatus;
039    import org.apache.mina.core.session.IoSession;
040    import org.apache.mina.filter.codec.ProtocolCodecFilter;
041    import org.slf4j.Logger;
042    import org.slf4j.LoggerFactory;
043    
044    
045    /**
046     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047     * @version $Rev: 901657 $, $Date: 2010-01-21 12:27:15 +0100 (Thu, 21 Jan 2010) $
048     */
049    public class DnsProtocolHandler implements IoHandler
050    {
051        private static final Logger LOG = LoggerFactory.getLogger( DnsProtocolHandler.class );
052    
053        private DnsServer config;
054        private RecordStore store;
055        private String contextKey = "context";
056    
057    
058        /**
059         * Creates a new instance of DnsProtocolHandler.
060         *
061         * @param config
062         * @param store
063         */
064        public DnsProtocolHandler( DnsServer config, RecordStore store )
065        {
066            this.config = config;
067            this.store = store;
068        }
069    
070    
071        public void sessionCreated( IoSession session ) throws Exception
072        {
073            if ( LOG.isDebugEnabled() )
074            {
075                LOG.debug( "{} CREATED:  {}", session.getRemoteAddress(), session.getTransportMetadata() );
076            }
077    
078            if ( session.getTransportMetadata().isConnectionless() )
079            {
080                session.getFilterChain().addFirst( "codec",
081                    new ProtocolCodecFilter( DnsProtocolUdpCodecFactory.getInstance() ) );
082            }
083            else
084            {
085                session.getFilterChain().addFirst( "codec",
086                    new ProtocolCodecFilter( DnsProtocolTcpCodecFactory.getInstance() ) );
087            }
088        }
089    
090    
091        public void sessionOpened( IoSession session )
092        {
093            LOG.debug( "{} OPENED", session.getRemoteAddress() );
094        }
095    
096    
097        public void sessionClosed( IoSession session )
098        {
099            LOG.debug( "{} CLOSED", session.getRemoteAddress() );
100        }
101    
102    
103        public void sessionIdle( IoSession session, IdleStatus status )
104        {
105            LOG.debug( "{} IDLE ({})", session.getRemoteAddress(), status );
106        }
107    
108    
109        public void exceptionCaught( IoSession session, Throwable cause )
110        {
111            LOG.error( session.getRemoteAddress() + " EXCEPTION", cause );
112            session.close( true );
113        }
114    
115    
116        public void messageReceived( IoSession session, Object message )
117        {
118            LOG.debug( "{} RCVD:  {}", session.getRemoteAddress(), message );
119    
120            try
121            {
122                DnsContext dnsContext = new DnsContext();
123                dnsContext.setConfig( config );
124                dnsContext.setStore( store );
125                session.setAttribute( getContextKey(), dnsContext );
126    
127                DomainNameService.execute( dnsContext, (DnsMessage)message );
128    
129                DnsMessage response = dnsContext.getReply();
130    
131                session.write( response );
132            }
133            catch ( Exception e )
134            {
135                LOG.error( e.getLocalizedMessage(), e );
136    
137                DnsMessage request = ( DnsMessage ) message;
138                DnsException de = ( DnsException ) e;
139    
140                DnsMessageModifier modifier = new DnsMessageModifier();
141    
142                modifier.setTransactionId( request.getTransactionId() );
143                modifier.setMessageType( MessageType.RESPONSE );
144                modifier.setOpCode( OpCode.QUERY );
145                modifier.setAuthoritativeAnswer( false );
146                modifier.setTruncated( false );
147                modifier.setRecursionDesired( request.isRecursionDesired() );
148                modifier.setRecursionAvailable( false );
149                modifier.setReserved( false );
150                modifier.setAcceptNonAuthenticatedData( false );
151                modifier.setResponseCode( ResponseCode.convert( ( byte ) de.getResponseCode() ) );
152                modifier.setQuestionRecords( request.getQuestionRecords() );
153                modifier.setAnswerRecords( new ArrayList<ResourceRecord>() );
154                modifier.setAuthorityRecords( new ArrayList<ResourceRecord>() );
155                modifier.setAdditionalRecords( new ArrayList<ResourceRecord>() );
156    
157                session.write( modifier.getDnsMessage() );
158            }
159        }
160    
161    
162        public void messageSent( IoSession session, Object message )
163        {
164            LOG.debug( "{} SENT:  {}", session.getRemoteAddress(), message );
165        }
166    
167    
168        protected String getContextKey()
169        {
170            return ( this.contextKey );
171        }
172    }