Refactor PCMM aspects of COPS message data objects.
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / PCMMPdpReqStateMan.java
index 0693525d29335b879c26672d73a355a18d6c84ea..9aed78cf44d6fb1cb21a347703db80a8037f4748 100644 (file)
-/**\r
- @header@\r
- */\r
-\r
-package org.pcmm;\r
-\r
-/*\r
-import java.io.*;\r
-import java.util.UUID.*;\r
-*/\r
-import org.pcmm.gates.ITransactionID;\r
-import org.pcmm.gates.impl.PCMMGateReq;\r
-import org.umu.cops.common.COPSDebug;\r
-import org.umu.cops.prpdp.COPSPdpException;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.net.Socket;\r
-import java.util.Arrays;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-import java.util.Vector;\r
-/*\r
-import org.pcmm.base.IPCMMBaseObject;\r
-import org.pcmm.gates.IAMID;\r
-import org.pcmm.gates.IGateID;\r
-import org.pcmm.gates.ISubscriberID;\r
-import org.pcmm.gates.IPCError;\r
-import org.pcmm.gates.impl.AMID;\r
-import org.pcmm.gates.impl.GateID;\r
-import org.pcmm.gates.impl.SubscriberID;\r
-import org.pcmm.gates.impl.TransactionID;\r
-import org.pcmm.gates.impl.PCError;\r
-*/\r
-\r
-\r
-\r
-\r
-/**\r
- * State manager class for provisioning requests, at the PDP side.\r
- */\r
-public class PCMMPdpReqStateMan {\r
-\r
-    /**\r
-     * Request State created\r
-     */\r
-    public final static short ST_CREATE = 1;\r
-    /**\r
-     * Request received\r
-     */\r
-    public final static short ST_INIT = 2;\r
-    /**\r
-     * Decisions sent\r
-     */\r
-    public final static short ST_DECS = 3;\r
-    /**\r
-     * Report received\r
-     */\r
-    public final static short ST_REPORT = 4;\r
-    /**\r
-     * Request State finalized\r
-     */\r
-    public final static short ST_FINAL = 5;\r
-    /**\r
-     * New Request State solicited\r
-     */\r
-    public final static short ST_NEW = 6;\r
-    /**\r
-     * Delete Request State solicited\r
-     */\r
-    public final static short ST_DEL = 7;\r
-    /**\r
-     * SYNC request sent\r
-     */\r
-    public final static short ST_SYNC = 8;\r
-    /**\r
-     * SYNC completed\r
-     */\r
-    public final static short ST_SYNCALL = 9;\r
-    /**\r
-     * Close connection received\r
-     */\r
-    public final static short ST_CCONN = 10;\r
-    /**\r
-     * Keep-alive timeout\r
-     */\r
-    public final static short ST_NOKA = 11;\r
-    /**\r
-     * Accounting timeout\r
-     */\r
-    public final static short ST_ACCT = 12;\r
-\r
-    /**\r
-     * COPS client-type that identifies the policy client\r
-     */\r
-    protected short _clientType;\r
-\r
-    /**\r
-     *  COPS client handle used to uniquely identify a particular\r
-     *  PEP's request for a client-type\r
-     */\r
-    protected COPSHandle _handle;\r
-\r
-    /**\r
-     * Object for performing policy data processing\r
-     */\r
-    protected PCMMPdpDataProcess _process;\r
-\r
-    /**\r
-     *  Current state of the request being managed\r
-     */\r
-    protected short _status;\r
-\r
-    /** COPS message transceiver used to send COPS messages */\r
-    protected PCMMPdpMsgSender _sender;\r
-\r
-    /**\r
-     * Creates a request state manager\r
-     * @param clientType    Client-type\r
-     * @param clientHandle  Client handle\r
-     */\r
-    public PCMMPdpReqStateMan(short clientType, String clientHandle) {\r
-        _handle = new COPSHandle(new COPSData(clientHandle));\r
-        _clientType = clientType;\r
-        _status = ST_CREATE;\r
-    }\r
-\r
-    /**\r
-     * Gets the client handle\r
-     * @return   Client's <tt>COPSHandle</tt>\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _handle;\r
-    }\r
-\r
-    /**\r
-     * Gets the client-type\r
-     * @return   Client-type value\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Gets the status of the request\r
-     * @return      Request state value\r
-     */\r
-    public short getStatus() {\r
-        return _status;\r
-    }\r
-\r
-    /**\r
-     * Gets the policy data processing object\r
-     * @return   Policy data processing object\r
-     */\r
-    public PCMMPdpDataProcess getDataProcess() {\r
-        return _process;\r
-    }\r
-\r
-    /**\r
-     * Sets the policy data processing object\r
-     * @param   process Policy data processing object\r
-     */\r
-    public void setDataProcess(PCMMPdpDataProcess process) {\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Called when COPS sync is completed\r
-     * @param    repMsg              COPS sync message\r
-     * @throws   COPSPdpException\r
-     */\r
-    protected void processSyncComplete(COPSSyncStateMsg repMsg)\r
-    throws COPSPdpException {\r
-\r
-        _status = ST_SYNCALL;\r
-\r
-        // maybe we should notifySyncComplete ...\r
-    }\r
-\r
-    /**\r
-     * Initializes a new request state over a socket\r
-     * @param sock  Socket to the PEP\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void initRequestState(Socket sock)\r
-    throws COPSPdpException {\r
-        // Inits an object for sending COPS messages to the PEP\r
-        _sender = new PCMMPdpMsgSender(_clientType, _handle, sock);\r
-\r
-        // Initial state\r
-        _status = ST_INIT;\r
-    }\r
-\r
-\r
-\r
-    /**\r
-     * Processes a COPS request\r
-     * @param msg   COPS request received from the PEP\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void processRequest(COPSReqMsg msg)\r
-    throws COPSPdpException {\r
-\r
-        COPSHeader hdrmsg = msg.getHeader();\r
-        COPSHandle handlemsg = msg.getClientHandle();\r
-        COPSContext contextmsg = msg.getContext();\r
-\r
-        //** Analyze the request\r
-        //**\r
-\r
-        /* <Request> ::= <Common Header>\r
-        *                   <Client Handle>\r
-        *                   <Context>\r
-        *                   *(<Named ClientSI>)\r
-        *                   [<Integrity>]\r
-        * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
-        *\r
-        * Very important, this is actually being treated like this:\r
-        * <Named ClientSI> ::= <PRID> | <EPD>\r
-        *\r
-\r
-        // Named ClientSI\r
-        Vector clientSIs = msg.getClientSI();\r
-        Hashtable reqSIs = new Hashtable(40);\r
-        String strobjprid = new String();\r
-        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-\r
-            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());\r
-            switch (obj.getSNum())\r
-            {\r
-                case COPSPrObjBase.PR_PRID:\r
-                    strobjprid = obj.getData().str();\r
-                    break;\r
-                case COPSPrObjBase.PR_EPD:\r
-                    reqSIs.put(strobjprid, obj.getData().str());\r
-                    // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);\r
-                    // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());\r
-                    break;\r
-                default:\r
-                    break;\r
-            }\r
-        }\r
-\r
-        //** Here we must retrieve a decision depending on\r
-        //** the supplied ClientSIs\r
-        // reqSIs is a hashtable with the prid and epds\r
-\r
-        // ................\r
-        //\r
-        Hashtable removeDecs = new Hashtable();\r
-        Hashtable installDecs = new Hashtable();\r
-        _process.setClientData(this, reqSIs);\r
-\r
-        removeDecs = _process.getRemovePolicy(this);\r
-        installDecs = _process.getInstallPolicy(this);\r
-\r
-        //** We create the SOLICITED decision\r
-        //**\r
-        _sender.sendDecision(removeDecs, installDecs);\r
-        _status = ST_DECS;\r
-        */\r
-    }\r
-\r
-    /**\r
-     * Processes a report\r
-     * @param msg   Report message from the PEP\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void processReport(COPSReportMsg msg)\r
-    throws COPSPdpException {\r
-\r
-        //** Analyze the report\r
-        //**\r
-\r
-        /*\r
-           * <Report State> ::= <Common Header>\r
-           *                        <Client Handle>\r
-          *                     <Report Type>\r
-         *                      *(<Named ClientSI>)\r
-          *                     [<Integrity>]\r
-         * <Named ClientSI: Report> ::= <[<GPERR>] *(<report>)>\r
-         * <report> ::= <ErrorPRID> <CPERR> *(<PRID><EPD>)\r
-         *\r
-         * Important, <Named ClientSI> is not parsed\r
-        */\r
-\r
-        // COPSHeader hdrmsg = msg.getHeader();\r
-        // COPSHandle handlemsg = msg.getClientHandle();\r
-\r
-        // WriteBinaryDump("COPSReportMessage", msg.getData().getData());\r
-        // Report Type\r
-        COPSReportType rtypemsg = msg.getReport();\r
-\r
-        // Named ClientSI\r
-        Vector clientSIs = msg.getClientSI();\r
-        COPSClientSI myclientSI = (COPSClientSI) msg.getClientSI().elementAt(0);\r
-        byte[] data = Arrays.copyOfRange(myclientSI.getData().getData(), 0, myclientSI.getData().getData().length );\r
-\r
-        // PCMMUtils.WriteBinaryDump("COPSReportClientSI", data);\r
-        System.out.println("PCMMGateReq Parse Gate Message");\r
-        PCMMGateReq gateMsg = new PCMMGateReq(data);\r
-\r
-        Hashtable repSIs = new Hashtable(40);\r
-        String strobjprid = new String();\r
-        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-\r
-            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());\r
-            switch (obj.getSNum()) {\r
-            case COPSPrObjBase.PR_PRID:\r
-                System.out.println("COPSPrObjBase.PR_PRID");\r
-                strobjprid = obj.getData().str();\r
-                break;\r
-            case COPSPrObjBase.PR_EPD:\r
-                System.out.println("COPSPrObjBase.PR_EPD");\r
-                repSIs.put(strobjprid, obj.getData().str());\r
-                // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);\r
-                // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());\r
-                break;\r
-            default:\r
-                COPSDebug.err(getClass().getName(),"Object s-num: " + obj.getSNum() + "stype " + obj.getSType());\r
-                COPSDebug.err(getClass().getName(),"PRID: " + strobjprid);\r
-                COPSDebug.err(getClass().getName(),"EPD: " + obj.getData().str());\r
-                break;\r
-            }\r
-        }\r
-\r
-        System.out.println("rtypemsg process");\r
-        //** Here we must act in accordance with\r
-        //** the report received\r
-        if (rtypemsg.isSuccess()) {\r
-        System.out.println("rtypemsg success");\r
-            _status = ST_REPORT;\r
-            if (_process != null)\r
-            _process.successReport(this, gateMsg);\r
-            else\r
-{\r
-       if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck ) {\r
-            System.out.println(getClass().getName()+ ": GateDeleteAck ");\r
-            System.out.println(getClass().getName()+ ": GateID = " + gateMsg.getGateID().getGateID());\r
-            if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID1())\r
-                PCMMGlobalConfig.setGateID1(0);\r
-            if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID2())\r
-                PCMMGlobalConfig.setGateID2(0);\r
-\r
-        }\r
-        if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck ) {\r
-            System.out.println(getClass().getName()+ ": GateSetAck ");\r
-            System.out.println(getClass().getName()+ ": GateID = " + gateMsg.getGateID().getGateID());\r
-            if (0 == PCMMGlobalConfig.getGateID1())\r
-                PCMMGlobalConfig.setGateID1(gateMsg.getGateID().getGateID());\r
-            if (0 == PCMMGlobalConfig.getGateID2())\r
-                PCMMGlobalConfig.setGateID2(gateMsg.getGateID().getGateID());\r
-        }\r
-\r
-}\r
-        } else if (rtypemsg.isFailure()) {\r
-        System.out.println("rtypemsg failure");\r
-            _status = ST_REPORT;\r
-            if (_process != null)\r
-            _process.failReport(this, gateMsg);\r
-else\r
-{\r
-        System.out.println(getClass().getName()+ ": " + gateMsg.getError().toString());\r
-}\r
-\r
-        } else if (rtypemsg.isAccounting()) {\r
-        System.out.println("rtypemsg account");\r
-            _status = ST_ACCT;\r
-            if (_process != null)\r
-            _process.acctReport(this, gateMsg);\r
-        }\r
-        System.out.println("Out processReport");\r
-    }\r
-\r
-    /**\r
-    * Called when connection is closed\r
-    * @param error  Reason\r
-    * @throws COPSPdpException\r
-    */\r
-    protected void processClosedConnection(COPSError error)\r
-    throws COPSPdpException {\r
-        if (_process != null)\r
-            _process.notifyClosedConnection(this, error);\r
-\r
-        _status = ST_CCONN;\r
-    }\r
-\r
-    /**\r
-     * Called when no keep-alive is received\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void processNoKAConnection()\r
-    throws COPSPdpException {\r
-        if (_process != null)\r
-            _process.notifyNoKAliveReceived(this);\r
-\r
-        _status = ST_NOKA;\r
-    }\r
-\r
-    /**\r
-    * Deletes the request state\r
-    * @throws COPSPdpException\r
-    */\r
-    protected void finalizeRequestState()\r
-    throws COPSPdpException {\r
-        _sender.sendDeleteRequestState();\r
-        _status = ST_FINAL;\r
-    }\r
-\r
-    /**\r
-    * Asks for a COPS sync\r
-    * @throws COPSPdpException\r
-    */\r
-    protected void syncRequestState()\r
-    throws COPSPdpException {\r
-        _sender.sendSyncRequestState();\r
-        _status = ST_SYNC;\r
-    }\r
-\r
-    /**\r
-     * Opens a new request state\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void openNewRequestState()\r
-    throws COPSPdpException {\r
-        _sender.sendOpenNewRequestState();\r
-        _status = ST_NEW;\r
-    }\r
-\r
-    /**\r
-     * Processes a COPS delete message\r
-     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void processDeleteRequestState(COPSDeleteMsg dMsg)\r
-    throws COPSPdpException {\r
-        if (_process != null)\r
-            _process.closeRequestState(this);\r
-\r
-        _status = ST_DEL;\r
-    }\r
-\r
-}\r
+/*
+ * (c) 2015 Cable Television Laboratories, Inc.  All rights reserved.
+ */
+
+package org.pcmm;
+
+import org.pcmm.gates.IGateID;
+import org.pcmm.gates.IPCMMError.ErrorCode;
+import org.pcmm.gates.IPCMMGate;
+import org.pcmm.gates.ITransactionID;
+import org.pcmm.gates.ITransactionID.GateCommandType;
+import org.pcmm.gates.impl.PCMMError;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.prpdp.COPSPdpException;
+import org.umu.cops.prpdp.COPSPdpReqStateMan;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSReportType.ReportType;
+
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * State manager class for provisioning requests, at the PDP side.
+ */
+public class PCMMPdpReqStateMan extends COPSPdpReqStateMan {
+
+    private final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
+
+    /**
+     * Object for performing policy data processing
+     */
+    protected final PCMMPdpDataProcess _thisProcess;
+
+    /** COPS message transceiver used to send COPS messages */
+    protected final PCMMPdpMsgSender _sender;
+
+    /**
+     * Creates a request state manager
+     * @param clientType    Client-type
+     * @param clientHandle  Client handle
+     */
+    // TODO - consider sending in the COPSHandle object instead
+    public PCMMPdpReqStateMan(final short clientType, final COPSHandle clientHandle, final PCMMPdpDataProcess process,
+                              final Socket socket) {
+        super(clientType, clientHandle, process, socket);
+        this._thisProcess = process;
+        _sender = new PCMMPdpMsgSender(_clientType, _handle, _socket);
+        // Initial state
+        _status = Status.ST_INIT;
+    }
+
+    @Override
+    public void processRequest(final COPSReqMsg msg) throws COPSPdpException {
+        // TODO - Implement me - see commented out code from history prior to May 4, 2015...
+    }
+
+     // TODO - break apart this method
+    @Override
+    protected void processReport(final COPSReportMsg msg) throws COPSPdpException {
+        // Report Type
+        final COPSReportType rtypemsg = msg.getReport();
+
+        if (msg.getClientSI() != null) {
+            final COPSClientSI clientSI = msg.getClientSI();
+            // Named ClientSI
+            final byte[] data = Arrays.copyOfRange(clientSI.getData().getData(), 0, clientSI.getData().getData().length);
+
+            // PCMMUtils.WriteBinaryDump("COPSReportClientSI", data);
+            logger.info("PCMMGateReq Parse Gate Message");
+            final PCMMGateReq gateMsg = PCMMGateReq.parse(data);
+
+            // TODO FIXME - Why is this Map being filled but never used???
+            final Map<String, String> repSIs = new HashMap<>();
+            String strobjprid = "";
+            final COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());
+            switch (obj.getSNum()) {
+                case COPSPrObjBase.PR_PRID:
+                    logger.info("COPSPrObjBase.PR_PRID");
+                    // TODO FIXME - this value is never used
+                    strobjprid = obj.getData().str();
+                    break;
+                case COPSPrObjBase.PR_EPD:
+                    logger.info("COPSPrObjBase.PR_EPD");
+                    // TODO FIXME - strobjprid is always empty
+                    repSIs.put(strobjprid, obj.getData().str());
+                    logger.info("PRID: " + strobjprid);
+                    logger.info("EPD: " + obj.getData().str());
+                    break;
+                default:
+                    logger.error("Object s-num: " + obj.getSNum() + "stype " + obj.getSType());
+                    logger.error("PRID: " + strobjprid);
+                    logger.error("EPD: " + obj.getData().str());
+                    break;
+            }
+
+            logger.info("rtypemsg process");
+            //** Here we must act in accordance with
+            //** the report received
+
+            // retrieve and remove the transactionId to gate request map entry
+            // see PCMMPdpMsgSender.sendGateSet(IPCMMGate gate)
+            final ITransactionID trID = gateMsg.getTransactionID();
+            final Short trIDnum = trID.getTransactionIdentifier();
+
+            logger.info("Removing gate from cache with key - " + trIDnum);
+            final IPCMMGate gate = PCMMGlobalConfig.transactionGateMap.remove(trIDnum);
+            if (gate != null) {
+                // capture the "error" message if any
+                gate.setError(gateMsg.getError());
+                logger.info("Setting error on gate - " + gateMsg.getError());
+            }else {
+                logger.error("processReport(): gateReq not found for transactionID {}", trIDnum);
+                return;
+            }
+
+            if (rtypemsg.getReportType().equals(ReportType.SUCCESS)) {
+                logger.info("rtypemsg success");
+                _status = Status.ST_REPORT;
+                final IGateID gateID = gateMsg.getGateID();
+                logger.info("Setting gate ID on gate object - " + gateID);
+                gate.setGateID(gateID);
+                if (_thisProcess != null)
+                    _thisProcess.successReport(this, gateMsg);
+            } else {
+                final String cmdType;
+                if (trID.getGateCommandType().equals(GateCommandType.GATE_DELETE_ACK)) {
+                    cmdType = "GateDeleteAck";
+                } else if (trID.getGateCommandType().equals(GateCommandType.GATE_SET_ACK)) {
+                    cmdType = "GateSetAck";
+                } else cmdType = null;
+                // capture the gateId from the response message
+                final IGateID gateID = gateMsg.getGateID();
+                logger.info("Setting gate ID on gate object - " + gateID);
+                gate.setGateID(gateID);
+
+                if (gateID != null) {
+                    int gateIdInt = gateID.getGateID();
+                    String gateIdHex = String.format("%08x", gateIdInt);
+                    logger.info(getClass().getName() + ": " + cmdType + ": GateID = " + gateIdHex);
+                } else {
+                    logger.warn("Gate ID is null");
+                }
+            }
+            if (rtypemsg.getReportType().equals(ReportType.FAILURE)) {
+                logger.info("rtypemsg failure");
+                _status = Status.ST_REPORT;
+                if (_thisProcess != null)
+                    _thisProcess.failReport(this, gateMsg);
+                else
+                    if (gateMsg.getError() != null)
+                        logger.info("Gate message error - " + gateMsg.getError().toString());
+                    else {
+                        // TODO - Determine if this is the correct error code
+                        final PCMMError error = new PCMMError(ErrorCode.UNK_GATE_CMD);
+                        gate.setError(error);
+                        logger.warn("Gate request failed without an error, setting one - " + error);
+                    }
+            } else if (rtypemsg.getReportType().equals(ReportType.ACCOUNTING)) {
+                    logger.info("rtypemsg account");
+                    _status = Status.ST_ACCT;
+                    if (_thisProcess != null)
+                        _thisProcess.acctReport(this, gateMsg);
+            }
+
+            // let the waiting gateSet/gateDelete sender proceed
+            // TODO - see PCMMService#processReport() gate.notify(). Should determine a better means to
+            // TODO - handle this synchronization.
+            logger.info("Notify gate request has been updated with ID - " + gate.getGateID());
+            synchronized(gate) {
+                gate.notify();
+            }
+            logger.info("Out processReport");
+        }
+    }
+
+}