/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */


package com.sun.jmx.snmp.daemon;


// java imports
//
import java.util.Vector;
import java.util.Enumeration;
import java.util.logging.Level;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.InterruptedIOException;


// jmx imports
//
import javax.management.MBeanServer;
import javax.management.MBeanRegistration;
import javax.management.ObjectName;
import javax.management.InstanceAlreadyExistsException;
import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
import com.sun.jmx.snmp.SnmpIpAddress;
import com.sun.jmx.snmp.SnmpMessage;
import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.snmp.SnmpPduFactory;
import com.sun.jmx.snmp.SnmpPduPacket;
import com.sun.jmx.snmp.SnmpPduRequest;
import com.sun.jmx.snmp.SnmpPduTrap;
import com.sun.jmx.snmp.SnmpTimeticks;
import com.sun.jmx.snmp.SnmpVarBind;
import com.sun.jmx.snmp.SnmpVarBindList;
import com.sun.jmx.snmp.SnmpDefinitions;
import com.sun.jmx.snmp.SnmpStatusException;
import com.sun.jmx.snmp.SnmpTooBigException;
import com.sun.jmx.snmp.InetAddressAcl;
import com.sun.jmx.snmp.SnmpPeer;
import com.sun.jmx.snmp.SnmpParameters;
// SNMP Runtime imports
//
import com.sun.jmx.snmp.SnmpPduFactoryBER;
import com.sun.jmx.snmp.agent.SnmpMibAgent;
import com.sun.jmx.snmp.agent.SnmpMibHandler;
import com.sun.jmx.snmp.agent.SnmpUserDataFactory;
import com.sun.jmx.snmp.agent.SnmpErrorHandlerAgent;

import com.sun.jmx.snmp.IPAcl.SnmpAcl;

import com.sun.jmx.snmp.tasks.ThreadService;

/**
 * Implements an adaptor on top of the SNMP protocol.
 * <P>
 * When this SNMP protocol adaptor is started it creates a datagram socket
 * and is able to receive requests and send traps or inform requests.
 * When it is stopped, the socket is closed and neither requests
 * and nor traps/inform request are processed.
 * <P>
 * The default port number of the socket is 161. This default value can be
 * changed by specifying a port number:
 * <UL>
 * <LI>in the object constructor</LI>
 * <LI>using the {@link com.sun.jmx.snmp.daemon.CommunicatorServer#setPort
 *     setPort} method before starting the adaptor</LI>
 * </UL>
 * The default object name is defined by {@link
 * com.sun.jmx.snmp.ServiceName#DOMAIN com.sun.jmx.snmp.ServiceName.DOMAIN}
 * and {@link com.sun.jmx.snmp.ServiceName#SNMP_ADAPTOR_SERVER
 * com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER}.
 * <P>
 * The SNMP protocol adaptor supports versions 1 and 2 of the SNMP protocol
 * in a stateless way: when it receives a v1 request, it replies with a v1
 * response, when it receives a v2 request it replies with a v2 response.
 * <BR>The method {@link #snmpV1Trap snmpV1Trap} sends traps using SNMP v1
 * format.
 * The method {@link #snmpV2Trap snmpV2Trap} sends traps using SNMP v2 format.
 * The method {@link #snmpInformRequest snmpInformRequest} sends inform
 * requests using SNMP v2 format.
 * <P>
 * To receive data packets, the SNMP protocol adaptor uses a buffer
 * which size can be configured using the property <CODE>bufferSize</CODE>
 * (default value is 1024).
 * Packets which do not fit into the buffer are rejected.
 * Increasing <CODE>bufferSize</CODE> allows the exchange of bigger packets.
 * However, the underlying networking system may impose a limit on the size
 * of UDP packets.
 * Packets which size exceed this limit will be rejected, no matter what
 * the value of <CODE>bufferSize</CODE> actually is.
 * <P>
 * An SNMP protocol adaptor may serve several managers concurrently. The
 * number of concurrent managers can be limited using the property
 * <CODE>maxActiveClientCount</CODE>.
 * <p>
 * The SNMP protocol adaptor specifies a default value (10) for the
 * <CODE>maxActiveClientCount</CODE> property. When the adaptor is stopped,
 * the active requests are interrupted and an error result is sent to
 * the managers.
 * <p><b>This API is a Sun Microsystems internal API  and is subject
 * to change without notice.</b></p>
 */

public class SnmpAdaptorServer extends CommunicatorServer
    implements SnmpAdaptorServerMBean, MBeanRegistration, SnmpDefinitions,
               SnmpMibHandler {

    // PRIVATE VARIABLES
    //------------------

    /**
     * Port number for sending SNMP traps.
     * <BR>The default value is 162.
     */
    private int                 trapPort = 162;

    /**
     * Port number for sending SNMP inform requests.
     * <BR>The default value is 162.
     */
    private int                 informPort = 162;

    /**
     * The <CODE>InetAddress</CODE> used when creating the datagram socket.
     * <BR>It is specified when creating the SNMP protocol adaptor.
     * If not specified, the local host machine is used.
     */
    InetAddress address = null;

    /**
     * The IP address based ACL used by this SNMP protocol adaptor.
     */
    private Object ipacl = null;

    /**
     * The factory object.
     */
    private SnmpPduFactory pduFactory = null;

    /**
     * The user-data factory object.
     */
    private SnmpUserDataFactory userDataFactory = null;

    /**
     * Indicates if the SNMP protocol adaptor sends a response in case
     * of authentication failure
     */
    private boolean authRespEnabled = true;

    /**
     * Indicates if authentication traps are enabled.
     */
    private boolean authTrapEnabled = true;

    /**
     * The enterprise OID.
     * <BR>The default value is "1.3.6.1.4.1.42".
     */
    private SnmpOid enterpriseOid = new SnmpOid("1.3.6.1.4.1.42");

    /**
     * The buffer size of the SNMP protocol adaptor.
     * This buffer size is used for both incoming request and outgoing
     * inform requests.
     * <BR>The default value is 1024.
     */
    int bufferSize = 1024;

    private transient long            startUpTime     = 0;
    private transient DatagramSocket  socket          = null;
    transient DatagramSocket          trapSocket      = null;
    private transient SnmpSession     informSession   = null;
    private transient DatagramPacket  packet          = null;
    transient Vector<SnmpMibAgent>    mibs            = new Vector<SnmpMibAgent>();
    private transient SnmpMibTree     root;

    /**
     * Whether ACL must be used.
     */
    private transient boolean         useAcl = true;


    // SENDING SNMP INFORMS STUFF
    //---------------------------

    /**
     * Number of times to try an inform request before giving up.
     * The default number is 3.
     */
    private int maxTries = 3 ;

    /**
     * The amount of time to wait for an inform response from the manager.
     * The default amount of time is 3000 millisec.
     */
    private int timeout = 3 * 1000 ;

    // VARIABLES REQUIRED FOR IMPLEMENTING SNMP GROUP (MIBII)
    //-------------------------------------------------------

    /**
     * The <CODE>snmpOutTraps</CODE> value defined in MIB-II.
     */
    int snmpOutTraps=0;

    /**
     * The <CODE>snmpOutGetResponses</CODE> value defined in MIB-II.
     */
    private int snmpOutGetResponses=0;

    /**
     * The <CODE>snmpOutGenErrs</CODE> value defined in MIB-II.
     */
    private int snmpOutGenErrs=0;

    /**
     * The <CODE>snmpOutBadValues</CODE> value defined in MIB-II.
     */
    private int snmpOutBadValues=0;

    /**
     * The <CODE>snmpOutNoSuchNames</CODE> value defined in MIB-II.
     */
    private int snmpOutNoSuchNames=0;

    /**
     * The <CODE>snmpOutTooBigs</CODE> value defined in MIB-II.
     */
    private int snmpOutTooBigs=0;

    /**
     * The <CODE>snmpOutPkts</CODE> value defined in MIB-II.
     */
    int snmpOutPkts=0;

    /**
     * The <CODE>snmpInASNParseErrs</CODE> value defined in MIB-II.
     */
    private int snmpInASNParseErrs=0;

    /**
     * The <CODE>snmpInBadCommunityUses</CODE> value defined in MIB-II.
     */
    private int snmpInBadCommunityUses=0;

    /**
     * The <CODE>snmpInBadCommunityNames</CODE> value defined in MIB-II.
     */
    private int snmpInBadCommunityNames=0;

    /**
     * The <CODE>snmpInBadVersions</CODE> value defined in MIB-II.
     */
    private int snmpInBadVersions=0;

    /**
     * The <CODE>snmpInGetRequests</CODE> value defined in MIB-II.
     */
    private int snmpInGetRequests=0;

    /**
     * The <CODE>snmpInGetNexts</CODE> value defined in MIB-II.
     */
    private int snmpInGetNexts=0;

    /**
     * The <CODE>snmpInSetRequests</CODE> value defined in MIB-II.
     */
    private int snmpInSetRequests=0;

    /**
     * The <CODE>snmpInPkts</CODE> value defined in MIB-II.
     */
    private int snmpInPkts=0;

    /**
     * The <CODE>snmpInTotalReqVars</CODE> value defined in MIB-II.
     */
    private int snmpInTotalReqVars=0;

    /**
     * The <CODE>snmpInTotalSetVars</CODE> value defined in MIB-II.
     */
    private int snmpInTotalSetVars=0;

    /**
     * The <CODE>snmpInTotalSetVars</CODE> value defined in rfc 1907 MIB-II.
     */
    private int snmpSilentDrops=0;

    private static final String InterruptSysCallMsg =
        "Interrupted system call";
    static final SnmpOid sysUpTimeOid = new SnmpOid("1.3.6.1.2.1.1.3.0") ;
    static final SnmpOid snmpTrapOidOid = new SnmpOid("1.3.6.1.6.3.1.1.4.1.0");

    private ThreadService threadService;

    private static int threadNumber = 6;

    static {
        String s = System.getProperty("com.sun.jmx.snmp.threadnumber");

        if (s != null) {
            try {
                threadNumber = Integer.parseInt(System.getProperty(s));
            } catch (Exception e) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINER,
                        SnmpAdaptorServer.class.getName(),
                        "<static init>",
                        "Got wrong value for com.sun.jmx.snmp.threadnumber: " +
                        s + ". Use the default value: " + threadNumber);
            }
        }
    }

    // PUBLIC CONSTRUCTORS
    //--------------------

    /**
     * Initializes this SNMP protocol adaptor using the default port (161).
     * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
     * implementation of the <CODE>InetAddressAcl</CODE> interface.
     */
    public SnmpAdaptorServer() {
        this(true, null, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
             null) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the specified port.
     * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
     * implementation of the <CODE>InetAddressAcl</CODE> interface.
     *
     * @param port The port number for sending SNMP responses.
     */
    public SnmpAdaptorServer(int port) {
        this(true, null, port, null) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the default port (161)
     * and the specified IP address based ACL implementation.
     *
     * @param acl The <CODE>InetAddressAcl</CODE> implementation.
     *        <code>null</code> means no ACL - everybody is authorized.
     *
     * @since 1.5
     */
    public SnmpAdaptorServer(InetAddressAcl acl) {
        this(false, acl, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
             null) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the default port (161)
     * and the
     * specified <CODE>InetAddress</CODE>.
     * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
     * implementation of the <CODE>InetAddressAcl</CODE> interface.
     *
     * @param addr The IP address to bind.
     */
    public SnmpAdaptorServer(InetAddress addr) {
        this(true, null, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
             addr) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the specified port and the
     * specified IP address based ACL implementation.
     *
     * @param acl The <CODE>InetAddressAcl</CODE> implementation.
     *        <code>null</code> means no ACL - everybody is authorized.
     * @param port The port number for sending SNMP responses.
     *
     * @since 1.5
     */
    public SnmpAdaptorServer(InetAddressAcl acl, int port) {
        this(false, acl, port, null) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the specified port and the
     * specified <CODE>InetAddress</CODE>.
     * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
     * implementation of the <CODE>InetAddressAcl</CODE> interface.
     *
     * @param port The port number for sending SNMP responses.
     * @param addr The IP address to bind.
     */
    public SnmpAdaptorServer(int port, InetAddress addr) {
        this(true, null, port, addr) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the specified IP
     * address based ACL implementation and the specified
     * <CODE>InetAddress</CODE>.
     *
     * @param acl The <CODE>InetAddressAcl</CODE> implementation.
     * @param addr The IP address to bind.
     *
     * @since 1.5
     */
    public SnmpAdaptorServer(InetAddressAcl acl, InetAddress addr) {
        this(false, acl, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
             addr) ;
    }

    /**
     * Initializes this SNMP protocol adaptor using the specified port, the
     * specified  address based ACL implementation and the specified
     * <CODE>InetAddress</CODE>.
     *
     * @param acl The <CODE>InetAddressAcl</CODE> implementation.
     * @param port The port number for sending SNMP responses.
     * @param addr The IP address to bind.
     *
     * @since 1.5
     */
    public SnmpAdaptorServer(InetAddressAcl acl, int port, InetAddress addr) {
        this(false, acl, port, addr);
    }

    /**
     * Initializes this SNMP protocol adaptor using the specified port and the
     * specified <CODE>InetAddress</CODE>.
     * This constructor allows to initialize an SNMP adaptor without using
     * the ACL mechanism (by setting the <CODE>useAcl</CODE> parameter to
     * false).
     * <br>This constructor must be used in particular with a platform that
     * does not support the <CODE>java.security.acl</CODE> package like pJava.
     *
     * @param useAcl Specifies if this new SNMP adaptor uses the ACL mechanism.
     * If the specified parameter is set to <CODE>true</CODE>, this
     * constructor is equivalent to
     * <CODE>SnmpAdaptorServer((int)port,(InetAddress)addr)</CODE>.
     * @param port The port number for sending SNMP responses.
     * @param addr The IP address to bind.
     */
    public SnmpAdaptorServer(boolean useAcl, int port, InetAddress addr) {
        this(useAcl,null,port,addr);
    }

    // If forceAcl is `true' and InetAddressAcl is null, then a default
    // SnmpAcl object is created.
    //
    private SnmpAdaptorServer(boolean forceAcl, InetAddressAcl acl,
                              int port, InetAddress addr) {
        super(CommunicatorServer.SNMP_TYPE) ;


        // Initialize the ACL implementation.
        //
        if (acl == null && forceAcl) {
            try {
                acl = (InetAddressAcl)
                    new SnmpAcl("SNMP protocol adaptor IP ACL");
            } catch (UnknownHostException e) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "constructor", "UnknowHostException when creating ACL",e);
                }
            }
        } else {
            this.useAcl = (acl!=null) || forceAcl;
        }

        init(acl, port, addr) ;
    }

    // GETTERS AND SETTERS
    //--------------------

    /**
     * Gets the number of managers that have been processed by this
     * SNMP protocol adaptor  since its creation.
     *
     * @return The number of managers handled by this SNMP protocol adaptor
     * since its creation. This counter is not reset by the <CODE>stop</CODE>
     * method.
     */
    public int getServedClientCount() {
        return super.getServedClientCount();
    }

    /**
     * Gets the number of managers currently being processed by this
     * SNMP protocol adaptor.
     *
     * @return The number of managers currently being processed by this
     * SNMP protocol adaptor.
     */
    public int getActiveClientCount() {
        return super.getActiveClientCount();
    }

    /**
     * Gets the maximum number of managers that this SNMP protocol adaptor can
     * process concurrently.
     *
     * @return The maximum number of managers that this SNMP protocol adaptor
     *         can process concurrently.
     */
    public int getMaxActiveClientCount() {
        return super.getMaxActiveClientCount();
    }

    /**
     * Sets the maximum number of managers this SNMP protocol adaptor can
     * process concurrently.
     *
     * @param c The number of managers.
     *
     * @exception java.lang.IllegalStateException This method has been invoked
     * while the communicator was <CODE>ONLINE</CODE> or <CODE>STARTING</CODE>.
     */
    public void setMaxActiveClientCount(int c)
        throws java.lang.IllegalStateException {
        super.setMaxActiveClientCount(c);
    }

    /**
     * Returns the Ip address based ACL used by this SNMP protocol adaptor.
     * @return The <CODE>InetAddressAcl</CODE> implementation.
     *
     * @since 1.5
     */
    public InetAddressAcl getInetAddressAcl() {
        return (InetAddressAcl)ipacl;
    }

    /**
     * Returns the port used by this SNMP protocol adaptor for sending traps.
     * By default, port 162 is used.
     *
     * @return The port number for sending SNMP traps.
     */
    public Integer getTrapPort() {
        return new Integer(trapPort) ;
    }

    /**
     * Sets the port used by this SNMP protocol adaptor for sending traps.
     *
     * @param port The port number for sending SNMP traps.
     */
    public void setTrapPort(Integer port) {
        setTrapPort(port.intValue());
    }

    /**
     * Sets the port used by this SNMP protocol adaptor for sending traps.
     *
     * @param port The port number for sending SNMP traps.
     */
    public void setTrapPort(int port) {
        int val= port ;
        if (val < 0) throw new
            IllegalArgumentException("Trap port cannot be a negative value");
        trapPort= val ;
    }

    /**
     * Returns the port used by this SNMP protocol adaptor for sending
     * inform requests. By default, port 162 is used.
     *
     * @return The port number for sending SNMP inform requests.
     */
    public int getInformPort() {
        return informPort;
    }

    /**
     * Sets the port used by this SNMP protocol adaptor for sending
     * inform requests.
     *
     * @param port The port number for sending SNMP inform requests.
     */
    public void setInformPort(int port) {
        if (port < 0)
            throw new IllegalArgumentException("Inform request port "+
                                               "cannot be a negative value");
        informPort= port ;
    }

    /**
     * Returns the protocol of this SNMP protocol adaptor.
     *
     * @return The string "snmp".
     */
    public String getProtocol() {
        return "snmp";
    }

    /**
     * Returns the buffer size of this SNMP protocol adaptor.
     * This buffer size is used for both incoming request and outgoing
     * inform requests.
     * By default, buffer size 1024 is used.
     *
     * @return The buffer size.
     */
    public Integer getBufferSize() {
        return new Integer(bufferSize) ;
    }

    /**
     * Sets the buffer size of this SNMP protocol adaptor.
     * This buffer size is used for both incoming request and outgoing
     * inform requests.
     *
     * @param s The buffer size.
     *
     * @exception java.lang.IllegalStateException This method has been invoked
     * while the communicator was <CODE>ONLINE</CODE> or <CODE>STARTING</CODE>.
     */
    public void setBufferSize(Integer s)
        throws java.lang.IllegalStateException {
        if ((state == ONLINE) || (state == STARTING)) {
            throw new IllegalStateException("Stop server before carrying out"+
                                            " this operation");
        }
        bufferSize = s.intValue() ;
    }

    /**
     * Gets the number of times to try sending an inform request before
     * giving up.
     * By default, a maximum of 3 tries is used.
     * @return The maximun number of tries.
     */
    final public int getMaxTries() {
        return maxTries;
    }

    /**
     * Changes the maximun number of times to try sending an inform
     * request before giving up.
     * @param newMaxTries The maximun number of tries.
     */
    final public synchronized void setMaxTries(int newMaxTries) {
        if (newMaxTries < 0)
            throw new IllegalArgumentException();
        maxTries = newMaxTries;
    }

    /**
     * Gets the timeout to wait for an inform response from the manager.
     * By default, a timeout of 3 seconds is used.
     * @return The value of the timeout property.
     */
    final public int getTimeout() {
        return timeout;
    }

    /**
     * Changes the timeout to wait for an inform response from the manager.
     * @param newTimeout The timeout (in milliseconds).
     */
    final public synchronized void setTimeout(int newTimeout) {
        if (newTimeout < 0)
            throw new IllegalArgumentException();
        timeout= newTimeout;
    }

    /**
     * Returns the message factory of this SNMP protocol adaptor.
     *
     * @return The factory object.
     */
    public SnmpPduFactory getPduFactory() {
        return pduFactory ;
    }

    /**
     * Sets the message factory of this SNMP protocol adaptor.
     *
     * @param factory The factory object (null means the default factory).
     */
    public void setPduFactory(SnmpPduFactory factory) {
        if (factory == null)
            pduFactory = new SnmpPduFactoryBER() ;
        else
            pduFactory = factory ;
    }

    /**
     * Set the user-data factory of this SNMP protocol adaptor.
     *
     * @param factory The factory object (null means no factory).
     * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory
     */
    public void setUserDataFactory(SnmpUserDataFactory factory) {
        userDataFactory = factory ;
    }

    /**
     * Get the user-data factory associated with this SNMP protocol adaptor.
     *
     * @return The factory object (null means no factory).
     * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory
     */
    public SnmpUserDataFactory getUserDataFactory() {
        return userDataFactory;
    }

    /**
     * Returns <CODE>true</CODE> if authentication traps are enabled.
     * <P>
     * When this feature is enabled, the SNMP protocol adaptor sends
     * an <CODE>authenticationFailure</CODE> trap each time an
     * authentication fails.
     * <P>
     * The default behaviour is to send authentication traps.
     *
     * @return <CODE>true</CODE> if authentication traps are enabled,
     *         <CODE>false</CODE> otherwise.
     */
    public boolean getAuthTrapEnabled() {
        return authTrapEnabled ;
    }

    /**
     * Sets the flag indicating if traps need to be sent in case of
     * authentication failure.
     *
     * @param enabled Flag indicating if traps need to be sent.
     */
    public void setAuthTrapEnabled(boolean enabled) {
        authTrapEnabled = enabled ;
    }

    /**
     * Returns <code>true</code> if this SNMP protocol adaptor sends a
     * response in case of authentication failure.
     * <P>
     * When this feature is enabled, the SNMP protocol adaptor sends a
     * response with <CODE>noSuchName</CODE> or <CODE>readOnly</CODE> when
     * the authentication failed. If the flag is disabled, the
     * SNMP protocol adaptor trashes the PDU silently.
     * <P>
     * The default behavior is to send responses.
     *
     * @return <CODE>true</CODE> if responses are sent.
     */
    public boolean getAuthRespEnabled() {
        return authRespEnabled ;
    }

    /**
     * Sets the flag indicating if responses need to be sent in case of
     * authentication failure.
     *
     * @param enabled Flag indicating if responses need to be sent.
     */
    public void setAuthRespEnabled(boolean enabled) {
        authRespEnabled = enabled ;
    }

    /**
     * Returns the enterprise OID. It is used by
     * {@link #snmpV1Trap snmpV1Trap} to fill the 'enterprise' field of the
     * trap request.
     *
     * @return The OID in string format "x.x.x.x".
     */
    public String getEnterpriseOid() {
        return enterpriseOid.toString() ;
    }

    /**
     * Sets the enterprise OID.
     *
     * @param oid The OID in string format "x.x.x.x".
     *
     * @exception IllegalArgumentException The string format is incorrect
     */
    public void setEnterpriseOid(String oid) throws IllegalArgumentException {
        enterpriseOid = new SnmpOid(oid) ;
    }

    /**
     * Returns the names of the MIBs available in this SNMP protocol adaptor.
     *
     * @return An array of MIB names.
     */
    public String[] getMibs() {
        String[] result = new String[mibs.size()] ;
        int i = 0 ;
        for (Enumeration e = mibs.elements() ; e.hasMoreElements() ;) {
            SnmpMibAgent mib = (SnmpMibAgent)e.nextElement() ;
            result[i++] = mib.getMibName();
        }
        return result ;
    }

    // GETTERS FOR SNMP GROUP (MIBII)
    //-------------------------------

    /**
     * Returns the <CODE>snmpOutTraps</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutTraps</CODE> value.
     */
    public Long getSnmpOutTraps() {
        return new Long(snmpOutTraps);
    }

    /**
     * Returns the <CODE>snmpOutGetResponses</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutGetResponses</CODE> value.
     */
    public Long getSnmpOutGetResponses() {
        return new Long(snmpOutGetResponses);
    }

    /**
     * Returns the <CODE>snmpOutGenErrs</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutGenErrs</CODE> value.
     */
    public Long getSnmpOutGenErrs() {
        return new Long(snmpOutGenErrs);
    }

    /**
     * Returns the <CODE>snmpOutBadValues</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutBadValues</CODE> value.
     */
    public Long getSnmpOutBadValues() {
        return new Long(snmpOutBadValues);
    }

    /**
     * Returns the <CODE>snmpOutNoSuchNames</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutNoSuchNames</CODE> value.
     */
    public Long getSnmpOutNoSuchNames() {
        return new Long(snmpOutNoSuchNames);
    }

    /**
     * Returns the <CODE>snmpOutTooBigs</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutTooBigs</CODE> value.
     */
    public Long getSnmpOutTooBigs() {
        return new Long(snmpOutTooBigs);
    }

    /**
     * Returns the <CODE>snmpInASNParseErrs</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInASNParseErrs</CODE> value.
     */
    public Long getSnmpInASNParseErrs() {
        return new Long(snmpInASNParseErrs);
    }

    /**
     * Returns the <CODE>snmpInBadCommunityUses</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInBadCommunityUses</CODE> value.
     */
    public Long getSnmpInBadCommunityUses() {
        return new Long(snmpInBadCommunityUses);
    }

    /**
     * Returns the <CODE>snmpInBadCommunityNames</CODE> value defined in
     * MIB-II.
     *
     * @return The <CODE>snmpInBadCommunityNames</CODE> value.
     */
    public Long getSnmpInBadCommunityNames() {
        return new Long(snmpInBadCommunityNames);
    }

    /**
     * Returns the <CODE>snmpInBadVersions</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInBadVersions</CODE> value.
     */
    public Long getSnmpInBadVersions() {
        return new Long(snmpInBadVersions);
    }

    /**
     * Returns the <CODE>snmpOutPkts</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpOutPkts</CODE> value.
     */
    public Long getSnmpOutPkts() {
        return new Long(snmpOutPkts);
    }

    /**
     * Returns the <CODE>snmpInPkts</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInPkts</CODE> value.
     */
    public Long getSnmpInPkts() {
        return new Long(snmpInPkts);
    }

    /**
     * Returns the <CODE>snmpInGetRequests</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInGetRequests</CODE> value.
     */
    public Long getSnmpInGetRequests() {
        return new Long(snmpInGetRequests);
    }

    /**
     * Returns the <CODE>snmpInGetNexts</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInGetNexts</CODE> value.
     */
    public Long getSnmpInGetNexts() {
        return new Long(snmpInGetNexts);
    }

    /**
     * Returns the <CODE>snmpInSetRequests</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInSetRequests</CODE> value.
     */
    public Long getSnmpInSetRequests() {
        return new Long(snmpInSetRequests);
    }

    /**
     * Returns the <CODE>snmpInTotalSetVars</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInTotalSetVars</CODE> value.
     */
    public Long getSnmpInTotalSetVars() {
        return new Long(snmpInTotalSetVars);
    }

    /**
     * Returns the <CODE>snmpInTotalReqVars</CODE> value defined in MIB-II.
     *
     * @return The <CODE>snmpInTotalReqVars</CODE> value.
     */
    public Long getSnmpInTotalReqVars() {
        return new Long(snmpInTotalReqVars);
    }

    /**
     * Returns the <CODE>snmpSilentDrops</CODE> value defined in RFC
     * 1907 NMPv2-MIB .
     *
     * @return The <CODE>snmpSilentDrops</CODE> value.
     *
     * @since 1.5
     */
    public Long getSnmpSilentDrops() {
        return new Long(snmpSilentDrops);
    }

    /**
     * Returns the <CODE>snmpProxyDrops</CODE> value defined in RFC
     * 1907 NMPv2-MIB .
     *
     * @return The <CODE>snmpProxyDrops</CODE> value.
     *
     * @since 1.5
     */
    public Long getSnmpProxyDrops() {
        return new Long(0);
    }


    // PUBLIC METHODS
    //---------------

    /**
     * Allows the MBean to perform any operations it needs before being
     * registered in the MBean server.
     * If the name of the SNMP protocol adaptor MBean is not specified,
     * it is initialized with the default value:
     * {@link com.sun.jmx.snmp.ServiceName#DOMAIN
     *   com.sun.jmx.snmp.ServiceName.DOMAIN}:{@link
     * com.sun.jmx.snmp.ServiceName#SNMP_ADAPTOR_SERVER
     * com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER}.
     * If any exception is raised, the SNMP protocol adaptor MBean will
     * not be registered in the MBean server.
     *
     * @param server The MBean server to register the service with.
     * @param name The object name.
     *
     * @return The name of the SNMP protocol adaptor registered.
     *
     * @exception java.lang.Exception
     */
    public ObjectName preRegister(MBeanServer server, ObjectName name)
        throws java.lang.Exception {

        if (name == null) {
            name = new ObjectName(server.getDefaultDomain() + ":" +
                             com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER);
        }
        return (super.preRegister(server, name));
    }

    /**
     * Not used in this context.
     */
    public void postRegister (Boolean registrationDone) {
        super.postRegister(registrationDone);
    }

    /**
     * Not used in this context.
     */
    public void preDeregister() throws java.lang.Exception {
        super.preDeregister();
    }

    /**
     * Not used in this context.
     */
    public void postDeregister() {
        super.postDeregister();
    }

    /**
     * Adds a new MIB in the SNMP MIB handler.
     *
     * @param mib The MIB to add.
     *
     * @return A reference to the SNMP MIB handler.
     *
     * @exception IllegalArgumentException If the parameter is null.
     */
    public SnmpMibHandler addMib(SnmpMibAgent mib)
        throws IllegalArgumentException {
        if (mib == null) {
            throw new IllegalArgumentException() ;
        }

        if(!mibs.contains(mib))
            mibs.addElement(mib);

        root.register(mib);

        return this;
    }

    /**
     * Adds a new MIB in the SNMP MIB handler.
     * This method is to be called to set a specific agent to a specific OID.
     * This can be useful when dealing with MIB overlapping.
     * Some OID can be implemented in more than one MIB. In this case,
     * the OID nearer agent will be used on SNMP operations.
     *
     * @param mib The MIB to add.
     * @param oids The set of OIDs this agent implements.
     *
     * @return A reference to the SNMP MIB handler.
     *
     * @exception IllegalArgumentException If the parameter is null.
     *
     * @since 1.5
     */
    public SnmpMibHandler addMib(SnmpMibAgent mib, SnmpOid[] oids)
        throws IllegalArgumentException {
        if (mib == null) {
            throw new IllegalArgumentException() ;
        }

        //If null oid array, just add it to the mib.
        if(oids == null)
            return addMib(mib);

        if(!mibs.contains(mib))
            mibs.addElement(mib);

        for (int i = 0; i < oids.length; i++) {
            root.register(mib, oids[i].longValue());
        }
        return this;
    }

    /**
     * Adds a new MIB in the SNMP MIB handler. In SNMP V1 and V2 the
     * <CODE>contextName</CODE> is useless and this method
     * is equivalent to <CODE>addMib(SnmpMibAgent mib)</CODE>.
     *
     * @param mib The MIB to add.
     * @param contextName The MIB context name.
     * @return A reference on the SNMP MIB handler.
     *
     * @exception IllegalArgumentException If the parameter is null.
     *
     * @since 1.5
     */
    public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName)
        throws IllegalArgumentException {
        return addMib(mib);
    }

    /**
     * Adds a new MIB in the SNMP MIB handler. In SNMP V1 and V2 the
     * <CODE>contextName</CODE> is useless and this method
     * is equivalent to <CODE>addMib(SnmpMibAgent mib, SnmpOid[] oids)</CODE>.
     *
     * @param mib The MIB to add.
     * @param contextName The MIB context. If null is passed, will be
     *        registered in the default context.
     * @param oids The set of OIDs this agent implements.
     *
     * @return A reference to the SNMP MIB handler.
     *
     * @exception IllegalArgumentException If the parameter is null.
     *
     * @since 1.5
     */
    public SnmpMibHandler addMib(SnmpMibAgent mib,
                                 String contextName,
                                 SnmpOid[] oids)
        throws IllegalArgumentException {
        return addMib(mib, oids);
    }

    /**
     * Removes the specified MIB from the SNMP protocol adaptor.
     * In SNMP V1 and V2 the <CODE>contextName</CODE> is useless and this
     * method is equivalent to <CODE>removeMib(SnmpMibAgent mib)</CODE>.
     *
     * @param mib The MIB to be removed.
     * @param contextName The context name used at registration time.
     *
     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was
     * a MIB included in the SNMP MIB handler, <CODE>false</CODE>
     * otherwise.
     *
     * @since 1.5
     */
    public boolean removeMib(SnmpMibAgent mib, String contextName) {
        return removeMib(mib);
    }

    /**
     * Removes the specified MIB from the SNMP protocol adaptor.
     *
     * @param mib The MIB to be removed.
     *
     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB
     *         included in the SNMP MIB handler, <CODE>false</CODE> otherwise.
     */
    public boolean removeMib(SnmpMibAgent mib) {
        root.unregister(mib);
        return (mibs.removeElement(mib)) ;
    }

    /**
     * Removes the specified MIB from the SNMP protocol adaptor.
     *
     * @param mib The MIB to be removed.
     * @param oids The oid the MIB was previously registered for.
     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was
     * a MIB included in the SNMP MIB handler, <CODE>false</CODE>
     * otherwise.
     *
     * @since 1.5
     */
    public boolean removeMib(SnmpMibAgent mib, SnmpOid[] oids) {
        root.unregister(mib, oids);
        return (mibs.removeElement(mib)) ;
    }

     /**
     * Removes the specified MIB from the SNMP protocol adaptor.
     *
     * @param mib The MIB to be removed.
     * @param contextName The context name used at registration time.
     * @param oids The oid the MIB was previously registered for.
     * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was
     * a MIB included in the SNMP MIB handler, <CODE>false</CODE>
     * otherwise.
     *
     * @since 1.5
     */
    public boolean removeMib(SnmpMibAgent mib,
                             String contextName,
                             SnmpOid[] oids) {
        return removeMib(mib, oids);
    }

    // SUBCLASSING OF COMMUNICATOR SERVER
    //-----------------------------------

    /**
     * Creates the datagram socket.
     */
    protected void doBind()
        throws CommunicationException, InterruptedException {

        try {
            synchronized (this) {
                socket = new DatagramSocket(port, address) ;
            }
            dbgTag = makeDebugTag();
        } catch (SocketException e) {
            if (e.getMessage().equals(InterruptSysCallMsg))
                throw new InterruptedException(e.toString()) ;
            else {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "doBind", "cannot bind on port " + port);
                }
                throw new CommunicationException(e) ;
            }
        }
    }

    /**
     * Return the actual port to which the adaptor is bound.
     * Can be different from the port given at construction time if
     * that port number was 0.
     * @return the actual port to which the adaptor is bound.
     **/
    public int getPort() {
        synchronized (this) {
            if (socket != null) return socket.getLocalPort();
        }
        return super.getPort();
    }

    /**
     * Closes the datagram socket.
     */
    protected void doUnbind()
        throws CommunicationException, InterruptedException {
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "doUnbind","Finally close the socket");
        }
        synchronized (this) {
            if (socket != null) {
                socket.close() ;
                socket = null ;
                // Important to inform finalize() that the socket is closed...
            }
        }
        closeTrapSocketIfNeeded() ;
        closeInformSocketIfNeeded() ;
    }

    void createSnmpRequestHandler(SnmpAdaptorServer server, int id,
                                  DatagramSocket s, DatagramPacket p,
                                  SnmpMibTree tree, Vector m, Object a,
                                  SnmpPduFactory factory,
                                  SnmpUserDataFactory dataFactory,
                                  MBeanServer f, ObjectName n) {
        final SnmpRequestHandler handler =
            new SnmpRequestHandler(this, id, s, p, tree, m, a, factory,
                                   dataFactory, f, n);
        threadService.submitTask(handler);
    }

    /**
     * Reads a packet from the datagram socket and creates a request
     * handler which decodes and processes the request.
     */
    protected void doReceive()
        throws CommunicationException, InterruptedException {

        // Let's wait for something to be received.
        //
        try {
            packet = new DatagramPacket(new byte[bufferSize], bufferSize) ;
            socket.receive(packet);
            int state = getState();

            if(state != ONLINE) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                        "doReceive","received a message but state not online, returning.");
                }
                return;
            }

            createSnmpRequestHandler(this, servedClientCount, socket,
                                     packet, root, mibs, ipacl, pduFactory,
                                     userDataFactory, topMBS, objectName);
        } catch (SocketException e) {
            // Let's check if we have been interrupted by stop().
            //
            if (e.getMessage().equals(InterruptSysCallMsg))
                throw new InterruptedException(e.toString()) ;
            else
                throw new CommunicationException(e) ;
        } catch (InterruptedIOException e) {
            throw new InterruptedException(e.toString()) ;
        } catch (CommunicationException e) {
            throw e ;
        } catch (Exception e) {
            throw new CommunicationException(e) ;
        }
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "doReceive", "received a message");
        }
    }

    protected void doError(Exception e) throws CommunicationException {
        return;
    }

    /**
     * Not used in this context.
     */
    protected void doProcess()
        throws CommunicationException, InterruptedException {
    }


    /**
     * The number of times the communicator server will attempt
     * to bind before giving up.
     * We attempt only once...
     * @return 1
     **/
    protected int getBindTries() {
        return 1;
    }

    /**
     * Stops this SNMP protocol adaptor.
     * Closes the datagram socket.
     * <p>
     * Has no effect if this SNMP protocol adaptor is <CODE>OFFLINE</CODE> or
     * <CODE>STOPPING</CODE>.
     */
    public void stop(){

        final int port = getPort();
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "stop", "Stopping: using port " + port);
        }
        if ((state == ONLINE) || (state == STARTING)){
            super.stop();
            try {
                DatagramSocket sn = new DatagramSocket(0);
                try {
                    byte[] ob = new byte[1];

                    DatagramPacket pk;
                    if (address != null)
                        pk = new DatagramPacket(ob , 1, address, port);
                    else
                        pk = new DatagramPacket(ob , 1,
                                 java.net.InetAddress.getLocalHost(), port);

                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                            "stop", "Sending: using port " + port);
                    }
                    sn.send(pk);
                } finally {
                    sn.close();
                }
            } catch (Throwable e){
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "stop", "Got unexpected Throwable", e);
                }
            }
        }
    }

    // SENDING SNMP TRAPS STUFF
    //-------------------------

    /**
     * Sends a trap using SNMP V1 trap format.
     * <BR>The trap is sent to each destination defined in the ACL file
     * (if available).
     * If no ACL file or no destinations are available, the trap is sent
     * to the local host.
     *
     * @param generic The generic number of the trap.
     * @param specific The specific number of the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit defined
     *            by <CODE>bufferSize</CODE>.
     */
    public void snmpV1Trap(int generic, int specific,
                           SnmpVarBindList varBindList)
        throws IOException, SnmpStatusException {

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpV1Trap", "generic=" + generic +
                  ", specific=" + specific);
        }

        // First, make an SNMP V1 trap pdu
        //
        SnmpPduTrap pdu = new SnmpPduTrap() ;
        pdu.address = null ;
        pdu.port = trapPort ;
        pdu.type = pduV1TrapPdu ;
        pdu.version = snmpVersionOne ;
        pdu.community = null ;
        pdu.enterprise = enterpriseOid ;
        pdu.genericTrap = generic ;
        pdu.specificTrap = specific ;
        pdu.timeStamp = getSysUpTime();

        if (varBindList != null) {
            pdu.varBindList = new SnmpVarBind[varBindList.size()] ;
            varBindList.copyInto(pdu.varBindList);
        }
        else
            pdu.varBindList = null ;

        // If the local host cannot be determined, we put 0.0.0.0 in agentAddr
        try {
            if (address != null)
                pdu.agentAddr = handleMultipleIpVersion(address.getAddress());
            else pdu.agentAddr =
              handleMultipleIpVersion(InetAddress.getLocalHost().getAddress());
        } catch (UnknownHostException e) {
            byte[] zeroedAddr = new byte[4];
            pdu.agentAddr = handleMultipleIpVersion(zeroedAddr) ;
        }

        // Next, send the pdu to all destinations defined in ACL
        //
        sendTrapPdu(pdu) ;
    }

    private SnmpIpAddress handleMultipleIpVersion(byte[] address) {
        if(address.length == 4)
          return new SnmpIpAddress(address);
        else {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                    "handleMultipleIPVersion",
                      "Not an IPv4 address, return null");
            }
            return null;
        }
    }

    /**
     * Sends a trap using SNMP V1 trap format.
     * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
     * destination using the specified community string (and the ACL file
     * is not used).
     *
     * @param addr The <CODE>InetAddress</CODE> destination of the trap.
     * @param cs The community string to be used for the trap.
     * @param generic The generic number of the trap.
     * @param specific The specific number of the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit defined
     *            by <CODE>bufferSize</CODE>.
     */
    public void snmpV1Trap(InetAddress addr, String cs, int generic,
                           int specific, SnmpVarBindList varBindList)
        throws IOException, SnmpStatusException {

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpV1Trap", "generic=" + generic + ", specific=" +
                  specific);
        }

        // First, make an SNMP V1 trap pdu
        //
        SnmpPduTrap pdu = new SnmpPduTrap() ;
        pdu.address = null ;
        pdu.port = trapPort ;
        pdu.type = pduV1TrapPdu ;
        pdu.version = snmpVersionOne ;

        if(cs != null)
            pdu.community = cs.getBytes();
        else
            pdu.community = null ;

        pdu.enterprise = enterpriseOid ;
        pdu.genericTrap = generic ;
        pdu.specificTrap = specific ;
        pdu.timeStamp = getSysUpTime();

        if (varBindList != null) {
            pdu.varBindList = new SnmpVarBind[varBindList.size()] ;
            varBindList.copyInto(pdu.varBindList);
        }
        else
            pdu.varBindList = null ;

        // If the local host cannot be determined, we put 0.0.0.0 in agentAddr
        try {
            if (address != null)
                pdu.agentAddr = handleMultipleIpVersion(address.getAddress());
            else pdu.agentAddr =
              handleMultipleIpVersion(InetAddress.getLocalHost().getAddress());
        } catch (UnknownHostException e) {
            byte[] zeroedAddr = new byte[4];
            pdu.agentAddr = handleMultipleIpVersion(zeroedAddr) ;
        }

        // Next, send the pdu to the specified destination
        //
        if(addr != null)
            sendTrapPdu(addr, pdu) ;
        else
            sendTrapPdu(pdu);
    }

    /**
     * Sends a trap using SNMP V1 trap format.
     * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
     * destination using the specified parameters (and the ACL file is not
     * used).
     * Note that if the specified <CODE>InetAddress</CODE> destination is null,
     * then the ACL file mechanism is used.
     *
     * @param addr The <CODE>InetAddress</CODE> destination of the trap.
     * @param agentAddr The agent address to be used for the trap.
     * @param cs The community string to be used for the trap.
     * @param enterpOid The enterprise OID to be used for the trap.
     * @param generic The generic number of the trap.
     * @param specific The specific number of the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     * @param time The time stamp (overwrite the current time).
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit defined
     *            by <CODE>bufferSize</CODE>.
     *
     * @since 1.5
     */
    public void snmpV1Trap(InetAddress addr,
                           SnmpIpAddress agentAddr,
                           String cs,
                           SnmpOid enterpOid,
                           int generic,
                           int specific,
                           SnmpVarBindList varBindList,
                           SnmpTimeticks time)
        throws IOException, SnmpStatusException {
        snmpV1Trap(addr,
                   trapPort,
                   agentAddr,
                   cs,
                   enterpOid,
                   generic,
                   specific,
                   varBindList,
                   time);
    }

    /**
     * Sends a trap using SNMP V1 trap format.
     * <BR>The trap is sent to the specified <CODE>SnmpPeer</CODE> destination.
     * The community string used is the one located in the
     * <CODE>SnmpPeer</CODE> parameters
     * (<CODE>SnmpParameters.getRdCommunity() </CODE>).
     *
     * @param peer The <CODE>SnmpPeer</CODE> destination of the trap.
     * @param agentAddr The agent address to be used for the trap.
     * @param enterpOid The enterprise OID to be used for the trap.
     * @param generic The generic number of the trap.
     * @param specific The specific number of the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     * @param time The time stamp (overwrite the current time).
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit
     * defined by <CODE>bufferSize</CODE>.
     *
     * @since 1.5
     */
    public void snmpV1Trap(SnmpPeer peer,
                           SnmpIpAddress agentAddr,
                           SnmpOid enterpOid,
                           int generic,
                           int specific,
                           SnmpVarBindList varBindList,
                           SnmpTimeticks time)
        throws IOException, SnmpStatusException {
        SnmpParameters p = (SnmpParameters) peer.getParams();
        snmpV1Trap(peer.getDestAddr(),
                   peer.getDestPort(),
                   agentAddr,
                   p.getRdCommunity(),
                   enterpOid,
                   generic,
                   specific,
                   varBindList,
                   time);
    }

    private void snmpV1Trap(InetAddress addr,
                            int port,
                            SnmpIpAddress agentAddr,
                            String cs,
                            SnmpOid enterpOid,
                            int generic,
                            int specific,
                            SnmpVarBindList varBindList,
                            SnmpTimeticks time)
        throws IOException, SnmpStatusException {

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpV1Trap", "generic=" + generic + ", specific=" +
                  specific);
        }

        // First, make an SNMP V1 trap pdu
        //
        SnmpPduTrap pdu = new SnmpPduTrap() ;
        pdu.address = null ;
        pdu.port = port ;
        pdu.type = pduV1TrapPdu ;
        pdu.version = snmpVersionOne ;

        //Diff start
        if(cs != null)
            pdu.community = cs.getBytes();
        else
            pdu.community = null ;
        //Diff end

        // Diff start
        if(enterpOid != null)
            pdu.enterprise = enterpOid;
        else
            pdu.enterprise = enterpriseOid ;
        //Diff end
        pdu.genericTrap = generic ;
        pdu.specificTrap = specific ;
        //Diff start
        if(time != null)
            pdu.timeStamp = time.longValue();
        else
            pdu.timeStamp = getSysUpTime();
        //Diff end

        if (varBindList != null) {
            pdu.varBindList = new SnmpVarBind[varBindList.size()] ;
            varBindList.copyInto(pdu.varBindList);
        }
        else
            pdu.varBindList = null ;

        if (agentAddr == null) {
            // If the local host cannot be determined,
            // we put 0.0.0.0 in agentAddr
            try {
                final InetAddress inetAddr =
                    (address!=null)?address:InetAddress.getLocalHost();
                agentAddr = handleMultipleIpVersion(inetAddr.getAddress());
            }  catch (UnknownHostException e) {
                byte[] zeroedAddr = new byte[4];
                agentAddr = handleMultipleIpVersion(zeroedAddr);
            }
        }

        pdu.agentAddr = agentAddr;

        // Next, send the pdu to the specified destination
        //
        // Diff start
        if(addr != null)
            sendTrapPdu(addr, pdu) ;
        else
            sendTrapPdu(pdu);

        //End diff
    }

    /**
     * Sends a trap using SNMP V2 trap format.
     * <BR>The trap is sent to the specified <CODE>SnmpPeer</CODE> destination.
     * <BR>The community string used is the one located in the
     * <CODE>SnmpPeer</CODE> parameters
     * (<CODE>SnmpParameters.getRdCommunity() </CODE>).
     * <BR>The variable list included in the outgoing trap is composed of
     * the following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with the value specified by
     *     <CODE>time</CODE></LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *     <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     *
     * @param peer The <CODE>SnmpPeer</CODE> destination of the trap.
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     * @param time The time stamp (overwrite the current time).
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit
     * defined by <CODE>bufferSize</CODE>.
     *
     * @since 1.5
     */
    public void snmpV2Trap(SnmpPeer peer,
                           SnmpOid trapOid,
                           SnmpVarBindList varBindList,
                           SnmpTimeticks time)
        throws IOException, SnmpStatusException {
        SnmpParameters p = (SnmpParameters) peer.getParams();
        snmpV2Trap(peer.getDestAddr(),
                   peer.getDestPort(),
                   p.getRdCommunity(),
                   trapOid,
                   varBindList,
                   time);
    }

    /**
     * Sends a trap using SNMP V2 trap format.
     * <BR>The trap is sent to each destination defined in the ACL file
     * (if available). If no ACL file or no destinations are available,
     * the trap is sent to the local host.
     * <BR>The variable list included in the outgoing trap is composed of
     * the following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *     <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     *
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit defined
     *            by <CODE>bufferSize</CODE>.
     */
    public void snmpV2Trap(SnmpOid trapOid, SnmpVarBindList varBindList)
        throws IOException, SnmpStatusException {

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpV2Trap", "trapOid=" + trapOid);
        }

        // First, make an SNMP V2 trap pdu
        // We clone varBindList and insert sysUpTime and snmpTrapOid
        //
        SnmpPduRequest pdu = new SnmpPduRequest() ;
        pdu.address = null ;
        pdu.port = trapPort ;
        pdu.type = pduV2TrapPdu ;
        pdu.version = snmpVersionTwo ;
        pdu.community = null ;

        SnmpVarBindList fullVbl ;
        if (varBindList != null)
            fullVbl = (SnmpVarBindList)varBindList.clone() ;
        else
            fullVbl = new SnmpVarBindList(2) ;
        SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
        fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
        fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
                                0);
        pdu.varBindList = new SnmpVarBind[fullVbl.size()] ;
        fullVbl.copyInto(pdu.varBindList) ;

        // Next, send the pdu to all destinations defined in ACL
        //
        sendTrapPdu(pdu) ;
    }

    /**
     * Sends a trap using SNMP V2 trap format.
     * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
     * destination using the specified community string (and the ACL file
     * is not used).
     * <BR>The variable list included in the outgoing trap is composed of
     * the following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *     <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     *
     * @param addr The <CODE>InetAddress</CODE> destination of the trap.
     * @param cs The community string to be used for the trap.
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit
     *            defined by <CODE>bufferSize</CODE>.
     */
    public void snmpV2Trap(InetAddress addr, String cs, SnmpOid trapOid,
                           SnmpVarBindList varBindList)
        throws IOException, SnmpStatusException {

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpV2Trap", "trapOid=" + trapOid);
        }

        // First, make an SNMP V2 trap pdu
        // We clone varBindList and insert sysUpTime and snmpTrapOid
        //
        SnmpPduRequest pdu = new SnmpPduRequest() ;
        pdu.address = null ;
        pdu.port = trapPort ;
        pdu.type = pduV2TrapPdu ;
        pdu.version = snmpVersionTwo ;

        if(cs != null)
            pdu.community = cs.getBytes();
        else
            pdu.community = null;

        SnmpVarBindList fullVbl ;
        if (varBindList != null)
            fullVbl = (SnmpVarBindList)varBindList.clone() ;
        else
            fullVbl = new SnmpVarBindList(2) ;
        SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
        fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
        fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
                                0);
        pdu.varBindList = new SnmpVarBind[fullVbl.size()] ;
        fullVbl.copyInto(pdu.varBindList) ;

        // Next, send the pdu to the specified destination
        //
        if(addr != null)
            sendTrapPdu(addr, pdu);
        else
            sendTrapPdu(pdu);
    }

    /**
     * Sends a trap using SNMP V2 trap format.
     * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
     * destination using the specified parameters (and the ACL file is not
     * used).
     * Note that if the specified <CODE>InetAddress</CODE> destination is null,
     * then the ACL file mechanism is used.
     * <BR>The variable list included in the outgoing trap is composed of the
     * following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with the value specified by
     *     <CODE>time</CODE></LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *     <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     *
     * @param addr The <CODE>InetAddress</CODE> destination of the trap.
     * @param cs The community string to be used for the trap.
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     * @param time The time stamp (overwrite the current time).
     *
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit
     * defined by <CODE>bufferSize</CODE>.
     *
     * @since 1.5
     */
    public void snmpV2Trap(InetAddress addr,
                           String cs,
                           SnmpOid trapOid,
                           SnmpVarBindList varBindList,
                           SnmpTimeticks time)
        throws IOException, SnmpStatusException {

        snmpV2Trap(addr,
                   trapPort,
                   cs,
                   trapOid,
                   varBindList,
                   time);
    }

    private void snmpV2Trap(InetAddress addr,
                            int port,
                            String cs,
                            SnmpOid trapOid,
                            SnmpVarBindList varBindList,
                            SnmpTimeticks time)
        throws IOException, SnmpStatusException {

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            final StringBuilder strb = new StringBuilder()
                .append("trapOid=").append(trapOid)
                .append("\ncommunity=").append(cs)
                .append("\naddr=").append(addr)
                .append("\nvarBindList=").append(varBindList)
                .append("\ntime=").append(time)
                .append("\ntrapPort=").append(port);
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpV2Trap", strb.toString());
        }

        // First, make an SNMP V2 trap pdu
        // We clone varBindList and insert sysUpTime and snmpTrapOid
        //
        SnmpPduRequest pdu = new SnmpPduRequest() ;
        pdu.address = null ;
        pdu.port = port ;
        pdu.type = pduV2TrapPdu ;
        pdu.version = snmpVersionTwo ;

        if(cs != null)
            pdu.community = cs.getBytes();
        else
            pdu.community = null;

        SnmpVarBindList fullVbl ;
        if (varBindList != null)
            fullVbl = (SnmpVarBindList)varBindList.clone() ;
        else
            fullVbl = new SnmpVarBindList(2) ;

        // Only difference with other
        SnmpTimeticks sysUpTimeValue = null;
        if(time != null)
            sysUpTimeValue = time;
        else
            sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
        //End of diff

        fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
        fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
                                0);
        pdu.varBindList = new SnmpVarBind[fullVbl.size()] ;
        fullVbl.copyInto(pdu.varBindList) ;

        // Next, send the pdu to the specified destination
        //
        // Diff start
        if(addr != null)
            sendTrapPdu(addr, pdu) ;
        else
            sendTrapPdu(pdu);
        //End diff
    }

    /**
     * Send the specified trap PDU to the passed <CODE>InetAddress</CODE>.
     * @param address The destination address.
     * @param pdu The pdu to send.
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit
     * defined by <CODE>bufferSize</CODE>.
     *
     * @since 1.5
     */
    public void snmpPduTrap(InetAddress address, SnmpPduPacket pdu)
            throws IOException, SnmpStatusException {

        if(address != null)
            sendTrapPdu(address, pdu);
        else
            sendTrapPdu(pdu);
    }

    /**
     * Send the specified trap PDU to the passed <CODE>SnmpPeer</CODE>.
     * @param peer The destination peer. The Read community string is used of
     * <CODE>SnmpParameters</CODE> is used as the trap community string.
     * @param pdu The pdu to send.
     * @exception IOException An I/O error occurred while sending the trap.
     * @exception SnmpStatusException If the trap exceeds the limit defined
     * by <CODE>bufferSize</CODE>.
     * @since 1.5
     */
    public void snmpPduTrap(SnmpPeer peer,
                            SnmpPduPacket pdu)
        throws IOException, SnmpStatusException {
        if(peer != null) {
            pdu.port = peer.getDestPort();
            sendTrapPdu(peer.getDestAddr(), pdu);
        }
        else {
            pdu.port = getTrapPort().intValue();
            sendTrapPdu(pdu);
        }
    }

    /**
     * Send the specified trap PDU to every destinations from the ACL file.
     */
    private void sendTrapPdu(SnmpPduPacket pdu)
     throws SnmpStatusException, IOException {

        // Make an SNMP message from the pdu
        //
        SnmpMessage msg = null ;
        try {
            msg = (SnmpMessage)pduFactory.encodeSnmpPdu(pdu, bufferSize) ;
            if (msg == null) {
                throw new SnmpStatusException(
                          SnmpDefinitions.snmpRspAuthorizationError) ;
            }
        }
        catch (SnmpTooBigException x) {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                    "sendTrapPdu", "Trap pdu is too big. " +
                     "Trap hasn't been sent to anyone" );
            }
            throw new SnmpStatusException(SnmpDefinitions.snmpRspTooBig) ;
            // FIXME: is the right exception to throw ?
            // We could simply forward SnmpTooBigException ?
        }

        // Now send the SNMP message to each destination
        //
        int sendingCount = 0 ;
        openTrapSocketIfNeeded() ;
        if (ipacl != null) {
            Enumeration ed = ((InetAddressAcl)ipacl).getTrapDestinations() ;
            while (ed.hasMoreElements()) {
                msg.address = (InetAddress)ed.nextElement() ;
                Enumeration ec = ((InetAddressAcl)ipacl).
                    getTrapCommunities(msg.address) ;
                while (ec.hasMoreElements()) {
                    msg.community = ((String)ec.nextElement()).getBytes() ;
                    try {
                        sendTrapMessage(msg) ;
                        sendingCount++ ;
                    }
                    catch (SnmpTooBigException x) {
                        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                                "sendTrapPdu", "Trap pdu is too big. " +
                                 "Trap hasn't been sent to "+msg.address);
                        }
                    }
                }
            }
        }

        // If there is no destination defined or if everything has failed
        // we tried to send the trap to the local host (as suggested by
        // mister Olivier Reisacher).
        //
        if (sendingCount == 0) {
            try {
                msg.address = InetAddress.getLocalHost() ;
                sendTrapMessage(msg) ;
            } catch (SnmpTooBigException x) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "sendTrapPdu", "Trap pdu is too big. " +
                         "Trap hasn't been sent.");
                }
            } catch (UnknownHostException e) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "sendTrapPdu", "Trap pdu is too big. " +
                         "Trap hasn't been sent.");
                }
            }
        }

        closeTrapSocketIfNeeded() ;
    }

    /**
     * Send the specified trap PDU to the specified destination.
     */
    private void sendTrapPdu(InetAddress addr, SnmpPduPacket pdu)
        throws SnmpStatusException, IOException {

        // Make an SNMP message from the pdu
        //
        SnmpMessage msg = null ;
        try {
            msg = (SnmpMessage)pduFactory.encodeSnmpPdu(pdu, bufferSize) ;
            if (msg == null) {
                throw new SnmpStatusException(
                          SnmpDefinitions.snmpRspAuthorizationError) ;
            }
        } catch (SnmpTooBigException x) {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                    "sendTrapPdu", "Trap pdu is too big. " +
                     "Trap hasn't been sent to the specified host.");
            }
            throw new SnmpStatusException(SnmpDefinitions.snmpRspTooBig) ;
            // FIXME: is the right exception to throw ?
            // We could simply forward SnmpTooBigException ?
        }

        // Now send the SNMP message to specified destination
        //
        openTrapSocketIfNeeded() ;
        if (addr != null) {
            msg.address = addr;
            try {
                sendTrapMessage(msg) ;
            } catch (SnmpTooBigException x) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "sendTrapPdu", "Trap pdu is too big. " +
                         "Trap hasn't been sent to " +  msg.address);
                }
            }
        }

        closeTrapSocketIfNeeded() ;
    }

    /**
     * Send the specified message on trapSocket.
     */
    private void sendTrapMessage(SnmpMessage msg)
        throws IOException, SnmpTooBigException {
        byte[] buffer = new byte[bufferSize] ;
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length) ;
        int encodingLength = msg.encodeMessage(buffer) ;
        packet.setLength(encodingLength) ;
        packet.setAddress(msg.address) ;
        packet.setPort(msg.port) ;
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "sendTrapMessage", "sending trap to " + msg.address + ":" +
                  msg.port);
        }
        trapSocket.send(packet) ;
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "sendTrapMessage", "sent to " + msg.address + ":" +
                  msg.port);
        }
        snmpOutTraps++;
        snmpOutPkts++;
    }

    /**
     * Open trapSocket if it's not already done.
     */
    synchronized void openTrapSocketIfNeeded() throws SocketException {
        if (trapSocket == null) {
            trapSocket = new DatagramSocket(0, address) ;
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                    "openTrapSocketIfNeeded", "using port " +
                      trapSocket.getLocalPort() + " to send traps");
            }
        }
    }

    /**
     * Close trapSocket if the SNMP protocol adaptor is not ONLINE.
     */
    synchronized void closeTrapSocketIfNeeded() {
        if ((trapSocket != null) && (state != ONLINE)) {
            trapSocket.close() ;
            trapSocket = null ;
        }
    }

    // SENDING SNMP INFORMS STUFF
    //---------------------------

    /**
     * Sends an inform using SNMP V2 inform request format.
     * <BR>The inform request is sent to each destination defined in the ACL
     * file (if available).
     * If no ACL file or no destinations are available, the inform request is
     * sent to the local host.
     * <BR>The variable list included in the outgoing inform is composed of
     * the following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *     <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     * To send an inform request, the SNMP adaptor server must be active.
     *
     * @param cb The callback that is invoked when a request is complete.
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @return A vector of {@link com.sun.jmx.snmp.daemon.SnmpInformRequest}
     *         objects.
     *         <P>If there is no destination host for this inform request,
     *         the returned vector will be empty.
     *
     * @exception IllegalStateException  This method has been invoked while
     *            the SNMP adaptor server was not active.
     * @exception IOException An I/O error occurred while sending the
     *            inform request.
     * @exception SnmpStatusException If the inform request exceeds the
     *            limit defined by <CODE>bufferSize</CODE>.
     */
    public Vector snmpInformRequest(SnmpInformHandler cb, SnmpOid trapOid,
                                    SnmpVarBindList varBindList)
        throws IllegalStateException, IOException, SnmpStatusException {

        if (!isActive()) {
            throw new IllegalStateException(
               "Start SNMP adaptor server before carrying out this operation");
        }
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpInformRequest", "trapOid=" + trapOid);
        }

        // First, make an SNMP inform pdu:
        // We clone varBindList and insert sysUpTime and snmpTrapOid variables.
        //
        SnmpVarBindList fullVbl ;
        if (varBindList != null)
            fullVbl = (SnmpVarBindList)varBindList.clone() ;
        else
            fullVbl = new SnmpVarBindList(2) ;
        SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
        fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
        fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
                                0);

        // Next, send the pdu to the specified destination
        //
        openInformSocketIfNeeded() ;

        // Now send the SNMP message to each destination
        //
        Vector<SnmpInformRequest> informReqList = new Vector<SnmpInformRequest>();
        InetAddress addr = null;
        String cs = null;
        if (ipacl != null) {
            Enumeration ed = ((InetAddressAcl)ipacl).getInformDestinations() ;
            while (ed.hasMoreElements()) {
                addr = (InetAddress)ed.nextElement() ;
                Enumeration ec = ((InetAddressAcl)ipacl).
                    getInformCommunities(addr) ;
                while (ec.hasMoreElements()) {
                    cs = (String)ec.nextElement() ;
                    informReqList.addElement(
                       informSession.makeAsyncRequest(addr, cs, cb,
                                              fullVbl,getInformPort())) ;
                }
            }
        }

        return informReqList ;
    }

    /**
     * Sends an inform using SNMP V2 inform request format.
     * <BR>The inform is sent to the specified <CODE>InetAddress</CODE>
     * destination
     * using the specified community string.
     * <BR>The variable list included in the outgoing inform is composed
     *     of the following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *      <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     * To send an inform request, the SNMP adaptor server must be active.
     *
     * @param addr The <CODE>InetAddress</CODE> destination for this inform
     *             request.
     * @param cs The community string to be used for the inform request.
     * @param cb The callback that is invoked when a request is complete.
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @return The inform request object.
     *
     * @exception IllegalStateException  This method has been invoked
     *            while the SNMP adaptor server was not active.
     * @exception IOException An I/O error occurred while sending the
     *            inform request.
     * @exception SnmpStatusException If the inform request exceeds the
     *            limit defined by <CODE>bufferSize</CODE>.
     */
    public SnmpInformRequest snmpInformRequest(InetAddress addr,
                                               String cs,
                                               SnmpInformHandler cb,
                                               SnmpOid trapOid,
                                               SnmpVarBindList varBindList)
        throws IllegalStateException, IOException, SnmpStatusException {

        return snmpInformRequest(addr,
                                 getInformPort(),
                                 cs,
                                 cb,
                                 trapOid,
                                 varBindList);
    }

    /**
     * Sends an inform using SNMP V2 inform request format.
     * <BR>The inform is sent to the specified <CODE>SnmpPeer</CODE>
     *     destination.
     * <BR>The community string used is the one located in the
     *     <CODE>SnmpPeer</CODE> parameters
     *     (<CODE>SnmpParameters.getInformCommunity() </CODE>).
     * <BR>The variable list included in the outgoing inform is composed
     *     of the following items:
     * <UL>
     * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
     * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
     *     <CODE>trapOid</CODE></LI>
     * <LI><CODE>all the (oid,values)</CODE> from the specified
     *     <CODE>varBindList</CODE></LI>
     * </UL>
     * To send an inform request, the SNMP adaptor server must be active.
     *
     * @param peer The <CODE>SnmpPeer</CODE> destination for this inform
     *             request.
     * @param cb The callback that is invoked when a request is complete.
     * @param trapOid The OID identifying the trap.
     * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
     *
     * @return The inform request object.
     *
     * @exception IllegalStateException  This method has been invoked while
     *            the SNMP adaptor server was not active.
     * @exception IOException An I/O error occurred while sending the
     *            inform request.
     * @exception SnmpStatusException If the inform request exceeds the
     *            limit defined by <CODE>bufferSize</CODE>.
     *
     * @since 1.5
     */
    public SnmpInformRequest snmpInformRequest(SnmpPeer peer,
                                               SnmpInformHandler cb,
                                               SnmpOid trapOid,
                                               SnmpVarBindList varBindList)
        throws IllegalStateException, IOException, SnmpStatusException {
        SnmpParameters p = (SnmpParameters) peer.getParams();
        return snmpInformRequest(peer.getDestAddr(),
                                 peer.getDestPort(),
                                 p.getInformCommunity(),
                                 cb,
                                 trapOid,
                                 varBindList);
    }

    /**
     * Method that maps an SNMP error status in the passed protocolVersion
     * according to the provided pdu type.
     * @param errorStatus The error status to convert.
     * @param protocolVersion The protocol version.
     * @param reqPduType The pdu type.
     */
    public static final int mapErrorStatus(int errorStatus,
                                           int protocolVersion,
                                           int reqPduType) {
        return SnmpSubRequestHandler.mapErrorStatus(errorStatus,
                                                    protocolVersion,
                                                    reqPduType);
    }

    private SnmpInformRequest snmpInformRequest(InetAddress addr,
                                                int port,
                                                String cs,
                                                SnmpInformHandler cb,
                                                SnmpOid trapOid,
                                                SnmpVarBindList varBindList)
        throws IllegalStateException, IOException, SnmpStatusException {
        if (!isActive()) {
            throw new IllegalStateException(
              "Start SNMP adaptor server before carrying out this operation");
        }
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                "snmpInformRequest", "trapOid=" + trapOid);
        }

        // First, make an SNMP inform pdu:
        // We clone varBindList and insert sysUpTime and snmpTrapOid variables.
        //
        SnmpVarBindList fullVbl ;
        if (varBindList != null)
            fullVbl = (SnmpVarBindList)varBindList.clone() ;
        else
            fullVbl = new SnmpVarBindList(2) ;
        SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
        fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
        fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
                                0);

        // Next, send the pdu to the specified destination
        //
        openInformSocketIfNeeded() ;
        return informSession.makeAsyncRequest(addr, cs, cb, fullVbl, port) ;
    }


    /**
     * Open informSocket if it's not already done.
     */
    synchronized void openInformSocketIfNeeded() throws SocketException {
        if (informSession == null) {
            informSession = new SnmpSession(this) ;
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                   "openInformSocketIfNeeded",
                      "to send inform requests and receive inform responses");
            }
        }
    }

    /**
     * Close informSocket if the SNMP protocol adaptor is not ONLINE.
     */
    synchronized void closeInformSocketIfNeeded() {
        if ((informSession != null) && (state != ONLINE)) {
            informSession.destroySession() ;
            informSession = null ;
        }
    }

    /**
     * Gets the IP address to bind.
     * This getter is used to initialize the DatagramSocket in the
     * SnmpSocket object created for the inform request stuff.
     */
    InetAddress getAddress() {
        return address;
    }


    // PROTECTED METHODS
    //------------------

    /**
     * Finalizer of the SNMP protocol adaptor objects.
     * This method is called by the garbage collector on an object
     * when garbage collection determines that there are no more
     * references to the object.
     * <P>Closes the datagram socket associated to this SNMP protocol adaptor.
     */
    protected void finalize() {
        try {
            if (socket != null) {
                socket.close() ;
                socket = null ;
            }

            threadService.terminate();
        } catch (Exception e) {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                   "finalize", "Exception in finalizer", e);
            }
        }
    }

    // PACKAGE METHODS
    //----------------

    /**
     * Returns the string used in debug traces.
     */
    String makeDebugTag() {
        return "SnmpAdaptorServer["+ getProtocol() + ":" + getPort() + "]";
    }

    void updateRequestCounters(int pduType) {
        switch(pduType)  {

        case pduGetRequestPdu:
            snmpInGetRequests++;
            break;
        case pduGetNextRequestPdu:
            snmpInGetNexts++;
            break;
        case pduSetRequestPdu:
            snmpInSetRequests++;
            break;
        default:
            break;
        }
        snmpInPkts++ ;
    }

    void updateErrorCounters(int errorStatus) {
        switch(errorStatus) {

        case snmpRspNoError:
            snmpOutGetResponses++;
            break;
        case snmpRspGenErr:
            snmpOutGenErrs++;
            break;
        case snmpRspBadValue:
            snmpOutBadValues++;
            break;
        case snmpRspNoSuchName:
            snmpOutNoSuchNames++;
            break;
        case snmpRspTooBig:
            snmpOutTooBigs++;
            break;
        default:
            break;
        }
        snmpOutPkts++ ;
    }

    void updateVarCounters(int pduType, int n) {
        switch(pduType) {

        case pduGetRequestPdu:
        case pduGetNextRequestPdu:
        case pduGetBulkRequestPdu:
            snmpInTotalReqVars += n ;
            break ;
        case pduSetRequestPdu:
            snmpInTotalSetVars += n ;
            break ;
        }
    }

    void incSnmpInASNParseErrs(int n) {
        snmpInASNParseErrs += n ;
    }

    void incSnmpInBadVersions(int n) {
        snmpInBadVersions += n ;
    }

    void incSnmpInBadCommunityUses(int n) {
        snmpInBadCommunityUses += n ;
    }

    void incSnmpInBadCommunityNames(int n) {
        snmpInBadCommunityNames += n ;
    }

    void incSnmpSilentDrops(int n) {
        snmpSilentDrops += n ;
    }
    // PRIVATE METHODS
    //----------------

    /**
     * Returns the time (in hundreths of second) elapsed since the SNMP
     * protocol adaptor startup.
     */
    long getSysUpTime() {
        return (System.currentTimeMillis() - startUpTime) / 10 ;
    }

    /**
     * Control the way the SnmpAdaptorServer service is deserialized.
     */
    private void readObject(ObjectInputStream stream)
        throws IOException, ClassNotFoundException {

        // Call the default deserialization of the object.
        //
        stream.defaultReadObject();

        // Call the specific initialization for the SnmpAdaptorServer service.
        // This is for transient structures to be initialized to specific
        // default values.
        //
        mibs      = new Vector<SnmpMibAgent>() ;
    }

    /**
     * Common initializations.
     */
    private void init(Object acl, int p, InetAddress a) {

        root= new SnmpMibTree();

        // The default Agent is initialized with a SnmpErrorHandlerAgent agent.
        root.setDefaultAgent(new SnmpErrorHandlerAgent());

        // For the trap time, use the time the agent started ...
        //
        startUpTime= java.lang.System.currentTimeMillis();
        maxActiveClientCount = 10;

        // Create the default message factory
        pduFactory = new SnmpPduFactoryBER() ;

        port = p ;
        ipacl = acl ;
        address = a ;

        if ((ipacl == null) && (useAcl == true))
            throw new IllegalArgumentException("ACL object cannot be null") ;

        threadService = new ThreadService(threadNumber);
    }

    SnmpMibAgent getAgentMib(SnmpOid oid) {
        return root.getAgentMib(oid);
    }

    protected Thread createMainThread() {
        final Thread t = super.createMainThread();
        t.setDaemon(true);
        return t;
    }

}
