Refactor PCMM aspects of COPS message data objects.
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / PCMMPdpReqStateMan.java
index a8ab70568e546bb171af269586329c3e3e9b4443..9aed78cf44d6fb1cb21a347703db80a8037f4748 100644 (file)
@@ -1,14 +1,20 @@
-/**
- @header@
+/*
+ * (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;
 
@@ -20,238 +26,41 @@ import java.util.Map;
 /**
  * State manager class for provisioning requests, at the PDP side.
  */
-public class PCMMPdpReqStateMan {
-
-    public final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
+public class PCMMPdpReqStateMan extends COPSPdpReqStateMan {
 
-    /**
-     * Request State created
-     */
-    public final static short ST_CREATE = 1;
-    /**
-     * Request received
-     */
-    public final static short ST_INIT = 2;
-    /**
-     * Decisions sent
-     */
-    public final static short ST_DECS = 3;
-    /**
-     * Report received
-     */
-    public final static short ST_REPORT = 4;
-    /**
-     * Request State finalized
-     */
-    public final static short ST_FINAL = 5;
-    /**
-     * New Request State solicited
-     */
-    public final static short ST_NEW = 6;
-    /**
-     * Delete Request State solicited
-     */
-    public final static short ST_DEL = 7;
-    /**
-     * SYNC request sent
-     */
-    public final static short ST_SYNC = 8;
-    /**
-     * SYNC completed
-     */
-    public final static short ST_SYNCALL = 9;
-    /**
-     * Close connection received
-     */
-    public final static short ST_CCONN = 10;
-    /**
-     * Keep-alive timeout
-     */
-    public final static short ST_NOKA = 11;
-    /**
-     * Accounting timeout
-     */
-    public final static short ST_ACCT = 12;
-
-    /**
-     * COPS client-type that identifies the policy client
-     */
-    protected short _clientType;
-
-    /**
-     *  COPS client handle used to uniquely identify a particular
-     *  PEP's request for a client-type
-     */
-    protected COPSHandle _handle;
+    private final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
 
     /**
      * Object for performing policy data processing
      */
-    protected PCMMPdpDataProcess _process;
-
-    /**
-     *  Current state of the request being managed
-     */
-    protected short _status;
+    protected final PCMMPdpDataProcess _thisProcess;
 
     /** COPS message transceiver used to send COPS messages */
-    protected PCMMPdpMsgSender _sender;
+    protected final PCMMPdpMsgSender _sender;
 
     /**
      * Creates a request state manager
      * @param clientType    Client-type
      * @param clientHandle  Client handle
      */
-    public PCMMPdpReqStateMan(final short clientType, final String clientHandle) {
-        _handle = new COPSHandle(new COPSData(clientHandle));
-        _clientType = clientType;
-        _status = ST_CREATE;
-    }
-
-    /**
-     * Gets the client handle
-     * @return   Client's <tt>COPSHandle</tt>
-     */
-    public COPSHandle getClientHandle() {
-        return _handle;
-    }
-
-    /**
-     * Gets the client-type
-     * @return   Client-type value
-     */
-    public int getClientType() {
-        return _clientType;
-    }
-
-    /**
-     * Gets the status of the request
-     * @return      Request state value
-     */
-    public short getStatus() {
-        return _status;
-    }
-
-    /**
-     * Gets the policy data processing object
-     * @return   Policy data processing object
-     */
-    public PCMMPdpDataProcess getDataProcess() {
-        return _process;
-    }
-
-    /**
-     * Sets the policy data processing object
-     * @param   process Policy data processing object
-     */
-    public void setDataProcess(PCMMPdpDataProcess process) {
-        _process = process;
-    }
-
-    /**
-     * Called when COPS sync is completed
-     * @param    repMsg              COPS sync message
-     * @throws   COPSPdpException
-     */
-    protected void processSyncComplete(COPSSyncStateMsg repMsg)
-    throws COPSPdpException {
-
-        _status = ST_SYNCALL;
-
-        // maybe we should notifySyncComplete ...
-    }
-
-    /**
-     * Initializes a new request state over a socket
-     * @param sock  Socket to the PEP
-     * @throws COPSPdpException
-     */
-    protected void initRequestState(Socket sock)
-    throws COPSPdpException {
-        // Inits an object for sending COPS messages to the PEP
-        _sender = new PCMMPdpMsgSender(_clientType, _handle, sock);
-
+    // 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 = ST_INIT;
+        _status = Status.ST_INIT;
     }
 
-
-
-    /**
-     * Processes a COPS request
-     * @param msg   COPS request received from the PEP
-     * @throws COPSPdpException
-     */
-    protected void processRequest(COPSReqMsg msg)
-    throws COPSPdpException {
-
-        COPSHeader hdrmsg = msg.getHeader();
-        COPSHandle handlemsg = msg.getClientHandle();
-        COPSContext contextmsg = msg.getContext();
-
-        //** Analyze the request
-        //**
-
-        /* <Request> ::= <Common Header>
-        *                   <Client Handle>
-        *                   <Context>
-        *                   *(<Named ClientSI>)
-        *                   [<Integrity>]
-        * <Named ClientSI> ::= <*(<PRID> <EPD>)>
-        *
-        * Very important, this is actually being treated like this:
-        * <Named ClientSI> ::= <PRID> | <EPD>
-        *
-
-        // Named ClientSI
-        Vector clientSIs = msg.getClientSI();
-        Hashtable reqSIs = new Hashtable(40);
-        String strobjprid = new String();
-        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();
-
-            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());
-            switch (obj.getSNum())
-            {
-                case COPSPrObjBase.PR_PRID:
-                    strobjprid = obj.getData().str();
-                    break;
-                case COPSPrObjBase.PR_EPD:
-                    reqSIs.put(strobjprid, obj.getData().str());
-                    // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);
-                    // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        //** Here we must retrieve a decision depending on
-        //** the supplied ClientSIs
-        // reqSIs is a hashtable with the prid and epds
-
-        // ................
-        //
-        Hashtable removeDecs = new Hashtable();
-        Hashtable installDecs = new Hashtable();
-        _process.setClientData(this, reqSIs);
-
-        removeDecs = _process.getRemovePolicy(this);
-        installDecs = _process.getInstallPolicy(this);
-
-        //** We create the SOLICITED decision
-        //**
-        _sender.sendDecision(removeDecs, installDecs);
-        _status = ST_DECS;
-        */
+    @Override
+    public void processRequest(final COPSReqMsg msg) throws COPSPdpException {
+        // TODO - Implement me - see commented out code from history prior to May 4, 2015...
     }
 
-    /**
-     * Processes a report
-     * @param msg   Report message from the PEP
-     * @throws COPSPdpException
-     */
-    protected void processReport(COPSReportMsg msg) throws COPSPdpException {
+     // TODO - break apart this method
+    @Override
+    protected void processReport(final COPSReportMsg msg) throws COPSPdpException {
         // Report Type
         final COPSReportType rtypemsg = msg.getReport();
 
@@ -262,21 +71,24 @@ public class PCMMPdpReqStateMan {
 
             // PCMMUtils.WriteBinaryDump("COPSReportClientSI", data);
             logger.info("PCMMGateReq Parse Gate Message");
-            PCMMGateReq gateMsg = new PCMMGateReq(data);
+            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());
-                    // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);
-                    // COPSDebug.out(getClass().getName(),"EPD: " + 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());
@@ -288,111 +100,81 @@ public class PCMMPdpReqStateMan {
             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 = ST_REPORT;
-                if (_process != null)
-                    _process.successReport(this, gateMsg);
+                _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 {
-                if (gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck) {
-                    logger.info("GateDeleteAck: GateID = " + gateMsg.getGateID().getGateID());
-                    if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID1())
-                        PCMMGlobalConfig.setGateID1(0);
-                    if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID2())
-                        PCMMGlobalConfig.setGateID2(0);
-
-                }
-                if (gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck) {
-                    logger.info("GateSetAck: GateID = " + gateMsg.getGateID().getGateID());
-                    if (0 == PCMMGlobalConfig.getGateID1())
-                        PCMMGlobalConfig.setGateID1(gateMsg.getGateID().getGateID());
-                    if (0 == PCMMGlobalConfig.getGateID2())
-                        PCMMGlobalConfig.setGateID2(gateMsg.getGateID().getGateID());
+                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 = ST_REPORT;
-                if (_process != null)
-                    _process.failReport(this, gateMsg);
+                _status = Status.ST_REPORT;
+                if (_thisProcess != null)
+                    _thisProcess.failReport(this, gateMsg);
                 else
-                    logger.info("Gate message error - " + gateMsg.getError().toString());
-            } else
-                if (rtypemsg.getReportType().equals(ReportType.ACCOUNTING)) {
+                    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 = ST_ACCT;
-                    if (_process != null)
-                        _process.acctReport(this, gateMsg);
-                }
-        }
-    }
-
-    /**
-    * Called when connection is closed
-    * @param error  Reason
-    * @throws COPSPdpException
-    */
-    protected void processClosedConnection(COPSError error)
-    throws COPSPdpException {
-        if (_process != null)
-            _process.notifyClosedConnection(this, error);
-
-        _status = ST_CCONN;
-    }
-
-    /**
-     * Called when no keep-alive is received
-     * @throws COPSPdpException
-     */
-    protected void processNoKAConnection()
-    throws COPSPdpException {
-        if (_process != null)
-            _process.notifyNoKAliveReceived(this);
-
-        _status = ST_NOKA;
-    }
-
-    /**
-    * Deletes the request state
-    * @throws COPSPdpException
-    */
-    protected void finalizeRequestState()
-    throws COPSPdpException {
-        _sender.sendDeleteRequestState();
-        _status = ST_FINAL;
-    }
-
-    /**
-    * Asks for a COPS sync
-    * @throws COPSPdpException
-    */
-    protected void syncRequestState()
-    throws COPSPdpException {
-        _sender.sendSyncRequestState();
-        _status = ST_SYNC;
-    }
-
-    /**
-     * Opens a new request state
-     * @throws COPSPdpException
-     */
-    protected void openNewRequestState()
-    throws COPSPdpException {
-        _sender.sendOpenNewRequestState();
-        _status = ST_NEW;
-    }
-
-    /**
-     * Processes a COPS delete message
-     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP
-     * @throws COPSPdpException
-     */
-    protected void processDeleteRequestState(COPSDeleteMsg dMsg)
-    throws COPSPdpException {
-        if (_process != null)
-            _process.closeRequestState(this);
+                    _status = Status.ST_ACCT;
+                    if (_thisProcess != null)
+                        _thisProcess.acctReport(this, gateMsg);
+            }
 
-        _status = ST_DEL;
+            // 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");
+        }
     }
 
 }