/*
 * 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.dhcp.service;


import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Iterator;

import org.apache.directory.server.dhcp.DhcpException;
import org.apache.directory.server.dhcp.messages.DhcpMessage;
import org.apache.directory.server.dhcp.options.DhcpOption;
import org.apache.directory.server.dhcp.options.OptionsField;
import org.apache.directory.server.dhcp.options.dhcp.ParameterRequestList;
import org.apache.directory.server.dhcp.options.dhcp.ServerIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Abstract implementation of the server-side DHCP protocol. This class just
 * provides some utility methods and dispatches server-bound messages to handler
 * methods which can be overridden to provide the functionality.
 * <p>
 * Client-bound messages and BOOTP messages are ignored.
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * 
 */
public abstract class AbstractDhcpService implements DhcpService
{
    private static final Logger logger = LoggerFactory
        .getLogger( AbstractDhcpService.class );


    /*
     * @see org.apache.directory.server.dhcp.DhcpService#getReplyFor(org.apache.directory.server.dhcp.messages.DhcpMessage)
     */
    public final DhcpMessage getReplyFor( InetSocketAddress localAddress,
        InetSocketAddress clientAddress, DhcpMessage request )
        throws DhcpException
    {
        // ignore messages with an op != REQUEST/REPLY
        if ( ( request.getOp() != DhcpMessage.OP_BOOTREQUEST )
            && ( request.getOp() != DhcpMessage.OP_BOOTREPLY ) )
        {
            return null;
        }

        // message type option MUST be set - we don't support plain BOOTP.
        if ( null == request.getMessageType() )
        {
            logger.warn( "Missing message type option - plain BOOTP not supported." );

            return null;
        }

        // dispatch based on the message type
        switch ( request.getMessageType() )
        {
        // client-to-server messages
            case DHCPDISCOVER:
                return handleDISCOVER( localAddress, clientAddress, request );

            case DHCPREQUEST:
                return handleREQUEST( localAddress, clientAddress, request );

            case DHCPRELEASE:
                return handleRELEASE( localAddress, clientAddress, request );

            case DHCPINFORM:
                return handleINFORM( localAddress, clientAddress, request );

            case DHCPOFFER:
                return handleOFFER( localAddress, clientAddress, request );

                // server-to-client messages
            case DHCPDECLINE:
            case DHCPACK:
            case DHCPNAK:
                return null; // just ignore them

            default:
                return handleUnknownMessage( clientAddress, request );
        }
    }


    /**
     * Handle unknown DHCP message. The default implementation just logs and
     * ignores it.
     * 
     * @param clientAddress
     * @param request the request message
     * @return DhcpMessage response message or <code>null</code> to ignore (don't reply to)
     *         it.
     */
    protected DhcpMessage handleUnknownMessage( InetSocketAddress clientAddress,
        DhcpMessage request )
    {
        if ( logger.isWarnEnabled() )
        {
            logger.warn( "Got unknkown DHCP message: {} from: {}", request, clientAddress );
        }

        return null;
    }


    /**
     * Handle DHCPINFORM message. The default implementation just ignores it.
     * 
     * @param localAddress
     * @param clientAddress
     * @param request the request message
     * @return DhcpMessage response message or <code>null</code> to ignore (don't reply to)
     *         it.
     */
    protected DhcpMessage handleINFORM( InetSocketAddress localAddress,
        InetSocketAddress clientAddress, DhcpMessage request )
        throws DhcpException
    {
        if ( logger.isDebugEnabled() )
        {
            logger.debug( "Got INFORM message: {} from: {}", request, clientAddress );
        }

        return null;
    }


    /**
     * Handle DHCPRELEASE message. The default implementation just ignores it.
     * 
     * @param localAddress
     * @param clientAddress
     * @param request the request message
     * @return DhcpMessage response message or <code>null</code> to ignore (don't reply to)
     *         it.
     */
    protected DhcpMessage handleRELEASE( InetSocketAddress localAddress,
        InetSocketAddress clientAddress, DhcpMessage request )
        throws DhcpException
    {
        if ( logger.isDebugEnabled() )
            logger.debug( "Got RELEASE message: {} from: {}", request, clientAddress );
        return null;
    }


    /**
     * Handle DHCPREQUEST message. The default implementation just ignores it.
     * 
     * @param localAddress
     * @param clientAddress
     * @param request the request message
     * @return DhcpMessage response message or <code>null</code> to ignore (don't reply to)
     *         it.
     */
    protected DhcpMessage handleREQUEST( InetSocketAddress localAddress,
        InetSocketAddress clientAddress, DhcpMessage request )
        throws DhcpException
    {
        if ( logger.isDebugEnabled() )
        {
            logger.debug( "Got REQUEST message: {} from: {}", request, clientAddress );
        }

        return null;
    }


    /**
     * Handle DHCPDISCOVER message. The default implementation just ignores it.
     * 
     * @param localAddress
     * @param clientAddress
     * @param request the request message
     * @return DhcpMessage response message or <code>null</code> to ignore (don't reply to)
     *         it.
     * @throws DhcpException
     */
    protected DhcpMessage handleDISCOVER( InetSocketAddress localAddress,
        InetSocketAddress clientAddress, DhcpMessage request )
        throws DhcpException
    {
        if ( logger.isDebugEnabled() )
        {
            logger.debug( "Got DISCOVER message: {} from: {}", request, clientAddress );
        }

        return null;
    }


    /**
     * Handle DHCPOFFER message. The default implementation just ignores it.
     * 
     * @param localAddress
     * @param clientAddress
     * @param request the request message
     * @return DhcpMessage response message or <code>null</code> to ignore (don't reply to)
     *         it.
     * @throws DhcpException
     */
    protected DhcpMessage handleOFFER( InetSocketAddress localAddress,
        InetSocketAddress clientAddress, DhcpMessage request )
        throws DhcpException
    {
        if ( logger.isDebugEnabled() )
        {
            logger.debug( "Got OFFER message: {} from: {}", request, clientAddress );
        }

        return null;
    }


    /**
     * Initialize a general DHCP reply message. Sets:
     * <ul>
     * <li>op=BOOTREPLY
     * <li>htype, hlen, xid, flags, giaddr, chaddr like in request message
     * <li>hops, secs to 0.
     * <li>server hostname to the hostname appropriate for the interface the
     * request was received on
     * <li>the server identifier set to the address of the interface the request
     * was received on
     * </ul>
     * 
     * @param localAddress
     * @param request
     * @return DhcpMessage
     */
    protected final DhcpMessage initGeneralReply( InetSocketAddress localAddress,
        DhcpMessage request )
    {
        DhcpMessage reply = new DhcpMessage();

        reply.setOp( DhcpMessage.OP_BOOTREPLY );

        reply.setHardwareAddress( request.getHardwareAddress() );
        reply.setTransactionId( request.getTransactionId() );
        reply.setFlags( request.getFlags() );
        reply.setRelayAgentAddress( request.getRelayAgentAddress() );

        // set server hostname
        reply.setServerHostname( localAddress.getHostName() );

        // set server identifier based on the IF on which we received the packet
        reply.getOptions().add( new ServerIdentifier( localAddress.getAddress() ) );

        return reply;
    }


    /**
     * Check if an address is the zero-address
     * 
     * @param addr
     * @return boolean
     */
    private boolean isZeroAddress( byte[] addr )
    {
        for ( int i = 0; i < addr.length; i++ )
        {
            if ( addr[i] != 0 )
            {
                return false;
            }
        }

        return true;
    }


    /**
     * Determine address on which to base selection. If the relay agent address is
     * set, we use the relay agent's address, otherwise we use the address we
     * received the request from.
     * 
     * @param clientAddress
     * @param request
     * @return InetAddress
     */
    protected final InetAddress determineSelectionBase(
        InetSocketAddress clientAddress, DhcpMessage request )
    {
        // FIXME: do we know
        // a) the interface address over which we received a message (!)
        // b) the client address (if specified)
        // c) the relay agent address?

        // if the relay agent address is set, we use it as the selection base
        if ( !isZeroAddress( request.getRelayAgentAddress().getAddress() ) )
        {
            return request.getRelayAgentAddress();
        }

        return clientAddress.getAddress();
    }


    /**
     * Strip options that the client doesn't want, if the ParameterRequestList
     * option is present.
     * 
     * @param request
     * @param options
     */
    protected final void stripUnwantedOptions( DhcpMessage request,
        OptionsField options )
    {
        ParameterRequestList prl = ( ParameterRequestList ) request
            .getOptions().get( ParameterRequestList.class );

        if ( null != prl )
        {
            byte[] list = prl.getData();

            for ( Iterator i = options.iterator(); i.hasNext(); )
            {
                DhcpOption o = ( DhcpOption ) i.next();

                boolean found = false;

                for ( int j = 0; j < list.length; j++ )
                {
                    if ( list[j] == o.getTag() )
                    {
                        found = true;
                        break;
                    }
                }

                if ( !found )
                {
                    i.remove();
                }
            }
        }
    }
}
