/*
 * Copyright 1998-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 import
//
import java.util.Vector;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Level;
import java.io.InterruptedIOException;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.SocketException;

// jmx imports
//
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.sun.jmx.snmp.SnmpMessage;
import com.sun.jmx.snmp.SnmpPduFactory;
import com.sun.jmx.snmp.SnmpPduBulk;
import com.sun.jmx.snmp.SnmpPduPacket;
import com.sun.jmx.snmp.SnmpPduRequest;
import com.sun.jmx.snmp.SnmpPduTrap;
import com.sun.jmx.snmp.SnmpValue;
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.SnmpDataTypeEnums;

// RI imports
//
import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;

// SNMP runtime import
//
import com.sun.jmx.snmp.agent.SnmpMibAgent;
import com.sun.jmx.snmp.agent.SnmpUserDataFactory;
//import com.sun.jmx.snmp.IPAcl.IPAcl;
import com.sun.jmx.snmp.InetAddressAcl;


class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions {

    private transient DatagramSocket      socket = null ;
    private transient DatagramPacket      packet = null ;
    private transient Vector              mibs = null ;

    /**
     * Contains the list of sub-requests associated to the current request.
     */
    private transient Hashtable<SnmpMibAgent, SnmpSubRequestHandler> subs = null;

    /**
     * Reference on the MIBS
     */
    private transient SnmpMibTree root;

    private transient Object              ipacl = null ;
    private transient SnmpPduFactory      pduFactory = null ;
    private transient SnmpUserDataFactory userDataFactory = null ;
    private transient SnmpAdaptorServer adaptor = null;
    /**
     * Full constructor
     */
    public SnmpRequestHandler(SnmpAdaptorServer server, int id,
                              DatagramSocket s, DatagramPacket p,
                              SnmpMibTree tree, Vector m, Object a,
                              SnmpPduFactory factory,
                              SnmpUserDataFactory dataFactory,
                              MBeanServer f, ObjectName n)
    {
        super(server, id, f, n);

        // Need a reference on SnmpAdaptorServer for getNext & getBulk,
        // in case of oid equality (mib overlapping).
        //
        adaptor = server;
        socket = s;
        packet = p;
        root= tree;
        mibs = (Vector) m.clone();
        subs= new Hashtable<SnmpMibAgent, SnmpSubRequestHandler>(mibs.size());
        ipacl = a;
        pduFactory = factory ;
        userDataFactory = dataFactory ;
        //thread.start();
    }

    /**
     * Treat the request available in 'packet' and send the result
     * back to the client.
     * Note: we overwrite 'packet' with the response bytes.
     */
    public void doRun() {

        // Trace the input packet
        //
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                    "doRun","Packet received:\n" +
                    SnmpMessage.dumpHexBuffer(packet.getData(), 0, packet.getLength()));
        }

        // Let's build the response packet
        //
        DatagramPacket respPacket = makeResponsePacket(packet) ;

        // Trace the output packet
        //
        if ((SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) && (respPacket != null)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                    "doRun","Packet to be sent:\n" +
                    SnmpMessage.dumpHexBuffer(respPacket.getData(), 0, respPacket.getLength()));
        }

        // Send the response packet if any
        //
        if (respPacket != null) {
            try {
                socket.send(respPacket) ;
            } catch (SocketException e) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    if (e.getMessage().equals(InterruptSysCallMsg)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                            "doRun", "interrupted");
                    } else {
                      SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                            "doRun", "I/O exception", e);
                    }
                }
            } catch(InterruptedIOException e) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "doRun", "interrupted");
                }
            } catch(Exception e) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "doRun", "failure when sending response", e);
                }
            }
        }
    }

    /**
     * Here we make a response packet from a request packet.
     * We return null if there no response packet to sent.
     */
    private DatagramPacket makeResponsePacket(DatagramPacket reqPacket) {
        DatagramPacket respPacket = null ;

        // Transform the request packet into a request SnmpMessage
        //
        SnmpMessage reqMsg = new SnmpMessage() ;
        try {
            reqMsg.decodeMessage(reqPacket.getData(), reqPacket.getLength()) ;
            reqMsg.address = reqPacket.getAddress() ;
            reqMsg.port = reqPacket.getPort() ;
        }
        catch(SnmpStatusException x) {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                    "makeResponsePacket", "packet decoding failed", x);
            }
            reqMsg = null ;
            ((SnmpAdaptorServer)adaptorServer).incSnmpInASNParseErrs(1) ;
        }

        // Make the response SnmpMessage if any
        //
        SnmpMessage respMsg = null ;
        if (reqMsg != null) {
            respMsg = makeResponseMessage(reqMsg) ;
        }

        // Try to transform the response SnmpMessage into response packet.
        // NOTE: we overwrite the request packet.
        //
        if (respMsg != null) {
            try {
                reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ;
                respPacket = reqPacket ;
            }
            catch(SnmpTooBigException x) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "makeResponsePacket", "response message is too big");
                }
                try {
                    respMsg = newTooBigMessage(reqMsg) ;
                    reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ;
                    respPacket = reqPacket ;
                }
                catch(SnmpTooBigException xx) {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                            "makeResponsePacket", "'too big' is 'too big' !!!");
                    }
                    adaptor.incSnmpSilentDrops(1);
                }
            }
        }

        return respPacket ;
    }

    /**
     * Here we make a response message from a request message.
     * We return null if there is no message to reply.
     */
    private SnmpMessage makeResponseMessage(SnmpMessage reqMsg) {
        SnmpMessage respMsg = null ;

        // Transform the request message into a request pdu
        //
        SnmpPduPacket reqPdu = null ;
        Object userData = null;
        try {
            reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ;
            if (reqPdu != null && userDataFactory != null)
                userData = userDataFactory.allocateUserData(reqPdu);
        }
        catch(SnmpStatusException x) {
            reqPdu = null ;
            SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ;
            snmpServer.incSnmpInASNParseErrs(1) ;
            if (x.getStatus()== SnmpDefinitions.snmpWrongSnmpVersion)
                snmpServer.incSnmpInBadVersions(1) ;
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                    "makeResponseMessage", "message decoding failed", x);
            }
        }

        // Make the response pdu if any
        //
        SnmpPduPacket respPdu = null ;
        if (reqPdu != null) {
            respPdu = makeResponsePdu(reqPdu,userData) ;
            try {
                if (userDataFactory != null)
                    userDataFactory.releaseUserData(userData,respPdu);
            } catch (SnmpStatusException x) {
                respPdu = null;
            }
        }

        // Try to transform the response pdu into a response message if any
        //
        if (respPdu != null) {
            try {
                respMsg = (SnmpMessage)pduFactory.
                    encodeSnmpPdu(respPdu, packet.getData().length) ;
            }
            catch(SnmpStatusException x) {
                respMsg = null ;
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "makeResponseMessage", "failure when encoding the response message", x);
                }
            }
            catch(SnmpTooBigException x) {
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                        "makeResponseMessage", "response message is too big");
                }

                try {
                    // if the PDU is too small, why should we try to do
                    // recovery ?
                    //
                    if (packet.getData().length <=32)
                        throw x;
                    int pos= x.getVarBindCount();
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                            "makeResponseMessage", "fail on element" + pos);
                    }
                    int old= 0;
                    while (true) {
                        try {
                            respPdu = reduceResponsePdu(reqPdu, respPdu, pos) ;
                            respMsg = (SnmpMessage)pduFactory.
                                encodeSnmpPdu(respPdu,
                                              packet.getData().length -32) ;
                            break;
                        } catch (SnmpTooBigException xx) {
                            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                                    "makeResponseMessage", "response message is still too big");
                            }
                            old= pos;
                            pos= xx.getVarBindCount();
                            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                                    "makeResponseMessage","fail on element" + pos);
                            }
                            if (pos == old) {
                                // we can not go any further in trying to
                                // reduce the message !
                                //
                                throw xx;
                            }
                        }
                    }// end of loop
                } catch(SnmpStatusException xx) {
                    respMsg = null ;
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                           "makeResponseMessage", "failure when encoding the response message", xx);
                    }
                }
                catch(SnmpTooBigException xx) {
                    try {
                        respPdu = newTooBigPdu(reqPdu) ;
                        respMsg = (SnmpMessage)pduFactory.
                            encodeSnmpPdu(respPdu, packet.getData().length) ;
                    }
                    catch(SnmpTooBigException xxx) {
                        respMsg = null ;
                        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                               "makeResponseMessage", "'too big' is 'too big' !!!");
                        }
                        adaptor.incSnmpSilentDrops(1);
                    }
                    catch(Exception xxx) {
                        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                               "makeResponseMessage", "Got unexpected exception", xxx);
                        }
                        respMsg = null ;
                    }
                }
                catch(Exception xx) {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                           "makeResponseMessage", "Got unexpected exception", xx);
                    }
                    respMsg = null ;
                }
            }
        }
        return respMsg ;
    }

    /**
     * Here we make a response pdu from a request pdu.
     * We return null if there is no pdu to reply.
     */
    private SnmpPduPacket makeResponsePdu(SnmpPduPacket reqPdu,
                                          Object userData) {

        SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ;
        SnmpPduPacket respPdu = null ;

        snmpServer.updateRequestCounters(reqPdu.type) ;
        if (reqPdu.varBindList != null)
            snmpServer.updateVarCounters(reqPdu.type,
                                         reqPdu.varBindList.length) ;

        if (checkPduType(reqPdu)) {
            respPdu = checkAcl(reqPdu) ;
            if (respPdu == null) { // reqPdu is accepted by ACLs
                if (mibs.size() < 1) {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                           "makeResponsePdu", "Request " + reqPdu.requestId +
                           " received but no MIB registered.");
                    }
                    return makeNoMibErrorPdu((SnmpPduRequest)reqPdu, userData);
                }
                switch(reqPdu.type) {
                case SnmpPduPacket.pduGetRequestPdu:
                case SnmpPduPacket.pduGetNextRequestPdu:
                case SnmpPduPacket.pduSetRequestPdu:
                    respPdu = makeGetSetResponsePdu((SnmpPduRequest)reqPdu,
                                                    userData) ;
                    break ;

                case SnmpPduPacket.pduGetBulkRequestPdu:
                    respPdu = makeGetBulkResponsePdu((SnmpPduBulk)reqPdu,
                                                     userData) ;
                    break ;
                }
            }
            else { // reqPdu is rejected by ACLs
                // respPdu contains the error response to be sent.
                // We send this response only if authResEnabled is true.
                if (!snmpServer.getAuthRespEnabled()) { // No response should be sent
                    respPdu = null ;
                }
                if (snmpServer.getAuthTrapEnabled()) { // A trap must be sent
                    try {
                        snmpServer.snmpV1Trap(SnmpPduTrap.
                                              trapAuthenticationFailure, 0,
                                              new SnmpVarBindList()) ;
                    }
                    catch(Exception x) {
                        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                            SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                               "makeResponsePdu", "Failure when sending authentication trap", x);
                        }
                    }
                }
            }
        }
        return respPdu ;
    }

    //
    // Generates a response packet, filling the values in the
    // varbindlist with one of endOfMibView, noSuchObject, noSuchInstance
    // according to the value of <code>status</code>
    //
    // @param statusTag should be one of:
    //        <li>SnmpDataTypeEnums.errEndOfMibViewTag</li>
    //        <li>SnmpDataTypeEnums.errNoSuchObjectTag</li>
    //        <li>SnmpDataTypeEnums.errNoSuchInstanceTag</li>
    //
    SnmpPduPacket makeErrorVarbindPdu(SnmpPduPacket req, int statusTag) {

        final SnmpVarBind[] vblist = req.varBindList;
        final int length = vblist.length;

        switch (statusTag) {
        case SnmpDataTypeEnums.errEndOfMibViewTag:
            for (int i=0 ; i<length ; i++)
                vblist[i].value = SnmpVarBind.endOfMibView;
            break;
        case SnmpDataTypeEnums.errNoSuchObjectTag:
            for (int i=0 ; i<length ; i++)
                vblist[i].value = SnmpVarBind.noSuchObject;
            break;
        case SnmpDataTypeEnums.errNoSuchInstanceTag:
            for (int i=0 ; i<length ; i++)
                vblist[i].value = SnmpVarBind.noSuchInstance;
            break;
        default:
            return newErrorResponsePdu(req,snmpRspGenErr,1);
        }
        return newValidResponsePdu(req,vblist);
    }

    // Generates an appropriate response when no mib is registered in
    // the adaptor.
    //
    // <li>If the version is V1:</li>
    // <ul><li>Generates a NoSuchName error V1 response PDU</li></ul>
    // <li>If the version is V2:</li>
    // <ul><li>If the request is a GET, fills the varbind list with
    //         NoSuchObject's</li>
    //     <li>If the request is a GET-NEXT/GET-BULK, fills the varbind
    //         list with EndOfMibView's</li>
    //     <li>If the request is a SET, generates a NoAccess error V2
    //          response PDU</li>
    // </ul>
    //
    //
    SnmpPduPacket makeNoMibErrorPdu(SnmpPduRequest req, Object userData) {
        // There is no agent registered
        //
        if (req.version == SnmpDefinitions.snmpVersionOne) {
            // Version 1: => NoSuchName
            return
                newErrorResponsePdu(req,snmpRspNoSuchName,1);
        } else if (req.version == SnmpDefinitions.snmpVersionTwo) {
            // Version 2: => depends on PDU type
            switch (req.type) {
            case pduSetRequestPdu :
            case pduWalkRequest :
                // SET request => NoAccess
                return
                    newErrorResponsePdu(req,snmpRspNoAccess,1);
            case pduGetRequestPdu :
                // GET request => NoSuchObject
                return
                    makeErrorVarbindPdu(req,SnmpDataTypeEnums.
                                        errNoSuchObjectTag);
            case pduGetNextRequestPdu :
            case pduGetBulkRequestPdu :
                // GET-NEXT or GET-BULK => EndOfMibView
                return
                    makeErrorVarbindPdu(req,SnmpDataTypeEnums.
                                        errEndOfMibViewTag);
            default:
            }
        }
        // Something wrong here: => snmpRspGenErr
        return newErrorResponsePdu(req,snmpRspGenErr,1);
    }

    /**
     * Here we make the response pdu from a get/set request pdu.
     * At this level, the result is never null.
     */
    private SnmpPduPacket makeGetSetResponsePdu(SnmpPduRequest req,
                                                Object userData) {

        // Create the trhead group specific for handling sub-requests
        // associated to the current request. Use the invoke id
        //
        // Nice idea to use a thread group on a request basis.
        // However the impact on performance is terrible !
        // theGroup= new ThreadGroup(thread.getThreadGroup(),
        //                "request " + String.valueOf(req.requestId));

        // Let's build the varBindList for the response pdu
        //

        if (req.varBindList == null) {
            // Good ! Let's make a full response pdu.
            //
            return newValidResponsePdu(req, null) ;
        }

        // First we need to split the request into subrequests
        //
        splitRequest(req);
        int nbSubRequest= subs.size();
        if (nbSubRequest == 1)
            return turboProcessingGetSet(req,userData);


        // Execute all the subrequests resulting from the split of the
        // varbind list.
        //
        SnmpPduPacket result= executeSubRequest(req,userData);
        if (result != null)
            // It means that an error occured. The error is already
            // formatted by the executeSubRequest
            // method.
            return result;

        // So far so good. So we need to concatenate all the answers.
        //
        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
               "makeGetSetResponsePdu",
               "Build the unified response for request " + req.requestId);
        }
        return mergeResponses(req);
    }

    /**
     * The method runs all the sub-requests associated to the current
     * instance of SnmpRequestHandler.
     */
    private SnmpPduPacket executeSubRequest(SnmpPduPacket req,
                                            Object userData) {

        int errorStatus = SnmpDefinitions.snmpRspNoError ;
        int nbSubRequest= subs.size();

        int i=0;
        // If it's a set request, we must first check any varBind
        //
        if (req.type == pduSetRequestPdu) {

            i=0;
            for(Enumeration e= subs.elements(); e.hasMoreElements() ; i++) {
                // Indicate to the sub request that a check must be invoked ...
                // OK we should have defined out own tag for that !
                //
                SnmpSubRequestHandler sub= (SnmpSubRequestHandler)
                    e.nextElement();
                sub.setUserData(userData);
                sub.type= pduWalkRequest;

                sub.run();

                sub.type= pduSetRequestPdu;

                if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) {
                    // No point to go any further.
                    //
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                           "executeSubRequest", "an error occurs");
                    }

                    return newErrorResponsePdu(req, errorStatus,
                                               sub.getErrorIndex() + 1) ;
                }
            }
        }// end processing check operation for a set PDU.

        // Let's start the sub-requests.
        //
        i=0;
        for(Enumeration e= subs.elements(); e.hasMoreElements() ;i++) {
            SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement();
        /* NPCTE fix for bugId 4492741, esc 0, 16-August 2001 */
            sub.setUserData(userData);
        /* end of NPCTE fix for bugId 4492741 */

            sub.run();

            if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) {
                // No point to go any further.
                //
                if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                    SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                       "executeSubRequest", "an error occurs");
                }

                return newErrorResponsePdu(req, errorStatus,
                                           sub.getErrorIndex() + 1) ;
            }
        }

        // everything is ok
        //
        return null;
    }

    /**
     * Optimize when there is only one sub request
     */
    private SnmpPduPacket turboProcessingGetSet(SnmpPduRequest req,
                                                Object userData) {

        int errorStatus = SnmpDefinitions.snmpRspNoError ;
        SnmpSubRequestHandler sub = subs.elements().nextElement();
        sub.setUserData(userData);

        // Indicate to the sub request that a check must be invoked ...
        // OK we should have defined out own tag for that !
        //
        if (req.type == SnmpDefinitions.pduSetRequestPdu) {
            sub.type= pduWalkRequest;
            sub.run();
            sub.type= pduSetRequestPdu;

            // Check the error status.
            //
            errorStatus= sub.getErrorStatus();
            if (errorStatus != SnmpDefinitions.snmpRspNoError) {
                // No point to go any further.
                //
                return newErrorResponsePdu(req, errorStatus,
                                           sub.getErrorIndex() + 1) ;
            }
        }

        // process the operation
        //

        sub.run();
        errorStatus= sub.getErrorStatus();
        if (errorStatus != SnmpDefinitions.snmpRspNoError) {
            // No point to go any further.
            //
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                   "turboProcessingGetSet", "an error occurs");
            }
            int realIndex= sub.getErrorIndex() + 1;
            return newErrorResponsePdu(req, errorStatus, realIndex) ;
        }

        // So far so good. So we need to concatenate all the answers.
        //

        if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
            SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
               "turboProcessingGetSet",  "build the unified response for request "
                + req.requestId);
        }
        return mergeResponses(req);
    }

    /**
     * Here we make the response pdu for a bulk request.
     * At this level, the result is never null.
     */
    private SnmpPduPacket makeGetBulkResponsePdu(SnmpPduBulk req,
                                                 Object userData) {

        SnmpVarBind[] respVarBindList = null ;

        // RFC 1905, Section 4.2.3, p14
        int L = req.varBindList.length ;
        int N = Math.max(Math.min(req.nonRepeaters, L), 0) ;
        int M = Math.max(req.maxRepetitions, 0) ;
        int R = L - N ;

        if (req.varBindList == null) {
            // Good ! Let's make a full response pdu.
            //
            return newValidResponsePdu(req, null) ;
        }

        // Split the request into subrequests.
        //
        splitBulkRequest(req, N, M, R);
        SnmpPduPacket result= executeSubRequest(req,userData);
        if (result != null)
            return result;

        respVarBindList= mergeBulkResponses(N + (M * R));

        // Now we remove useless trailing endOfMibView.
        //
        int m2 ; // respVarBindList[m2] item and next are going to be removed
        int t = respVarBindList.length ;
        while ((t > N) && (respVarBindList[t-1].
                           value.equals(SnmpVarBind.endOfMibView))) {
            t-- ;
        }
        if (t == N)
            m2 = N + R ;
        else
            m2 = N + ((t -1 -N) / R + 2) * R ; // Trivial, of course...
        if (m2 < respVarBindList.length) {
            SnmpVarBind[] truncatedList = new SnmpVarBind[m2] ;
            for (int i = 0 ; i < m2 ; i++) {
                truncatedList[i] = respVarBindList[i] ;
            }
            respVarBindList = truncatedList ;
        }

        // Good ! Let's make a full response pdu.
        //
        return newValidResponsePdu(req, respVarBindList) ;
    }

    /**
     * Check the type of the pdu: only the get/set/bulk request
     * are accepted.
     */
    private boolean checkPduType(SnmpPduPacket pdu) {

        boolean result = true ;

        switch(pdu.type) {

        case SnmpDefinitions.pduGetRequestPdu:
        case SnmpDefinitions.pduGetNextRequestPdu:
        case SnmpDefinitions.pduSetRequestPdu:
        case SnmpDefinitions.pduGetBulkRequestPdu:
            result = true ;
            break;

        default:
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                   "checkPduType", "cannot respond to this kind of PDU");
            }
            result = false ;
            break;
        }

        return result ;
    }

    /**
     * Check if the specified pdu is conform to the ACL.
     * This method returns null if the pdu is ok. If not, it returns
     * the response pdu to be replied.
     */
    private SnmpPduPacket checkAcl(SnmpPduPacket pdu) {
        SnmpPduPacket response = null ;
        String community = new String(pdu.community) ;

        // We check the pdu type and create an error response if
        // the check failed.
        //
        if (ipacl != null) {
            if (pdu.type == SnmpDefinitions.pduSetRequestPdu) {
                if (!((InetAddressAcl)ipacl).
                    checkWritePermission(pdu.address, community)) {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                           "checkAcl", "sender is " + pdu.address +
                              " with " + community +". Sender has no write permission");
                    }
                    int err = SnmpSubRequestHandler.
                        mapErrorStatus(SnmpDefinitions.
                                       snmpRspAuthorizationError,
                                       pdu.version, pdu.type);
                    response = newErrorResponsePdu(pdu, err, 0) ;
                }
                else {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                           "checkAcl", "sender is " + pdu.address +
                              " with " + community +". Sender has write permission");
                    }
                }
            }
            else {
                if (!((InetAddressAcl)ipacl).checkReadPermission(pdu.address, community)) {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                           "checkAcl", "sender is " + pdu.address +
                              " with " + community +". Sender has no read permission");
                    }
                    int err = SnmpSubRequestHandler.
                        mapErrorStatus(SnmpDefinitions.
                                       snmpRspAuthorizationError,
                                       pdu.version, pdu.type);
                    response = newErrorResponsePdu(pdu,
                                                   err,
                                                   0);
                    SnmpAdaptorServer snmpServer =
                        (SnmpAdaptorServer)adaptorServer;
                    snmpServer.updateErrorCounters(SnmpDefinitions.
                                                   snmpRspNoSuchName);
                }
                else {
                    if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                        SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                           "checkAcl", "sender is " + pdu.address +
                              " with " + community +". Sender has read permission");
                    }
                }
            }
        }

        // If the response is not null, this means the pdu is rejected.
        // So let's update the statistics.
        //
        if (response != null) {
            SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ;
            snmpServer.incSnmpInBadCommunityUses(1) ;
            if (((InetAddressAcl)ipacl).checkCommunity(community) == false)
                snmpServer.incSnmpInBadCommunityNames(1) ;
        }

        return response ;
    }

    /**
     * Make a response pdu with the specified error status and index.
     * NOTE: the response pdu share its varBindList with the request pdu.
     */
    private SnmpPduRequest newValidResponsePdu(SnmpPduPacket reqPdu,
                                               SnmpVarBind[] varBindList) {
        SnmpPduRequest result = new SnmpPduRequest() ;

        result.address = reqPdu.address ;
        result.port = reqPdu.port ;
        result.version = reqPdu.version ;
        result.community = reqPdu.community ;
        result.type = result.pduGetResponsePdu ;
        result.requestId = reqPdu.requestId ;
        result.errorStatus = SnmpDefinitions.snmpRspNoError ;
        result.errorIndex = 0 ;
        result.varBindList = varBindList ;

        ((SnmpAdaptorServer)adaptorServer).
            updateErrorCounters(result.errorStatus) ;

        return result ;
    }

    /**
     * Make a response pdu with the specified error status and index.
     * NOTE: the response pdu share its varBindList with the request pdu.
     */
    private SnmpPduRequest newErrorResponsePdu(SnmpPduPacket req,int s,int i) {
        SnmpPduRequest result = newValidResponsePdu(req, null) ;
        result.errorStatus = s ;
        result.errorIndex = i ;
        result.varBindList = req.varBindList ;

        ((SnmpAdaptorServer)adaptorServer).
            updateErrorCounters(result.errorStatus) ;

        return result ;
    }

    private SnmpMessage newTooBigMessage(SnmpMessage reqMsg)
        throws SnmpTooBigException {
        SnmpMessage result = null ;
        SnmpPduPacket reqPdu = null ;

        try {
            reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ;
            if (reqPdu != null) {
                SnmpPduPacket respPdu = newTooBigPdu(reqPdu) ;
                result = (SnmpMessage)pduFactory.
                    encodeSnmpPdu(respPdu, packet.getData().length) ;
            }
        }
        catch(SnmpStatusException x) {
            // This should not occur because decodeIncomingRequest has normally
            // been successfully called before.
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                   "newTooBigMessage", "Internal error", x);
            }
            throw new InternalError() ;
        }

        return result ;
    }

    private SnmpPduPacket newTooBigPdu(SnmpPduPacket req) {
        SnmpPduRequest result =
            newErrorResponsePdu(req, SnmpDefinitions.snmpRspTooBig, 0) ;
        result.varBindList = null ;
        return result ;
    }

    private SnmpPduPacket reduceResponsePdu(SnmpPduPacket req,
                                            SnmpPduPacket resp,
                                            int acceptedVbCount)
        throws SnmpTooBigException {

        // Reduction can be attempted only on bulk response
        //
        if (req.type != req.pduGetBulkRequestPdu) {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                   "reduceResponsePdu", "cannot remove anything");
            }
            throw new SnmpTooBigException(acceptedVbCount) ;
        }

        // We're going to reduce the varbind list.
        // First determine which items should be removed.
        // Next duplicate and replace the existing list by the reduced one.
        //
        // acceptedVbCount is the number of varbind which have been
        // successfully encoded before reaching bufferSize:
        //   * when it is >= 2, we split the varbindlist at this
        //     position (-1 to be safe),
        //   * when it is 1, we only put one (big?) item in the varbindlist
        //   * when it is 0 (in fact, acceptedVbCount is not available),
        //     we split the varbindlist by 2.
        //
        int vbCount = resp.varBindList.length ;
        if (acceptedVbCount >= 3)
            vbCount = Math.min(acceptedVbCount - 1, resp.varBindList.length) ;
        else if (acceptedVbCount == 1)
            vbCount = 1 ;
        else // acceptedCount == 0 ie it is unknown
            vbCount = resp.varBindList.length / 2 ;

        if (vbCount < 1) {
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                   "reduceResponsePdu", "cannot remove anything");
            }
            throw new SnmpTooBigException(acceptedVbCount) ;
        }
        else {
            SnmpVarBind[] newVbList = new SnmpVarBind[vbCount] ;
            for (int i = 0 ; i < vbCount ; i++) {
                newVbList[i] = resp.varBindList[i] ;
            }
            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
                   "reduceResponsePdu", (resp.varBindList.length - newVbList.length) +
                    " items have been removed");
            }
            resp.varBindList = newVbList ;
        }

        return resp ;
    }

    /**
     * The method takes the incoming requests and split it into subrequests.
     */
    private void splitRequest(SnmpPduRequest req) {

        int nbAgents= mibs.size();
        SnmpMibAgent agent= (SnmpMibAgent) mibs.firstElement();
        if (nbAgents == 1) {
            // Take all the oids contained in the request and
            //
            subs.put(agent, new SnmpSubRequestHandler(agent, req, true));
            return;
        }

        // For the get next operation we are going to send the varbind list
        // to all agents
        //
        if (req.type == pduGetNextRequestPdu) {
            for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) {
                SnmpMibAgent ag= (SnmpMibAgent) e.nextElement();
                subs.put(ag, new SnmpSubNextRequestHandler(adaptor, ag, req));
            }
            return;
        }

        int nbReqs= req.varBindList.length;
        SnmpVarBind[] vars= req.varBindList;
        SnmpSubRequestHandler sub;
        for(int i=0; i < nbReqs; i++) {
            agent= root.getAgentMib(vars[i].oid);
            sub= subs.get(agent);
            if (sub == null) {
                // We need to create the sub request handler and update
                // the hashtable
                //
                sub= new SnmpSubRequestHandler(agent, req);
                subs.put(agent, sub);
            }

            // Update the translation table within the subrequest
            //
            sub.updateRequest(vars[i], i);
        }
    }

    /**
     * The method takes the incoming get bulk requests and split it into
     * subrequests.
     */
    private void splitBulkRequest(SnmpPduBulk req,
                                  int nonRepeaters,
                                  int maxRepetitions,
                                  int R) {
        // Send the getBulk to all agents
        //
        for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) {
            SnmpMibAgent agent = (SnmpMibAgent) e.nextElement();

            if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
                SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
                   "splitBulkRequest", "Create a sub with : " + agent + " " + nonRepeaters
                   + " " + maxRepetitions + " " + R);
            }

            subs.put(agent,
                     new SnmpSubBulkRequestHandler(adaptor,
                                                   agent,
                                                   req,
                                                   nonRepeaters,
                                                   maxRepetitions,
                                                   R));
        }
        return;
    }

    private SnmpPduPacket mergeResponses(SnmpPduRequest req) {

        if (req.type == pduGetNextRequestPdu) {
            return mergeNextResponses(req);
        }

        SnmpVarBind[] result= req.varBindList;

        // Go through the list of subrequests and concatenate.
        // Hopefully, by now all the sub-requests should be finished
        //
        for(Enumeration e= subs.elements(); e.hasMoreElements();) {
            SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement();
            sub.updateResult(result);
        }
        return newValidResponsePdu(req,result);
    }

    private SnmpPduPacket mergeNextResponses(SnmpPduRequest req) {
        int max= req.varBindList.length;
        SnmpVarBind[] result= new SnmpVarBind[max];

        // Go through the list of subrequests and concatenate.
        // Hopefully, by now all the sub-requests should be finished
        //
        for(Enumeration e= subs.elements(); e.hasMoreElements();) {
            SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement();
            sub.updateResult(result);
        }

        if (req.version == snmpVersionTwo) {
            return newValidResponsePdu(req,result);
        }

        // In v1 make sure there is no endOfMibView ...
        //
        for(int i=0; i < max; i++) {
            SnmpValue val= result[i].value;
            if (val == SnmpVarBind.endOfMibView)
                return newErrorResponsePdu(req,
                                   SnmpDefinitions.snmpRspNoSuchName, i+1);
        }

        // So far so good ...
        //
        return newValidResponsePdu(req,result);
    }

    private SnmpVarBind[] mergeBulkResponses(int size) {
        // Let's allocate the array for storing the result
        //
        SnmpVarBind[] result= new SnmpVarBind[size];
        for(int i= size-1; i >=0; --i) {
            result[i]= new SnmpVarBind();
            result[i].value= SnmpVarBind.endOfMibView;
        }

        // Go through the list of subrequests and concatenate.
        // Hopefully, by now all the sub-requests should be finished
        //
        for(Enumeration e= subs.elements(); e.hasMoreElements();) {
            SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement();
            sub.updateResult(result);
        }

        return result;
    }

    protected String makeDebugTag() {
        return "SnmpRequestHandler[" + adaptorServer.getProtocol() + ":" +
            adaptorServer.getPort() + "]";
    }

    Thread createThread(Runnable r) {
        return null;
    }

    static final private String InterruptSysCallMsg =
        "Interrupted system call";

    static final private SnmpStatusException noSuchNameException =
        new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName) ;
}
