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