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    package org.apache.directory.server.dns;
021    
022    
023    import java.io.IOException;
024    
025    import org.apache.directory.server.dns.protocol.DnsProtocolHandler;
026    import org.apache.directory.server.dns.store.RecordStore;
027    import org.apache.directory.server.dns.store.jndi.JndiRecordStoreImpl;
028    import org.apache.directory.server.protocol.shared.DirectoryBackedService;
029    import org.apache.directory.server.protocol.shared.transport.Transport;
030    import org.apache.directory.server.protocol.shared.transport.UdpTransport;
031    import org.apache.mina.core.service.IoAcceptor;
032    import org.apache.mina.transport.socket.DatagramAcceptor;
033    import org.apache.mina.transport.socket.DatagramSessionConfig;
034    import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
035    import org.slf4j.Logger;
036    import org.slf4j.LoggerFactory;
037    
038    
039    /**
040     * Contains the configuration parameters for the DNS protocol provider.
041     *
042     * @org.apache.xbean.XBean
043     *
044     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045     * @version $Rev: 925572 $, $Date: 2010-03-20 11:23:01 +0100 (Sat, 20 Mar 2010) $
046     */
047    public class DnsServer extends DirectoryBackedService
048    {
049        private static final long serialVersionUID = 6943138644427163149L;
050    
051        /** logger for this class */
052        private static final Logger LOG = LoggerFactory.getLogger( DnsServer.class.getName() );
053        
054        /** The default IP port. */
055        private static final int DEFAULT_IP_PORT = 53;
056    
057        /** The default service pid. */
058        private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.dns";
059    
060        /** The default service name. */
061        private static final String SERVICE_NAME_DEFAULT = "ApacheDS DNS Service";
062    
063    
064        /**
065         * Creates a new instance of DnsConfiguration.
066         */
067        public DnsServer()
068        {
069            super.setServiceId( SERVICE_PID_DEFAULT );
070            super.setServiceName( SERVICE_NAME_DEFAULT );
071        }
072    
073    
074        /**
075         * @throws IOException if we cannot bind to the specified ports
076         */
077        public void start() throws IOException
078        {
079            RecordStore store = new JndiRecordStoreImpl( getSearchBaseDn(), getSearchBaseDn(), getDirectoryService() );
080    
081            if ( ( transports == null ) || ( transports.size() == 0 ) )
082            {
083                // Default to UDP with port 53
084                // We have to create a DatagramAcceptor
085                UdpTransport transport = new UdpTransport( DEFAULT_IP_PORT );
086                setTransports( transport );
087                
088                DatagramAcceptor acceptor = (DatagramAcceptor)transport.getAcceptor();
089    
090                // Set the handler
091                acceptor.setHandler( new DnsProtocolHandler( this, store ) );
092        
093                // Allow the port to be reused even if the socket is in TIME_WAIT state
094                ((DatagramSessionConfig)acceptor.getSessionConfig()).setReuseAddress( true );
095                
096                // Start the listener
097                acceptor.bind();
098            }
099            else
100            {
101                for ( Transport transport:transports )
102                {
103                    // Get the acceptor
104                    IoAcceptor acceptor = transport.getAcceptor();
105        
106                    // Set the handler
107                    acceptor.setHandler( new DnsProtocolHandler( this, store ) );
108            
109                    if ( transport instanceof UdpTransport )
110                    {
111                    // Allow the port to be reused even if the socket is in TIME_WAIT state
112                        ((DatagramSessionConfig)acceptor.getSessionConfig()).setReuseAddress( true );
113                    }
114                    else
115                    {
116                        // Disable the disconnection of the clients on unbind
117                        acceptor.setCloseOnDeactivation( false );
118                        
119                        // Allow the port to be reused even if the socket is in TIME_WAIT state
120                        ((NioSocketAcceptor)acceptor).setReuseAddress( true );
121                        
122                        // No Nagle's algorithm
123                        ((NioSocketAcceptor)acceptor).getSessionConfig().setTcpNoDelay( true );
124                    }
125            
126                    // Start the listener
127                    acceptor.bind();
128                }
129            }
130    
131            LOG.info( "DNS service started." );
132            System.out.println( "DNS service started." );
133        }
134    
135    
136        public void stop() {
137            for ( Transport transport :getTransports() )
138            {
139                IoAcceptor acceptor = transport.getAcceptor();
140                
141                if ( acceptor != null )
142                {
143                    acceptor.dispose();
144                }
145            }
146            
147            LOG.info( "DNS service stopped." );
148            System.out.println( "DNS service stopped." );
149        }
150        
151        
152        /**
153         * @see Object#toString()
154         */
155        public String toString()
156        {
157            StringBuilder sb = new StringBuilder();
158            
159            sb.append( "DNSServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' );
160            
161            if ( getTransports() != null )
162            {
163                for ( Transport transport:getTransports() )
164                {
165                    sb.append( "    " ).append( transport ).append( '\n' );
166                }
167            }
168            
169            return sb.toString();
170        }
171    }