Merge "Copyright"
authorThomas Kee <xsited@yahoo.com>
Fri, 8 May 2015 18:30:20 +0000 (18:30 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 8 May 2015 18:30:20 +0000 (18:30 +0000)
120 files changed:
packetcable-driver/src/main/java/org/pcmm/PCMMPdpAgent.java
packetcable-driver/src/main/java/org/pcmm/PCMMPdpConnection.java
packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java
packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java
packetcable-driver/src/main/java/org/pcmm/PCMMPepAgent.java
packetcable-driver/src/main/java/org/pcmm/messages/IMessageFactory.java
packetcable-driver/src/main/java/org/pcmm/messages/impl/COPSDecisionMsgEX.java
packetcable-driver/src/main/java/org/pcmm/messages/impl/MessageFactory.java
packetcable-driver/src/main/java/org/pcmm/nio/PCMMChannel.java
packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMClient.java
packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMServer.java
packetcable-driver/src/main/java/org/pcmm/rcd/impl/CMTS.java
packetcable-driver/src/main/java/org/pcmm/rcd/impl/PCMMPolicyServer.java
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSAgent.java
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSConnection.java
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSDataProcess.java
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSMsgSender.java
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSReqStateMan.java
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSAgent.java
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSConnection.java
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSMsgSender.java
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSReqStateMan.java
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpConnection.java
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpDataProcess.java
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpMsgSender.java
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpReqStateMan.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepAgent.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepConnection.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepDataProcess.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepMsgSender.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepReqStateMan.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSAcctTimer.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientAcceptMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientCloseMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientOpenMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientSI.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSContext.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSData.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecision.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecisionMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSDeleteMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSError.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSException.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSHandle.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeader.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeaderData.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIntegrity.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSInterface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpAddress.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Address.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4InInterface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Interface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4LastPdpAddr.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4OutInterface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpAddress.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpRedirectAddress.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Address.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6InInterface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Interface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6LastPdpAddr.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6OutInterface.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpAddress.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpRedirectAddress.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSKAMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSKATimer.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSLPDPDecision.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsgParser.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjBase.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeader.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeaderData.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjectParser.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPdpAddress.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPepId.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReason.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportType.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReqMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSSyncStateMsg.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSTimer.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSTransceiver.java
packetcable-driver/src/main/java/org/umu/cops/stack/COPSUtil.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSAcctTimerTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientAcceptMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientCloseMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientOpenMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientSITest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSContextTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSDataFirstConstructorTest.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSDeleteMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSErrorTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleFirstConstructorTest.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleSecondConstructorTest.java [deleted file]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSHeaderTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIntegrityTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4AddressTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4InInterfaceTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4LastPdpAddrTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4OutInterfaceTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4PdpRedirectAddressTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6AddressTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6InInterfaceTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6LastPdpAddrTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6OutInterfaceTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6PdpRedirectAddressTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSKAMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSKATimerTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSLPDPDecisionTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSMsgParserTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSPepIdTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSReasonTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSReportMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSReportTypeTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSReqMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/COPSSyncStateMsgTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/umu/cops/stack/TestCOPSServer.java [new file with mode: 0644]

index 7c1f47cf9892cf081cd54e6f760c24f7b6375586..28eae315d5b20a003d9618b6a0e6e2f7edb24625 100644 (file)
@@ -10,10 +10,14 @@ import org.slf4j.LoggerFactory;
 import org.umu.cops.prpdp.COPSPdpAgent;
 import org.umu.cops.prpdp.COPSPdpException;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Core PDP agent for provisioning
@@ -43,9 +47,14 @@ public class PCMMPdpAgent extends COPSPdpAgent {
      * Policy data processing object
      */
     private PCMMPdpDataProcess _process;
-    private MMVersionInfo _mminfo;
     private COPSHandle _handle;
-    private short _transactionID;
+//    private short _transactionID;
+
+    /**
+     * Temporary until can refactor PdpAgent classes
+     */
+    @Deprecated
+    private final Map<String, PCMMPdpConnection> _connectionMap;
 
     /**
      * Creates a PDP Agent
@@ -75,6 +84,7 @@ public class PCMMPdpAgent extends COPSPdpAgent {
         super(psPort, clientType, null);
         this._process = process;
         this.psHost = psHost;
+        this._connectionMap = new ConcurrentHashMap<>();
     }
 
     /**
@@ -121,7 +131,7 @@ public class PCMMPdpAgent extends COPSPdpAgent {
             try {
                 logger.info("PDP  COPSTransceiver.receiveMsg");
                 COPSMsg msg = COPSTransceiver.receiveMsg(socket);
-                if (msg.getHeader().isAClientOpen()) {
+                if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
                     logger.info("PDP msg.getHeader().isAClientOpen");
                     handleClientOpenMsg(socket, msg);
                 } else {
@@ -153,21 +163,15 @@ public class PCMMPdpAgent extends COPSPdpAgent {
      * @throws COPSException
      * @throws IOException
      */
-    private void handleClientOpenMsg(Socket conn, COPSMsg msg)
-    throws COPSException, IOException {
-        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
-        COPSPepId pepId = cMsg.getPepId();
+    private void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+        final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
+        final COPSPepId pepId = cMsg.getPepId();
 
         // Validate Client Type
         if (msg.getHeader().getClientType() != getClientType()) {
             // Unsupported client type
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
-                                             .getHeader().getClientType());
-            COPSError err = new COPSError(
-                COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
-            closeMsg.add(cHdr);
-            closeMsg.add(err);
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                    new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
             try {
                 closeMsg.writeData(conn);
             } catch (IOException unae) {
@@ -180,13 +184,8 @@ public class PCMMPdpAgent extends COPSPdpAgent {
         // PEPId is mandatory
         if (pepId == null) {
             // Mandatory COPS object missing
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
-                                             .getHeader().getClientType());
-            COPSError err = new COPSError(
-                COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
-            closeMsg.add(cHdr);
-            closeMsg.add(err);
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                    new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
             try {
                 closeMsg.writeData(conn);
             } catch (IOException unae) {
@@ -198,21 +197,13 @@ public class PCMMPdpAgent extends COPSPdpAgent {
         setPepId(pepId);
         // Support
         if ((cMsg.getClientSI() != null) ) {
-            _mminfo = new MMVersionInfo(cMsg
-                                        .getClientSI().getData().getData());
-            logger.info("CMTS sent MMVersion info : major:"
-                               + _mminfo.getMajorVersionNB() + "  minor:"
-                               + _mminfo.getMinorVersionNB());
+            final MMVersionInfo _mminfo = new MMVersionInfo(cMsg.getClientSI().getData().getData());
+            logger.info("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + "  minor:" +
+                    _mminfo.getMinorVersionNB());
 
         } else {
-            // Unsupported objects
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
-                                             .getHeader().getClientType());
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT,
-                                          (short) 0);
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
-            closeMsg.add(cHdr);
-            closeMsg.add(err);
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                    new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
             try {
                 closeMsg.writeData(conn);
             } catch (IOException unae) {
@@ -225,31 +216,25 @@ public class PCMMPdpAgent extends COPSPdpAgent {
         */
 
         // Connection accepted
-        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg
-                                         .getHeader().getClientType());
-        COPSKATimer katimer = new COPSKATimer(getKaTimer());
-        COPSAcctTimer acctTimer = new COPSAcctTimer(getAcctTimer());
-        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();
-        acceptMsg.add(ahdr);
-        acceptMsg.add(katimer);
+        final COPSKATimer katimer = new COPSKATimer(getKaTimer());
+        final COPSAcctTimer acctTimer = new COPSAcctTimer(getAcctTimer());
+        final COPSClientAcceptMsg acceptMsg;
         if (getAcctTimer() != 0)
-            acceptMsg.add(acctTimer);
+            acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, acctTimer, null);
+        else
+            acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
+
         acceptMsg.writeData(conn);
         // XXX - handleRequestMsg
         try {
             logger.info("PDP COPSTransceiver.receiveMsg");
             COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
             // Client-Close
-            if (rmsg.getHeader().isAClientClose()) {
+            if (rmsg.getHeader().getOpCode().equals(OPCode.CC)) {
                 logger.info("Client close description - " + ((COPSClientCloseMsg) rmsg).getError().getDescription());
                 // close the socket
-                COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
-                                                 .getHeader().getClientType());
-                COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT,
-                                              (short) 0);
-                COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
-                closeMsg.add(cHdr);
-                closeMsg.add(err);
+                final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                        new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
                 try {
                     closeMsg.writeData(conn);
                 } catch (IOException unae) {
@@ -258,7 +243,7 @@ public class PCMMPdpAgent extends COPSPdpAgent {
                 throw new COPSException("CMTS requetsed Client-Close");
             } else {
                 // Request
-                if (rmsg.getHeader().isARequest()) {
+                if (rmsg.getHeader().getOpCode().equals(OPCode.REQ)) {
                     COPSReqMsg rMsg = (COPSReqMsg) rmsg;
                     _handle = rMsg.getClientHandle();
                 } else
@@ -289,7 +274,7 @@ public class PCMMPdpAgent extends COPSPdpAgent {
 
         logger.info("PDP Thread(pdpConn).start");
         new Thread(pdpConn).start();
-        getConnectionMap().put(pepId.getData().str(), pdpConn);
+        _connectionMap.put(pepId.getData().str(), pdpConn);
     }
 
     /**
index a6c2c01b4a6a754c9aef238af42c92157102db0f..2967f811eff51b1379dd4c95cd990a371f68f531 100644 (file)
@@ -8,12 +8,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.umu.cops.prpdp.COPSPdpException;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.net.Socket;
 import java.util.Date;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Class for managing an provisioning connection at the PDP side.
@@ -33,16 +35,6 @@ public class PCMMPdpConnection implements Runnable {
     */
     private COPSPepId _pepId;
 
-    /**
-    Time of the latest keep-alive sent
-     */
-    private Date _lastKa;
-
-    /**
-   Opcode of the latest message sent
-    */
-    private byte _lastmessage;
-
     /**
      *  Time of the latest keep-alive received
      */
@@ -51,8 +43,7 @@ public class PCMMPdpConnection implements Runnable {
     /**
    Maps a Client Handle to a Handler
      */
-    protected Hashtable _managerMap;
-    // map < String(COPSHandle), COPSPdpHandler> HandlerMap;
+    protected Map<String, PCMMPdpReqStateMan> _managerMap;
 
     /**
      *  PDP policy data processor class
@@ -84,44 +75,24 @@ public class PCMMPdpConnection implements Runnable {
     public PCMMPdpConnection(COPSPepId pepId, Socket sock, PCMMPdpDataProcess process) {
         _sock = sock;
         _pepId = pepId;
-
-        _lastKa = new Date();
-        _lastmessage = COPSHeader.COPS_OP_OPN;
-        _managerMap = new Hashtable(20);
-
+        _managerMap = new ConcurrentHashMap<>();
         _kaTimer = 120;
         _process = process;
     }
 
-    /**
-     * Gets the time of that latest keep-alive sent
-     * @return Time of that latest keep-alive sent
-     */
-    public Date getLastKAlive() {
-        return _lastKa;
-    }
-
     /**
      * Sets the keep-alive timer value
      * @param kaTimer Keep-alive timer value (secs)
      */
-    public void setKaTimer(short kaTimer) {
+    public void setKaTimer(final short kaTimer) {
         _kaTimer = kaTimer;
     }
 
-    /**
-     * Gets the keep-alive timer value
-     * @return Keep-alive timer value (secs)
-     */
-    public short getKaTimer() {
-        return _kaTimer;
-    }
-
     /**
      * Sets the accounting timer value
      * @param acctTimer Accounting timer value (secs)
      */
-    public void setAccTimer(short acctTimer) {
+    public void setAccTimer(final short acctTimer) {
         _acctTimer = acctTimer;
     }
 
@@ -133,36 +104,13 @@ public class PCMMPdpConnection implements Runnable {
         return _acctTimer;
     }
 
-    /**
-     * Gets the latest COPS message
-     * @return   Code of the latest message sent
-     */
-    public byte getLastMessage() {
-        return _lastmessage;
-    }
-
-    /**
-     * Gets active handles
-     * @return   An <tt>Enumeration</tt> holding all active handles
-     */
-    public Enumeration getHandles() {
-        return _managerMap.keys();
-    }
-
     /**
      * Gets the handle map
      * @return   A <tt>Hashtable</tt> holding the handle map
      */
-    public Hashtable getReqStateMans() {
-        return _managerMap;
-    }
-
-    /**
-     * Gets the PEP-ID
-     * @return   The ID of the PEP, as a <tt>String</tt>
-     */
-    public String getPepId() {
-        return _pepId.getData().str();
+    public Map<String, PCMMPdpReqStateMan> getReqStateMans() {
+        // Defensive copy
+        return new HashMap<>(_managerMap);
     }
 
     /**
@@ -199,7 +147,7 @@ public class PCMMPdpConnection implements Runnable {
         try {
             while (!_sock.isClosed()) {
                 if (_sock.getInputStream().available() != 0) {
-                    _lastmessage = processMessage(_sock);
+                    processMessage(_sock);
                     _lastRecKa = new Date();
                 }
 
@@ -209,7 +157,7 @@ public class PCMMPdpConnection implements Runnable {
                     int _startTime = (int) (_lastRecKa.getTime());
                     int cTime = (int) (new Date().getTime());
 
-                    if ((int)(cTime - _startTime) > _kaTimer*1000) {
+                    if ((cTime - _startTime) > _kaTimer*1000) {
                         _sock.close();
                         // Notify all Request State Managers
                         notifyNoKAAllReqStateMan();
@@ -219,12 +167,9 @@ public class PCMMPdpConnection implements Runnable {
                     _startTime = (int) (_lastSendKa.getTime());
                     cTime = (int) (new Date().getTime());
 
-                    if ((cTime - _startTime) > ((_kaTimer * 3/4) * 1000)) {
-                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);
-                        COPSKAMsg msg = new COPSKAMsg();
-
-                        msg.add(hdr);
-
+                    if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
+                        // TODO - determine what is the client type to be used here?
+                        final COPSKAMsg msg = new COPSKAMsg(null);
                         COPSTransceiver.sendMsg(msg, _sock);
                         _lastSendKa = new Date();
                     }
@@ -260,30 +205,22 @@ public class PCMMPdpConnection implements Runnable {
     /**
      * Gets a COPS message from the socket and processes it
      * @param    conn Socket connected to the PEP
-     * @return Type of COPS message
      */
-    private byte processMessage(Socket conn)
-    throws COPSPdpException, COPSException, IOException {
-        COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+    private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
+        final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
 
-        if (msg.getHeader().isAClientClose()) {
+        if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
             handleClientCloseMsg(conn, msg);
-            return COPSHeader.COPS_OP_CC;
-        } else if (msg.getHeader().isAKeepAlive()) {
+        } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
             handleKeepAliveMsg(conn, msg);
-            return COPSHeader.COPS_OP_KA;
-        } else if (msg.getHeader().isARequest()) {
+        } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
             handleRequestMsg(conn, msg);
-            return COPSHeader.COPS_OP_REQ;
-        } else if (msg.getHeader().isAReport()) {
+        } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
             handleReportMsg(conn, msg);
-            return COPSHeader.COPS_OP_RPT;
-        } else if (msg.getHeader().isADeleteReq()) {
+        } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
             handleDeleteRequestMsg(conn, msg);
-            return COPSHeader.COPS_OP_DRQ;
-        } else if (msg.getHeader().isASyncComplete()) {
+        } else if (msg.getHeader().getOpCode().equals(OPCode.SSQ)) {
             handleSyncComplete(conn, msg);
-            return COPSHeader.COPS_OP_SSC;
         } else {
             throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
         }
@@ -306,10 +243,6 @@ public class PCMMPdpConnection implements Runnable {
     private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
         COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
         _error = cMsg.getError();
-
-        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
-
         try {
             // Support
             if (cMsg.getIntegrity() != null) {
@@ -372,8 +305,7 @@ public class PCMMPdpConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
-    throws COPSPdpException {
+    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
         COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
         // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
         //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
@@ -385,11 +317,12 @@ public class PCMMPdpConnection implements Runnable {
 
         // Delete clientHandler
         if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
+            // TODO - Determine what to do here???
             // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
             //  cMsg.getClientHandle().getId().getData());
         }
 
-        PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+        final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
         if (man == null) {
             logger.warn("State manager not found");
         } else {
@@ -414,14 +347,13 @@ public class PCMMPdpConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleRequestMsg(Socket conn, COPSMsg msg)
-    throws COPSPdpException {
+    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
 
-        COPSReqMsg reqMsg = (COPSReqMsg) msg;
-        COPSContext cntxt = reqMsg.getContext();
-        COPSHeader header = reqMsg.getHeader();
+        final COPSReqMsg reqMsg = (COPSReqMsg) msg;
+//        COPSContext cntxt = reqMsg.getContext();
+        final COPSHeader header = reqMsg.getHeader();
         //short reqType = cntxt.getRequestType();
-        short cType   = header.getClientType();
+        final short cType = header.getClientType();
 
         // Support
         if (reqMsg.getIntegrity() != null) {
@@ -429,11 +361,11 @@ public class PCMMPdpConnection implements Runnable {
         }
 
         PCMMPdpReqStateMan man;
-        man = (PCMMPdpReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());
+        man = _managerMap.get(reqMsg.getClientHandle().getId().str());
         if (man == null) {
 
             man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
-            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
+            _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
             man.setDataProcess(_process);
             man.initRequestState(_sock);
 
@@ -471,7 +403,7 @@ public class PCMMPdpConnection implements Runnable {
             logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
         }
 
-        PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());
+        final PCMMPdpReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
         if (man == null) {
             logger.warn("State manager not found");
         } else {
@@ -497,7 +429,7 @@ public class PCMMPdpConnection implements Runnable {
             logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
         }
 
-        PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+        final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
         if (man == null) {
             logger.warn("State manager not found");
         } else {
@@ -510,39 +442,21 @@ public class PCMMPdpConnection implements Runnable {
      * @throws COPSException
      * @throws COPSPdpException
      */
-    protected void syncAllRequestState()
-    throws COPSException, COPSPdpException {
-        if (_managerMap.size() > 0) {
-            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
-                String handle = (String) e.nextElement();
-                PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(handle);
-
-                man.syncRequestState();
-            }
+    protected void syncAllRequestState() throws COPSException, COPSPdpException {
+        for (final PCMMPdpReqStateMan man : _managerMap.values()) {
+            man.syncRequestState();
         }
     }
 
-    private void notifyCloseAllReqStateMan()
-    throws COPSPdpException {
-        if (_managerMap.size() > 0) {
-            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
-                String handle = (String) e.nextElement();
-                PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(handle);
-
-                man.processClosedConnection(_error);
-            }
+    private void notifyCloseAllReqStateMan() throws COPSPdpException {
+        for (final PCMMPdpReqStateMan man : _managerMap.values()) {
+            man.processClosedConnection(_error);
         }
     }
 
-    private void notifyNoKAAllReqStateMan()
-    throws COPSPdpException {
-        if (_managerMap.size() > 0) {
-            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
-                String handle = (String) e.nextElement();
-                PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(handle);
-
-                man.processNoKAConnection();
-            }
+    private void notifyNoKAAllReqStateMan() throws COPSPdpException {
+        for (final PCMMPdpReqStateMan man : _managerMap.values()) {
+            man.processNoKAConnection();
         }
     }
 
index 515b595bab76d0d7a19cee26314b1ee62d799304..770a578fadd5b80989dfcde8329524cb981e1234 100644 (file)
@@ -12,13 +12,20 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.umu.cops.prpdp.COPSPdpException;
 import org.umu.cops.stack.*;
-import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSHeader.OPCode;
 import org.umu.cops.stack.COPSObjHeader.CType;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 //temp
 //pcmm
@@ -75,8 +82,7 @@ public class PCMMPdpMsgSender {
      * @param sock
      *            Socket to the PEP
      */
-    public PCMMPdpMsgSender(short clientType, COPSHandle clientHandle,
-                            Socket sock) {
+    public PCMMPdpMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
         // COPS Handle
         _handle = clientHandle;
         _clientType = clientType;
@@ -86,8 +92,8 @@ public class PCMMPdpMsgSender {
         _sock = sock;
     }
 
-    public PCMMPdpMsgSender(short clientType, short tID,
-                            COPSHandle clientHandle, Socket sock) {
+    public PCMMPdpMsgSender(final short clientType, final short tID, final COPSHandle clientHandle,
+                            final Socket sock) {
         // COPS Handle
         _handle = clientHandle;
         _clientType = clientType;
@@ -126,20 +132,11 @@ public class PCMMPdpMsgSender {
 
     /**
      * Sends a PCMM GateSet COPS Decision message
-     *
-     * @param
+     * @param gate - the gate
      * @throws COPSPdpException
      */
-    public void sendGateSet(IPCMMGate gate)
-    throws COPSPdpException {
-        // Common Header with the same ClientType as the request
-
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
-
-        // Client Handle with the same clientHandle as the request
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
-        ITransactionID trID = new TransactionID();
+    public void sendGateSet(final IPCMMGate gate) throws COPSPdpException {
+        final ITransactionID trID = new TransactionID();
 
         // set transaction ID to gate set
         trID.setGateCommandType(ITransactionID.GateSet);
@@ -150,38 +147,26 @@ public class PCMMPdpMsgSender {
 
 
         // new pcmm specific clientsi
-        COPSClientSI clientSD = new COPSClientSI((byte)CNum.DEC.ordinal(), (byte)CType.CSI.ordinal());
-        byte[] data = gate.getData();
-        clientSD.setData(new COPSData(data, 0, data.length));
-        try {
-            decisionMsg.add(hdr);
-            decisionMsg.add(handle);
-            // Decisions (no flags supplied)
-            // <Context>
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
-            COPSDecision install = new COPSDecision();
-            install.setCmdCode(COPSDecision.DEC_INSTALL);
-            install.setFlags(COPSDecision.F_REQERROR);
-            decisionMsg.addDecision(install, cntxt);
-            decisionMsg.add(clientSD); // setting up the gate
-            /*
-                        try {
-                            decisionMsg.dump(System.out);
-                        } catch (IOException unae) {
-                            System.out.println("Error dumping " + unae.getMessage());
-                        }
-            */
-
-        } catch (COPSException e) {
-            logger.error("Error making Msg", e);
-        }
+        final byte[] data = gate.getData();
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
+                new COPSData(data, 0, data.length)));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
+                decisionMap, null);
+//                new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
+        //                new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null));
         // ** Send the GateSet Decision
         // **
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
-            logger.error("Failed to send the decision, reason: ", e);
+            logger.error("Failed to send the decision", e);
         }
 
     }
@@ -189,35 +174,24 @@ public class PCMMPdpMsgSender {
     /**
      * Sends a PCMM GateSet COPS Decision message
      *
-     * @param
+     * @param num - the number
      * @throws COPSPdpException
      */
-    public void sendGateSetDemo(int num)
-    throws COPSPdpException {
-
-        // Common Header with the same ClientType as the request
-
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
-
-        // Client Handle with the same clientHandle as the request
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
-
-        IPCMMGate gate = new PCMMGateReq();
-        ITransactionID trID = new TransactionID();
-
-        IAMID amid = new AMID();
-        ISubscriberID subscriberID = new SubscriberID();
-        IGateSpec gateSpec = new GateSpec();
-        IClassifier classifier = new Classifier();
-        IExtendedClassifier eclassifier = new ExtendedClassifier();
+    public void sendGateSetDemo(int num) throws COPSPdpException {
+        final IPCMMGate gate = new PCMMGateReq();
+        final ITransactionID trID = new TransactionID();
+        final IAMID amid = new AMID();
+        final ISubscriberID subscriberID = new SubscriberID();
+        final IGateSpec gateSpec = new GateSpec();
+        final IClassifier classifier = new Classifier();
+        final IExtendedClassifier eclassifier = new ExtendedClassifier();
         final int trafficRate;
-
         if (num == 1)
             trafficRate =   PCMMGlobalConfig.DefaultBestEffortTrafficRate;
         else
             trafficRate =   PCMMGlobalConfig.DefaultLowBestEffortTrafficRate;
 
-        ITrafficProfile trafficProfile = new BestEffortService(
+        final ITrafficProfile trafficProfile = new BestEffortService(
             (byte) 7); //BestEffortService.DEFAULT_ENVELOP);
         ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
         .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
@@ -264,11 +238,6 @@ public class PCMMPdpMsgSender {
 
 
 
-        // new pcmm specific clientsi
-        COPSClientSI clientSD = new COPSClientSI((byte)CNum.DEC.ordinal(), (byte)CType.CSI.ordinal());
-
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());
-
         // set transaction ID to gate set
         trID.setGateCommandType(ITransactionID.GateSet);
         _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID);
@@ -284,6 +253,7 @@ public class PCMMPdpMsgSender {
         gateSpec.setTimerT4(PCMMGlobalConfig.GateT4);
 
         // XXX - if the version major is less than 4 we need to use Classifier
+        // TODO - Use some variable here or remove...
         if (true) {
             //eclassifier.setProtocol(IClassifier.Protocol.NONE);
             eclassifier.setProtocol(IClassifier.Protocol.TCP);
@@ -348,68 +318,46 @@ public class PCMMPdpMsgSender {
         gate.setTrafficProfile(trafficProfile);
         gate.setClassifier(eclassifier);
 
-        byte[] data = gate.getData();
+        final byte[] data = gate.getData();
 
-        // new pcmm specific clientsi
-        clientSD.setData(new COPSData(data, 0, data.length));
-        try {
-            decisionMsg.add(hdr);
-            decisionMsg.add(handle);
-            // Decisions (no flags supplied)
-            // <Context>
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
-            COPSDecision install = new COPSDecision();
-            install.setCmdCode(COPSDecision.DEC_INSTALL);
-            install.setFlags(COPSDecision.F_REQERROR);
-            decisionMsg.addDecision(install, cntxt);
-            decisionMsg.add(clientSD); // setting up the gate
-            /*
-                        try {
-                            decisionMsg.dump(System.out);
-                        } catch (IOException unae) {
-                            System.out.println("Error dumping " + unae.getMessage());
-                        }
-            */
-
-        } catch (COPSException e) {
-            logger.error("Error making Msg", e);
-        }
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
+                new COPSData(data, 0, data.length)));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(),
+                new COPSHandle(getClientHandle().getId()), decisionMap, null);
+//                new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
+                //                new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length))); TODO - what does the value of 4 mean here???
 
         // ** Send the GateSet Decision
         // **
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
-            logger.error("Failed to send the decision, reason: ", e);
+            logger.error("Failed to send the decision", e);
         }
 
     }
     /**
      * Sends a PCMM GateSet COPS Decision message
-     *
-     * @param
      * @throws COPSPdpException
      */
-    public void sendGateSetBestEffortWithExtendedClassifier()
-    throws COPSPdpException {
-        // Common Header with the same ClientType as the request
-
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
-
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
-
-        IPCMMGate gate = new PCMMGateReq();
-        ITransactionID trID = new TransactionID();
-
-        IAMID amid = new AMID();
-        ISubscriberID subscriberID = new SubscriberID();
-        IGateSpec gateSpec = new GateSpec();
-        IClassifier classifier = new Classifier();
-        IExtendedClassifier eclassifier = new ExtendedClassifier();
+    public void sendGateSetBestEffortWithExtendedClassifier() throws COPSPdpException {
+        final IPCMMGate gate = new PCMMGateReq();
+        final ITransactionID trID = new TransactionID();
+        final IAMID amid = new AMID();
+        final ISubscriberID subscriberID = new SubscriberID();
+        final IGateSpec gateSpec = new GateSpec();
+        final IClassifier classifier = new Classifier();
+        final IExtendedClassifier eclassifier = new ExtendedClassifier();
 
         // XXX check if other values should be provided
         //
-        ITrafficProfile trafficProfile = new BestEffortService(
+        final ITrafficProfile trafficProfile = new BestEffortService(
             (byte) 7); //BestEffortService.DEFAULT_ENVELOP);
         ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
         .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
@@ -453,12 +401,6 @@ public class PCMMPdpMsgSender {
 
 
 
-        // new pcmm specific clientsi
-        COPSClientSI clientSD = new COPSClientSI((byte)CNum.DEC.ordinal(), (byte)CType.CSI.ordinal());
-
-        // Client Handle with the same clientHandle as the request
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());
-
         // set transaction ID to gate set
         trID.setGateCommandType(ITransactionID.GateSet);
         _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID);
@@ -540,30 +482,17 @@ public class PCMMPdpMsgSender {
 
         byte[] data = gate.getData();
 
-        // new pcmm specific clientsi
-        clientSD.setData(new COPSData(data, 0, data.length));
-        try {
-            decisionMsg.add(hdr);
-            decisionMsg.add(handle);
-            // Decisions (no flags supplied)
-            // <Context>
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
-            COPSDecision install = new COPSDecision();
-            install.setCmdCode(COPSDecision.DEC_INSTALL);
-            install.setFlags(COPSDecision.F_REQERROR);
-            decisionMsg.addDecision(install, cntxt);
-            decisionMsg.add(clientSD); // setting up the gate
-            /*
-                        try {
-                            decisionMsg.dump(System.out);
-                        } catch (IOException unae) {
-                            System.out.println("Error dumping " + unae.getMessage());
-                        }
-            */
-
-        } catch (COPSException e) {
-            logger.error("Error making Msg", e);
-        }
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData(data, 0, data.length)));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
+                decisionMap, null);
+//                new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
+        //                new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null)); TODO - what does the value of 4 mean here???
 
         // ** Send the GateSet Decision
         // **
@@ -576,20 +505,17 @@ public class PCMMPdpMsgSender {
     }
 
 
-    public boolean handleGateReport(Socket socket) throws COPSPdpException {
+    public boolean handleGateReport(final Socket socket) throws COPSPdpException {
         try {
             // waits for the gate-set-ack or error
-            COPSMsg responseMsg = COPSTransceiver.receiveMsg(socket);
-            if (responseMsg.getHeader().isAReport()) {
+            final COPSMsg responseMsg = COPSTransceiver.receiveMsg(socket);
+            if (responseMsg.getHeader().getOpCode().equals(OPCode.RPT)) {
                 logger.info("processing received report from CMTS");
-                COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
-                if (reportMsg.getClientSI().size() == 0) {
+                final COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
+                if (reportMsg.getClientSI() == null) {
                     return false;
                 }
-                COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI()
-                                        .elementAt(0);
-                IPCMMGate responseGate = new PCMMGateReq(clientSI.getData()
-                        .getData());
+                final IPCMMGate responseGate = new PCMMGateReq(reportMsg.getClientSI().getData().getData());
                 if (responseGate.getTransactionID() != null
                         && responseGate.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck) {
                     logger.info("the CMTS has sent a Gate-Set-Ack response");
@@ -611,25 +537,20 @@ public class PCMMPdpMsgSender {
     /**
      * Sends a PCMM GateSet COPS Decision message
      *
-     * @param
      * @throws COPSPdpException
      */
     public void sendGateSet() throws COPSPdpException {
         // Common Header with the same ClientType as the request
 
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
-
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
-
-        IPCMMGate gate = new PCMMGateReq();
-        ITransactionID trID = new TransactionID();
+        final IPCMMGate gate = new PCMMGateReq();
+        final ITransactionID trID = new TransactionID();
 
-        IAMID amid = new AMID();
-        ISubscriberID subscriberID = new SubscriberID();
-        IGateSpec gateSpec = new GateSpec();
-        IClassifier classifier = new Classifier();
+        final IAMID amid = new AMID();
+        final ISubscriberID subscriberID = new SubscriberID();
+        final IGateSpec gateSpec = new GateSpec();
+        final IClassifier classifier = new Classifier();
         // XXX check if other values should be provided
-        ITrafficProfile trafficProfile = new BestEffortService(
+        final ITrafficProfile trafficProfile = new BestEffortService(
             BestEffortService.DEFAULT_ENVELOP);
         ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
         .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
@@ -640,11 +561,6 @@ public class PCMMPdpMsgSender {
         .setRequestTransmissionPolicy(
             PCMMGlobalConfig.BETransmissionPolicy);
 
-        // new pcmm specific clientsi
-        COPSClientSI clientSD = new COPSClientSI((byte)CNum.DEC.ordinal(), (byte)CType.CSI.ordinal());
-
-        // Client Handle with the same clientHandle as the request
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());
         // byte[] content = "1234".getBytes();
 
         // handle.setId(new COPSData(content, 0, content.length));
@@ -689,33 +605,19 @@ public class PCMMPdpMsgSender {
         gate.setTrafficProfile(trafficProfile);
         gate.setClassifier(classifier);
 
-        byte[] data = gate.getData();
+        final byte[] data = gate.getData();
 
-        // new pcmm specific clientsi
-        clientSD.setData(new COPSData(data, 0, data.length));
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL,
+                DecisionFlag.REQERROR, new COPSData(data, 0, data.length)));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
-        try {
-            decisionMsg.add(hdr);
-            decisionMsg.add(handle);
-            // Decisions (no flags supplied)
-            // <Context>
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
-            COPSDecision install = new COPSDecision();
-            install.setCmdCode(COPSDecision.DEC_INSTALL);
-            install.setFlags(COPSDecision.F_REQERROR);
-            decisionMsg.addDecision(install, cntxt);
-            decisionMsg.add(clientSD); // setting up the gate
-            /*
-                        try {
-                            decisionMsg.dump(System.out);
-                        } catch (IOException unae) {
-                            System.out.println("Error dumping " + unae.getMessage());
-                        }
-            */
-
-        } catch (COPSException e) {
-            logger.error("Error making Msg", e);
-        }
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(),
+                new COPSHandle(getClientHandle().getId()), decisionMap, null);
+//                new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
+        //                new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null));
 
         // ** Send the GateSet Decision
         // **
@@ -741,22 +643,13 @@ public class PCMMPdpMsgSender {
          * <Decision Header> <TransactionID> <AMID> <SubscriberID> <GateID>
          */
         // Common Header with the same ClientType as the request
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
-
-        // Client Handle with the same clientHandle as the request
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
-
-        IPCMMGate gate = new PCMMGateReq();
-        ITransactionID trID = new TransactionID();
+        final IPCMMGate gate = new PCMMGateReq();
+        final ITransactionID trID = new TransactionID();
 
-        IAMID amid = new AMID();
-        ISubscriberID subscriberID = new SubscriberID();
-        IGateID gateID = new GateID();
-
-        // new pcmm specific clientsi
-        COPSClientSI clientSD = new COPSClientSI((byte)CNum.DEC.ordinal(), (byte)CType.CSI.ordinal());
-
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());
+        final IAMID amid = new AMID();
+        final ISubscriberID subscriberID = new SubscriberID();
+        final IGateSpec gateSpec = new GateSpec();
+        final IGateID gateID = new GateID();
 
         // set transaction ID to gate set
         trID.setGateCommandType(ITransactionID.GateDelete);
@@ -780,33 +673,18 @@ public class PCMMPdpMsgSender {
         gate.setGateID(gateID);
 
         // XXX - GateID
-        byte[] data = gate.getData();
+        final byte[] data = gate.getData();
 
-        // new pcmm specific clientsi
-        clientSD.setData(new COPSData(data, 0, data.length));
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
+                new COPSData(data, 0, data.length)));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
 
-        try {
-            decisionMsg.add(hdr);
-            decisionMsg.add(handle);
-            // Decisions (no flags supplied)
-            // <Context>
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
-            COPSDecision install = new COPSDecision();
-            install.setCmdCode(COPSDecision.DEC_INSTALL);
-            install.setFlags(COPSDecision.F_REQERROR);
-            decisionMsg.addDecision(install, cntxt);
-            decisionMsg.add(clientSD); // setting up the gate
-            /*
-                        try {
-                            decisionMsg.dump(System.out);
-                        } catch (IOException unae) {
-                            System.out.println("Error dumping " + unae.getMessage());
-                        }
-            */
-
-        } catch (COPSException e) {
-            logger.error("Error making Msg", e);
-        }
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(),
+                new COPSHandle(getClientHandle().getId()), decisionMap, null);
+//                new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
+        //                new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null));
 
         // ** Send the GateDelete Decision
         // **
@@ -830,29 +708,13 @@ public class PCMMPdpMsgSender {
          * <Decision: Flags> <Decision: Flags> ::= Install Request-State
          */
 
-        // Common Header with the same ClientType as the request (default
-        // UNSOLICITED)
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
-
-        // Client Handle with the same clientHandle as the request
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
-        // Decisions
-        // <Context>
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
-        // <Decision: Flags>
-        COPSDecision dec = new COPSDecision();
-        dec.setCmdCode(COPSDecision.DEC_INSTALL);
-        dec.setFlags(COPSDecision.F_REQSTATE);
-
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
-        try {
-            decisionMsg.add(hdr);
-            decisionMsg.add(clienthandle);
-            decisionMsg.addDecision(dec, cntxt);
-        } catch (COPSException e) {
-            throw new COPSPdpException("Error making Msg");
-        }
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
+                decisionMap, null);
 
         try {
             decisionMsg.writeData(_sock);
@@ -872,21 +734,7 @@ public class PCMMPdpMsgSender {
         /*
          * <Gate-Info> ::= <Common Header> [<Client Handle>] [<Integrity>]
          */
-
-        // Common Header with the same ClientType as the request
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_SSQ, getClientType());
-
-        // Client Handle with the same clientHandle as the request
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());
-
-        COPSSyncStateMsg msg = new COPSSyncStateMsg();
-        try {
-            msg.add(hdr);
-            msg.add(clienthandle);
-        } catch (Exception e) {
-            throw new COPSPdpException("Error making Msg");
-        }
-
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), new COPSHandle(_handle.getId()), null);
         try {
             msg.writeData(_sock);
         } catch (IOException e) {
@@ -907,20 +755,8 @@ public class PCMMPdpMsgSender {
          * [<Integrity>]
          */
 
-        // Common Header with the same ClientType as the request
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_SSQ, getClientType());
-
         // Client Handle with the same clientHandle as the request
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());
-
-        COPSSyncStateMsg msg = new COPSSyncStateMsg();
-        try {
-            msg.add(hdr);
-            msg.add(clienthandle);
-        } catch (Exception e) {
-            throw new COPSPdpException("Error making Msg");
-        }
-
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), new COPSHandle(_handle.getId()), null);
         try {
             msg.writeData(_sock);
         } catch (IOException e) {
index 1459c6ca62fd1f7601796c88d870a29e36c20f6b..a8ab70568e546bb171af269586329c3e3e9b4443 100644 (file)
-/**\r
- @header@\r
- */\r
-\r
-package org.pcmm;\r
-\r
-import org.pcmm.gates.ITransactionID;\r
-import org.pcmm.gates.impl.PCMMGateReq;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.prpdp.COPSPdpException;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.net.Socket;\r
-import java.util.*;\r
-\r
-/**\r
- * State manager class for provisioning requests, at the PDP side.\r
- */\r
-public class PCMMPdpReqStateMan {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);\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
-        logger.info("PCMMGateReq Parse Gate Message");\r
-        PCMMGateReq gateMsg = new PCMMGateReq(data);\r
-\r
-        // TODO - Determine why this Map is being populated but never used???\r
-        Map<String, String> repSIs = new HashMap<>();\r
-        String strobjprid = "";\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
-                logger.info("COPSPrObjBase.PR_PRID");\r
-                strobjprid = obj.getData().str();\r
-                break;\r
-            case COPSPrObjBase.PR_EPD:\r
-                logger.info("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
-                logger.error("Object s-num: " + obj.getSNum() + "stype " + obj.getSType());\r
-                logger.error("PRID: " + strobjprid);\r
-                logger.error("EPD: " + obj.getData().str());\r
-                break;\r
-            }\r
-        }\r
-\r
-        logger.info("rtypemsg process");\r
-        //** Here we must act in accordance with\r
-        //** the report received\r
-        if (rtypemsg.isSuccess()) {\r
-            logger.info("rtypemsg success");\r
-            _status = ST_REPORT;\r
-            if (_process != null)\r
-            _process.successReport(this, gateMsg);\r
-            else {\r
-                if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck ) {\r
-                    logger.info("GateDeleteAck: 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
-                    logger.info("GateSetAck: 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
-        } else if (rtypemsg.isFailure()) {\r
-            logger.info("rtypemsg failure");\r
-            _status = ST_REPORT;\r
-            if (_process != null)\r
-            _process.failReport(this, gateMsg);\r
-            else\r
-                logger.info("Gate message error - " + gateMsg.getError().toString());\r
-        } else if (rtypemsg.isAccounting()) {\r
-            logger.info("rtypemsg account");\r
-            _status = ST_ACCT;\r
-            if (_process != null)\r
-            _process.acctReport(this, gateMsg);\r
-        }\r
-        logger.info("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
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+import org.pcmm.gates.ITransactionID;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.prpdp.COPSPdpException;
+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 {
+
+    public final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
+
+    /**
+     * 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;
+
+    /**
+     * Object for performing policy data processing
+     */
+    protected PCMMPdpDataProcess _process;
+
+    /**
+     *  Current state of the request being managed
+     */
+    protected short _status;
+
+    /** COPS message transceiver used to send COPS messages */
+    protected 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);
+
+        // Initial state
+        _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;
+        */
+    }
+
+    /**
+     * Processes a report
+     * @param msg   Report message from the PEP
+     * @throws COPSPdpException
+     */
+    protected void processReport(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");
+            PCMMGateReq gateMsg = new PCMMGateReq(data);
+
+            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");
+                    strobjprid = obj.getData().str();
+                    break;
+                case COPSPrObjBase.PR_EPD:
+                    logger.info("COPSPrObjBase.PR_EPD");
+                    repSIs.put(strobjprid, obj.getData().str());
+                    // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);
+                    // COPSDebug.out(getClass().getName(),"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
+            if (rtypemsg.getReportType().equals(ReportType.SUCCESS)) {
+                logger.info("rtypemsg success");
+                _status = ST_REPORT;
+                if (_process != null)
+                    _process.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());
+                }
+            }
+            if (rtypemsg.getReportType().equals(ReportType.FAILURE)) {
+                logger.info("rtypemsg failure");
+                _status = ST_REPORT;
+                if (_process != null)
+                    _process.failReport(this, gateMsg);
+                else
+                    logger.info("Gate message error - " + gateMsg.getError().toString());
+            } 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 = ST_DEL;
+    }
+
+}
index 263a8db9aeeddd8655683bc5f121a2c774c37747..cbe268b022ac0d9e07b4c1bd808db4e35f184d7e 100644 (file)
@@ -10,6 +10,7 @@ import org.umu.cops.prpep.COPSPepAgent;
 import org.umu.cops.prpep.COPSPepConnection;
 import org.umu.cops.prpep.COPSPepException;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.net.ServerSocket;
@@ -49,7 +50,7 @@ public class PCMMPepAgent extends COPSPepAgent implements Runnable {
      * @param clientType
      *            Client-type
      */
-    public PCMMPepAgent(String pepID, short clientType) {
+    public PCMMPepAgent(final String pepID, final short clientType) {
         super(pepID, clientType);
         serverPort = WELL_KNOWN_CMTS_PORT;
     }
@@ -60,7 +61,7 @@ public class PCMMPepAgent extends COPSPepAgent implements Runnable {
      * @param clientType
      *            Client-type
      */
-    public PCMMPepAgent(short clientType) {
+    public PCMMPepAgent(final short clientType) {
         super(clientType);
         serverPort = WELL_KNOWN_CMTS_PORT;
     }
@@ -122,15 +123,8 @@ public class PCMMPepAgent extends COPSPepAgent implements Runnable {
      */
     private COPSPepConnection processConnection(Socket socket) throws IOException, COPSException, COPSPepException {
         // Build OPN
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, getClientType());
-
-        COPSPepId pepId = new COPSPepId();
-        COPSData d = new COPSData(getPepID());
-        pepId.setData(d);
-
-        COPSClientOpenMsg msg = new COPSClientOpenMsg();
-        msg.add(hdr);
-        msg.add(pepId);
+        final COPSPepId pepId = new COPSPepId(new COPSData(getPepID()));
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(getClientType(), pepId, null, null, null);
 
         // Create Socket and send OPN
         /*
@@ -144,7 +138,7 @@ public class PCMMPepAgent extends COPSPepAgent implements Runnable {
         logger.info("Receive the resposne from PDP");
         COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
 
-        if (recvmsg.getHeader().isAClientAccept()) {
+        if (recvmsg.getHeader().getOpCode().equals(OPCode.CAT)) {
             logger.info("isAClientAccept from PDP");
             COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
 
@@ -175,7 +169,7 @@ public class PCMMPepAgent extends COPSPepAgent implements Runnable {
             new Thread(conn).start();
 
             return conn;
-        } else if (recvmsg.getHeader().isAClientClose()) {
+        } else if (recvmsg.getHeader().getOpCode().equals(OPCode.CC)) {
             logger.info("isAClientClose from PDP");
             COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
             error = cMsg.getError();
index 3a7757935ebde9de4a48b1edb334ced983af360f..56af33e28449904f8a5550c7753dd9c0b41b276a 100644 (file)
@@ -3,10 +3,11 @@
  */
 package org.pcmm.messages;
 
-import java.util.Properties;
-
+import org.umu.cops.stack.COPSHeader.OPCode;
 import org.umu.cops.stack.COPSMsg;
 
+import java.util.Properties;
+
 /**
  * 
  * Factory used to create {@code COPSMsg} based on message type input and a list
@@ -22,7 +23,7 @@ public interface IMessageFactory {
      *            message type
      * @return new message.
      */
-    COPSMsg create(byte messageType);
+    COPSMsg create(OPCode messageType);
 
     /**
      * creates a new message with the specified message type and content
@@ -33,5 +34,5 @@ public interface IMessageFactory {
      *            message content.
      * @return new message.
      */
-    COPSMsg create(byte messageType, Properties properties);
+    COPSMsg create(OPCode messageType, Properties properties);
 }
index f2a48cf520c8fb268a8ed88fe07bf64b00054068..b7fcd706d379863df806244d10bc7b7c24ed68a1 100644 (file)
@@ -4,13 +4,14 @@
 package org.pcmm.messages.impl;
 
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * COPS Decision Message
@@ -21,305 +22,66 @@ import java.util.Vector;
 public class COPSDecisionMsgEX extends COPSMsg {
 
     /* COPSHeader coming from base class */
-    private COPSHandle _clientHandle;
-    private COPSError _error;
-    private Hashtable _decisions;
-    private COPSIntegrity _integrity;
-    private COPSContext _decContext;
-    private COPSClientSI clientSI;
-
-    // /
-    public COPSDecisionMsgEX() {
-        _clientHandle = null;
-        _error = null;
-        _decisions = new Hashtable(20);
-        _integrity = null;
-        _decContext = null;
-        clientSI = null;
-    }
-
-    /**
-     * Checks the sanity of COPS message and throw an COPSBadDataException when
-     * data is bad.
-     */
-    public void checkSanity() throws COPSException {
-        if ((_hdr == null) || (_clientHandle == null)
-                || ((_error == null) && (_decisions.size() == 0))) {
-            throw new COPSException("Bad message format");
-        }
-    }
-
-    // /
-    protected COPSDecisionMsgEX(byte[] data) throws COPSException {
-        _decisions = new Hashtable(20);
-        _clientHandle = null;
-        _error = null;
-        _integrity = null;
-        _decContext = null;
-        clientSI = null;
-        parse(data);
-    }
-
-    /**
-     * Parses the data and fills COPSDecisionMsg with its constituents
-     *
-     * @param data
-     *            a byte[]
-     *
-     * @throws COPSException
-     *
-     */
-    protected void parse(byte[] data) throws COPSException {
-        super.parseHeader(data);
-
-        while (_dataStart < _dataLength) {
-            byte[] buf = new byte[data.length - _dataStart];
-            System.arraycopy(data, _dataStart, buf, 0, data.length - _dataStart);
-
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);
-            switch (objHdr.getCNum()) {
-                case HANDLE:
-                    _clientHandle = new COPSHandle(buf) {
-                    };
-                    _dataStart += _clientHandle.getDataLength();
-                    break;
-                case CONTEXT:
-                    // dec context
-                    _decContext = new COPSContext(buf) {
-                    };
-                    _dataStart += _decContext.getDataLength();
-                    break;
-                case ERROR:
-                    _error = new COPSError(buf) {
-                    };
-                    _dataStart += _error.getDataLength();
-                    break;
-                case DEC:
-                    COPSDecision decs = new COPSDecision(buf) {
-                    };
-                    _dataStart += decs.getDataLength();
-                    addDecision(decs, _decContext);
-                    break;
-                case MSG_INTEGRITY:
-                    _integrity = new COPSIntegrity(buf);
-                    _dataStart += _integrity.getDataLength();
-                    break;
-                case CSI:
-                    clientSI = new COPSClientSI(buf) {
-                    };
-                    _dataStart += clientSI.getDataLength();
-                    break;
-                default:
-                    throw new COPSException(
-                        "Bad Message format, unknown object type");
-            }
-        }
-        checkSanity();
-    }
-
-    /**
-     * Parses the data and fills that follows the header hdr and fills
-     * COPSDecisionMsg
-     *
-     * @param hdr
-     *            a COPSHeader
-     * @param data
-     *            a byte[]
-     *
-     * @throws COPSException
-     *
-     */
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {
-        _hdr = hdr;
-        parse(data);
-        setMsgLength();
-    }
-
-    /**
-     * Add message header
-     *
-     * @param hdr
-     *            a COPSHeader
-     *
-     * @throws COPSException
-     *
-     */
-    public void add(COPSHeader hdr) throws COPSException {
-        if (hdr == null)
-            throw new COPSException("Null Header");
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC)
-            throw new COPSException("Error Header (no COPS_OP_DEC)");
-        _hdr = hdr;
-        setMsgLength();
-    }
-
-    /**
-     * Add client handle to the message
-     *
-     * @param handle
-     *            a COPSHandle
-     *
-     * @throws COPSException
-     *
-     */
-    public void add(COPSHandle handle) throws COPSException {
-        if (handle == null)
-            throw new COPSException("Null Handle");
-        _clientHandle = handle;
-        setMsgLength();
-    }
-
-    /**
-     * Add an Error object
-     *
-     * @param error
-     *            a COPSError
-     *
-     * @throws COPSException
-     *
-     */
-    public void add(COPSError error) throws COPSException {
-        if (_decisions.size() != 0)
-            throw new COPSException("No null decisions");
-        if (_error != null)
-            throw new COPSException("No null error");
-        // Message integrity object should be the very last one
-        // If it is already added
-        if (_integrity != null)
-            throw new COPSException("No null integrity");
-        _error = error;
-        setMsgLength();
+    private final COPSHandle _clientHandle;
+    private final COPSError _error;
+    private final COPSIntegrity _integrity;
+//    private COPSContext _decContext;
+    private final COPSClientSI clientSI;
+    private final Map<COPSContext, List<COPSDecision>> _decisions;
+
+    public COPSDecisionMsgEX(final short clientType, final COPSHandle _clientHandle, final COPSError _error,
+                             final COPSIntegrity _integrity, final COPSClientSI clientSI,
+                             final Map<COPSContext, List<COPSDecision>> _decisions) {
+        super(new COPSHeader(OPCode.DEC, clientType));
+        this._clientHandle = _clientHandle;
+        this._error = _error;
+        this._integrity = _integrity;
+        this.clientSI = clientSI;
+        this._decisions = new ConcurrentHashMap<>(_decisions);
     }
 
-    /**
-     * Add one or more local decision object for a given decision context the
-     * context is optional, if null all decision object are tided to message
-     * context
-     *
-     * @param decision
-     *            a COPSDecision
-     * @param context
-     *            a COPSContext
-     *
-     * @throws COPSException
-     *
-     */
-    public void addDecision(COPSDecision decision, COPSContext context)
-    throws COPSException {
-        // Either error or decision can be added
-        // If error is aleady there assert
-        if (_error != null)
-            throw new COPSException("No null error");
-
-        if (decision.isLocalDecision())
-            throw new COPSException("Is local decision");
+    @Override
+    protected int getDataLength() {
+        int out = 0;
+        if (_clientHandle != null) out += _clientHandle.getDataLength();
+        if (_error != null) out += _error.getDataLength();
 
-        Vector v = (Vector) _decisions.get(context);
-        if (v == null)
-            v = new Vector();
-
-        if (decision.isFlagSet()) {// Commented out as advised by Felix
-            // if (v.size() != 0)
-            // {
-            // Only one set of decision flags is allowed
-            // for each context
-            // throw new COPSException
-            // ("Bad Message format, only one set of decision flags is allowed.");
-            // }
-        } else {
-            if (v.size() == 0) {
-                // The flags decision must precede any other
-                // decision message, since the decision is not
-                // flags throw exception
-                throw new COPSException(
-                    "Bad Message format, flags decision must precede any other decision object.");
+        // Display decisions
+        // Display any local decisions
+        for (final Map.Entry<COPSContext, List<COPSDecision>> entry : _decisions.entrySet()) {
+            out += entry.getKey().getDataLength();
+            for (final COPSDecision decision : entry.getValue()) {
+                out += decision.getDataLength();
             }
         }
-        v.add(decision);
-        _decisions.put(context, v);
-
-        setMsgLength();
+        if (clientSI != null) out += clientSI.getDataLength();
+        if (_integrity != null) out += _integrity.getDataLength();
+        return out;
     }
 
-    /**
-     * Add integrity object
-     *
-     * @param integrity
-     *            a COPSIntegrity
-     *
-     * @throws COPSException
-     *
-     */
-    public void add(COPSIntegrity integrity) throws COPSException {
-        if (integrity == null)
-            throw new COPSException("Null Integrity");
-        if (!integrity.isMessageIntegrity())
-            throw new COPSException("Error Integrity");
-        _integrity = integrity;
-        setMsgLength();
-    }
-
-    /**
-     * Add a client specific informations
-     *
-     * @param clientSI
-     *            a COPSClientSI
-     *
-     * @throws COPSException
-     *
-     */
-    public void add(COPSClientSI clientSI) throws COPSException {
-        if (clientSI == null)
-            throw new COPSException("Null ClientSI");
-        this.clientSI = clientSI;
-        setMsgLength();
-    }
-
-    /**
-     * Writes data to given socket
-     *
-     * @param id
-     *            a Socket
-     *
-     * @throws IOException
-     *
-     */
-    public void writeData(Socket id) throws IOException {
-        // checkSanity();
-        if (_hdr != null)
-            _hdr.writeData(id);
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
         if (_clientHandle != null)
-            _clientHandle.writeData(id);
+            _clientHandle.writeData(socket);
         if (_error != null)
-            _error.writeData(id);
+            _error.writeData(socket);
 
         // Display decisions
         // Display any local decisions
-        for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
+        for (final Map.Entry<COPSContext, List<COPSDecision>> entry : _decisions.entrySet()) {
 
-            COPSContext context = (COPSContext) e.nextElement();
-            Vector v = (Vector) _decisions.get(context);
-            context.writeData(id);
+            final COPSContext context = entry.getKey();
+            final List<COPSDecision> decisions = entry.getValue();
+            context.writeData(socket);
 
-            for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
-                COPSDecision decision = (COPSDecision) ee.nextElement();
-                decision.writeData(id);
+            for (final COPSDecision decision : decisions) {
+                decision.writeData(socket);
             }
         }
         if (clientSI != null)
-            clientSI.writeData(id);
+            clientSI.writeData(socket);
         if (_integrity != null)
-            _integrity.writeData(id);
-    }
-
-    /**
-     * Method getHeader
-     *
-     * @return a COPSHeader
-     *
-     */
-    public COPSHeader getHeader() {
-        return _hdr;
+            _integrity.writeData(socket);
     }
 
     /**
@@ -336,117 +98,20 @@ public class COPSDecisionMsgEX extends COPSMsg {
         return clientSI;
     }
 
-    /**
-     * Returns true if it has error object
-     *
-     * @return a boolean
-     *
-     */
-    public boolean hasError() {
-        return (_error != null);
-    };
-
-    /**
-     * Should check hasError() before calling
-     *
-     * @return a COPSError
-     *
-     */
-    public COPSError getError() {
-        return _error;
-    };
-
-    /**
-     * Returns a map of decision for which is an arry of context and vector of
-     * associated decision object.
-     *
-     * @return a Hashtable
-     *
-     */
-    public Hashtable getDecisions() {
-        return _decisions;
-    };
-
-    /**
-     * Returns true if it has integrity object
-     *
-     * @return a boolean
-     *
-     */
-    public boolean hasIntegrity() {
-        return (_integrity != null);
-    };
-
-    /**
-     * Should check hasIntegrity() before calling
-     *
-     * @return a COPSIntegrity
-     *
-     */
-    public COPSIntegrity getIntegrity() {
-        return _integrity;
-    };
-
-    /**
-     * Method setMsgLength
-     *
-     * @throws COPSException
-     *
-     */
-    protected void setMsgLength() throws COPSException {
-        short len = 0;
-        if (_clientHandle != null)
-            len += _clientHandle.getDataLength();
-        if (_error != null)
-            len += _error.getDataLength();
-
-        // Display any local decisions
-        for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
-
-            COPSContext context = (COPSContext) e.nextElement();
-            Vector v = (Vector) _decisions.get(context);
-            len += context.getDataLength();
-
-            for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
-                COPSDecision decision = (COPSDecision) ee.nextElement();
-                len += decision.getDataLength();
-            }
-        }
-        if (clientSI != null)
-            len += clientSI.getDataLength();
-        if (_integrity != null) {
-            len += _integrity.getDataLength();
-        }
-
-        _hdr.setMsgLength((int) len);
-    }
-
-    /**
-     * Write an object textual description in the output stream
-     *
-     * @param os
-     *            an OutputStream
-     *
-     * @throws IOException
-     *
-     */
-    public void dump(OutputStream os) throws IOException {
-        _hdr.dump(os);
-
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
         if (_clientHandle != null)
             _clientHandle.dump(os);
         if (_error != null)
             _error.dump(os);
 
         // Display any local decisions
-        for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
-
-            COPSContext context = (COPSContext) e.nextElement();
-            Vector v = (Vector) _decisions.get(context);
+        for (final Map.Entry<COPSContext, List<COPSDecision>> entry : _decisions.entrySet()) {
+            final COPSContext context = entry.getKey();
+            final List<COPSDecision> v = entry.getValue();
             context.dump(os);
 
-            for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
-                COPSDecision decision = (COPSDecision) ee.nextElement();
+            for (final COPSDecision decision : v) {
                 decision.dump(os);
             }
         }
index fdcbeacfe2f85741b85ec6ab5e8a2c69c6e23087..ce2d60597a591438cc7d9b910b8023f39d2d8cc5 100644 (file)
@@ -11,11 +11,16 @@ import org.pcmm.rcd.IPCMMClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.*;
-import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSClientSI.CSIType;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.OPCode;
 import org.umu.cops.stack.COPSObjHeader.CType;
 
 import java.net.InetAddress;
-import java.util.Properties;
+import java.util.*;
 
 /**
  *
@@ -44,7 +49,7 @@ public class MessageFactory implements IMessageFactory {
      *
      * @see pcmm.messages.IMessageFactory#create(pcmm.messages.MessageType)
      */
-    public COPSMsg create(final byte messageType) {
+    public COPSMsg create(final OPCode messageType) {
         return create(messageType, new Properties());
     }
 
@@ -54,29 +59,29 @@ public class MessageFactory implements IMessageFactory {
      * @see org.pcmm.messages.IMessageFactory#create(org.pcmm.messages.IMessage.
      * MessageType, java.util.Properties)
      */
-    public COPSMsg create(final byte messageType, final Properties properties) {
+    public COPSMsg create(final OPCode messageType, final Properties properties) {
         logger.info("Creating message of type - " + messageType);
         // return new PCMMMessage(messageType, content);
         switch (messageType) {
-            case COPSHeader.COPS_OP_OPN:
+            case OPN:
                 return createOPNMessage(properties);
-            case COPSHeader.COPS_OP_REQ:
+            case REQ:
                 return createREQMessage(properties);
-            case COPSHeader.COPS_OP_CAT:
+            case CAT:
                 return createCATMessage(properties);
-            case COPSHeader.COPS_OP_CC:
+            case CC:
                 return createCCMessage(properties);
-            case COPSHeader.COPS_OP_DEC:
+            case DEC:
                 return createDECMessage(properties);
-            case COPSHeader.COPS_OP_DRQ:
+            case DRQ:
                 break;
-            case COPSHeader.COPS_OP_KA:
+            case KA:
                 return createKAMessage(properties);
-            case COPSHeader.COPS_OP_RPT:
+            case RPT:
                 break;
-            case COPSHeader.COPS_OP_SSC:
+            case SSC:
                 break;
-            case COPSHeader.COPS_OP_SSQ:
+            case SSQ:
                 break;
         }
         return null;
@@ -88,45 +93,52 @@ public class MessageFactory implements IMessageFactory {
      * @return - the message
      */
     protected COPSMsg createDECMessage(final Properties prop) {
-        final COPSDecisionMsg msg = new COPSDecisionMsg();
+
         // ===common part between all gate control messages
-        final COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, IPCMMClient.CLIENT_TYPE);
+        //        final COPSHeader hdr = new COPSHeader(OPCode.DEC, IPCMMClient.CLIENT_TYPE);
         // handle
         // context
-        final COPSContext context = new COPSContext(COPSContext.CONFIG, (short) 0);
         // decision
-        final COPSDecision decision = new COPSDecision();
+        // TODO - the old command and flag codes are not congruent with the ones described in COPSDecision
+        // TODO - what is the correct client type to be using here???
+/*
         if (prop.get(MessageProperties.DECISION_CMD_CODE) != null)
             decision.setCmdCode((byte) prop.get(MessageProperties.DECISION_CMD_CODE));
         if (prop.get(MessageProperties.DECISION_FLAG) != null)
             decision.setFlags((short) prop.get(MessageProperties.DECISION_FLAG));
+*/
 
-        final COPSClientSI si = new COPSClientSI((byte)CNum.DEC.ordinal(), (byte)CType.CSI.ordinal());
+        final COPSData data;
         if (prop.get(MessageProperties.GATE_CONTROL) != null)
-            si.setData((COPSData) prop.get(MessageProperties.GATE_CONTROL));
-        try {
-            msg.add(hdr);
-            final COPSHandle handle;
-            if (prop.get(MessageProperties.CLIENT_HANDLE) != null) {
-                handle = new COPSHandle(new COPSData((String) prop.get(MessageProperties.CLIENT_HANDLE)));
-            }
-            else {
-                // TODO - This smells wrong to have a null handle ID
-                handle = new COPSHandle(null);
-            }
-            msg.add(handle);
-            msg.addDecision(decision, context);
-            msg.add(si);
+            data = (COPSData) prop.get(MessageProperties.GATE_CONTROL);
+        else
+            data = null;
 
-            // TODO - determine why this block has been commented out
-            // try {
-            // msg.dump(System.out);
-            // } catch (IOException unae) {
-            // }
+        // TODO - Need to determine is SIGNALED is the correct default CSIType
+        // Decided that CSI object is not what should be encapsulated by the COPSDecisionMsg, therefore placing
+        // data into the COPSDecision object located in the decisionMap
+        //        final COPSClientSI si = new COPSClientSI(CSIType.SIGNALED, data);
 
-        } catch (final COPSException e) {
-            logger.error(e.getMessage());
+        final COPSHandle handle;
+        if (prop.get(MessageProperties.CLIENT_HANDLE) != null) {
+            handle = new COPSHandle(new COPSData((String) prop.get(MessageProperties.CLIENT_HANDLE)));
         }
+        else {
+            // TODO - This smells wrong to have a null handle ID
+            handle = new COPSHandle(null);
+        }
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.DEF, Command.NULL, DecisionFlag.NA, data));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        final COPSDecisionMsg msg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, handle, decisionMap, null);
+
+        // TODO - determine why this block has been commented out
+        // try {
+        // msg.dump(System.out);
+        // } catch (IOException unae) {
+        // }
 
         return msg;
     }
@@ -139,8 +151,6 @@ public class MessageFactory implements IMessageFactory {
      * @return COPS message
      */
     protected COPSMsg createOPNMessage(final Properties prop) {
-        final COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, IPCMMClient.CLIENT_TYPE);
-        final COPSPepId pepId = new COPSPepId();
         // version infor object
         short majorVersion = MMVersionInfo.DEFAULT_MAJOR_VERSION_INFO;
         short minorVersion = MMVersionInfo.DEFAULT_MINOR_VERSION_INFO;
@@ -149,24 +159,22 @@ public class MessageFactory implements IMessageFactory {
         if (prop.get(MessageProperties.MM_MINOR_VERSION_INFO) != null)
             minorVersion = (Short) prop.get(MessageProperties.MM_MINOR_VERSION_INFO);
         // Mandatory MM version.
-        final COPSClientSI clientSI = new COPSClientSI((byte) 1);
         byte[] versionInfo = new MMVersionInfo(majorVersion, minorVersion).getAsBinaryArray();
-        clientSI.setData(new COPSData(versionInfo, 0, versionInfo.length));
-        final COPSClientOpenMsg msg = new COPSClientOpenMsg();
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData(versionInfo, 0, versionInfo.length));
         try {
             final COPSData d;
             if (prop.get(MessageProperties.PEP_ID) != null)
                 d = new COPSData((String) prop.get(MessageProperties.PEP_ID));
             else
                 d = new COPSData(InetAddress.getLocalHost().getHostName());
-            pepId.setData(d);
-            msg.add(hdr);
-            msg.add(pepId);
-            msg.add(clientSI);
+            final COPSPepId pepId = new COPSPepId(d);
+            return new COPSClientOpenMsg(IPCMMClient.CLIENT_TYPE, pepId, clientSI, null, null);
         } catch (Exception e) {
             logger.error("Error creating OPN message", e);
         }
-        return msg;
+
+        // TODO - this probably should not return null and throw an exception instead
+        return null;
     }
 
     /**
@@ -175,29 +183,23 @@ public class MessageFactory implements IMessageFactory {
      * @return COPS message
      */
     protected COPSMsg createCATMessage(final Properties prop) {
-        final COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_CAT, IPCMMClient.CLIENT_TYPE);
+        // TODO - determine what the first constructor parameter really should be???
         final COPSKATimer katimer;
         if (prop.get(MessageProperties.KA_TIMER) != null)
-            katimer = new COPSKATimer((short) prop.get(MessageProperties.KA_TIMER));
+            katimer = new COPSKATimer((short)prop.get(MessageProperties.KA_TIMER));
         else
             katimer = new COPSKATimer(KA_TIMER_VALUE);
 
+        // TODO - determine what the first constructor parameter really should be???
         final COPSAcctTimer acctTimer;
         if (prop.get(MessageProperties.ACCEPT_TIMER) != null)
             acctTimer = new COPSAcctTimer((short) prop.get(MessageProperties.ACCEPT_TIMER));
         else
             acctTimer = new COPSAcctTimer(ACCT_TIMER_VALUE);
 
-        final COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();
-        try {
-            acceptMsg.add(hdr);
-            acceptMsg.add(katimer);
-            if (acctTimer.getTimerVal() != 0)
-                acceptMsg.add(acctTimer);
-        } catch (COPSException e) {
-            logger.error(e.getMessage());
-        }
-        return acceptMsg;
+        if (acctTimer.getTimerVal() != 0)
+            return new COPSClientAcceptMsg(IPCMMClient.CLIENT_TYPE, katimer, acctTimer, null);
+        else return new COPSClientAcceptMsg(IPCMMClient.CLIENT_TYPE, katimer, null, null);
     }
 
     /**
@@ -208,25 +210,18 @@ public class MessageFactory implements IMessageFactory {
      * @return COPS message
      */
     protected COPSMsg createCCMessage(final Properties prop) {
-        final COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, IPCMMClient.CLIENT_TYPE);
         final COPSError err;
         if (prop.get(MessageProperties.ERR_MESSAGE) != null) {
-            short code = (short) 0;
-            final short error = (short) prop.get(MessageProperties.ERR_MESSAGE);
+            ErrorTypes code = ErrorTypes.NA;
+            final ErrorTypes error = (ErrorTypes) prop.get(MessageProperties.ERR_MESSAGE);
             if (prop.get(MessageProperties.ERR_MESSAGE_SUB_CODE) != null)
-                code = (short) prop.get(MessageProperties.ERR_MESSAGE_SUB_CODE);
-            err = new COPSError(error, code);
+                code = (ErrorTypes) prop.get(MessageProperties.ERR_MESSAGE_SUB_CODE);
+            err = new COPSError(COPSError.ERROR_CODE_TO_TYPE.get(error.ordinal()),
+                    COPSError.ERROR_CODE_TO_TYPE.get(code.ordinal()));
         } else
-            err = new COPSError(COPSError.COPS_ERR_UNKNOWN, (short) 0);
+            err = new COPSError(ErrorTypes.UNKNOWN, ErrorTypes.NA);
 
-        final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
-        try {
-            closeMsg.add(cHdr);
-            closeMsg.add(err);
-        } catch (COPSException e) {
-            logger.error(e.getMessage());
-        }
-        return closeMsg;
+        return new COPSClientCloseMsg(IPCMMClient.CLIENT_TYPE, err, null, null);
     }
 
     /**
@@ -237,9 +232,6 @@ public class MessageFactory implements IMessageFactory {
      * @return Request message
      */
     protected COPSMsg createREQMessage(final Properties prop) {
-        final COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_REQ, IPCMMClient.CLIENT_TYPE);
-        final COPSReqMsg req = new COPSReqMsg();
-
         final short rType;
         if (prop.get(MessageProperties.R_TYPE) != null)
             rType = (Short) prop.get(MessageProperties.R_TYPE);
@@ -250,21 +242,15 @@ public class MessageFactory implements IMessageFactory {
             mType = (Short) prop.get(MessageProperties.M_TYPE);
         else mType = ICMTS.DEFAULT_M_TYPE;
 
-        final COPSContext copsContext = new COPSContext(rType, mType);
+        final COPSContext copsContext = new COPSContext(COPSContext.VAL_TO_RTYPE.get((int)rType), mType);
         final COPSHandle copsHandle;
         if (prop.get(MessageProperties.CLIENT_HANDLE) != null)
             copsHandle = new COPSHandle(new COPSData((String) prop.get(MessageProperties.CLIENT_HANDLE)));
         else
             // just a random handle
             copsHandle = new COPSHandle(new COPSData("" + Math.random() * 82730));
-        try {
-            req.add(cHdr);
-            req.add(copsContext);
-            req.add(copsHandle);
-        } catch (COPSException e) {
-            logger.error(e.getMessage());
-        }
-        return req;
+
+        return new COPSReqMsg(IPCMMClient.CLIENT_TYPE, copsHandle, copsContext, null, null, null, null, null);
     }
 
     /**
@@ -276,18 +262,14 @@ public class MessageFactory implements IMessageFactory {
      * TODO - Why is there a timer being instantiated but never used?
      */
     protected COPSMsg createKAMessage(final Properties prop) {
-        final COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_KA, (short) 0);
-        final COPSKAMsg kaMsg = new COPSKAMsg();
+        // TODO - determine why this isn't really doing anything
+        return new COPSKAMsg(null);
+/*
         final COPSKATimer timer;
         if (prop.get(MessageProperties.KA_TIMER) != null)
-            timer = new COPSKATimer((Short) prop.get(MessageProperties.KA_TIMER));
+            timer = new COPSKATimer((short)0, (Short) prop.get(MessageProperties.KA_TIMER));
         else
             timer = new COPSKATimer();
-        try {
-            kaMsg.add(cHdr);
-        } catch (COPSException e) {
-            logger.error(e.getMessage());
-        }
-        return kaMsg;
+*/
     }
 }
index f87677abe694b466388619c5551b9dfb2c79120c..ba0bc2c2a1f4131f74bb79ffd42f9dd1302d5da6 100644 (file)
@@ -3,20 +3,16 @@
  */
 package org.pcmm.nio;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.util.Date;
-
 import org.pcmm.PCMMProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.COPSException;
-import org.umu.cops.stack.COPSHeader;
 import org.umu.cops.stack.COPSMsg;
 import org.umu.cops.stack.COPSMsgParser;
 
+import java.io.IOException;
+import java.net.Socket;
+
 /**
  * this class provides a set of utilities to efficiently read/write data from a
  * stream, it could parameterized with a reading timeout or -1 for blocking
@@ -26,20 +22,18 @@ import org.umu.cops.stack.COPSMsgParser;
 public class PCMMChannel {
 
        private Logger logger = LoggerFactory.getLogger(getClass().getName());
-       private ByteBuffer dataBuffer;
-       private Socket socket;
+       private final Socket socket;
        private int timeout;
        public static final int DEFAULT_BYTE_BUFFER_SIZE = 2048;
        public static final int DEFAULT_READ_TIMEOUT = -1;
 
-       public PCMMChannel(Socket socket) {
+       public PCMMChannel(final Socket socket) {
                this(socket, PCMMProperties.get(PCMMProperties.DEFAULT_TIEMOUT,
                                Integer.class, DEFAULT_READ_TIMEOUT));
        }
 
-       public PCMMChannel(Socket socket, int timeout) {
+       public PCMMChannel(final Socket socket, int timeout) {
                this.socket = socket;
-               dataBuffer = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);
                logger.info("Allocated byte buffer with size = "
                                + DEFAULT_BYTE_BUFFER_SIZE);
                this.timeout = timeout;
@@ -47,96 +41,25 @@ public class PCMMChannel {
 
        }
 
-       public int readData(byte[] dataRead, int nchar) throws IOException {
-               InputStream input;
-               input = getSocket().getInputStream();
-               int nread = 0;
-               int startTime = (int) (new Date().getTime());
-               do {
-                       if (timeout == -1 || input.available() != 0) {
-                               nread += input.read(dataRead, nread, nchar - nread);
-                               startTime = (int) (new Date().getTime());
-                       } else {
-                               int nowTime = (int) (new Date().getTime());
-                               if ((nowTime - startTime) > timeout)
-                                       break;
-                       }
-               } while (nread != nchar);
-               return nread;
-       }
-
        /**
         * Method sendMsg
-        * 
-        * @param msg
-        *            a COPSMsg
-        * 
+        * @param msg - a COPSMsg
         * @throws IOException
         * @throws COPSException
-        * 
         */
-       public void sendMsg(COPSMsg msg) throws IOException, COPSException {
+       public void sendMsg(final COPSMsg msg) throws IOException, COPSException {
                logger.debug("sendMsg({})==>{}", getSocket(), msg);
-               msg.checkSanity();
                msg.writeData(getSocket());
        }
 
        /**
         * Method receiveMessage
-        * 
         * @return a COPSMsg
-        * 
         * @throws IOException
         * @throws COPSException
-        * 
         */
        public COPSMsg receiveMessage() throws IOException, COPSException {
-               int nread = 0;
-               byte[] hBuf = new byte[8];
-
-               logger.debug("receiveMessage({})", getSocket());
-
-               nread = readData(hBuf, 8);
-
-               if (nread == 0) {
-                       throw new COPSException("Error reading connection");
-               }
-
-               if (nread != 8) {
-                       throw new COPSException("Bad COPS message");
-               }
-
-               COPSHeader hdr = new COPSHeader(hBuf);
-               int dataLen = hdr.getMsgLength() - hdr.getHdrLength();
-               logger.debug("COPS Msg length :[" + dataLen + "]\n");
-               byte[] buf = new byte[dataLen + 1];
-               nread = 0;
-
-               nread = readData(buf, dataLen);
-               buf[dataLen] = (byte) '\0';
-               logger.debug("Data read length:[" + nread + "]\n");
-
-               if (nread != dataLen) {
-                       throw new COPSException("Bad COPS message");
-               }
-               COPSMsgParser prser = new COPSMsgParser();
-               COPSMsg msg = prser.parse(hdr, buf);
-               return msg;
-       }
-
-       /**
-        * @return the dataBuffer
-        */
-       public ByteBuffer getDataBuffer() {
-               return dataBuffer;
-       }
-
-       /**
-        * @param dataBuffer
-        *            the dataBuffer to set
-        */
-       public void setDataBuffer(ByteBuffer dataBuffer) {
-               this.dataBuffer = dataBuffer;
+        return COPSMsgParser.parseMessage(socket);
        }
 
        /**
@@ -146,14 +69,6 @@ public class PCMMChannel {
                return socket;
        }
 
-       /**
-        * @param socket
-        *            the socket to set
-        */
-       public void setSocket(Socket socket) {
-               this.socket = socket;
-       }
-
        /**
         * @return the timeout
         */
index d1b13413faaab35601881a150b7dbef35b004b30..4317021d76a2cd5a86a7e58d549b30c0469bfc8d 100644 (file)
@@ -4,10 +4,10 @@
 
 package org.pcmm.rcd;
 
-import java.net.InetAddress;
-
 import org.umu.cops.stack.COPSMsg;
 
+import java.net.InetAddress;
+
 /**
  * <p>
  * This is a Client Type 1, which represents existing "legacy" endpoints (e.g.,
index bac49793b5eaca1c923f690d4448c848864f3d42..f8d519e4ed43d78e82131826096c80a067de57e2 100644 (file)
@@ -3,24 +3,25 @@
  */
 package org.pcmm.rcd.impl;
 
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.concurrent.Executors;
-
 import org.pcmm.PCMMConstants;
 import org.pcmm.PCMMProperties;
 import org.pcmm.concurrent.IWorkerPool;
 import org.pcmm.concurrent.impl.WorkerPool;
-// import org.junit.Assert;
 import org.pcmm.messages.impl.MessageFactory;
 import org.pcmm.rcd.IPCMMServer;
 import org.pcmm.state.IState;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSHeader.OPCode;
 import org.umu.cops.stack.COPSMsg;
 
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.Executors;
+
+// import org.junit.Assert;
+
 /*
  * (non-Javadoc)
  *
@@ -109,7 +110,7 @@ public abstract class AbstractPCMMServer implements IPCMMServer {
         * This client is used to handle requests from within the Application
         * Manager
         * 
-        * @param socket
+        * @param socket - the connection to the PCMM server
         * @return client handler
         */
        protected abstract IPCMMClientHandler getPCMMClientHandler(Socket socket);
@@ -204,7 +205,7 @@ public abstract class AbstractPCMMServer implements IPCMMServer {
                         */
                        // if (getSocket() != null)
                        // handlersPool.remove(getSocket());
-                       COPSMsg message = MessageFactory.getInstance().create(COPSHeader.COPS_OP_CC);
+                       COPSMsg message = MessageFactory.getInstance().create(OPCode.CC);
                        sendRequest(message);
                        return super.disconnect();
                }
index fa89754a344657ac46d1a669124dc98a05f673bb..927063100a6eb485fcf6058f9c8bcc1bd0ba439c 100644 (file)
@@ -3,13 +3,6 @@
  */
 package org.pcmm.rcd.impl;
 
-import java.net.Socket;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Properties;
-import java.util.Vector;
-import java.util.concurrent.Callable;
-
 import org.pcmm.gates.IPCMMGate;
 import org.pcmm.gates.ITransactionID;
 import org.pcmm.gates.impl.PCMMGateReq;
@@ -19,20 +12,12 @@ import org.umu.cops.prpep.COPSPepConnection;
 import org.umu.cops.prpep.COPSPepDataProcess;
 import org.umu.cops.prpep.COPSPepException;
 import org.umu.cops.prpep.COPSPepReqStateMan;
-import org.umu.cops.stack.COPSAcctTimer;
-import org.umu.cops.stack.COPSClientAcceptMsg;
-import org.umu.cops.stack.COPSClientCloseMsg;
-import org.umu.cops.stack.COPSContext;
-import org.umu.cops.stack.COPSData;
-import org.umu.cops.stack.COPSDecision;
-import org.umu.cops.stack.COPSDecisionMsg;
-import org.umu.cops.stack.COPSError;
-import org.umu.cops.stack.COPSException;
-import org.umu.cops.stack.COPSHeader;
-import org.umu.cops.stack.COPSKATimer;
-import org.umu.cops.stack.COPSMsg;
-import org.umu.cops.stack.COPSPrObjBase;
-import org.umu.cops.stack.COPSReqMsg;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.net.Socket;
+import java.util.*;
+import java.util.concurrent.Callable;
 
 /**
  *
@@ -56,18 +41,18 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                        // set the major version info and minor version info to
                                        // default (5,0)
                                        logger.info("Send OPN message to the PS");
-                                       sendRequest(MessageFactory.getInstance().create(COPSHeader.COPS_OP_OPN, new Properties()));
+                                       sendRequest(MessageFactory.getInstance().create(OPCode.OPN, new Properties()));
                                        // wait for CAT
                                        COPSMsg recvMsg = readMessage();
 
-                                       if (recvMsg.getHeader().isAClientClose()) {
+                                       if (recvMsg.getHeader().getOpCode().equals(OPCode.CC)) {
                                                COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvMsg;
                                                logger.info("PS requested Client-Close" + cMsg.getError().getDescription());
                                                // send a CC message and close the socket
                                                disconnect();
                                                return;
                                        }
-                                       if (recvMsg.getHeader().isAClientAccept()) {
+                                       if (recvMsg.getHeader().getOpCode().equals(OPCode.CAT)) {
                                                logger.info("received Client-Accept from PS");
                                                COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvMsg;
                                                // Support
@@ -90,7 +75,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                                logger.info("Send a REQ message to the PS");
                                                {
                                                        Properties prop = new Properties();
-                                                       COPSMsg reqMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_REQ, prop);
+                                                       COPSMsg reqMsg = MessageFactory.getInstance().create(OPCode.REQ, prop);
                                                        handle = ((COPSReqMsg) reqMsg).getClientHandle().getId().str();
                                                        sendRequest(reqMsg);
                                                }
@@ -136,7 +121,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
 
        /* public */class PCMMCmtsConnection extends COPSPepConnection {
 
-               public PCMMCmtsConnection(short clientType, Socket sock) {
+               public PCMMCmtsConnection(final short clientType, final Socket sock) {
                        super(clientType, sock);
                }
 
@@ -154,7 +139,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
        @SuppressWarnings("rawtypes")
        class PCMMPSReqStateMan extends COPSPepReqStateMan {
 
-               public PCMMPSReqStateMan(short clientType, String clientHandle) {
+               public PCMMPSReqStateMan(final short clientType, final String clientHandle) {
                        super(clientType, clientHandle);
                        _process = new CmtsDataProcessor();
 
@@ -165,59 +150,57 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                throws COPSPepException {
 
                        // COPSHandle handle = dMsg.getClientHandle();
-                       Hashtable decisions = dMsg.getDecisions();
+                       Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
 
-                       Hashtable<String, String> removeDecs = new Hashtable<String, String>(10);
-                       Hashtable<String, String> installDecs = new Hashtable<String, String>(10);
-                       Hashtable<String, String> errorDecs = new Hashtable<String, String>(10);
-                       for (Enumeration e = decisions.keys(); e.hasMoreElements();) {
+            Map<String, String> removeDecs = new HashMap<>();
+            Map<String, String> installDecs = new HashMap<>();
+            Map<String, String> errorDecs = new HashMap<>();
 
-                               COPSContext context = (COPSContext) e.nextElement();
-                               Vector v = (Vector) decisions.get(context);
-                               Enumeration ee = v.elements();
-                               COPSDecision cmddecision = (COPSDecision) ee.nextElement();
+                       for (final Set<COPSDecision> copsDecisions : dMsg.getDecisions().values()) {
+                               final COPSDecision cmddecision = copsDecisions.iterator().next();
 
                                // cmddecision --> we must check whether it is an error!
+                String prid = "";
+                switch (cmddecision.getCommand()) {
+                    case INSTALL:
+                        for (final COPSDecision decision : copsDecisions) {
+                            COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                            switch (obj.getSNum()) {
+                                // TODO when there is install request only the PR_PRID
+                                // is git but the ClientSI object containing the PR_EPD
+                                // is null??? this is why the tests fail and so I set
+                                // the assertion to NOT true....
+                                case COPSPrObjBase.PR_PRID:
+                                    prid = obj.getData().str();
+                                    break;
+                                case COPSPrObjBase.PR_EPD:
+                                    installDecs.put(prid, obj.getData().str());
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                    case REMOVE:
+                        for (final COPSDecision decision : copsDecisions) {
+                            COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                            switch (obj.getSNum()) {
+                                // TODO when there is install request only the PR_PRID
+                                // is git but the ClientSI object containing the PR_EPD
+                                // is null??? this is why the tests fail and so I set
+                                // the assertion to NOT true....
+                                case COPSPrObjBase.PR_PRID:
+                                    prid = obj.getData().str();
+                                    break;
+                                case COPSPrObjBase.PR_EPD:
+                                    removeDecs.put(prid, obj.getData().str());
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                }
+            }
 
-                               if (cmddecision.isInstallDecision()) {
-                                       String prid = new String();
-                                       for (; ee.hasMoreElements();) {
-                                               COPSDecision decision = (COPSDecision) ee.nextElement();
-                                               COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
-                                               switch (obj.getSNum()) {
-                                               // TODO when there is install request only the PR_PRID
-                                               // is git but the ClientSI object containing the PR_EPD
-                                               // is null??? this is why the tests fail and so I set
-                                               // the assertion to NOT true....
-                                               case COPSPrObjBase.PR_PRID:
-                                                       prid = obj.getData().str();
-                                               break;
-                                               case COPSPrObjBase.PR_EPD:
-                                                       installDecs.put(prid, obj.getData().str());
-                                               break;
-                                               default:
-                                               break;
-                                               }
-                                       }
-                               }
-                               if (cmddecision.isRemoveDecision()) {
-                                       String prid = new String();
-                                       for (; ee.hasMoreElements();) {
-                                               COPSDecision decision = (COPSDecision) ee.nextElement();
-                                               COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
-                                               switch (obj.getSNum()) {
-                                               case COPSPrObjBase.PR_PRID:
-                                                       prid = obj.getData().str();
-                                               break;
-                                               case COPSPrObjBase.PR_EPD:
-                                                       removeDecs.put(prid, obj.getData().str());
-                                               break;
-                                               default:
-                                               break;
-                                               }
-                                       }
-                               }
-                       }
                        if (_process != null) {
                                // ** Apply decisions to the configuration
                                _process.setDecisions(this, removeDecs, installDecs, errorDecs);
@@ -237,20 +220,21 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
        @SuppressWarnings("rawtypes")
        class CmtsDataProcessor extends COPSPepDataProcess {
 
-               private Hashtable<String, String> removeDecs;
-               private Hashtable<String, String> installDecs;
-               private Hashtable<String, String> errorDecs;
+               private Map<String, String> removeDecs;
+               private Map<String, String> installDecs;
+               private Map<String, String> errorDecs;
                private COPSPepReqStateMan stateManager;
 
                public CmtsDataProcessor() {
-                       setRemoveDecs(new Hashtable<String, String>(10));
-                       setInstallDecs(new Hashtable<String, String>(10));
-                       setErrorDecs(new Hashtable<String, String>(10));
+                       setRemoveDecs(new HashMap<String, String>());
+                       setInstallDecs(new HashMap<String, String>());
+                       setErrorDecs(new HashMap<String, String>());
                }
 
                @SuppressWarnings("unchecked")
                @Override
-               public void setDecisions(COPSPepReqStateMan man, Hashtable removeDecs, Hashtable installDecs, Hashtable errorDecs) {
+               public void setDecisions(final COPSPepReqStateMan man, final Map<String, String> removeDecs,
+                                 final Map<String, String> installDecs, final Map<String, String> errorDecs) {
                        setRemoveDecs(removeDecs);
                        setInstallDecs(installDecs);
                        setErrorDecs(errorDecs);
@@ -263,22 +247,23 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                }
 
                @Override
-               public Hashtable getReportData(COPSPepReqStateMan man) {
+               public Map<String, String> getReportData(COPSPepReqStateMan man) {
                        if (isFailReport(man)) {
                                return errorDecs;
                        } else {
-                               ITransactionID transactionID = null;
-                               String key = null;
-                               Hashtable<String, String> siDataHashTable = new Hashtable<String, String>();
+                               Map<String, String> siDataHashTable = new HashMap<>();
                                if (installDecs.size() > 0) {
                                        String data = "";
                                        for (String k : installDecs.keySet()) {
                                                data = installDecs.get(k);
                                                break;
                                        }
-                                       transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
+                                       final ITransactionID transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
                                        IPCMMGate responseGate = new PCMMGateReq();
                                        responseGate.setTransactionID(transactionID);
+
+                    // TODO FIXME - Why is the key always null??? What value should be used here???
+                    final String key = null;
                                        siDataHashTable.put(key, new String(responseGate.getData()));
                                }
                                return siDataHashTable;
@@ -320,28 +305,28 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
 
                }
 
-               public Hashtable<String, String> getRemoveDecs() {
-                       return removeDecs;
+               public Map<String, String> getRemoveDecs() {
+                       return new HashMap<>(removeDecs);
                }
 
-               public void setRemoveDecs(Hashtable<String, String> removeDecs) {
-                       this.removeDecs = removeDecs;
+               public void setRemoveDecs(final Map<String, String> removeDecs) {
+                       this.removeDecs = new HashMap<>(removeDecs);
                }
 
-               public Hashtable<String, String> getInstallDecs() {
-                       return installDecs;
+               public Map<String, String> getInstallDecs() {
+                       return new HashMap<>(installDecs);
                }
 
-               public void setInstallDecs(Hashtable<String, String> installDecs) {
-                       this.installDecs = installDecs;
+               public void setInstallDecs(final Map<String, String> installDecs) {
+                       this.installDecs = new HashMap<>(installDecs);
                }
 
-               public Hashtable<String, String> getErrorDecs() {
+               public Map<String, String> getErrorDecs() {
                        return errorDecs;
                }
 
-               public void setErrorDecs(Hashtable<String, String> errorDecs) {
-                       this.errorDecs = errorDecs;
+               public void setErrorDecs(final Map<String, String> errorDecs) {
+                       this.errorDecs = new HashMap<>(errorDecs);
                }
 
                public COPSPepReqStateMan getStateManager() {
index 06419eaccf29b9bc84e92c6b079c072474682cbf..1b2ee2aaece391803ba7d5d8cbf0fde4aa23f5ba 100644 (file)
@@ -20,6 +20,8 @@ import org.slf4j.LoggerFactory;
 import org.umu.cops.prpdp.COPSPdpConnection;
 import org.umu.cops.prpdp.COPSPdpDataProcess;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -75,13 +77,14 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
                     logger.debug("waiting for OPN message from CMTS");
                     COPSMsg opnMessage = client.readMessage();
                     // Client-Close
-                    if (opnMessage.getHeader().isAClientClose()) {
+                    if (opnMessage.getHeader().getOpCode().equals(OPCode.CC)) {
                         COPSError error = ((COPSClientCloseMsg) opnMessage).getError();
                         logger.debug("CMTS requetsed Client-Close");
-                        throw new PCMMException(new PCMMError(error.getErrCode(), error.getErrSubCode()));
+                        throw new PCMMException(new PCMMError((short)error.getErrCode().ordinal(),
+                                (short)error.getErrSubCode().ordinal()));
                     } else // Client-Open
                     {
-                        if (opnMessage.getHeader().isAClientOpen()) {
+                        if (opnMessage.getHeader().getOpCode().equals(OPCode.OPN)) {
                             logger.debug("OPN message received from CMTS");
                             COPSClientOpenMsg opn = (COPSClientOpenMsg) opnMessage;
                             if (opn.getClientSI() == null) {
@@ -103,18 +106,19 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
                             // send CAT response
                             Properties prop = new Properties();
                             logger.debug("send CAT to the CMTS ");
-                            COPSMsg catMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_CAT, prop);
+                            COPSMsg catMsg = MessageFactory.getInstance().create(OPCode.CAT, prop);
                             client.sendRequest(catMsg);
                             // wait for REQ msg
                             COPSMsg reqMsg = client.readMessage();
                             // Client-Close
-                            if (reqMsg.getHeader().isAClientClose()) {
+                            if (reqMsg.getHeader().getOpCode().equals(OPCode.CC)) {
                                 COPSError error = ((COPSClientCloseMsg) opnMessage).getError();
                                 logger.debug("CMTS requetsed Client-Close");
-                                throw new PCMMException(new PCMMError(error.getErrCode(), error.getErrSubCode()));
+                                throw new PCMMException(new PCMMError((short)error.getErrCode().ordinal(),
+                                        (short)error.getErrSubCode().ordinal()));
                             } else // Request
                             {
-                                if (reqMsg.getHeader().isARequest()) {
+                                if (reqMsg.getHeader().getOpCode().equals(OPCode.REQ)) {
                                     logger.debug("Received REQ message form CMTS");
                                     // end connection attempts
                                     COPSReqMsg req = (COPSReqMsg) reqMsg;
@@ -208,24 +212,24 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             // configure message properties
             Properties prop = new Properties();
             prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
-            prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
-            prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+            prop.put(MessageProperties.DECISION_CMD_CODE, Command.INSTALL);
+            prop.put(MessageProperties.DECISION_FLAG, Command.NULL);
             prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
-            COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+            COPSMsg decisionMsg = MessageFactory.getInstance().create(OPCode.DEC, prop);
             // ** Send the GateSet Decision
             // **
             sendRequest(decisionMsg);
             // TODO check on this ?
             // waits for the gate-set-ack or error
             COPSMsg responseMsg = readMessage();
-            if (responseMsg.getHeader().isAReport()) {
+            if (responseMsg.getHeader().getOpCode().equals(OPCode.RPT)) {
                 logger.info("processing received report from CMTS");
                 COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
-                if (reportMsg.getClientSI().size() == 0) {
+                if (reportMsg.getClientSI() == null) {
                     logger.debug("CMTS responded with an empty SI");
                     return false;
                 }
-                COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                COPSClientSI clientSI = reportMsg.getClientSI();
                 IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
                 IPCMMError error = responseGate.getError();
                 if (error != null) {
@@ -284,11 +288,11 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             // configure message properties
             Properties prop = new Properties();
             prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
-            prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
-            prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+            prop.put(MessageProperties.DECISION_CMD_CODE, Command.INSTALL);
+            prop.put(MessageProperties.DECISION_FLAG, Command.NULL);
             byte[] data = gate.getData();
             prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
-            COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+            COPSMsg decisionMsg = MessageFactory.getInstance().create(OPCode.DEC, prop);
             // ** Send the GateSet Decision
             // **
             try {
@@ -299,13 +303,13 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             }
             // waits for the gate-delete-ack or error
             COPSMsg responseMsg = readMessage();
-            if (responseMsg.getHeader().isAReport()) {
+            if (responseMsg.getHeader().getOpCode().equals(OPCode.RPT)) {
                 logger.info("processing received report from CMTS");
                 COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
-                if (reportMsg.getClientSI().size() == 0) {
+                if (reportMsg.getClientSI() == null) {
                     return false;
                 }
-                COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                COPSClientSI clientSI = reportMsg.getClientSI();
                 IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
                 IPCMMError error = responseGate.getError();
                 if (error != null) {
@@ -365,11 +369,11 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             // configure message properties
             Properties prop = new Properties();
             prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
-            prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
-            prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+            prop.put(MessageProperties.DECISION_CMD_CODE, Command.INSTALL);
+            prop.put(MessageProperties.DECISION_FLAG, Command.NULL);
             byte[] data = gate.getData();
             prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
-            COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+            COPSMsg decisionMsg = MessageFactory.getInstance().create(OPCode.DEC, prop);
             // ** Send the GateSet Decision
             // **
             try {
@@ -380,13 +384,13 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             }
             // waits for the gate-Info-ack or error
             COPSMsg responseMsg = readMessage();
-            if (responseMsg.getHeader().isAReport()) {
+            if (responseMsg.getHeader().getOpCode().equals(OPCode.RPT)) {
                 logger.info("processing received report from CMTS");
                 COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
-                if (reportMsg.getClientSI().size() == 0) {
+                if (reportMsg.getClientSI() == null) {
                     return false;
                 }
-                COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                COPSClientSI clientSI = reportMsg.getClientSI();
                 IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
                 IPCMMError error = responseGate.getError();
                 ITransactionID responseTransactionID = responseGate.getTransactionID();
@@ -459,11 +463,11 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             // configure message properties
             Properties prop = new Properties();
             prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
-            prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
-            prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+            prop.put(MessageProperties.DECISION_CMD_CODE, Command.INSTALL);
+            prop.put(MessageProperties.DECISION_FLAG, Command.NULL);
             byte[] data = gate.getData();
             prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
-            COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+            COPSMsg decisionMsg = MessageFactory.getInstance().create(OPCode.DEC, prop);
             // ** Send the GateSet Decision
             // **
             try {
@@ -474,13 +478,13 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             }
             // waits for the gate-Info-ack or error
             COPSMsg responseMsg = readMessage();
-            if (responseMsg.getHeader().isAReport()) {
+            if (responseMsg.getHeader().getOpCode().equals(OPCode.RPT)) {
                 logger.info("processing received report from CMTS");
                 COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
-                if (reportMsg.getClientSI().size() == 0) {
+                if (reportMsg.getClientSI() == null) {
                     return false;
                 }
-                COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                COPSClientSI clientSI = reportMsg.getClientSI();
                 IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
                 IPCMMError error = responseGate.getError();
                 ITransactionID responseTransactionID = responseGate.getTransactionID();
index d701d8fd9a720cc59ab84ab8ccfe7add976a17e4..e2fa6bf514c501768b0681a554f715aad342f25a 100644 (file)
-package org.umu.cops.ospdp;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.ServerSocket;\r
-import java.net.Socket;\r
-import java.util.Map;\r
-import java.util.concurrent.ConcurrentHashMap;\r
-\r
-/**\r
- * Core PDP agent for outsourcing.\r
- */\r
-public class COPSPdpOSAgent extends Thread {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSAgent.class);\r
-\r
-    /** Well-known port for COPS */\r
-    public static final int WELL_KNOWN_PDP_PORT = 3288;\r
-    /** Default keep-alive timer value (secs) */\r
-    public static final short KA_TIMER_VALUE = 30;\r
-    /** Default accounting timer value (secs) */\r
-    public static final short ACCT_TIMER_VALUE = 0;\r
-\r
-    /**\r
-        PDP host port\r
-     */\r
-    private int _serverPort;\r
-\r
-    /**\r
-        Client-type of connecting PEP\r
-     */\r
-    private short _clientType;\r
-\r
-    /**\r
-        Accounting timer (secs)\r
-     */\r
-    private short _acctTimer;\r
-\r
-    /**\r
-        Keep-alive timer (secs)\r
-     */\r
-    private short _kaTimer;\r
-\r
-    /**\r
-        Maps a PEP-ID to a connection\r
-     */\r
-    private final Map<String, COPSPdpOSConnection> _connectionMap;\r
-    // map < String(PEPID), COPSPdpOSConnection > ConnectionMap;\r
-\r
-    /**\r
-     *  Policy data processing object\r
-     */\r
-    private COPSPdpOSDataProcess _process;\r
-\r
-    /**\r
-     * Creates a PDP Agent\r
-     *\r
-     * @param clientType    COPS Client-type\r
-     * @param process       Object to perform policy data processing\r
-     */\r
-    public COPSPdpOSAgent(short clientType, COPSPdpOSDataProcess process) {\r
-        _serverPort = WELL_KNOWN_PDP_PORT;\r
-        _kaTimer = KA_TIMER_VALUE;\r
-        _acctTimer = ACCT_TIMER_VALUE;\r
-\r
-        _clientType = clientType;\r
-        _connectionMap = new ConcurrentHashMap<>();\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Creates a PDP Agent\r
-     *\r
-     * @param port  Port to listen to\r
-     * @param clientType    COPS Client-type\r
-     * @param process   Object to perform policy data processing\r
-     */\r
-    public COPSPdpOSAgent(int port, short clientType, COPSPdpOSDataProcess process) {\r
-        _serverPort = port;\r
-\r
-        _kaTimer = KA_TIMER_VALUE;\r
-        _acctTimer = ACCT_TIMER_VALUE;\r
-\r
-        _clientType = clientType;\r
-        _connectionMap = new ConcurrentHashMap<>();\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Sets the keep-alive timer value\r
-     * @param    kaTimer    Keep alive timer value (secs)\r
-     */\r
-    public void setKaTimer (short kaTimer) {\r
-        _kaTimer = kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Sets the accounting timer value\r
-     * @param    acctTimer  Accounting timer value (secs)\r
-     */\r
-    public void setAcctTimer (short acctTimer) {\r
-        _acctTimer = acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the value of the keep-alive timer\r
-     * @return   Keep-alive timer value (secs)\r
-     */\r
-    public short getKaTimer () {\r
-        return _kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the accounting timer value\r
-     * @return   Accounting timer value (secs)\r
-     */\r
-    public short getAcctTimer () {\r
-        return _acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the client-type\r
-     * @return   The client-type\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Disconnects a PEP\r
-     * @param pepID PEP-ID of the PEP to be disconnected\r
-     * @param error COPS Error to be reported as a reason\r
-     * @throws COPSException\r
-     * @throws IOException\r
-     */\r
-    public void disconnect (String pepID, COPSError error) throws COPSException, IOException {\r
-        COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);\r
-\r
-        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
-        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-        closeMsg.add(cHdr);\r
-        if (error != null)\r
-            closeMsg.add(error);\r
-\r
-        closeMsg.writeData(pdpConn.getSocket());\r
-        pdpConn.close();\r
-    }\r
-\r
-    /**\r
-     * Requests a COPS sync for a PEP\r
-     * @param pepID PEP-ID of the PEP to be synced\r
-     * @throws COPSException\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sync(String pepID) throws COPSException, COPSPdpException {\r
-        COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);\r
-        pdpConn.syncAllRequestState();\r
-    }\r
-\r
-    /**\r
-     * Removes a PEP from the connection map\r
-     * @param pepID PEP-ID of the PEP to be removed\r
-     */\r
-    public void delete (String pepID) {\r
-        _connectionMap.remove(pepID);\r
-    }\r
-\r
-    /**\r
-     * Runs the PDP process\r
-     */\r
-    public void run() {\r
-        try {\r
-            final ServerSocket serverSocket = new ServerSocket (_serverPort);\r
-\r
-            //Loop through for Incoming messages\r
-\r
-            // server infinite loop\r
-            while (true) {\r
-                // Wait for an incoming connection from a PEP\r
-                Socket socket = serverSocket.accept();\r
-\r
-                // COPSDebug.out(getClass().getName(),"New connection accepted " +\r
-                //           socket.getInetAddress() +\r
-                //           ":" + socket.getPort());\r
-\r
-                // We're waiting for an OPN message\r
-                try {\r
-                    COPSMsg msg = COPSTransceiver.receiveMsg(socket);\r
-                    if (msg.getHeader().isAClientOpen()) {\r
-                        handleClientOpenMsg(socket, msg);\r
-                    } else {\r
-                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
-                        try {\r
-                            socket.close();\r
-                        } catch (Exception ex) {\r
-                            logger.error("Error closing socket", ex);\r
-                        }\r
-                    }\r
-                } catch (Exception e) { // COPSException, IOException\r
-                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,\r
-                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);\r
-                    try {\r
-                        socket.close();\r
-                    } catch (Exception ex) {\r
-                        logger.error("Error closing socket", ex);\r
-                    }\r
-                }\r
-            }\r
-        } catch (IOException e) {\r
-            logger.error("Error processing socket messages", e);\r
-        }\r
-    }\r
-\r
-    /**\r
-      * Handles a COPS client-open message\r
-      * @param    conn Socket to the PEP\r
-      * @param    msg <tt>COPSMsg</tt> holding the client-open message\r
-      * @throws COPSException\r
-      * @throws IOException\r
-      */\r
-    private void handleClientOpenMsg(Socket conn, COPSMsg msg) throws COPSException, IOException {\r
-        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;\r
-        COPSPepId pepId = cMsg.getPepId();\r
-\r
-        // Validate Client Type\r
-        if (msg.getHeader().getClientType() != _clientType) {\r
-            // Unsupported client type\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing data", unae);\r
-            }\r
-\r
-            throw new COPSException("Unsupported client type");\r
-        }\r
-\r
-        // PEPId is mandatory\r
-        if (pepId == null) {\r
-            // Mandatory COPS object missing\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing data", unae);\r
-            }\r
-\r
-            throw new COPSException("Mandatory COPS object missing (PEPId)");\r
-        }\r
-\r
-        // Support\r
-        if ( (cMsg.getClientSI() != null) ||\r
-                (cMsg.getPdpAddress() != null) ||\r
-                (cMsg.getIntegrity() != null)) {\r
-\r
-            // Unsupported objects\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing data", unae);\r
-            }\r
-\r
-            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");\r
-        }\r
-\r
-        // Connection accepted\r
-        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());\r
-        COPSKATimer katimer = new COPSKATimer(_kaTimer);\r
-        COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);\r
-        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();\r
-        acceptMsg.add(ahdr);\r
-        acceptMsg.add(katimer) ;\r
-        if (_acctTimer != 0) acceptMsg.add(acctTimer);\r
-        acceptMsg.writeData(conn);\r
-\r
-        COPSPdpOSConnection pdpConn = new COPSPdpOSConnection(pepId, conn, _process);\r
-        pdpConn.setKaTimer(_kaTimer);\r
-        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);\r
-        new Thread(pdpConn).start();\r
-        _connectionMap.put(pepId.getData().str(),pdpConn);\r
-    }\r
-}\r
+package org.umu.cops.ospdp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Core PDP agent for outsourcing.
+ */
+public class COPSPdpOSAgent extends Thread {
+
+    public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSAgent.class);
+
+    /** Well-known port for COPS */
+    public static final int WELL_KNOWN_PDP_PORT = 3288;
+    /** Default keep-alive timer value (secs) */
+    public static final short KA_TIMER_VALUE = 30;
+    /** Default accounting timer value (secs) */
+    public static final short ACCT_TIMER_VALUE = 0;
+
+    /**
+        PDP host port
+     */
+    private int _serverPort;
+
+    /**
+        Client-type of connecting PEP
+     */
+    private short _clientType;
+
+    /**
+        Accounting timer (secs)
+     */
+    private short _acctTimer;
+
+    /**
+        Keep-alive timer (secs)
+     */
+    private short _kaTimer;
+
+    /**
+        Maps a PEP-ID to a connection
+     */
+    private final Map<String, COPSPdpOSConnection> _connectionMap;
+    // map < String(PEPID), COPSPdpOSConnection > ConnectionMap;
+
+    /**
+     *  Policy data processing object
+     */
+    private COPSPdpOSDataProcess _process;
+
+    /**
+     * Creates a PDP Agent
+     *
+     * @param clientType    COPS Client-type
+     * @param process       Object to perform policy data processing
+     */
+    public COPSPdpOSAgent(final short clientType, final COPSPdpOSDataProcess process) {
+        _serverPort = WELL_KNOWN_PDP_PORT;
+        _kaTimer = KA_TIMER_VALUE;
+        _acctTimer = ACCT_TIMER_VALUE;
+
+        _clientType = clientType;
+        _connectionMap = new ConcurrentHashMap<>();
+        _process = process;
+    }
+
+    /**
+     * Creates a PDP Agent
+     *
+     * @param port  Port to listen to
+     * @param clientType    COPS Client-type
+     * @param process   Object to perform policy data processing
+     */
+    public COPSPdpOSAgent(final int port, final short clientType, final COPSPdpOSDataProcess process) {
+        _serverPort = port;
+
+        _kaTimer = KA_TIMER_VALUE;
+        _acctTimer = ACCT_TIMER_VALUE;
+
+        _clientType = clientType;
+        _connectionMap = new ConcurrentHashMap<>();
+        _process = process;
+    }
+
+    /**
+     * Sets the keep-alive timer value
+     * @param    kaTimer    Keep alive timer value (secs)
+     */
+    public void setKaTimer (short kaTimer) {
+        _kaTimer = kaTimer;
+    }
+
+    /**
+     * Sets the accounting timer value
+     * @param    acctTimer  Accounting timer value (secs)
+     */
+    public void setAcctTimer (short acctTimer) {
+        _acctTimer = acctTimer;
+    }
+
+    /**
+     * Gets the value of the keep-alive timer
+     * @return   Keep-alive timer value (secs)
+     */
+    public short getKaTimer () {
+        return _kaTimer;
+    }
+
+    /**
+     * Gets the accounting timer value
+     * @return   Accounting timer value (secs)
+     */
+    public short getAcctTimer () {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets the client-type
+     * @return   The client-type
+     */
+    public int getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Disconnects a PEP
+     * @param pepID PEP-ID of the PEP to be disconnected
+     * @param error COPS Error to be reported as a reason
+     * @throws COPSException
+     * @throws IOException
+     */
+    public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
+        final COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);
+        final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
+        closeMsg.writeData(pdpConn.getSocket());
+        pdpConn.close();
+    }
+
+    /**
+     * Requests a COPS sync for a PEP
+     * @param pepID PEP-ID of the PEP to be synced
+     * @throws COPSException
+     * @throws COPSPdpException
+     */
+    public void sync(String pepID) throws COPSException, COPSPdpException {
+        COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);
+        pdpConn.syncAllRequestState();
+    }
+
+    /**
+     * Removes a PEP from the connection map
+     * @param pepID PEP-ID of the PEP to be removed
+     */
+    public void delete (String pepID) {
+        _connectionMap.remove(pepID);
+    }
+
+    /**
+     * Runs the PDP process
+     */
+    public void run() {
+        try {
+            final ServerSocket serverSocket = new ServerSocket (_serverPort);
+
+            //Loop through for Incoming messages
+
+            // server infinite loop
+            while (true) {
+                // Wait for an incoming connection from a PEP
+                Socket socket = serverSocket.accept();
+
+                // COPSDebug.out(getClass().getName(),"New connection accepted " +
+                //           socket.getInetAddress() +
+                //           ":" + socket.getPort());
+
+                // We're waiting for an OPN message
+                try {
+                    COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+                    if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
+                        handleClientOpenMsg(socket, msg);
+                    } else {
+                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+                        try {
+                            socket.close();
+                        } catch (Exception ex) {
+                            logger.error("Error closing socket", ex);
+                        }
+                    }
+                } catch (Exception e) { // COPSException, IOException
+                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,
+                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);
+                    try {
+                        socket.close();
+                    } catch (Exception ex) {
+                        logger.error("Error closing socket", ex);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            logger.error("Error processing socket messages", e);
+        }
+    }
+
+    /**
+      * Handles a COPS client-open message
+      * @param    conn Socket to the PEP
+      * @param    msg <tt>COPSMsg</tt> holding the client-open message
+      * @throws COPSException
+      * @throws IOException
+      */
+    private void handleClientOpenMsg(Socket conn, COPSMsg msg) throws COPSException, IOException {
+        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
+        COPSPepId pepId = cMsg.getPepId();
+
+        // Validate Client Type
+        if (msg.getHeader().getClientType() != _clientType) {
+            // Unsupported client type
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
+                    new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Error writing data", unae);
+            }
+
+            throw new COPSException("Unsupported client type");
+        }
+
+        // PEPId is mandatory
+        if (pepId == null) {
+            // Mandatory COPS object missing
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
+                    new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Error writing data", unae);
+            }
+
+            throw new COPSException("Mandatory COPS object missing (PEPId)");
+        }
+
+        // Support
+        if ( (cMsg.getClientSI() != null) || (cMsg.getPdpAddress() != null) || (cMsg.getIntegrity() != null)) {
+
+            // Unsupported objects
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
+                    new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Error writing data", unae);
+            }
+
+            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
+        }
+
+        // Connection accepted
+        final COPSKATimer katimer = new COPSKATimer(_kaTimer);
+        final COPSClientAcceptMsg acceptMsg;
+        if (_acctTimer != 0)
+            acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, new COPSAcctTimer(_acctTimer),
+                    null);
+        else
+            acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
+
+        acceptMsg.writeData(conn);
+
+        final COPSPdpOSConnection pdpConn = new COPSPdpOSConnection(pepId, conn, _process);
+        pdpConn.setKaTimer(_kaTimer);
+        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);
+        new Thread(pdpConn).start();
+        _connectionMap.put(pepId.getData().str(),pdpConn);
+    }
+}
index 5c09b38ebbb6e1b4c3b38e2f14853464a3cbe9f5..3619572fd39043f005306ce8447056c7f2012f2e 100644 (file)
-package org.umu.cops.ospdp;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Date;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * Class for managing an outsourcing connection at the PDP side.\r
- */\r
-public class COPSPdpOSConnection implements Runnable {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSConnection.class);\r
-\r
-    /**\r
-        Socket connected to PEP\r
-     */\r
-    private Socket _sock;\r
-\r
-    /**\r
-        PEP identifier\r
-    */\r
-    private COPSPepId _pepId;\r
-\r
-    /**\r
-        Time of the latest keep-alive sent\r
-     */\r
-    private Date _lastKa;\r
-\r
-    /**\r
-        Opcode of the latest message sent\r
-    */\r
-    private byte _lastmessage;\r
-\r
-    /**\r
-     *  Time of the latest keep-alive received\r
-     */\r
-    protected Date _lastRecKa;\r
-\r
-    /**\r
-        Maps a Client Handle to a Handler\r
-     */\r
-    protected Hashtable _managerMap;\r
-    // map < String(COPSHandle), COPSPdpHandler> HandlerMap;\r
-\r
-    /**\r
-     *  PDP policy data processor class\r
-     */\r
-    protected COPSPdpOSDataProcess _process;\r
-\r
-    /**\r
-        Accounting timer value (secs)\r
-     */\r
-    protected short _acctTimer;\r
-\r
-    /**\r
-        Keep-alive timer value (secs)\r
-     */\r
-    protected short _kaTimer;\r
-\r
-    /**\r
-        COPS error returned by PEP\r
-     */\r
-    protected COPSError _error;\r
-\r
-    /**\r
-     * Creates a new PDP connection\r
-     *\r
-     * @param pepId PEP-ID of the connected PEP\r
-     * @param sock  Socket connected to PEP\r
-     * @param process   Object for processing policy data\r
-     */\r
-    public COPSPdpOSConnection(COPSPepId pepId, Socket sock, COPSPdpOSDataProcess process) {\r
-        _sock = sock;\r
-        _pepId = pepId;\r
-\r
-        _lastKa = new Date();\r
-        _lastmessage = COPSHeader.COPS_OP_OPN;\r
-        _managerMap = new Hashtable(20);\r
-\r
-        _kaTimer = 0;\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Gets the time of that latest keep-alive sent\r
-     * @return Time of that latest keep-alive sent\r
-     */\r
-    public Date getLastKAlive() {\r
-        return _lastKa;\r
-    }\r
-\r
-    /**\r
-     * Sets the keep-alive timer value\r
-     * @param kaTimer Keep-alive timer value (secs)\r
-     */\r
-    public void setKaTimer(short kaTimer) {\r
-        _kaTimer = kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the keep-alive timer value\r
-     * @return Keep-alive timer value (secs)\r
-     */\r
-    public short getKaTimer() {\r
-        return _kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Sets the accounting timer value\r
-     * @param acctTimer Accounting timer value (secs)\r
-     */\r
-    public void setAccTimer(short acctTimer) {\r
-        _acctTimer = acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the accounting timer value\r
-     * @return Accounting timer value (secs)\r
-     */\r
-    public short getAcctTimer() {\r
-        return _acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the latest COPS message\r
-     * @return   Code of the latest message sent\r
-     */\r
-    public byte getLastMessage() {\r
-        return _lastmessage;\r
-    }\r
-\r
-    /**\r
-     * Gets active handles\r
-     * @return   An <tt>Enumeration</tt> holding all active handles\r
-     */\r
-    public Enumeration getHandles() {\r
-        return _managerMap.keys();\r
-    }\r
-\r
-    /**\r
-     * Gets the handle map\r
-     * @return   A <tt>Hashtable</tt> holding the handle map\r
-     */\r
-    public Hashtable getReqStateMans() {\r
-        return _managerMap;\r
-    }\r
-\r
-    /**\r
-     * Gets the PEP-ID\r
-     * @return   The ID of the PEP, as a <tt>String</tt>\r
-     */\r
-    public String getPepId() {\r
-        return _pepId.getData().str();\r
-    }\r
-\r
-    /**\r
-     * Checks whether the socket to the PEP is closed or not\r
-     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise\r
-     */\r
-    public boolean isClosed() {\r
-        return _sock.isClosed();\r
-    }\r
-\r
-    /**\r
-     * Closes the socket to the PEP\r
-     * @throws IOException\r
-     */\r
-    protected void close()\r
-    throws IOException {\r
-        _sock.close();\r
-    }\r
-\r
-    /**\r
-     * Gets the socket to the PEP\r
-     * @return   Socket connected to the PEP\r
-     */\r
-    public Socket getSocket() {\r
-        return _sock;\r
-    }\r
-\r
-    /**\r
-     * Main loop\r
-     */\r
-    public void run () {\r
-        Date _lastSendKa = new Date();\r
-        _lastRecKa = new Date();\r
-        try {\r
-            while (!_sock.isClosed()) {\r
-                if (_sock.getInputStream().available() != 0) {\r
-                    _lastmessage = processMessage(_sock);\r
-                    _lastRecKa = new Date();\r
-                }\r
-\r
-                // Keep Alive\r
-                if (_kaTimer > 0) {\r
-                    // Timeout at PDP\r
-                    int _startTime = (int) (_lastRecKa.getTime());\r
-                    int cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > _kaTimer*1000) {\r
-                        _sock.close();\r
-                        // Notify all Request State Managers\r
-                        notifyNoKAAllReqStateMan();\r
-                    }\r
-\r
-                    // Send to PEP\r
-                    _startTime = (int) (_lastSendKa.getTime());\r
-                    cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {\r
-                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
-                        COPSKAMsg msg = new COPSKAMsg();\r
-\r
-                        msg.add(hdr);\r
-\r
-                        COPSTransceiver.sendMsg(msg, _sock);\r
-                        _lastSendKa = new Date();\r
-                    }\r
-                }\r
-\r
-                try {\r
-                    Thread.sleep(500);\r
-                } catch (Exception e) {\r
-                    logger.error("Exception caught while sleeping", e);\r
-                }\r
-\r
-            }\r
-        } catch (Exception e) {\r
-            logger.error("Error processing COPS message from socket", e);\r
-        }\r
-\r
-        // connection closed by server\r
-        // COPSDebug.out(getClass().getName(),"Connection closed by client");\r
-        try {\r
-            _sock.close();\r
-        } catch (IOException e) {\r
-            logger.error("Error closing socket", e);\r
-        }\r
-\r
-        // Notify all Request State Managers\r
-        try {\r
-            notifyCloseAllReqStateMan();\r
-        } catch (COPSPdpException e) {\r
-            logger.error("Error closing state managers", e);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Gets a COPS message from the socket and processes it\r
-     * @param    conn Socket connected to the PEP\r
-     * @return Type of COPS message\r
-     */\r
-    private byte processMessage(Socket conn)\r
-    throws COPSPdpException, COPSException, IOException {\r
-        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
-\r
-        if (msg.getHeader().isAClientClose()) {\r
-            handleClientCloseMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_CC;\r
-        } else if (msg.getHeader().isAKeepAlive()) {\r
-            handleKeepAliveMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_KA;\r
-        } else if (msg.getHeader().isARequest()) {\r
-            handleRequestMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_REQ;\r
-        } else if (msg.getHeader().isAReport()) {\r
-            handleReportMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_RPT;\r
-        } else if (msg.getHeader().isADeleteReq()) {\r
-            handleDeleteRequestMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_DRQ;\r
-        } else if (msg.getHeader().isASyncComplete()) {\r
-            handleSyncComplete(conn, msg);\r
-            return COPSHeader.COPS_OP_SSC;\r
-        } else {\r
-            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handle Client Close Message, close the passed connection\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     *\r
-     * <Client-Close> ::= <Common Header>\r
-     *                      <Error>\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     */\r
-    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
-        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
-        _error = cMsg.getError();\r
-\r
-        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
-\r
-        try {\r
-            // Support\r
-            if (cMsg.getIntegrity() != null) {\r
-                logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-            }\r
-\r
-            conn.close();\r
-        } catch (Exception unae) {\r
-            logger.error("Unexpected exception while closing the connection", unae);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Gets the occurred COPS Error\r
-     * @return   <tt>COPSError</tt> object\r
-     */\r
-    protected COPSError getError()  {\r
-        return _error;\r
-    }\r
-\r
-    /**\r
-     * Handle Keep Alive Message\r
-     *\r
-     * <Keep-Alive> ::= <Common Header>\r
-     *                  [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
-        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
-\r
-        COPSKAMsg kaMsg = (COPSKAMsg) msg;\r
-        try {\r
-            // Support\r
-            if (cMsg.getIntegrity() != null) {\r
-                logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-            }\r
-\r
-            kaMsg.writeData(conn);\r
-        } catch (Exception unae) {\r
-            logger.error("Unexpected exception writing COPS data", unae);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handle Delete Request Message\r
-     *\r
-     * <Delete Request> ::= <Common Header>\r
-     *                      <Client Handle>\r
-     *                      <Reason>\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)\r
-    throws COPSPdpException {\r
-        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;\r
-        // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +\r
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");\r
-\r
-        // Support\r
-        if (cMsg.getIntegrity() != null) {\r
-            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        // Delete clientHandler\r
-        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {\r
-            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +\r
-            //  cMsg.getClientHandle().getId().getData());\r
-        }\r
-\r
-        COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());\r
-        } else {\r
-            man.processDeleteRequestState(cMsg);\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * Handle Request Message\r
-     *\r
-     * <Request> ::= <Common Header>\r
-     *                  <Client Handle>\r
-     *                  <Context>\r
-     *                  *(<Named ClientSI>)\r
-     *                  [<Integrity>]\r
-     * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {\r
-        COPSReqMsg reqMsg = (COPSReqMsg) msg;\r
-        COPSContext cntxt = reqMsg.getContext();\r
-        COPSHeader header = reqMsg.getHeader();\r
-        //short reqType = cntxt.getRequestType();\r
-        short cType   = header.getClientType();\r
-\r
-        // Support\r
-        if (reqMsg.getIntegrity() != null) {\r
-            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        COPSPdpOSReqStateMan man;\r
-        man = (COPSPdpOSReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle().getId().str());\r
-            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);\r
-            man.setDataProcess(_process);\r
-            man.initRequestState(_sock);\r
-\r
-            // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +\r
-            //    header.getClientType() + " msgType=" +\r
-            //    cntxt.getMessageType() + ", connId=" + conn.toString());\r
-        }\r
-\r
-        man.processRequest(reqMsg);\r
-    }\r
-\r
-    /**\r
-     * Handle Report Message\r
-     *\r
-     * <Report State> ::= <Common Header>\r
-     *                      <Client Handle>\r
-     *                      <Report Type>\r
-     *                      *(<Named ClientSI>)\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleReportMsg(Socket conn, COPSMsg msg) throws COPSPdpException {\r
-        COPSReportMsg repMsg = (COPSReportMsg) msg;\r
-        // COPSHandle handle = repMsg.getClientHandle();\r
-        // COPSHeader header = repMsg.getHeader();\r
-\r
-        // Support\r
-        if (repMsg.getIntegrity() != null) {\r
-            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            logger.warn("State manager not found for ID - " + repMsg.getClientHandle().getId().str());\r
-        } else {\r
-            man.processReport(repMsg);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Method handleSyncComplete\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleSyncComplete(Socket conn, COPSMsg msg)\r
-    throws COPSPdpException {\r
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
-        // COPSHandle handle = cMsg.getClientHandle();\r
-        // COPSHeader header = cMsg.getHeader();\r
-\r
-        // Support\r
-        if (cMsg.getIntegrity() != null) {\r
-            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());\r
-        } else {\r
-            man.processSyncComplete(cMsg);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Requests a COPS sync from the PEP\r
-     * @throws COPSException\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void syncAllRequestState()\r
-    throws COPSException, COPSPdpException {\r
-        if (_managerMap.size() > 0) {\r
-            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
-                String handle = (String) e.nextElement();\r
-                COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);\r
-\r
-                man.syncRequestState();\r
-            }\r
-        }\r
-    }\r
-\r
-    private void notifyCloseAllReqStateMan()\r
-    throws COPSPdpException {\r
-        if (_managerMap.size() > 0) {\r
-            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
-                String handle = (String) e.nextElement();\r
-                COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);\r
-\r
-                man.processClosedConnection(_error);\r
-            }\r
-        }\r
-    }\r
-\r
-    private void notifyNoKAAllReqStateMan()\r
-    throws COPSPdpException {\r
-        if (_managerMap.size() > 0) {\r
-            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
-                String handle = (String) e.nextElement();\r
-                COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);\r
-\r
-                man.processNoKAConnection();\r
-            }\r
-        }\r
-    }\r
-\r
-}\r
+package org.umu.cops.ospdp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Class for managing an outsourcing connection at the PDP side.
+ */
+public class COPSPdpOSConnection implements Runnable {
+
+    public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSConnection.class);
+
+    /**
+        Socket connected to PEP
+     */
+    private Socket _sock;
+
+    /**
+        PEP identifier
+    */
+    private COPSPepId _pepId;
+
+    /**
+        Time of the latest keep-alive sent
+     */
+    private Date _lastKa;
+
+    /**
+     *  Time of the latest keep-alive received
+     */
+    protected Date _lastRecKa;
+
+    /**
+        Maps a Client Handle to a Handler
+     */
+    protected final Map<String, COPSPdpOSReqStateMan> _managerMap;
+
+    /**
+     *  PDP policy data processor class
+     */
+    protected COPSPdpOSDataProcess _process;
+
+    /**
+        Accounting timer value (secs)
+     */
+    protected short _acctTimer;
+
+    /**
+        Keep-alive timer value (secs)
+     */
+    protected short _kaTimer;
+
+    /**
+        COPS error returned by PEP
+     */
+    protected COPSError _error;
+
+    /**
+     * Creates a new PDP connection
+     *
+     * @param pepId PEP-ID of the connected PEP
+     * @param sock  Socket connected to PEP
+     * @param process   Object for processing policy data
+     */
+    public COPSPdpOSConnection(COPSPepId pepId, Socket sock, COPSPdpOSDataProcess process) {
+        _sock = sock;
+        _pepId = pepId;
+
+        _lastKa = new Date();
+        _managerMap = new ConcurrentHashMap<>();
+
+        _kaTimer = 0;
+        _process = process;
+    }
+
+    /**
+     * Gets the time of that latest keep-alive sent
+     * @return Time of that latest keep-alive sent
+     */
+    public Date getLastKAlive() {
+        return _lastKa;
+    }
+
+    /**
+     * Sets the keep-alive timer value
+     * @param kaTimer Keep-alive timer value (secs)
+     */
+    public void setKaTimer(short kaTimer) {
+        _kaTimer = kaTimer;
+    }
+
+    /**
+     * Gets the keep-alive timer value
+     * @return Keep-alive timer value (secs)
+     */
+    public short getKaTimer() {
+        return _kaTimer;
+    }
+
+    /**
+     * Sets the accounting timer value
+     * @param acctTimer Accounting timer value (secs)
+     */
+    public void setAccTimer(short acctTimer) {
+        _acctTimer = acctTimer;
+    }
+
+    /**
+     * Gets the accounting timer value
+     * @return Accounting timer value (secs)
+     */
+    public short getAcctTimer() {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets the PEP-ID
+     * @return   The ID of the PEP, as a <tt>String</tt>
+     */
+    public String getPepId() {
+        return _pepId.getData().str();
+    }
+
+    /**
+     * Checks whether the socket to the PEP is closed or not
+     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise
+     */
+    public boolean isClosed() {
+        return _sock.isClosed();
+    }
+
+    /**
+     * Closes the socket to the PEP
+     * @throws IOException
+     */
+    protected void close()
+    throws IOException {
+        _sock.close();
+    }
+
+    /**
+     * Gets the socket to the PEP
+     * @return   Socket connected to the PEP
+     */
+    public Socket getSocket() {
+        return _sock;
+    }
+
+    /**
+     * Main loop
+     */
+    public void run() {
+        Date _lastSendKa = new Date();
+        _lastRecKa = new Date();
+        try {
+            while (!_sock.isClosed()) {
+                if (_sock.getInputStream().available() != 0) {
+//                    _lastmessage = processMessage(_sock);
+                    processMessage(_sock);
+                    _lastRecKa = new Date();
+                }
+
+                // Keep Alive
+                if (_kaTimer > 0) {
+                    // Timeout at PDP
+                    int _startTime = (int) (_lastRecKa.getTime());
+                    int cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > _kaTimer*1000) {
+                        _sock.close();
+                        // Notify all Request State Managers
+                        notifyNoKAAllReqStateMan();
+                    }
+
+                    // Send to PEP
+                    _startTime = (int) (_lastSendKa.getTime());
+                    cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
+                        // TODO - is 0 ok for a clientType here???
+                        final COPSKAMsg msg = new COPSKAMsg(null);
+                        COPSTransceiver.sendMsg(msg, _sock);
+                        _lastSendKa = new Date();
+                    }
+                }
+
+                try {
+                    Thread.sleep(500);
+                } catch (Exception e) {
+                    logger.error("Exception caught while sleeping", e);
+                }
+
+            }
+        } catch (Exception e) {
+            logger.error("Error processing COPS message from socket", e);
+        }
+
+        // connection closed by server
+        // COPSDebug.out(getClass().getName(),"Connection closed by client");
+        try {
+            _sock.close();
+        } catch (IOException e) {
+            logger.error("Error closing socket", e);
+        }
+
+        // Notify all Request State Managers
+        try {
+            notifyCloseAllReqStateMan();
+        } catch (COPSPdpException e) {
+            logger.error("Error closing state managers", e);
+        }
+    }
+
+    /**
+     * Gets a COPS message from the socket and processes it
+     * @param    conn Socket connected to the PEP
+     */
+    private void processMessage(Socket conn) throws COPSPdpException, COPSException, IOException {
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+
+        if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
+            handleClientCloseMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
+            handleKeepAliveMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
+            handleRequestMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
+            handleReportMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
+            handleDeleteRequestMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.SSC)) {
+            handleSyncComplete(conn, msg);
+        } else {
+            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+        }
+    }
+
+    /**
+     * Handle Client Close Message, close the passed connection
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     *
+     * <Client-Close> ::= <Common Header>
+     *                      <Error>
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     */
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+        _error = cMsg.getError();
+
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
+
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            }
+
+            conn.close();
+        } catch (Exception unae) {
+            logger.error("Unexpected exception while closing the connection", unae);
+        }
+    }
+
+    /**
+     * Gets the occurred COPS Error
+     * @return   <tt>COPSError</tt> object
+     */
+    protected COPSError getError()  {
+        return _error;
+    }
+
+    /**
+     * Handle Keep Alive Message
+     *
+     * <Keep-Alive> ::= <Common Header>
+     *                  [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
+        COPSKAMsg cMsg = (COPSKAMsg) msg;
+
+        COPSKAMsg kaMsg = (COPSKAMsg) msg;
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            }
+
+            kaMsg.writeData(conn);
+        } catch (Exception unae) {
+            logger.error("Unexpected exception writing COPS data", unae);
+        }
+    }
+
+    /**
+     * Handle Delete Request Message
+     *
+     * <Delete Request> ::= <Common Header>
+     *                      <Client Handle>
+     *                      <Reason>
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
+    throws COPSPdpException {
+        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
+        // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
+
+        // Support
+        if (cMsg.getIntegrity() != null) {
+            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        // Delete clientHandler
+        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
+            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
+            //  cMsg.getClientHandle().getId().getData());
+        }
+
+        final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
+        if (man == null) {
+            logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
+        } else {
+            man.processDeleteRequestState(cMsg);
+        }
+
+    }
+
+    /**
+     * Handle Request Message
+     *
+     * <Request> ::= <Common Header>
+     *                  <Client Handle>
+     *                  <Context>
+     *                  *(<Named ClientSI>)
+     *                  [<Integrity>]
+     * <Named ClientSI> ::= <*(<PRID> <EPD>)>
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
+        final COPSReqMsg reqMsg = (COPSReqMsg) msg;
+        final COPSHeader header = reqMsg.getHeader();
+        final short cType = header.getClientType();
+
+        // Support
+        if (reqMsg.getIntegrity() != null) {
+            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        final COPSPdpOSReqStateMan man;
+        if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
+            man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle().getId().str());
+            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
+            man.setDataProcess(_process);
+            man.initRequestState(_sock);
+        } else {
+            man = _managerMap.get(reqMsg.getClientHandle().getId().str());
+        }
+        man.processRequest(reqMsg);
+    }
+
+    /**
+     * Handle Report Message
+     *
+     * <Report State> ::= <Common Header>
+     *                      <Client Handle>
+     *                      <Report Type>
+     *                      *(<Named ClientSI>)
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleReportMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
+        COPSReportMsg repMsg = (COPSReportMsg) msg;
+        // COPSHandle handle = repMsg.getClientHandle();
+        // COPSHeader header = repMsg.getHeader();
+
+        // Support
+        if (repMsg.getIntegrity() != null) {
+            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        COPSPdpOSReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
+        if (man == null) {
+            logger.warn("State manager not found for ID - " + repMsg.getClientHandle().getId().str());
+        } else {
+            man.processReport(repMsg);
+        }
+    }
+
+    /**
+     * Method handleSyncComplete
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleSyncComplete(Socket conn, COPSMsg msg) throws COPSPdpException {
+        final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
+
+        // Support
+        if (cMsg.getIntegrity() != null) {
+            logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
+        if (man == null) {
+            logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
+        } else {
+            man.processSyncComplete(cMsg);
+        }
+    }
+
+    /**
+     * Requests a COPS sync from the PEP
+     * @throws COPSException
+     * @throws COPSPdpException
+     */
+    protected void syncAllRequestState() throws COPSException, COPSPdpException {
+        for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
+            man.syncRequestState();
+        }
+    }
+
+    private void notifyCloseAllReqStateMan() throws COPSPdpException {
+        for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
+            man.processClosedConnection(_error);
+        }
+    }
+
+    private void notifyNoKAAllReqStateMan() throws COPSPdpException {
+        for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
+            man.processNoKAConnection();
+        }
+    }
+
+}
index 4a5e438554b41adf81b579ff9f1ada42a69b9573..c45c7cbf75cb7decd04d6a556f59fa461e6df724 100644 (file)
@@ -1,78 +1,79 @@
-package org.umu.cops.ospdp;\r
-\r
-import java.util.Vector;\r
-\r
-import org.umu.cops.stack.COPSError;\r
-\r
-/**\r
- * Abstract class for implementing policy data processing classes for outsourcing PDPs.\r
- */\r
-abstract public class COPSPdpOSDataProcess {\r
-    /**\r
-     * Gets the policies to be uninstalled\r
-     * @param man   The associated request state manager\r
-     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
-     */\r
-    abstract public Vector getRemovePolicy(COPSPdpOSReqStateMan man);\r
-    /**\r
-     * Gets the policies to be installed\r
-     * @param man   The associated request state manager\r
-     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
-     */\r
-    abstract public Vector getInstallPolicy(COPSPdpOSReqStateMan man);\r
-    /**\r
-     * Makes a decision from the supplied request data\r
-     * @param man   The associated request state manager\r
-     * @param reqSIs    Client specific data suppplied in the COPS request\r
-     */\r
-    abstract public void setClientData(COPSPdpOSReqStateMan man, Vector reqSIs);\r
-    /**\r
-     * Builds a failure report\r
-     * @param man   The associated request state manager\r
-     * @param reportSIs Report data\r
-     */\r
-    abstract public void failReport (COPSPdpOSReqStateMan man, Vector reportSIs);\r
-    /**\r
-     * Builds a success report\r
-     * @param man   The associated request state manager\r
-     * @param reportSIs Report data\r
-     */\r
-    abstract public void successReport (COPSPdpOSReqStateMan man, Vector reportSIs);\r
-    /**\r
-     * Builds an accounting report\r
-     * @param man   The associated request state manager\r
-     * @param reportSIs Report data\r
-     */\r
-    abstract public void acctReport (COPSPdpOSReqStateMan man, Vector reportSIs);\r
-    /**\r
-     * Notifies that no accounting report has been received\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void notifyNoAcctReport (COPSPdpOSReqStateMan man);\r
-\r
-    /**\r
-     * Notifies a keep-alive timeout\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void notifyNoKAliveReceived (COPSPdpOSReqStateMan man);\r
-\r
-    /**\r
-      * Notifies that the connection has been closed\r
-      * @param man  The associated request state manager\r
-      * @param error Reason\r
-      */\r
-    public abstract void notifyClosedConnection (COPSPdpOSReqStateMan man, COPSError error);\r
-\r
-    /**\r
-     * Notifies that a request state has been deleted\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void notifyDeleteRequestState (COPSPdpOSReqStateMan man);\r
-\r
-    /**\r
-     * Notifies that a request state has been closed\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void closeRequestState(COPSPdpOSReqStateMan man);\r
-\r
-}\r
+package org.umu.cops.ospdp;
+
+import org.umu.cops.stack.COPSClientSI;
+import org.umu.cops.stack.COPSError;
+
+import java.util.Vector;
+
+/**
+ * Abstract class for implementing policy data processing classes for outsourcing PDPs.
+ */
+public interface COPSPdpOSDataProcess {
+    /**
+     * Gets the policies to be uninstalled
+     * @param man   The associated request state manager
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled
+     */
+    public Vector getRemovePolicy(COPSPdpOSReqStateMan man);
+    /**
+     * Gets the policies to be installed
+     * @param man   The associated request state manager
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled
+     */
+    public Vector getInstallPolicy(COPSPdpOSReqStateMan man);
+    /**
+     * Makes a decision from the supplied request data
+     * @param man   The associated request state manager
+     * @param reqSIs    Client specific data suppplied in the COPS request
+     */
+    public void setClientData(COPSPdpOSReqStateMan man, COPSClientSI... reqSIs);
+    /**
+     * Builds a failure report
+     * @param man   The associated request state manager
+     * @param reportSIs Report data
+     */
+    public void failReport (COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+    /**
+     * Builds a success report
+     * @param man   The associated request state manager
+     * @param reportSIs Report data
+     */
+    public void successReport (COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+    /**
+     * Builds an accounting report
+     * @param man   The associated request state manager
+     * @param reportSIs Report data
+     */
+    public void acctReport (COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+    /**
+     * Notifies that no accounting report has been received
+     * @param man   The associated request state manager
+     */
+    abstract void notifyNoAcctReport (COPSPdpOSReqStateMan man);
+
+    /**
+     * Notifies a keep-alive timeout
+     * @param man   The associated request state manager
+     */
+    abstract void notifyNoKAliveReceived (COPSPdpOSReqStateMan man);
+
+    /**
+      * Notifies that the connection has been closed
+      * @param man  The associated request state manager
+      * @param error Reason
+      */
+    abstract void notifyClosedConnection (COPSPdpOSReqStateMan man, COPSError error);
+
+    /**
+     * Notifies that a request state has been deleted
+     * @param man   The associated request state manager
+     */
+    abstract void notifyDeleteRequestState (COPSPdpOSReqStateMan man);
+
+    /**
+     * Notifies that a request state has been closed
+     * @param man   The associated request state manager
+     */
+    abstract void closeRequestState(COPSPdpOSReqStateMan man);
+
+}
index 25cacd609dbbf9b7fba45573396f528cb28d3ec9..e469e4fa06ece6e5d81b65cc4de10810ea3a7d49 100644 (file)
-package org.umu.cops.ospdp;\r
-\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Vector;\r
-\r
-/**\r
- * COPS message transceiver class for outsourcing connections at the PDP side.\r
- *\r
- * TODO - change all references of Vector to List<>\r
- */\r
-public class COPSPdpOSMsgSender {\r
-    /**\r
-     * Socket connected to PEP\r
-     */\r
-    protected Socket _sock;\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
-     * Creates a COPSPepMsgSender\r
-     *\r
-     * @param clientType        COPS client-type\r
-     * @param clientHandle      Client handle\r
-     * @param sock              Socket to the PEP\r
-     */\r
-    public COPSPdpOSMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
-        // COPS Handle\r
-        _handle = clientHandle;\r
-        _clientType = clientType;\r
-\r
-        _sock = sock;\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
-     * Sends a decision message which was requested by the PEP\r
-     * @param removeDecs    Decisions to be removed\r
-     * @param installDecs   Decisions to be installed\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendSolicitedDecision(Vector removeDecs, Vector installDecs) throws COPSPdpException {\r
-        sendDecision(removeDecs, installDecs, true);\r
-    }\r
-\r
-    /**\r
-     * Sends a decision message which was not requested by the PEP\r
-     * @param removeDecs    Decisions to be removed\r
-     * @param installDecs   Decisions to be installed\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendUnsolicitedDecision(Vector removeDecs, Vector installDecs) throws COPSPdpException {\r
-        sendDecision(removeDecs, installDecs, false);\r
-    }\r
-\r
-    /**\r
-     * Sends a decision message to the PEP\r
-     * @param removeDecs    Decisions to be removed\r
-     * @param installDecs   Decisions to be installed\r
-     * @param solicited     <tt>true</tt> if the PEP requested this decision, <tt>false</tt> otherwise\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendDecision(Vector removeDecs, Vector installDecs, boolean solicited) throws COPSPdpException {\r
-        // Common Header holding the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-\r
-        if (solicited)\r
-            hdr.setFlag(COPSHeader.COPS_FLAG_SOLICITED);\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(handle);\r
-\r
-            // Decisions (no flags supplied)\r
-            //  <Context>\r
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-\r
-            // Remove Decisions\r
-            //  <Decision: Flags>\r
-            if (removeDecs.size() > 0) {\r
-                COPSDecision rdec1 = new COPSDecision();\r
-                rdec1.setCmdCode(COPSDecision.DEC_REMOVE);\r
-\r
-                decisionMsg.addDecision(rdec1, cntxt);\r
-\r
-                Enumeration removeDecsEnum = removeDecs.elements();\r
-                while (removeDecsEnum.hasMoreElements())\r
-                    decisionMsg.addDecision((COPSDecision) removeDecsEnum.nextElement(), cntxt);\r
-            }\r
-\r
-            // Install Decisions\r
-            //  <Decision: Flags>\r
-            if (installDecs.size() > 0) {\r
-                COPSDecision idec1 = new COPSDecision();\r
-                idec1.setCmdCode(COPSDecision.DEC_INSTALL);\r
-\r
-                decisionMsg.addDecision(idec1, cntxt);\r
-\r
-                Enumeration installDecsEnum = installDecs.elements();\r
-                while (installDecsEnum.hasMoreElements())\r
-                    decisionMsg.addDecision((COPSDecision) installDecsEnum.nextElement(), cntxt);\r
-                /**\r
-                COPSIntegrity intr = new COPSIntegrity();\r
-                intr.setKeyId(19);\r
-                intr.setSeqNum(9);\r
-                intr.setKeyDigest(new COPSData("KEY DIGEST"));\r
-                decisionMsg.add(intr);\r
-                /**/\r
-            }\r
-        } catch (COPSException e) {\r
-            e.printStackTrace();\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        //** Send decision\r
-        //**\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**FIXME: unused?\r
-     * Sends a message asking that the request state be deleted\r
-     * @throws   COPSPdpException\r
-     */\r
-    public void sendDeleteRequestState() throws COPSPdpException {\r
-        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
-         *                          <Client Handle>\r
-         *                          *(<Decision>)\r
-         *                          [<Integrity>]\r
-         * <Decision> ::= <Context>\r
-         *                  <Decision: Flags>\r
-         * <Decision: Flags> ::= Remove Request-State\r
-         *\r
-        */\r
-\r
-        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());\r
-\r
-        // Decisions\r
-        //  <Context>\r
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-        //  <Decision: Flags>\r
-        COPSDecision dec = new COPSDecision();\r
-        dec.setCmdCode(COPSDecision.DEC_REMOVE);\r
-        dec.setFlags(COPSDecision.F_REQSTATE);\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(clienthandle);\r
-            decisionMsg.addDecision(dec, cntxt);\r
-        } catch (COPSException e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Method sendOpenNewRequestState\r
-     *\r
-     * @throws   COPSPdpException\r
-     *\r
-     */\r
-    //FIXME: Unused?\r
-    public void sendOpenNewRequestState() throws COPSPdpException {\r
-        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
-         *                          <Client Handle>\r
-         *                          *(<Decision>)\r
-         *                          [<Integrity>]\r
-         * <Decision> ::= <Context>\r
-         *                  <Decision: Flags>\r
-         * <Decision: Flags> ::= Install Request-State\r
-         *\r
-        */\r
-\r
-        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());\r
-\r
-        // Decisions\r
-        //  <Context>\r
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-        //  <Decision: Flags>\r
-        COPSDecision dec = new COPSDecision();\r
-        dec.setCmdCode(COPSDecision.DEC_INSTALL);\r
-        dec.setFlags(COPSDecision.F_REQSTATE);\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(clienthandle);\r
-            decisionMsg.addDecision(dec, cntxt);\r
-        } catch (COPSException e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a message asking for a COPS sync operation\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendSyncRequestState()\r
-    throws COPSPdpException {\r
-        /* <Synchronize State Request>  ::= <Common Header>\r
-         *                                  [<Client Handle>]\r
-         *                                  [<Integrity>]\r
-         */\r
-\r
-        // Common Header with the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSQ, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());\r
-\r
-        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
-        try {\r
-            msg.add(hdr);\r
-            msg.add(clienthandle);\r
-        } catch (Exception e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-}\r
+package org.umu.cops.ospdp;
+
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSHeader.Flag;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.*;
+
+/**
+ * COPS message transceiver class for outsourcing connections at the PDP side.
+ *
+ * TODO - change all references of Vector to List<>
+ */
+public class COPSPdpOSMsgSender {
+    /**
+     * Socket connected to PEP
+     */
+    protected final Socket _sock;
+
+    /**
+     * COPS client-type that identifies the policy client
+     */
+    protected final short _clientType;
+
+    /**
+     * COPS client handle used to uniquely identify a particular
+     * PEP's request for a client-type
+     */
+    protected final COPSHandle _handle;
+
+    /**
+     * Creates a COPSPepMsgSender
+     *
+     * @param clientType        COPS client-type
+     * @param clientHandle      Client handle
+     * @param sock              Socket to the PEP
+     */
+    public COPSPdpOSMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
+        // COPS Handle
+        _handle = clientHandle;
+        _clientType = clientType;
+
+        _sock = sock;
+    }
+
+    /**
+     * Gets the client handle
+     * @return   Client's <tt>COPSHandle</tt>
+     */
+    public COPSHandle getClientHandle() {
+        return _handle;
+    }
+
+    /**
+     * Gets the client-type
+     * @return   Client-type value
+     */
+    public short getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Sends a decision message which was requested by the PEP
+     * @param removeDecs    Decisions to be removed
+     * @param installDecs   Decisions to be installed
+     * @throws COPSPdpException
+     */
+    public void sendSolicitedDecision(Vector removeDecs, Vector installDecs) throws COPSPdpException {
+        sendDecision(removeDecs, installDecs, true);
+    }
+
+    /**
+     * Sends a decision message which was not requested by the PEP
+     * @param removeDecs    Decisions to be removed
+     * @param installDecs   Decisions to be installed
+     * @throws COPSPdpException
+     */
+    public void sendUnsolicitedDecision(Vector removeDecs, Vector installDecs) throws COPSPdpException {
+        sendDecision(removeDecs, installDecs, false);
+    }
+
+    /**
+     * Sends a decision message to the PEP
+     * @param removeDecs    Decisions to be removed
+     * @param installDecs   Decisions to be installed
+     * @param solicited     <tt>true</tt> if the PEP requested this decision, <tt>false</tt> otherwise
+     * @throws COPSPdpException
+     */
+    public void sendDecision(Vector removeDecs, Vector installDecs, boolean solicited) throws COPSPdpException {
+        // Common Header holding the same ClientType as the request
+        final Flag flag;
+        if (solicited)
+            flag= Flag.SOLICITED;
+        else
+            flag = Flag.UNSOLICITED;
+
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+
+        // Decisions (no flags supplied)
+        //  <Context>
+        final COPSContext cntxt = new COPSContext(RType.CONFIG, (short)0);
+
+        // Remove Decisions
+        //  <Decision: Flags>
+        final COPSDecision rdec1;
+        if (installDecs.size() == 0)
+            rdec1 = new COPSDecision(Command.REMOVE);
+        else
+            rdec1 = new COPSDecision(Command.INSTALL);
+
+        if (decisions.get(cntxt) == null) {
+            final Set<COPSDecision> decisionSet = new HashSet<>();
+            decisionSet.add(rdec1);
+            decisions.put(cntxt, decisionSet);
+        } else {
+            decisions.get(cntxt).add(rdec1);
+        }
+
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(1, flag, getClientType(),
+                new COPSHandle(getClientHandle().getId()), decisions, null);
+
+        //** Send decision
+        //**
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a message asking that the request state be deleted
+     * @throws   COPSPdpException
+     */
+    public void sendDeleteRequestState() throws COPSPdpException {
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        // Common Header with the same ClientType as the request (default UNSOLICITED)
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
+                decisionMap, null);
+
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Method sendOpenNewRequestState
+     *
+     * @throws   COPSPdpException
+     *
+     */
+    //FIXME: Unused?
+    public void sendOpenNewRequestState() throws COPSPdpException {
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
+         *                          <Client Handle>
+         *                          *(<Decision>)
+         *                          [<Integrity>]
+         * <Decision> ::= <Context>
+         *                  <Decision: Flags>
+         * <Decision: Flags> ::= Install Request-State
+         *
+        */
+
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        // Common Header with the same ClientType as the request (default UNSOLICITED)
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
+                decisionMap, null);
+
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a message asking for a COPS sync operation
+     * @throws COPSPdpException
+     */
+    public void sendSyncRequestState() throws COPSPdpException {
+        /* <Synchronize State Request>  ::= <Common Header>
+         *                                  [<Client Handle>]
+         *                                  [<Integrity>]
+         */
+
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, new COPSHandle(_handle.getId()), null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());
+        }
+    }
+
+}
index 855a14ca25b83c6dfae7976d78c52be6616e5f26..dce9b2b47f062ee57b77100a01263da2721e72c7 100644 (file)
-package org.umu.cops.ospdp;\r
-\r
-import org.umu.cops.stack.*;\r
-\r
-import java.net.Socket;\r
-import java.util.Vector;\r
-\r
-/**\r
- * State manager class for outsourcing requests, at the PDP side.\r
- */\r
-public class COPSPdpOSReqStateMan {\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 COPSPdpOSDataProcess _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 COPSPdpOSMsgSender _sender;\r
-\r
-    /**\r
-     * Creates a request state manager\r
-     * @param clientType    Client-type\r
-     * @param clientHandle  Client handle\r
-     */\r
-    public COPSPdpOSReqStateMan(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 COPSPdpOSDataProcess 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(COPSPdpOSDataProcess 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 PDP\r
-        _sender = new COPSPdpOSMsgSender(_clientType, _handle, sock);\r
-\r
-        // Initial state\r
-        _status = ST_INIT;\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) throws COPSPdpException {\r
-        Vector clientSIs = msg.getClientSI();\r
-\r
-        //** Here we must retrieve a decision depending on the\r
-        //** supplied ClientSIs\r
-        /*Vector removeDecs = new Vector();\r
-        Vector installDecs = new Vector();*/\r
-        _process.setClientData(this, clientSIs);\r
-\r
-        Vector removeDecs = _process.getRemovePolicy(this);\r
-        Vector installDecs = _process.getInstallPolicy(this);\r
-\r
-        //** We create a SOLICITED decision\r
-        //**\r
-        _sender.sendSolicitedDecision(removeDecs, installDecs);\r
-        _status = ST_DECS;\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) throws COPSPdpException {\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
-        // Report Type\r
-        COPSReportType rtypemsg = msg.getReport();\r
-\r
-        // Named ClientSI\r
-        Vector clientSIs = msg.getClientSI();\r
-\r
-        //** We should act here in accordance with\r
-        //** the received report\r
-        if (rtypemsg.isSuccess()) {\r
-            _status = ST_REPORT;\r
-            _process.successReport(this, clientSIs);\r
-        } else if (rtypemsg.isFailure()) {\r
-            _status = ST_REPORT;\r
-            _process.failReport(this, clientSIs);\r
-        } else if (rtypemsg.isAccounting()) {\r
-            _status = ST_ACCT;\r
-            _process.acctReport(this, clientSIs);\r
-        }\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()//FIXME: unused?\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
+package org.umu.cops.ospdp;
+
+import org.umu.cops.stack.*;
+
+import java.net.Socket;
+import java.util.Vector;
+
+/**
+ * State manager class for outsourcing requests, at the PDP side.
+ */
+public class COPSPdpOSReqStateMan {
+    /**
+     * 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;
+
+    /**
+     * Object for performing policy data processing
+     */
+    protected COPSPdpOSDataProcess _process;
+
+    /**
+     *  Current state of the request being managed
+     */
+    protected short _status;
+
+    /** COPS message transceiver used to send COPS messages */
+    protected COPSPdpOSMsgSender _sender;
+
+    /**
+     * Creates a request state manager
+     * @param clientType    Client-type
+     * @param clientHandle  Client handle
+     */
+    public COPSPdpOSReqStateMan(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 COPSPdpOSDataProcess getDataProcess() {
+        return _process;
+    }
+
+    /**
+     * Sets the policy data processing object
+     * @param   process Policy data processing object
+     */
+    public void setDataProcess(COPSPdpOSDataProcess 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 PDP
+        _sender = new COPSPdpOSMsgSender(_clientType, _handle, sock);
+
+        // Initial state
+        _status = ST_INIT;
+    }
+
+    /**
+     * Processes a COPS request
+     * @param msg   COPS request received from the PEP
+     * @throws COPSPdpException
+     */
+    protected void processRequest(COPSReqMsg msg) throws COPSPdpException {
+        //** Here we must retrieve a decision depending on the
+        //** supplied ClientSIs
+        /*Vector removeDecs = new Vector();
+        Vector installDecs = new Vector();*/
+        if (msg.getClientSI() != null)
+            _process.setClientData(this, msg.getClientSI().toArray(new COPSClientSI[msg.getClientSI().size()]));
+
+        Vector removeDecs = _process.getRemovePolicy(this);
+        Vector installDecs = _process.getInstallPolicy(this);
+
+        //** We create a SOLICITED decision
+        //**
+        _sender.sendSolicitedDecision(removeDecs, installDecs);
+        _status = ST_DECS;
+    }
+
+    /**
+     * Processes a report
+     * @param msg   Report message from the PEP
+     * @throws COPSPdpException
+     */
+    protected void processReport(final COPSReportMsg msg) throws COPSPdpException {
+        //** Analyze the report
+        //**
+
+        /*
+         * <Report State> ::= <Common Header>
+         *                      <Client Handle>
+         *                      <Report Type>
+         *                      *(<Named ClientSI>)
+         *                      [<Integrity>]
+         * <Named ClientSI: Report> ::= <[<GPERR>] *(<report>)>
+         * <report> ::= <ErrorPRID> <CPERR> *(<PRID><EPD>)
+         *
+         * Important, <Named ClientSI> is not parsed
+        */
+
+        // COPSHeader hdrmsg = msg.getHeader();
+        // COPSHandle handlemsg = msg.getClientHandle();
+
+        // Report Type
+        final COPSReportType rtypemsg = msg.getReport();
+
+        // Named ClientSI
+        if (msg.getClientSI() != null) {
+            //** Here we must act in accordance with
+            //** the report received
+            switch (rtypemsg.getReportType()) {
+                case SUCCESS:
+                    _status = ST_REPORT;
+                    _process.successReport(this, msg.getClientSI());
+                    break;
+                case FAILURE:
+                    _status = ST_REPORT;
+                    _process.failReport(this, msg.getClientSI());
+                    break;
+                case ACCOUNTING:
+                    _status = ST_ACCT;
+                    _process.acctReport(this, msg.getClientSI());
+                    break;
+            }
+        }
+
+    }
+
+    /**
+     * 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()//FIXME: unused?
+    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 = ST_DEL;
+    }
+
+}
index 4cd8256b0d41aefc7ccef8a4e921ba3ed4c369c3..1c16497f14a2e9d99f8a924ebd986145f7729268 100644 (file)
@@ -3,13 +3,13 @@ package org.umu.cops.ospep;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Socket;
-import java.net.UnknownHostException;
 import java.util.Hashtable;
-import java.util.Vector;
+import java.util.List;
 
 /**
  * This is a outsourcing COPS PEP. Responsible for making
@@ -59,7 +59,7 @@ public class COPSPepOSAgent {
      * @param    pepID              PEP-ID
      * @param    clientType         Client-type
      */
-    public COPSPepOSAgent(String pepID, short clientType) {
+    public COPSPepOSAgent(final String pepID, final short clientType) {
         _pepID = pepID;
         _clientType = clientType;
     }
@@ -68,7 +68,7 @@ public class COPSPepOSAgent {
      * Creates a PEP agent with a PEP-ID equal to "noname"
      * @param    clientType         Client-type
      */
-    public COPSPepOSAgent(short clientType) {
+    public COPSPepOSAgent(final short clientType) {
         // PEPId
         try {
             _pepID = InetAddress.getLocalHost().getHostName();
@@ -99,7 +99,7 @@ public class COPSPepOSAgent {
      * Gets the COPS client-type
      * @return  PEP's client-type
      */
-    public short getClientType() {
+    public int getClientType() {
         return _clientType;
     }
 
@@ -172,13 +172,8 @@ public class COPSPepOSAgent {
      * @throws COPSException
      * @throws IOException
      */
-    public void disconnect(COPSError error) throws COPSException, IOException {
-        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);
-        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
-        closeMsg.add(cHdr);
-        if (error != null)
-            closeMsg.add(error);
-
+    public void disconnect(final COPSError error) throws COPSException, IOException {
+        final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
         closeMsg.writeData(_conn.getSocket());
         _conn.close();
         _conn = null;
@@ -191,7 +186,7 @@ public class COPSPepOSAgent {
      * @throws COPSPepException
      * @throws COPSException
      */
-    public COPSPepOSReqStateMan addRequestState(COPSHandle handle, Vector clientSIs) throws COPSPepException, COPSException {
+    public COPSPepOSReqStateMan addRequestState(final COPSHandle handle, List<COPSClientSI> clientSIs) throws COPSPepException, COPSException {
         if (_conn != null)
             return _conn.addRequestState(handle.getId().str(), _process, clientSIs);
 
@@ -244,34 +239,27 @@ public class COPSPepOSAgent {
      *
      * Not send [<PDPRedirAddr>], [<Integrity>]
      *
-     * @throws   UnknownHostException
      * @throws   IOException
      * @throws   COPSException
      * @throws   COPSPepException
      *
      */
-    private COPSPepOSConnection processConnection(String psHost, int psPort) throws UnknownHostException, IOException, COPSException, COPSPepException {
+    private COPSPepOSConnection processConnection(final String psHost, final int psPort)
+            throws IOException, COPSException, COPSPepException {
         // Build OPN
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, _clientType);
-
-        COPSPepId pepId = new COPSPepId();
-        COPSData d = new COPSData(_pepID);
-        pepId.setData(d);
-
-        COPSClientOpenMsg msg = new COPSClientOpenMsg();
-        msg.add(hdr);
-        msg.add(pepId);
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, new COPSPepId(new COPSData(_pepID)),
+                null, null, null);
 
         // Create socket and send OPN
-        InetAddress addr = InetAddress.getByName(psHost);
-        Socket socket = new Socket(addr,psPort);
+        final InetAddress addr = InetAddress.getByName(psHost);
+        final Socket socket = new Socket(addr,psPort);
         msg.writeData(socket);
 
         // Get response
-        COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
+        final COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
 
-        if (recvmsg.getHeader().isAClientAccept()) {
-            COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
+        if (recvmsg.getHeader().getOpCode().equals(OPCode.CAT)) {
+            final COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
 
             // Support
             if (cMsg.getIntegrity() != null) {
@@ -279,26 +267,26 @@ public class COPSPepOSAgent {
             }
 
             // Mandatory KATimer
-            COPSKATimer kt = cMsg.getKATimer();
+            final COPSKATimer kt = cMsg.getKATimer();
             if (kt == null)
                 throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");
             short _kaTimeVal = kt.getTimerVal();
 
             // ACTimer
-            COPSAcctTimer at = cMsg.getAcctTimer();
-            short _acctTimer = 0;
-            if (at != null)
-                _acctTimer = at.getTimerVal();
+            final COPSAcctTimer at = cMsg.getAcctTimer();
+            short _acctTimer;
+            if (at != null) _acctTimer = at.getTimerVal();
+            else _acctTimer = 0;
 
             // Create connection manager
-            COPSPepOSConnection conn = new COPSPepOSConnection(_clientType, socket);
+            final COPSPepOSConnection conn = new COPSPepOSConnection(_clientType, socket);
             conn.setKaTimer(_kaTimeVal);
             conn.setAcctTimer(_acctTimer);
             new Thread(conn).start();
 
             return conn;
-        } else if (recvmsg.getHeader().isAClientClose()) {
-            COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
+        } else if (recvmsg.getHeader().getOpCode().equals(OPCode.CC)) {
+            final COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
             _error = cMsg.getError();
             socket.close();
             return null;
@@ -312,7 +300,7 @@ public class COPSPepOSAgent {
      * @param handle The COPS handle for this request
      * @param clientSIs The client specific data for this request
      */
-    public void dispatchEvent(COPSHandle handle, Vector clientSIs) {
+    public void dispatchEvent(COPSHandle handle, final List<COPSClientSI> clientSIs) {
         try {
             addRequestState(handle, clientSIs);
         } catch (Exception e) {
index 96bfa8e43f3171ef2c8d4673145a22bcc2f5a206..0154c09c5eab6fe1f13b463322f3a3038fdb8797 100644 (file)
-package org.umu.cops.ospep;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.*;\r
-import java.util.concurrent.ConcurrentHashMap;\r
-\r
-/**\r
- * COPSPepConnection represents a PEP-PDP Connection Manager.\r
- * Responsible for processing messages received from PDP.\r
- */\r
-public class COPSPepOSConnection implements Runnable {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(COPSPepOSConnection.class);\r
-\r
-    /** Socket connected to PDP */\r
-    protected Socket _sock;\r
-\r
-    /** Time to wait responses (milliseconds), default is 10 seconds */\r
-    protected final int _responseTime;\r
-\r
-    /** COPS Client-type */\r
-    protected final short _clientType;\r
-\r
-    /**\r
-        Accounting timer value (secs)\r
-     */\r
-    protected transient short _acctTimer;\r
-\r
-    /**\r
-        Keep-alive timer value (secs)\r
-     */\r
-    protected transient short _kaTimer;\r
-\r
-    /**\r
-     *  Time of the latest keep-alive received\r
-     */\r
-    protected Date _lastRecKa;\r
-\r
-    /**\r
-        Opcode of the latest message sent\r
-    */\r
-    protected byte _lastmessage;\r
-\r
-    /**\r
-        Maps a COPS Client Handle to a Request State Manager\r
-     */\r
-    protected final Map<String, COPSPepOSReqStateMan> _managerMap;\r
-    // map < String(COPSHandle), COPSPepOSReqStateMan>;\r
-\r
-    /**\r
-        COPS error returned by PDP\r
-     */\r
-    protected COPSError _error;\r
-\r
-    /**\r
-     * Creates a new PEP connection\r
-     * @param clientType    PEP's client-type\r
-     * @param sock          Socket connected to PDP\r
-     */\r
-    public COPSPepOSConnection(short clientType, Socket sock) {\r
-        _clientType = clientType;\r
-        _sock = sock;\r
-\r
-        // Timers\r
-        _acctTimer = 0;\r
-        _kaTimer = 0;\r
-        _responseTime = 10000;\r
-        _lastmessage = COPSHeader.COPS_OP_CAT;\r
-\r
-        _managerMap = new ConcurrentHashMap<>();\r
-    }\r
-\r
-    /**\r
-     * Gets the response time\r
-     * @return  Response time value (msecs)\r
-     */\r
-    public int getResponseTime() {\r
-        return _responseTime;\r
-    }\r
-\r
-    /**\r
-     * Gets the socket connected to the PDP\r
-     * @return  Socket connected to PDP\r
-     */\r
-    public Socket getSocket() {\r
-        return _sock;\r
-    }\r
-\r
-    /**\r
-     * Gets keep-alive timer\r
-     * @return  Keep-alive timer value (secs)\r
-     */\r
-    public short getKaTimer () {\r
-        return _kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets accounting timer\r
-     * @return  Accounting timer value (secs)\r
-     */\r
-    public short getAcctTimer () {\r
-        return _acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets all request state managers\r
-     * @return  A <tt>Hashatable</tt> holding all request state managers\r
-     * TODO - change the return to Map\r
-     */\r
-    protected Hashtable getReqStateMans() {\r
-        return new Hashtable(_managerMap);\r
-    }\r
-\r
-    /**\r
-     * Checks whether the socket to the PDP is closed or not\r
-     * @return  <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise\r
-     */\r
-    public boolean isClosed() {\r
-        return _sock.isClosed();\r
-    }\r
-\r
-    /**\r
-     * Closes the socket\r
-     *\r
-     * @throws java.io.IOException\r
-     */\r
-    protected void close() throws IOException {\r
-        _sock.close();\r
-    }\r
-\r
-    /**\r
-     * Gets the opcode of the lastest message sent\r
-     * @return  Message opcode\r
-     */\r
-    public byte getLastmessage() {\r
-        return _lastmessage;\r
-    }\r
-\r
-    /**\r
-     * Sets keep-alive timer\r
-     * @param kaTimer   Keep-alive timer value (secs)\r
-     */\r
-    public void setKaTimer(short kaTimer) {\r
-        _kaTimer = kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Sets accounting timer\r
-     * @param acctTimer Accounting timer value (secs)\r
-     */\r
-    public void setAcctTimer(short acctTimer) {\r
-        _acctTimer = acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Message-processing loop\r
-     */\r
-    public void run () {\r
-        Date _lastSendKa = new Date();\r
-        Date _lastSendAcc = new Date();\r
-        _lastRecKa = new Date();\r
-\r
-        try {\r
-            while (!_sock.isClosed()) {\r
-                if (_sock.getInputStream().available() != 0) {\r
-                    _lastmessage = processMessage(_sock);\r
-                    _lastRecKa = new Date();\r
-                }\r
-\r
-                // Keep Alive\r
-                if (_kaTimer > 0) {\r
-                    // Timeout del PDP\r
-                    int _startTime = (int) (_lastRecKa.getTime());\r
-                    int cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > _kaTimer*1000) {\r
-                        _sock.close();\r
-                        // Notify all Request State Managers\r
-                        notifyNoKAAllReqStateMan();\r
-                    }\r
-\r
-                    // Send to PEP\r
-                    _startTime = (int) (_lastSendKa.getTime());\r
-                    cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {\r
-                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
-                        COPSKAMsg msg = new COPSKAMsg();\r
-\r
-                        msg.add(hdr);\r
-\r
-                        COPSTransceiver.sendMsg(msg, _sock);\r
-                        _lastSendKa = new Date();\r
-                    }\r
-                }\r
-\r
-                // Accounting\r
-                if (_acctTimer > 0) {\r
-                    int _startTime = (int) (_lastSendAcc.getTime());\r
-                    int cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > ((_acctTimer*3/4)*1000)) {\r
-                        // Notify all Request State Managers\r
-                        notifyAcctAllReqStateMan();\r
-                        _lastSendAcc = new Date();\r
-                    }\r
-                }\r
-\r
-                try {\r
-                    Thread.sleep(500);\r
-                } catch (Exception e) {\r
-                    logger.error("Exception thrown while sleeping", e);\r
-                }\r
-            }\r
-        } catch (Exception e) {\r
-            logger.error("Error while processing socket messages", e);\r
-        }\r
-\r
-        // connection closed by server\r
-        // COPSDebug.out(getClass().getName(),"Connection closed by server");\r
-        try {\r
-            _sock.close();\r
-        } catch (IOException e) {\r
-            logger.error("Unexpected exception closing the socket", e);\r
-        }\r
-\r
-        // Notify all Request State Managers\r
-        try {\r
-            notifyCloseAllReqStateMan();\r
-        } catch (COPSPepException e) {\r
-            logger.error("Error closing state managers", e);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Gets a COPS message from the socket and processes it\r
-     * @param conn  Socket connected to the PDP\r
-     * @return COPS message type\r
-     * @throws COPSPepException\r
-     * @throws COPSException\r
-     * @throws IOException\r
-     */\r
-    protected byte processMessage(Socket conn) throws COPSPepException, COPSException, IOException {\r
-        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
-\r
-        if (msg.getHeader().isAClientClose()) {\r
-            handleClientCloseMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_CC;\r
-        } else if (msg.getHeader().isADecision()) {\r
-            handleDecisionMsg(/*OJO conn, */msg);\r
-            return COPSHeader.COPS_OP_DEC;\r
-        } else if (msg.getHeader().isASyncStateReq()) {\r
-            handleSyncStateReqMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_SSQ;\r
-        } else if (msg.getHeader().isAKeepAlive()) {\r
-            handleKeepAliveMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_KA;\r
-        } else {\r
-            throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handle Client Close Message, close the passed connection\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     *\r
-     * <Client-Close> ::= <Common Header>\r
-     *                      <Error>\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     */\r
-    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
-        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
-        _error = cMsg.getError();\r
-\r
-        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
-\r
-        try {\r
-            // Support\r
-            if (cMsg.getIntegrity() != null)\r
-                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-\r
-            conn.close();\r
-        } catch (Exception unae) {\r
-            logger.error("Unexpected exception closing connection", unae);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Gets the COPS error\r
-     * @return  <tt>COPSError</tt> returned by PDP\r
-     */\r
-    protected COPSError getError() {\r
-        return _error;\r
-    }\r
-\r
-    /**\r
-     * Handle Keep Alive Message\r
-     *\r
-     * <Keep-Alive> ::= <Common Header>\r
-     *                  [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
-        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
-\r
-        // COPSDebug.out(getClass().getName(),"Get KAlive Msg");\r
-\r
-        // Support\r
-        if (cMsg.getIntegrity() != null)\r
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-\r
-        // must we do anything else?\r
-    }\r
-\r
-    /**\r
-     * Method handleDecisionMsg\r
-     *\r
-     * <Decision Message> ::= <Common Header: Flag SOLICITED>\r
-     *                          <Client Handle>\r
-     *                          *(<Decision>) | <Error>\r
-     *                          [<Integrity>]\r
-     * <Decision> ::= <Context>\r
-     *                  <Decision: Flags>\r
-     *                  [<ClientSI Decision Data: Outsourcing>]\r
-     * <Decision: Flags> ::= <Command-Code> NULLFlag\r
-     * <Command-Code> ::= NULLDecision | Install | Remove\r
-     * <ClientSI Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
-     * <Install Decision> ::= *(<PRID> <EPD>)\r
-     * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
-     *\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleDecisionMsg(/*OJO Socket conn, */COPSMsg msg) throws COPSPepException {\r
-        COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;\r
-        COPSHandle handle = dMsg.getClientHandle();\r
-        COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(handle.getId().str());\r
-        manager.processDecision(dMsg);\r
-    }\r
-\r
-    /**\r
-     * Method handleSyncStateReqMsg\r
-     *\r
-     *              <Synchronize State> ::= <Common Header>\r
-     *                                      [<Client Handle>]\r
-     *                                      [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {\r
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
-        // COPSHandle handle = cMsg.getClientHandle();\r
-        // COPSHeader header = cMsg.getHeader();\r
-\r
-        // Support\r
-        if (cMsg.getIntegrity() != null)\r
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-\r
-        COPSPepOSReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());\r
-\r
-        if (manager == null)\r
-            logger.warn("Unable to find state manager with ID - " + cMsg.getClientHandle().getId().str());\r
-        else\r
-            manager.processSyncStateRequest(cMsg);\r
-    }\r
-\r
-    /**\r
-     * Adds a new request state\r
-     * @param clientHandle  Client's handle\r
-     * @param process       Policy data processing object\r
-     * @param clientSIs     Client data from the outsourcing event\r
-     * @return              The newly created request state manager\r
-     * @throws COPSException\r
-     * @throws COPSPepException\r
-     */\r
-    protected COPSPepOSReqStateMan addRequestState(String clientHandle, COPSPepOSDataProcess process, Vector clientSIs) throws COPSException, COPSPepException {\r
-        COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType, clientHandle);\r
-        if (_managerMap.get(clientHandle) != null)\r
-            throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);\r
-\r
-        manager.setDataProcess(process);\r
-        manager.setClientSI(clientSIs);\r
-        _managerMap.put(clientHandle, manager);\r
-        manager.initRequestState(_sock);\r
-        return manager;\r
-    }\r
-\r
-    /**\r
-     * Deletes a request state\r
-     * @param manager   Request state manager\r
-     * @throws COPSException\r
-     * @throws COPSPepException\r
-     */\r
-    protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {\r
-        manager.finalizeRequestState();\r
-    }\r
-\r
-    private void notifyCloseAllReqStateMan() throws COPSPepException {\r
-        for (final COPSPepOSReqStateMan man : _managerMap.values()) {\r
-                man.processClosedConnection(_error);\r
-        }\r
-    }\r
-\r
-    private void notifyNoKAAllReqStateMan() throws COPSPepException {\r
-        for (final COPSPepOSReqStateMan man : _managerMap.values()) {\r
-            man.processNoKAConnection();\r
-        }\r
-    }\r
-\r
-    private void notifyAcctAllReqStateMan() throws COPSPepException {\r
-        for (final COPSPepOSReqStateMan man : _managerMap.values()) {\r
-            man.processAcctReport();\r
-        }\r
-    }\r
-\r
-}\r
+package org.umu.cops.ospep;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPSPepConnection represents a PEP-PDP Connection Manager.
+ * Responsible for processing messages received from PDP.
+ */
+public class COPSPepOSConnection implements Runnable {
+
+    public final static Logger logger = LoggerFactory.getLogger(COPSPepOSConnection.class);
+
+    /** Socket connected to PDP */
+    protected Socket _sock;
+
+    /** Time to wait responses (milliseconds), default is 10 seconds */
+    protected final int _responseTime;
+
+    /** COPS Client-type */
+    protected short _clientType;
+
+    /**
+        Accounting timer value (secs)
+     */
+    protected transient short _acctTimer;
+
+    /**
+        Keep-alive timer value (secs)
+     */
+    protected transient short _kaTimer;
+
+    /**
+     *  Time of the latest keep-alive received
+     */
+    protected Date _lastRecKa;
+
+    /**
+        Maps a COPS Client Handle to a Request State Manager
+     */
+    protected final Map<String, COPSPepOSReqStateMan> _managerMap;
+
+    /**
+        COPS error returned by PDP
+     */
+    protected COPSError _error;
+
+    /**
+     * Creates a new PEP connection
+     * @param clientType    PEP's client-type
+     * @param sock          Socket connected to PDP
+     */
+    public COPSPepOSConnection(final short clientType, final Socket sock) {
+        _clientType = clientType;
+        _sock = sock;
+
+        // Timers
+        _acctTimer = 0;
+        _kaTimer = 0;
+        _responseTime = 10000;
+        _managerMap = new ConcurrentHashMap<>();
+    }
+
+    /**
+     * Gets the response time
+     * @return  Response time value (msecs)
+     */
+    public int getResponseTime() {
+        return _responseTime;
+    }
+
+    /**
+     * Gets the socket connected to the PDP
+     * @return  Socket connected to PDP
+     */
+    public Socket getSocket() {
+        return _sock;
+    }
+
+    /**
+     * Gets keep-alive timer
+     * @return  Keep-alive timer value (secs)
+     */
+    public short getKaTimer () {
+        return _kaTimer;
+    }
+
+    /**
+     * Gets accounting timer
+     * @return  Accounting timer value (secs)
+     */
+    public short getAcctTimer () {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets all request state managers
+     * @return  A <tt>Hashatable</tt> holding all request state managers
+     * TODO - change the return to Map
+     */
+    protected Hashtable getReqStateMans() {
+        return new Hashtable(_managerMap);
+    }
+
+    /**
+     * Checks whether the socket to the PDP is closed or not
+     * @return  <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise
+     */
+    public boolean isClosed() {
+        return _sock.isClosed();
+    }
+
+    /**
+     * Closes the socket
+     *
+     * @throws java.io.IOException
+     */
+    protected void close() throws IOException {
+        _sock.close();
+    }
+
+    /**
+     * Sets keep-alive timer
+     * @param kaTimer   Keep-alive timer value (secs)
+     */
+    public void setKaTimer(short kaTimer) {
+        _kaTimer = kaTimer;
+    }
+
+    /**
+     * Sets accounting timer
+     * @param acctTimer Accounting timer value (secs)
+     */
+    public void setAcctTimer(short acctTimer) {
+        _acctTimer = acctTimer;
+    }
+
+    /**
+     * Message-processing loop
+     */
+    public void run () {
+        Date _lastSendKa = new Date();
+        Date _lastSendAcc = new Date();
+        _lastRecKa = new Date();
+
+        try {
+            while (!_sock.isClosed()) {
+                if (_sock.getInputStream().available() != 0) {
+                    processMessage(_sock);
+                    _lastRecKa = new Date();
+                }
+
+                // Keep Alive
+                if (_kaTimer > 0) {
+                    // Timeout del PDP
+                    int _startTime = (int) (_lastRecKa.getTime());
+                    int cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > _kaTimer*1000) {
+                        _sock.close();
+                        // Notify all Request State Managers
+                        notifyNoKAAllReqStateMan();
+                    }
+
+                    // Send to PEP
+                    _startTime = (int) (_lastSendKa.getTime());
+                    cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {
+                        final COPSKAMsg msg = new COPSKAMsg(null);
+                        COPSTransceiver.sendMsg(msg, _sock);
+                        _lastSendKa = new Date();
+                    }
+                }
+
+                // Accounting
+                if (_acctTimer > 0) {
+                    int _startTime = (int) (_lastSendAcc.getTime());
+                    int cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > ((_acctTimer*3/4)*1000)) {
+                        // Notify all Request State Managers
+                        notifyAcctAllReqStateMan();
+                        _lastSendAcc = new Date();
+                    }
+                }
+
+                try {
+                    Thread.sleep(500);
+                } catch (Exception e) {
+                    logger.error("Exception thrown while sleeping", e);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("Error while processing socket messages", e);
+        }
+
+        // connection closed by server
+        // COPSDebug.out(getClass().getName(),"Connection closed by server");
+        try {
+            _sock.close();
+        } catch (IOException e) {
+            logger.error("Unexpected exception closing the socket", e);
+        }
+
+        // Notify all Request State Managers
+        try {
+            notifyCloseAllReqStateMan();
+        } catch (COPSPepException e) {
+            logger.error("Error closing state managers", e);
+        }
+    }
+
+    /**
+     * Gets a COPS message from the socket and processes it
+     * @param conn  Socket connected to the PDP
+     * @throws COPSPepException
+     * @throws COPSException
+     * @throws IOException
+     */
+    protected void processMessage(Socket conn) throws COPSPepException, COPSException, IOException {
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+
+        if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
+            handleClientCloseMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.DEC)) {
+            handleDecisionMsg(/*OJO conn, */msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.SSQ)) {
+            handleSyncStateReqMsg(conn, msg);
+        } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
+            handleKeepAliveMsg(conn, msg);
+        } else {
+            throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+        }
+    }
+
+    /**
+     * Handle Client Close Message, close the passed connection
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     *
+     * <Client-Close> ::= <Common Header>
+     *                      <Error>
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     */
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+        _error = cMsg.getError();
+
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
+
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null)
+                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+
+            conn.close();
+        } catch (Exception unae) {
+            logger.error("Unexpected exception closing connection", unae);
+        }
+    }
+
+    /**
+     * Gets the COPS error
+     * @return  <tt>COPSError</tt> returned by PDP
+     */
+    protected COPSError getError() {
+        return _error;
+    }
+
+    /**
+     * Handle Keep Alive Message
+     *
+     * <Keep-Alive> ::= <Common Header>
+     *                  [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
+        COPSKAMsg cMsg = (COPSKAMsg) msg;
+
+        // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
+
+        // Support
+        if (cMsg.getIntegrity() != null)
+            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+
+        // must we do anything else?
+    }
+
+    /**
+     * Method handleDecisionMsg
+     *
+     * <Decision Message> ::= <Common Header: Flag SOLICITED>
+     *                          <Client Handle>
+     *                          *(<Decision>) | <Error>
+     *                          [<Integrity>]
+     * <Decision> ::= <Context>
+     *                  <Decision: Flags>
+     *                  [<ClientSI Decision Data: Outsourcing>]
+     * <Decision: Flags> ::= <Command-Code> NULLFlag
+     * <Command-Code> ::= NULLDecision | Install | Remove
+     * <ClientSI Decision Data> ::= <<Install Decision> | <Remove Decision>>
+     * <Install Decision> ::= *(<PRID> <EPD>)
+     * <Remove Decision> ::= *(<PRID> | <PPRID>)
+     *
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleDecisionMsg(/*OJO Socket conn, */COPSMsg msg) throws COPSPepException {
+        COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+        COPSHandle handle = dMsg.getClientHandle();
+        COPSPepOSReqStateMan manager = _managerMap.get(handle.getId().str());
+        manager.processDecision(dMsg);
+    }
+
+    /**
+     * Method handleSyncStateReqMsg
+     *
+     *              <Synchronize State> ::= <Common Header>
+     *                                      [<Client Handle>]
+     *                                      [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
+        // COPSHandle handle = cMsg.getClientHandle();
+        // COPSHeader header = cMsg.getHeader();
+
+        // Support
+        if (cMsg.getIntegrity() != null)
+            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+
+        COPSPepOSReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
+
+        if (manager == null)
+            logger.warn("Unable to find state manager with ID - " + cMsg.getClientHandle().getId().str());
+        else
+            manager.processSyncStateRequest(cMsg);
+    }
+
+    /**
+     * Adds a new request state
+     * @param clientHandle  Client's handle
+     * @param process       Policy data processing object
+     * @param clientSIs     Client data from the outsourcing event
+     * @return              The newly created request state manager
+     * @throws COPSException
+     * @throws COPSPepException
+     */
+    protected COPSPepOSReqStateMan addRequestState(final String clientHandle, final COPSPepOSDataProcess process,
+                                                   final List<COPSClientSI> clientSIs)
+            throws COPSException, COPSPepException {
+        COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType, clientHandle);
+        if (_managerMap.get(clientHandle) != null)
+            throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
+
+        manager.setDataProcess(process);
+        manager.setClientSI(clientSIs);
+        _managerMap.put(clientHandle, manager);
+        manager.initRequestState(_sock);
+        return manager;
+    }
+
+    /**
+     * Deletes a request state
+     * @param manager   Request state manager
+     * @throws COPSException
+     * @throws COPSPepException
+     */
+    protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {
+        manager.finalizeRequestState();
+    }
+
+    private void notifyCloseAllReqStateMan() throws COPSPepException {
+        for (final COPSPepOSReqStateMan man : _managerMap.values()) {
+                man.processClosedConnection(_error);
+        }
+    }
+
+    private void notifyNoKAAllReqStateMan() throws COPSPepException {
+        for (final COPSPepOSReqStateMan man : _managerMap.values()) {
+            man.processNoKAConnection();
+        }
+    }
+
+    private void notifyAcctAllReqStateMan() throws COPSPepException {
+        for (final COPSPepOSReqStateMan man : _managerMap.values()) {
+            man.processAcctReport();
+        }
+    }
+
+}
index 2f8526ef820d0efb2a24d8b3d4ee80331be11d21..5ddeed14987f29902db68e061b2354d25dba57e8 100644 (file)
-package org.umu.cops.ospep;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Vector;\r
-\r
-import org.umu.cops.stack.COPSClientSI;\r
-import org.umu.cops.stack.COPSContext;\r
-import org.umu.cops.stack.COPSDeleteMsg;\r
-import org.umu.cops.stack.COPSException;\r
-import org.umu.cops.stack.COPSHandle;\r
-import org.umu.cops.stack.COPSHeader;\r
-import org.umu.cops.stack.COPSReason;\r
-import org.umu.cops.stack.COPSReportMsg;\r
-import org.umu.cops.stack.COPSReportType;\r
-import org.umu.cops.stack.COPSReqMsg;\r
-import org.umu.cops.stack.COPSSyncStateMsg;\r
-\r
-/**\r
- * COPS message transceiver class for outsourcing connections at the PEP side.\r
- */\r
-public class COPSPepOSMsgSender {\r
-    /**\r
-     * Socket connection to PDP\r
-     */\r
-    protected Socket _sock;\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
-     * Creates a COPSPepMsgSender\r
-     *\r
-     * @param clientType        Client-type\r
-     * @param clientHandle      Client handle\r
-     * @param sock              Socket connected to the PDP\r
-     */\r
-    public COPSPepOSMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
-        // COPS Handle\r
-        _handle = clientHandle;\r
-        _clientType = clientType;\r
-\r
-        _sock = sock;\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
-     * Sends a request to the PDP.\r
-     * The PEP establishes a request state client handle for which the\r
-     * remote PDP may maintain state.\r
-     * @param    clientSIs              Client data\r
-     * @throws   COPSPepException\r
-     */\r
-    public void sendRequest(Vector clientSIs) throws COPSPepException {\r
-        // Create COPS Message\r
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_REQ, _clientType);\r
-\r
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG , (short) 0);\r
-\r
-        COPSHandle handle = _handle;\r
-\r
-        COPSReqMsg msg = new COPSReqMsg();\r
-        try {\r
-            msg.add(hdr) ;\r
-            msg.add(handle) ;\r
-            msg.add(cntxt) ;\r
-\r
-            Enumeration clientSIEnum = clientSIs.elements();\r
-            while (clientSIEnum.hasMoreElements())\r
-                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
-        } catch (COPSException e) {\r
-            throw new COPSPepException("Error making Request Msg, reason: " + e.getMessage());\r
-        }\r
-\r
-        // Send message\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a failure report to the PDP. This report message notifies the PDP\r
-     * of failure when carrying out the PDP's decision, or when reporting\r
-     *  an accounting related state change.\r
-     * @param clientSIs Report data\r
-     * @throws   COPSPepException\r
-     */\r
-    public void sendFailReport(Vector clientSIs) throws COPSPepException {\r
-        COPSReportMsg msg = new COPSReportMsg();\r
-        // Report FAIL\r
-        try {\r
-            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
-            COPSHandle hnd = _handle;\r
-\r
-            COPSReportType report = new COPSReportType(COPSReportType.FAILURE);\r
-\r
-            msg.add(hdr);\r
-            msg.add(hnd);\r
-            msg.add(report);\r
-\r
-            Enumeration clientSIEnum = clientSIs.elements();\r
-            while (clientSIEnum.hasMoreElements())\r
-                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a success report to the PDP. This report message notifies the PDP\r
-     * of success when carrying out the PDP's decision, or when reporting\r
-     *  an accounting related state change.\r
-     * @param   clientSIs   Report data\r
-     * @throws  COPSPepException\r
-     */\r
-    public void sendSuccessReport(Vector clientSIs) throws COPSPepException {\r
-        COPSReportMsg msg = new COPSReportMsg();\r
-        // Report SUCESS\r
-        try {\r
-            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
-            COPSHandle hnd = _handle;\r
-\r
-            COPSReportType report = new COPSReportType(COPSReportType.SUCCESS);\r
-\r
-            msg.add(hdr);\r
-            msg.add(hnd);\r
-            msg.add(report);\r
-\r
-            Enumeration clientSIEnum = clientSIs.elements();\r
-            while (clientSIEnum.hasMoreElements())\r
-                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends an accounting report to the PDP\r
-     * @param clientSIs Report data\r
-     * @throws COPSPepException\r
-     */\r
-    public void sendAcctReport(Vector clientSIs) throws COPSPepException {\r
-        COPSReportMsg msg = new COPSReportMsg();\r
-        // Report SUCCESS\r
-        try {\r
-            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
-            COPSHandle hnd = _handle;\r
-\r
-            COPSReportType report = new COPSReportType(COPSReportType.ACCT);\r
-\r
-            msg.add(hdr);\r
-            msg.add(hnd);\r
-            msg.add(report);\r
-\r
-            Enumeration clientSIEnum = clientSIs.elements();\r
-            while (clientSIEnum.hasMoreElements())\r
-                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a sync-complete message to the PDP. This indicates the\r
-     * end of a synchronization requested by the PDP.\r
-     * @throws   COPSPepException\r
-     */\r
-    public void sendSyncComplete() throws COPSPepException {\r
-        // Common Header with the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSC, _clientType);\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        COPSHandle clienthandle = _handle;\r
-\r
-        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
-        try {\r
-            msg.add(hdr);\r
-            msg.add(clienthandle);\r
-        } catch (Exception e) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a delete request to the PDP.\r
-     * When sent from the PEP this message indicates to the remote PDP that\r
-     * the state identified by the client handle is no longer\r
-     * available/relevant.\r
-     * @throws   COPSPepException\r
-     */\r
-    public void sendDeleteRequest() throws COPSPepException {\r
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DRQ, _clientType);\r
-        COPSHandle handle = _handle;\r
-\r
-        // *** TODO: use real reason codes\r
-        COPSReason reason = new COPSReason((short) 234, (short) 345);\r
-\r
-        COPSDeleteMsg msg = new COPSDeleteMsg();\r
-        try {\r
-            msg.add(hdr);\r
-            msg.add(handle);\r
-            msg.add(reason);\r
-            msg.writeData(_sock);\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-}\r
+package org.umu.cops.ospep;
+
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSReason.ReasonCode;
+import org.umu.cops.stack.COPSReportType.ReportType;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * COPS message transceiver class for outsourcing connections at the PEP side.
+ */
+public class COPSPepOSMsgSender {
+    /**
+     * Socket connection to PDP
+     */
+    protected Socket _sock;
+
+    /**
+     * 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;
+
+    /**
+     * Creates a COPSPepMsgSender
+     *
+     * @param clientType        Client-type
+     * @param clientHandle      Client handle
+     * @param sock              Socket connected to the PDP
+     */
+    public COPSPepOSMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
+        // COPS Handle
+        _handle = clientHandle;
+        _clientType = clientType;
+
+        _sock = sock;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Sends a request to the PDP.
+     * The PEP establishes a request state client handle for which the
+     * remote PDP may maintain state.
+     * @param    clientSIs              Client data
+     * @throws   COPSPepException
+     */
+    public void sendRequest(final Set<COPSClientSI> clientSIs) throws COPSPepException {
+        // Create COPS Message
+        final COPSReqMsg msg = new COPSReqMsg(_clientType, _handle, new COPSContext(RType.CONFIG, (short)0), null,
+                null, null, clientSIs, null);
+
+        // Send message
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the request, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a failure report to the PDP. This report message notifies the PDP
+     * of failure when carrying out the PDP's decision, or when reporting
+     *  an accounting related state change.
+     * @param clientSIs Report data
+     * @throws   COPSPepException
+     */
+    public void sendFailReport(final List<COPSClientSI> clientSIs) throws COPSPepException {
+        sendReport(clientSIs, new COPSReportType(ReportType.FAILURE));
+    }
+
+    /**
+     * Sends a success report to the PDP. This report message notifies the PDP
+     * of success when carrying out the PDP's decision, or when reporting
+     *  an accounting related state change.
+     * @param   clientSIs   Report data
+     * @throws  COPSPepException
+     */
+    public void sendSuccessReport(final List<COPSClientSI> clientSIs) throws COPSPepException {
+        sendReport(clientSIs, new COPSReportType(ReportType.SUCCESS));
+    }
+
+    /**
+     * Sends an accounting report to the PDP
+     * @param clientSIs Report data
+     * @throws COPSPepException
+     */
+    public void sendAcctReport(final List<COPSClientSI> clientSIs) throws COPSPepException {
+        sendReport(clientSIs, new COPSReportType(ReportType.ACCOUNTING));
+    }
+
+    private void sendReport(final List<COPSClientSI> clientSIs, final COPSReportType type) throws COPSPepException {
+        // Change back to old way if it is ultimately determined that a report may contain more than one COPSClientSI
+        final COPSReportMsg msg = new COPSReportMsg(_clientType, _handle, type, null, null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a sync-complete message to the PDP. This indicates the
+     * end of a synchronization requested by the PDP.
+     * @throws   COPSPepException
+     */
+    public void sendSyncComplete() throws COPSPepException {
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a delete request to the PDP.
+     * When sent from the PEP this message indicates to the remote PDP that
+     * the state identified by the client handle is no longer
+     * available/relevant.
+     * @throws   COPSPepException
+     */
+    public void sendDeleteRequest() throws COPSPepException {
+        // *** TODO: use real reason codes
+        COPSReason reason = new COPSReason(ReasonCode.UNSPECIFIED, ReasonCode.NA);
+
+        final COPSDeleteMsg msg = new COPSDeleteMsg(_clientType, _handle, reason, null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());
+        }
+    }
+
+}
index 3cc66a3d74c5e0084fee8e636f92d504ffcbbddb..3a19c5059b11f7362afef55657000394b52092a2 100644 (file)
-package org.umu.cops.ospep;\r
-\r
-import org.umu.cops.stack.*;\r
-\r
-import java.net.Socket;\r
-import java.util.Vector;\r
-\r
-/**\r
- * State manager class for outsourcing requests, at the PEP side.\r
- */\r
-public class COPSPepOSReqStateMan {\r
-    /**\r
-     * Request State created\r
-     */\r
-    public final static short ST_CREATE = 1;\r
-    /**\r
-     * Request sent\r
-     */\r
-    public final static short ST_INIT = 2;\r
-    /**\r
-     * Decisions received\r
-     */\r
-    public final static short ST_DECS = 3;\r
-    /**\r
-     * Report sent\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 received\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 COPSPepOSDataProcess _process;\r
-\r
-    /**\r
-     * ClientSI data from signaling.\r
-     */\r
-    protected Vector _clientSIs;\r
-\r
-    /**\r
-     *  Current state of the request being managed\r
-     */\r
-    protected short _status;\r
-\r
-    /**\r
-        COPS message transceiver used to send COPS messages\r
-     */\r
-    protected COPSPepOSMsgSender _sender;\r
-\r
-    /**\r
-     * Sync state\r
-     */\r
-    protected boolean _syncState;\r
-\r
-    /**\r
-     * Creates a state request manager\r
-     * @param    clientType Client-type\r
-     * @param   clientHandle    Client's <tt>COPSHandle</tt>\r
-     */\r
-    public COPSPepOSReqStateMan(short clientType, String clientHandle) {\r
-        // COPS Handle\r
-        _handle = new COPSHandle(new COPSData(clientHandle));\r
-        _clientType = clientType;\r
-        _syncState = true;\r
-        _status = ST_CREATE;\r
-        _clientSIs = null;\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
-     * Sets the client SI data.\r
-     * @param someClientSIs Client SI data built by the event listener\r
-     */\r
-    public void setClientSI(Vector someClientSIs) {\r
-        _clientSIs = someClientSIs;\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 request status\r
-     * @return  Request status value\r
-     */\r
-    public short getStatus() {\r
-        return _status;\r
-    }\r
-\r
-    /**\r
-     * Gets the policy data processing object\r
-     *\r
-     * @return   Policy data processing object\r
-     *\r
-     */\r
-    public COPSPepOSDataProcess getDataProcess() {\r
-        return _process;\r
-    }\r
-\r
-    /**\r
-     * Sets the policy data processing object\r
-     *\r
-     * @param   process   Policy data processing object\r
-     *\r
-     */\r
-    public void setDataProcess(COPSPepOSDataProcess process) {\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Initializes a new request state over a socket\r
-     * @param sock  Socket to the PDP\r
-     * @throws COPSPepException\r
-     */\r
-    protected void initRequestState(Socket sock) throws COPSPepException {\r
-        // Inits an object for sending COPS messages to the PDP\r
-        _sender = new COPSPepOSMsgSender(_clientType, _handle, sock);\r
-\r
-        // If an object exists for retrieving the PEP features,\r
-        // use it for retrieving them.\r
-        /*      Hashtable clientSIs;\r
-                if (_process != null)\r
-                    clientSIs = _process.getClientData(this);\r
-                else\r
-                    clientSIs = null;*/\r
-\r
-        // Semd the request\r
-        _sender.sendRequest(_clientSIs);\r
-\r
-        // Initial state\r
-        _status = ST_INIT;\r
-    }\r
-\r
-    /**\r
-     * Deletes the request state\r
-     * @throws COPSPepException\r
-     */\r
-    protected void finalizeRequestState() throws COPSPepException {\r
-        _sender.sendDeleteRequest();\r
-        _status = ST_FINAL;\r
-    }\r
-\r
-    /**\r
-     * Processes the decision message\r
-     * @param    dMsg Decision message from the PDP\r
-     * @throws   COPSPepException\r
-     */\r
-    protected void processDecision(COPSDecisionMsg dMsg) throws COPSPepException {\r
-        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());\r
-\r
-        //Hashtable decisionsPerContext = dMsg.getDecisions();\r
-\r
-        //** Applies decisions to the configuration\r
-        //_process.setDecisions(this, removeDecs, installDecs, errorDecs);\r
-        // second param changed to dMsg so that the data processor\r
-        // can check the 'solicited' flag\r
-        boolean isFailReport = _process.setDecisions(this, dMsg /*decisionsPerContext*/);\r
-        _status = ST_DECS;\r
-\r
-        if (isFailReport) {\r
-            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");\r
-            _sender.sendFailReport(_process.getReportData(this));\r
-        } else {\r
-            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");\r
-            _sender.sendSuccessReport(_process.getReportData(this));\r
-        }\r
-        _status = ST_REPORT;\r
-\r
-        if (!_syncState) {\r
-            _sender.sendSyncComplete();\r
-            _syncState = true;\r
-            _status = ST_SYNCALL;\r
-        }\r
-    }\r
-\r
-\r
-    /**\r
-     * Processes a COPS delete message\r
-     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PDP\r
-     * @throws COPSPepException\r
-     */\r
-    protected void processDeleteRequestState(COPSDecisionMsg dMsg) throws COPSPepException {\r
-        if (_process != null)\r
-            _process.closeRequestState(this);\r
-\r
-        _status = ST_DEL;\r
-    }\r
-\r
-    /**\r
-     * Processes the message SycnStateRequest.\r
-     * The message SycnStateRequest indicates that the remote PDP\r
-     * wishes the client (which appears in the common header)\r
-     * to re-send its state.\r
-     *\r
-     * @param    ssMsg               The sync request from the PDP\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg) throws COPSPepException {\r
-        _syncState = false;\r
-        // If an object exists for retrieving the PEP features,\r
-        // use it for retrieving them.\r
-\r
-        // Send the request\r
-        _sender.sendRequest(_clientSIs);\r
-\r
-        _status = ST_SYNC;\r
-    }\r
-\r
-    /**\r
-     * Called when connection is closed\r
-     * @param error Reason\r
-     * @throws COPSPepException\r
-     */\r
-    protected void processClosedConnection(COPSError error) throws COPSPepException {\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 COPSPepException\r
-     */\r
-    protected void processNoKAConnection() throws COPSPepException {\r
-        if (_process != null)\r
-            _process.notifyNoKAliveReceived(this);\r
-\r
-        _status = ST_NOKA;\r
-    }\r
-\r
-    /**\r
-     * Processes the accounting report\r
-     * @throws COPSPepException\r
-     */\r
-    protected void processAcctReport() throws COPSPepException {\r
-        Vector report = new Vector();\r
-\r
-        if (_process != null)\r
-            report = _process.getAcctData(this);\r
-\r
-        _sender.sendAcctReport(report);\r
-\r
-        _status = ST_ACCT;\r
-    }\r
-}\r
+package org.umu.cops.ospep;
+
+import org.umu.cops.stack.*;
+
+import java.net.Socket;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * State manager class for outsourcing requests, at the PEP side.
+ */
+public class COPSPepOSReqStateMan {
+    /**
+     * Request State created
+     */
+    public final static short ST_CREATE = 1;
+    /**
+     * Request sent
+     */
+    public final static short ST_INIT = 2;
+    /**
+     * Decisions received
+     */
+    public final static short ST_DECS = 3;
+    /**
+     * Report sent
+     */
+    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 received
+     */
+    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;
+
+    /**
+        Object for performing policy data processing
+     */
+    protected COPSPepOSDataProcess _process;
+
+    /**
+     * ClientSI data from signaling.
+     */
+    protected final Set<COPSClientSI> _clientSIs;
+
+    /**
+     *  Current state of the request being managed
+     */
+    protected short _status;
+
+    /**
+        COPS message transceiver used to send COPS messages
+     */
+    protected COPSPepOSMsgSender _sender;
+
+    /**
+     * Sync state
+     */
+    protected boolean _syncState;
+
+    /**
+     * Creates a state request manager
+     * @param    clientType Client-type
+     * @param   clientHandle    Client's <tt>COPSHandle</tt>
+     */
+    public COPSPepOSReqStateMan(final short clientType, final String clientHandle) {
+        // COPS Handle
+        _handle = new COPSHandle(new COPSData(clientHandle));
+        _clientType = clientType;
+        _syncState = true;
+        _status = ST_CREATE;
+        _clientSIs = null;
+    }
+
+    /**
+     * Gets the client handle
+     * @return  Client's <tt>COPSHandle</tt>
+     */
+    public COPSHandle getClientHandle() {
+        return _handle;
+    }
+
+    /**
+     * Sets the client SI data.
+     * @param someClientSIs Client SI data built by the event listener
+     */
+    public void setClientSI(final List<COPSClientSI> someClientSIs) {
+        _clientSIs.addAll(someClientSIs);
+    }
+
+    /**
+     * Gets the client-type
+     * @return  Client-type value
+     */
+    public int getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Gets the request status
+     * @return  Request status value
+     */
+    public short getStatus() {
+        return _status;
+    }
+
+    /**
+     * Gets the policy data processing object
+     *
+     * @return   Policy data processing object
+     *
+     */
+    public COPSPepOSDataProcess getDataProcess() {
+        return _process;
+    }
+
+    /**
+     * Sets the policy data processing object
+     *
+     * @param   process   Policy data processing object
+     *
+     */
+    public void setDataProcess(COPSPepOSDataProcess process) {
+        _process = process;
+    }
+
+    /**
+     * Initializes a new request state over a socket
+     * @param sock  Socket to the PDP
+     * @throws COPSPepException
+     */
+    protected void initRequestState(Socket sock) throws COPSPepException {
+        // Inits an object for sending COPS messages to the PDP
+        _sender = new COPSPepOSMsgSender(_clientType, _handle, sock);
+
+        // If an object exists for retrieving the PEP features,
+        // use it for retrieving them.
+        /*      Hashtable clientSIs;
+                if (_process != null)
+                    clientSIs = _process.getClientData(this);
+                else
+                    clientSIs = null;*/
+
+        // Semd the request
+        _sender.sendRequest(_clientSIs);
+
+        // Initial state
+        _status = ST_INIT;
+    }
+
+    /**
+     * Deletes the request state
+     * @throws COPSPepException
+     */
+    protected void finalizeRequestState() throws COPSPepException {
+        _sender.sendDeleteRequest();
+        _status = ST_FINAL;
+    }
+
+    /**
+     * Processes the decision message
+     * @param    dMsg Decision message from the PDP
+     * @throws   COPSPepException
+     */
+    protected void processDecision(COPSDecisionMsg dMsg) throws COPSPepException {
+        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
+
+        //Hashtable decisionsPerContext = dMsg.getDecisions();
+
+        //** Applies decisions to the configuration
+        //_process.setDecisions(this, removeDecs, installDecs, errorDecs);
+        // second param changed to dMsg so that the data processor
+        // can check the 'solicited' flag
+        boolean isFailReport = _process.setDecisions(this, dMsg /*decisionsPerContext*/);
+        _status = ST_DECS;
+
+        if (isFailReport) {
+            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
+            _sender.sendFailReport(_process.getReportData(this));
+        } else {
+            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
+            _sender.sendSuccessReport(_process.getReportData(this));
+        }
+        _status = ST_REPORT;
+
+        if (!_syncState) {
+            _sender.sendSyncComplete();
+            _syncState = true;
+            _status = ST_SYNCALL;
+        }
+    }
+
+
+    /**
+     * Processes a COPS delete message
+     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PDP
+     * @throws COPSPepException
+     */
+    protected void processDeleteRequestState(COPSDecisionMsg dMsg) throws COPSPepException {
+        if (_process != null)
+            _process.closeRequestState(this);
+
+        _status = ST_DEL;
+    }
+
+    /**
+     * Processes the message SycnStateRequest.
+     * The message SycnStateRequest indicates that the remote PDP
+     * wishes the client (which appears in the common header)
+     * to re-send its state.
+     *
+     * @param    ssMsg               The sync request from the PDP
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg) throws COPSPepException {
+        _syncState = false;
+        // If an object exists for retrieving the PEP features,
+        // use it for retrieving them.
+
+        // Send the request
+        _sender.sendRequest(_clientSIs);
+
+        _status = ST_SYNC;
+    }
+
+    /**
+     * Called when connection is closed
+     * @param error Reason
+     * @throws COPSPepException
+     */
+    protected void processClosedConnection(COPSError error) throws COPSPepException {
+        if (_process != null)
+            _process.notifyClosedConnection(this, error);
+
+        _status = ST_CCONN;
+    }
+
+    /**
+     * Called when no keep-alive is received
+     * @throws COPSPepException
+     */
+    protected void processNoKAConnection() throws COPSPepException {
+        if (_process != null)
+            _process.notifyNoKAliveReceived(this);
+
+        _status = ST_NOKA;
+    }
+
+    /**
+     * Processes the accounting report
+     * @throws COPSPepException
+     */
+    protected void processAcctReport() throws COPSPepException {
+        Vector report = new Vector();
+
+        if (_process != null)
+            report = _process.getAcctData(this);
+
+        _sender.sendAcctReport(report);
+
+        _status = ST_ACCT;
+    }
+}
index be174403844701cc5d3c7803d58fd27ca90dfd18..a5c9dd6ef029d4af43ca701ca16dd010cce8dbba 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.ServerSocket;\r
-import java.net.Socket;\r
-import java.util.Hashtable;\r
-import java.util.Map;\r
-import java.util.concurrent.ConcurrentHashMap;\r
-\r
-/**\r
- * Core PDP agent for provisioning\r
- */\r
-public class COPSPdpAgent extends Thread {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);\r
-\r
-    /** Well-known port for COPS */\r
-    public static final int WELL_KNOWN_PDP_PORT = 3288;\r
-    /** Default keep-alive timer value (secs) */\r
-    public static final short KA_TIMER_VALUE = 30;\r
-    /** Default accounting timer value (secs) */\r
-    public static final short ACCT_TIMER_VALUE = 0;\r
-\r
-    /**\r
-        PDP host port\r
-     */\r
-    private int _serverPort;\r
-\r
-    /**\r
-        Client-type of connecting PEP\r
-     */\r
-    private short _clientType;\r
-\r
-    /**\r
-        Accounting timer (secs)\r
-     */\r
-    private short _acctTimer;\r
-\r
-    /**\r
-        Keep-alive timer (secs)\r
-     */\r
-    private short _kaTimer;\r
-\r
-    /**\r
-        Maps a PEP-ID to a connection\r
-     */\r
-    private final Map<String, COPSPdpConnection> _connectionMap;\r
-    // map < String(PEPID), COPSPdpConnection > ConnectionMap;\r
-\r
-    /**\r
-     *  Policy data processing object\r
-     */\r
-    private COPSPdpDataProcess _process;\r
-\r
-    /**\r
-     * Creates a PDP Agent\r
-     *\r
-     * @param clientType    COPS Client-type\r
-     * @param process       Object to perform policy data processing\r
-     */\r
-    public COPSPdpAgent(short clientType, COPSPdpDataProcess process) {\r
-        _serverPort = WELL_KNOWN_PDP_PORT;\r
-        _kaTimer = KA_TIMER_VALUE;\r
-        _acctTimer = ACCT_TIMER_VALUE;\r
-\r
-        _clientType = clientType;\r
-        _connectionMap = new ConcurrentHashMap<>();\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Creates a PDP Agent\r
-     *\r
-     * @param port  Port to listen to\r
-     * @param clientType    COPS Client-type\r
-     * @param process   Object to perform policy data processing\r
-     */\r
-    public COPSPdpAgent(int port, short clientType, COPSPdpDataProcess process) {\r
-        _serverPort = port;\r
-\r
-        _kaTimer = KA_TIMER_VALUE;\r
-        _acctTimer = ACCT_TIMER_VALUE;\r
-\r
-        _clientType = clientType;\r
-        _connectionMap = new ConcurrentHashMap<>();\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Sets the keep-alive timer value\r
-     * @param    kaTimer    Keep alive timer value (secs)\r
-     */\r
-    public void setKaTimer (short kaTimer) {\r
-        _kaTimer = kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Sets the accounting timer value\r
-     * @param    acctTimer  Accounting timer value (secs)\r
-     */\r
-    public void setAcctTimer (short acctTimer) {\r
-        _acctTimer = acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the value of the keep-alive timer\r
-     * @return   Keep-alive timer value (secs)\r
-     */\r
-    public short getKaTimer () {\r
-        return _kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the accounting timer value\r
-     * @return   Accounting timer value (secs)\r
-     */\r
-    public short getAcctTimer () {\r
-        return _acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the connection map\r
-     * @return   A <tt>Hashtable</tt> holding the connection map\r
-     */\r
-    public Hashtable getConnectionMap() {\r
-        return new Hashtable(_connectionMap);\r
-    }\r
-\r
-    /**\r
-     * Gets the client-type\r
-     * @return   The client-type\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Disconnects a PEP\r
-     * @param pepID PEP-ID of the PEP to be disconnected\r
-     * @param error COPS Error to be reported as a reason\r
-     * @throws COPSException\r
-     * @throws IOException\r
-     */\r
-    public void disconnect (String pepID, COPSError error)\r
-    throws COPSException, IOException {\r
-\r
-        COPSPdpConnection pdpConn = _connectionMap.get(pepID);\r
-\r
-        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
-        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-        closeMsg.add(cHdr);\r
-        if (error != null)\r
-            closeMsg.add(error);\r
-\r
-        closeMsg.writeData(pdpConn.getSocket());\r
-        pdpConn.close();\r
-    }\r
-\r
-    /**\r
-     * Requests a COPS sync for a PEP\r
-     * @param pepID PEP-ID of the PEP to be synced\r
-     * @throws COPSException\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sync (String pepID)\r
-    throws COPSException, COPSPdpException {\r
-\r
-        COPSPdpConnection pdpConn = _connectionMap.get(pepID);\r
-        pdpConn.syncAllRequestState();\r
-    }\r
-\r
-    /**\r
-     * Removes a PEP from the connection map\r
-     * @param pepID PEP-ID of the PEP to be removed\r
-     */\r
-    public void delete (String pepID) {\r
-        _connectionMap.remove(pepID);\r
-    }\r
-\r
-\r
-    /**\r
-     * Runs the PDP process\r
-     */\r
-    public void run() {\r
-        try {\r
-            final ServerSocket serverSocket = new ServerSocket (_serverPort);\r
-\r
-            //Loop through for Incoming messages\r
-\r
-            // server infinite loop\r
-            while (true) {\r
-\r
-                // Wait for an incoming connection from a PEP\r
-                Socket socket = serverSocket.accept();\r
-\r
-                // COPSDebug.out(getClass().getName(),"New connection accepted " +\r
-                //           socket.getInetAddress() +\r
-                //           ":" + socket.getPort());\r
-\r
-                // We're waiting for an OPN message\r
-                try {\r
-                    COPSMsg msg = COPSTransceiver.receiveMsg(socket);\r
-                    if (msg.getHeader().isAClientOpen()) {\r
-                        handleClientOpenMsg(socket, msg);\r
-                    } else {\r
-                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
-                        try {\r
-                            socket.close();\r
-                        } catch (Exception ex) {\r
-                            logger.error("Error closing socket", ex);\r
-                        }\r
-                    }\r
-                } catch (Exception e) { // COPSException, IOException\r
-                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,\r
-                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);\r
-                    try {\r
-                        socket.close();\r
-                    } catch (Exception ex) {\r
-                        logger.error("Error closing socket", ex);\r
-                    }\r
-                }\r
-            }\r
-        } catch (IOException e) {\r
-            logger.error("Error caught while processing socket messages", e);\r
-        }\r
-    }\r
-\r
-    /**\r
-      * Handles a COPS client-open message\r
-      * @param    conn Socket to the PEP\r
-      * @param    msg <tt>COPSMsg</tt> holding the client-open message\r
-      * @throws COPSException\r
-      * @throws IOException\r
-      */\r
-    private void handleClientOpenMsg(Socket conn, COPSMsg msg)\r
-    throws COPSException, IOException {\r
-        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;\r
-        COPSPepId pepId = cMsg.getPepId();\r
-\r
-        // Validate Client Type\r
-        if (msg.getHeader().getClientType() != _clientType) {\r
-            // Unsupported client type\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing COPS data", unae);\r
-            }\r
-\r
-            throw new COPSException("Unsupported client type");\r
-        }\r
-\r
-        // PEPId is mandatory\r
-        if (pepId == null) {\r
-            // Mandatory COPS object missing\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing close message", unae);\r
-            }\r
-\r
-            throw new COPSException("Mandatory COPS object missing (PEPId)");\r
-        }\r
-\r
-        // Support\r
-        if ( (cMsg.getClientSI() != null) ||\r
-                (cMsg.getPdpAddress() != null) ||\r
-                (cMsg.getIntegrity() != null)) {\r
-\r
-            // Unsupported objects\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing close message", unae);\r
-            }\r
-\r
-            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");\r
-        }\r
-\r
-        // Connection accepted\r
-        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());\r
-        COPSKATimer katimer = new COPSKATimer(_kaTimer);\r
-        COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);\r
-        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();\r
-        acceptMsg.add(ahdr);\r
-        acceptMsg.add(katimer) ;\r
-        if (_acctTimer != 0) acceptMsg.add(acctTimer);\r
-        acceptMsg.writeData(conn);\r
-\r
-        COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);\r
-        pdpConn.setKaTimer(_kaTimer);\r
-        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);\r
-        new Thread(pdpConn).start();\r
-        _connectionMap.put(pepId.getData().str(),pdpConn);\r
-    }\r
-\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Core PDP agent for provisioning
+ */
+public class COPSPdpAgent extends Thread {
+
+    public final static Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
+
+    /** Well-known port for COPS */
+    public static final int WELL_KNOWN_PDP_PORT = 3288;
+    /** Default keep-alive timer value (secs) */
+    public static final short KA_TIMER_VALUE = 30;
+    /** Default accounting timer value (secs) */
+    public static final short ACCT_TIMER_VALUE = 0;
+
+    /**
+        PDP host port
+     */
+    private int _serverPort;
+
+    /**
+        Client-type of connecting PEP
+     */
+    private short _clientType;
+
+    /**
+        Accounting timer (secs)
+     */
+    private short _acctTimer;
+
+    /**
+        Keep-alive timer (secs)
+     */
+    private short _kaTimer;
+
+    /**
+        Maps a PEP-ID to a connection
+     */
+    private final Map<String, COPSPdpConnection> _connectionMap;
+    // map < String(PEPID), COPSPdpConnection > ConnectionMap;
+
+    /**
+     *  Policy data processing object
+     */
+    private COPSPdpDataProcess _process;
+
+    /**
+     * Creates a PDP Agent
+     *
+     * @param clientType    COPS Client-type
+     * @param process       Object to perform policy data processing
+     */
+    public COPSPdpAgent(final short clientType, final COPSPdpDataProcess process) {
+        _serverPort = WELL_KNOWN_PDP_PORT;
+        _kaTimer = KA_TIMER_VALUE;
+        _acctTimer = ACCT_TIMER_VALUE;
+
+        _clientType = clientType;
+        _connectionMap = new ConcurrentHashMap<>();
+        _process = process;
+    }
+
+    /**
+     * Creates a PDP Agent
+     *
+     * @param port  Port to listen to
+     * @param clientType    COPS Client-type
+     * @param process   Object to perform policy data processing
+     */
+    public COPSPdpAgent(final int port, final short clientType, final COPSPdpDataProcess process) {
+        _serverPort = port;
+
+        _kaTimer = KA_TIMER_VALUE;
+        _acctTimer = ACCT_TIMER_VALUE;
+
+        _clientType = clientType;
+        _connectionMap = new ConcurrentHashMap<>();
+        _process = process;
+    }
+
+    /**
+     * Sets the keep-alive timer value
+     * @param    kaTimer    Keep alive timer value (secs)
+     */
+    public void setKaTimer (short kaTimer) {
+        _kaTimer = kaTimer;
+    }
+
+    /**
+     * Sets the accounting timer value
+     * @param    acctTimer  Accounting timer value (secs)
+     */
+    public void setAcctTimer (short acctTimer) {
+        _acctTimer = acctTimer;
+    }
+
+    /**
+     * Gets the value of the keep-alive timer
+     * @return   Keep-alive timer value (secs)
+     */
+    public short getKaTimer () {
+        return _kaTimer;
+    }
+
+    /**
+     * Gets the accounting timer value
+     * @return   Accounting timer value (secs)
+     */
+    public short getAcctTimer () {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets the client-type
+     * @return   The client-type
+     */
+    public short getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Disconnects a PEP
+     * @param pepID PEP-ID of the PEP to be disconnected
+     * @param error COPS Error to be reported as a reason
+     * @throws COPSException
+     * @throws IOException
+     */
+    public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
+        final COPSPdpConnection pdpConn = _connectionMap.get(pepID);
+        final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
+        closeMsg.writeData(pdpConn.getSocket());
+        pdpConn.close();
+    }
+
+    /**
+     * Requests a COPS sync for a PEP
+     * @param pepID PEP-ID of the PEP to be synced
+     * @throws COPSException
+     * @throws COPSPdpException
+     */
+    public void sync (String pepID)
+    throws COPSException, COPSPdpException {
+
+        COPSPdpConnection pdpConn = _connectionMap.get(pepID);
+        pdpConn.syncAllRequestState();
+    }
+
+    /**
+     * Removes a PEP from the connection map
+     * @param pepID PEP-ID of the PEP to be removed
+     */
+    public void delete (String pepID) {
+        _connectionMap.remove(pepID);
+    }
+
+
+    /**
+     * Runs the PDP process
+     */
+    public void run() {
+        try {
+            final ServerSocket serverSocket = new ServerSocket (_serverPort);
+
+            //Loop through for Incoming messages
+
+            // server infinite loop
+            while (true) {
+
+                // Wait for an incoming connection from a PEP
+                Socket socket = serverSocket.accept();
+
+                // COPSDebug.out(getClass().getName(),"New connection accepted " +
+                //           socket.getInetAddress() +
+                //           ":" + socket.getPort());
+
+                // We're waiting for an OPN message
+                try {
+                    final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+                    if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
+                        handleClientOpenMsg(socket, msg);
+                    } else {
+                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+                        try {
+                            socket.close();
+                        } catch (Exception ex) {
+                            logger.error("Error closing socket", ex);
+                        }
+                    }
+                } catch (Exception e) { // COPSException, IOException
+                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,
+                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);
+                    try {
+                        socket.close();
+                    } catch (Exception ex) {
+                        logger.error("Error closing socket", ex);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            logger.error("Error caught while processing socket messages", e);
+        }
+    }
+
+    /**
+      * Handles a COPS client-open message
+      * @param    conn Socket to the PEP
+      * @param    msg <tt>COPSMsg</tt> holding the client-open message
+      * @throws COPSException
+      * @throws IOException
+      */
+    private void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+        final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
+        final COPSPepId pepId = cMsg.getPepId();
+
+        // Validate Client Type
+        if (msg.getHeader().getClientType() == _clientType) {
+            // Unsupported client type
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                    new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Error writing COPS data", unae);
+            }
+
+            throw new COPSException("Unsupported client type");
+        }
+
+        // PEPId is mandatory
+        if (pepId == null) {
+            // Mandatory COPS object missing
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                    new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Error writing close message", unae);
+            }
+
+            throw new COPSException("Mandatory COPS object missing (PEPId)");
+        }
+
+        // Support
+        if ( (cMsg.getClientSI() != null) ||
+                (cMsg.getPdpAddress() != null) ||
+                (cMsg.getIntegrity() != null)) {
+
+            // Unsupported objects
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                    new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Error writing close message", unae);
+            }
+
+            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
+        }
+
+        // Connection accepted
+        final COPSKATimer katimer = new COPSKATimer(_kaTimer);
+        final COPSClientAcceptMsg acceptMsg;
+        if (_acctTimer != 0) acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
+        else acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer,
+                new COPSAcctTimer(_acctTimer), null);
+        acceptMsg.writeData(conn);
+
+        final COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);
+        pdpConn.setKaTimer(_kaTimer);
+        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);
+        new Thread(pdpConn).start();
+        _connectionMap.put(pepId.getData().str(),pdpConn);
+    }
+
+}
+
+
+
index c79abc6a9a4e85103c25324c0549370812fea77a..31a9379e143b0575c0c0bbb3e0f3943d5dda51d6 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Date;\r
-import java.util.Map;\r
-import java.util.concurrent.ConcurrentHashMap;\r
-\r
-/**\r
- * Class for managing an provisioning connection at the PDP side.\r
- */\r
-public class COPSPdpConnection implements Runnable {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(COPSPdpConnection.class);\r
-\r
-    /**\r
-        Socket connected to PEP\r
-     */\r
-    private Socket _sock;\r
-\r
-    /**\r
-        PEP identifier\r
-    */\r
-    private COPSPepId _pepId;\r
-\r
-    /**\r
-        Time of the latest keep-alive sent\r
-     */\r
-    private Date _lastKa;\r
-\r
-    /**\r
-        Opcode of the latest message sent\r
-    */\r
-    private byte _lastmessage;\r
-\r
-    /**\r
-     *  Time of the latest keep-alive received\r
-     */\r
-    protected Date _lastRecKa;\r
-\r
-    /**\r
-        Maps a Client Handle to a Handler\r
-     */\r
-    protected final Map<String, COPSPdpReqStateMan> _managerMap;\r
-    // map < String(COPSHandle), COPSPdpHandler> HandlerMap;\r
-\r
-    /**\r
-     *  PDP policy data processor class\r
-     */\r
-    protected COPSPdpDataProcess _process;\r
-\r
-    /**\r
-        Accounting timer value (secs)\r
-     */\r
-    protected short _acctTimer;\r
-\r
-    /**\r
-        Keep-alive timer value (secs)\r
-     */\r
-    protected short _kaTimer;\r
-\r
-    /**\r
-        COPS error returned by PEP\r
-     */\r
-    protected COPSError _error;\r
-\r
-    /**\r
-     * Creates a new PDP connection\r
-     *\r
-     * @param pepId PEP-ID of the connected PEP\r
-     * @param sock  Socket connected to PEP\r
-     * @param process   Object for processing policy data\r
-     */\r
-    public COPSPdpConnection(COPSPepId pepId, Socket sock, COPSPdpDataProcess process) {\r
-        _sock = sock;\r
-        _pepId = pepId;\r
-\r
-        _lastKa = new Date();\r
-        _lastmessage = COPSHeader.COPS_OP_OPN;\r
-        _managerMap = new ConcurrentHashMap<>();\r
-\r
-        _kaTimer = 0;\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Gets the time of that latest keep-alive sent\r
-     * @return Time of that latest keep-alive sent\r
-     */\r
-    public Date getLastKAlive() {\r
-        return _lastKa;\r
-    }\r
-\r
-    /**\r
-     * Sets the keep-alive timer value\r
-     * @param kaTimer Keep-alive timer value (secs)\r
-     */\r
-    public void setKaTimer(short kaTimer) {\r
-        _kaTimer = kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the keep-alive timer value\r
-     * @return Keep-alive timer value (secs)\r
-     */\r
-    public short getKaTimer() {\r
-        return _kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Sets the accounting timer value\r
-     * @param acctTimer Accounting timer value (secs)\r
-     */\r
-    public void setAccTimer(short acctTimer) {\r
-        _acctTimer = acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the accounting timer value\r
-     * @return Accounting timer value (secs)\r
-     */\r
-    public short getAcctTimer() {\r
-        return _acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the latest COPS message\r
-     * @return   Code of the latest message sent\r
-     */\r
-    public byte getLastMessage() {\r
-        return _lastmessage;\r
-    }\r
-\r
-    /**\r
-     * Gets the PEP-ID\r
-     * @return   The ID of the PEP, as a <tt>String</tt>\r
-     */\r
-    public String getPepId() {\r
-        return _pepId.getData().str();\r
-    }\r
-\r
-    /**\r
-     * Checks whether the socket to the PEP is closed or not\r
-     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise\r
-     */\r
-    public boolean isClosed() {\r
-        return _sock.isClosed();\r
-    }\r
-\r
-    /**\r
-     * Closes the socket to the PEP\r
-     * @throws IOException\r
-     */\r
-    protected void close()\r
-    throws IOException {\r
-        _sock.close();\r
-    }\r
-\r
-    /**\r
-     * Gets the socket to the PEP\r
-     * @return   Socket connected to the PEP\r
-     */\r
-    public Socket getSocket() {\r
-        return _sock;\r
-    }\r
-\r
-    /**\r
-     * Main loop\r
-     */\r
-    public void run () {\r
-        Date _lastSendKa = new Date();\r
-        _lastRecKa = new Date();\r
-        try {\r
-            while (!_sock.isClosed()) {\r
-                if (_sock.getInputStream().available() != 0) {\r
-                    _lastmessage = processMessage(_sock);\r
-                    _lastRecKa = new Date();\r
-                }\r
-\r
-                // Keep Alive\r
-                if (_kaTimer > 0) {\r
-                    // Timeout at PDP\r
-                    int _startTime = (int) (_lastRecKa.getTime());\r
-                    int cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > _kaTimer * 1000) {\r
-                        _sock.close();\r
-                        // Notify all Request State Managers\r
-                        notifyNoKAAllReqStateMan();\r
-                    }\r
-\r
-                    // Send to PEP\r
-                    _startTime = (int) (_lastSendKa.getTime());\r
-                    cTime = (int) (new Date().getTime());\r
-\r
-                    if ((cTime - _startTime) > ((_kaTimer * 3/4) * 1000)) {\r
-                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
-                        COPSKAMsg msg = new COPSKAMsg();\r
-\r
-                        msg.add(hdr);\r
-\r
-                        COPSTransceiver.sendMsg(msg, _sock);\r
-                        _lastSendKa = new Date();\r
-                    }\r
-                }\r
-\r
-                try {\r
-                    Thread.sleep(500);\r
-                } catch (Exception e) {\r
-                    logger.error("Exception thrown while sleeping", e);\r
-                }\r
-\r
-            }\r
-        } catch (Exception e) {\r
-            logger.error("Error while processing socket messages", e);\r
-        }\r
-\r
-        // connection closed by server\r
-        // COPSDebug.out(getClass().getName(),"Connection closed by client");\r
-        try {\r
-            _sock.close();\r
-        } catch (IOException e) {\r
-            logger.error("Error closing socket", e);\r
-        }\r
-\r
-        // Notify all Request State Managers\r
-        try {\r
-            notifyCloseAllReqStateMan();\r
-        } catch (COPSPdpException e) {\r
-            logger.error("Error closing state managers");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Gets a COPS message from the socket and processes it\r
-     * @param    conn Socket connected to the PEP\r
-     * @return Type of COPS message\r
-     */\r
-    private byte processMessage(Socket conn)\r
-    throws COPSPdpException, COPSException, IOException {\r
-        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
-\r
-        if (msg.getHeader().isAClientClose()) {\r
-            handleClientCloseMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_CC;\r
-        } else if (msg.getHeader().isAKeepAlive()) {\r
-            handleKeepAliveMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_KA;\r
-        } else if (msg.getHeader().isARequest()) {\r
-            handleRequestMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_REQ;\r
-        } else if (msg.getHeader().isAReport()) {\r
-            handleReportMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_RPT;\r
-        } else if (msg.getHeader().isADeleteReq()) {\r
-            handleDeleteRequestMsg(conn, msg);\r
-            return COPSHeader.COPS_OP_DRQ;\r
-        } else if (msg.getHeader().isASyncComplete()) {\r
-            handleSyncComplete(conn, msg);\r
-            return COPSHeader.COPS_OP_SSC;\r
-        } else {\r
-            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handle Client Close Message, close the passed connection\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     *\r
-     * <Client-Close> ::= <Common Header>\r
-     *                      <Error>\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     */\r
-    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
-        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
-        _error = cMsg.getError();\r
-\r
-        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
-\r
-        try {\r
-            // Support\r
-            if (cMsg.getIntegrity() != null) {\r
-                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-            }\r
-\r
-            conn.close();\r
-        } catch (Exception unae) {\r
-            logger.error("Unexpected exception closing connection", unae);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Gets the occurred COPS Error\r
-     * @return   <tt>COPSError</tt> object\r
-     */\r
-    protected COPSError getError()  {\r
-        return _error;\r
-    }\r
-\r
-    /**\r
-     * Handle Keep Alive Message\r
-     *\r
-     * <Keep-Alive> ::= <Common Header>\r
-     *                  [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
-        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
-\r
-        COPSKAMsg kaMsg = (COPSKAMsg) msg;\r
-        try {\r
-            // Support\r
-            if (cMsg.getIntegrity() != null) {\r
-                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-            }\r
-            kaMsg.writeData(conn);\r
-        } catch (Exception unae) {\r
-            logger.error("Unexpected exception while writing COPS data", unae);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handle Delete Request Message\r
-     *\r
-     * <Delete Request> ::= <Common Header>\r
-     *                      <Client Handle>\r
-     *                      <Reason>\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)\r
-    throws COPSPdpException {\r
-        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;\r
-        // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +\r
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");\r
-\r
-        // Support\r
-        if (cMsg.getIntegrity() != null) {\r
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        // Delete clientHandler\r
-        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {\r
-            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +\r
-            //  cMsg.getClientHandle().getId().getData());\r
-        }\r
-\r
-        COPSPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());\r
-        } else {\r
-            man.processDeleteRequestState(cMsg);\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * Handle Request Message\r
-     *\r
-     * <Request> ::= <Common Header>\r
-     *                  <Client Handle>\r
-     *                  <Context>\r
-     *                  *(<Named ClientSI>)\r
-     *                  [<Integrity>]\r
-     * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleRequestMsg(Socket conn, COPSMsg msg)\r
-    throws COPSPdpException {\r
-\r
-        COPSReqMsg reqMsg = (COPSReqMsg) msg;\r
-        COPSContext cntxt = reqMsg.getContext();\r
-        COPSHeader header = reqMsg.getHeader();\r
-        //short reqType = cntxt.getRequestType();\r
-        short cType   = header.getClientType();\r
-\r
-        // Support\r
-        if (reqMsg.getIntegrity() != null) {\r
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        COPSPdpReqStateMan man;\r
-        man = (COPSPdpReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-\r
-            man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());\r
-            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);\r
-            man.setDataProcess(_process);\r
-            man.initRequestState(_sock);\r
-\r
-            // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +\r
-            //    header.getClientType() + " msgType=" +\r
-            //    cntxt.getMessageType() + ", connId=" + conn.toString());\r
-        }\r
-\r
-        man.processRequest(reqMsg);\r
-    }\r
-\r
-    /**\r
-     * Handle Report Message\r
-     *\r
-     * <Report State> ::= <Common Header>\r
-     *                      <Client Handle>\r
-     *                      <Report Type>\r
-     *                      *(<Named ClientSI>)\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not support [<Integrity>]\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleReportMsg(Socket conn, COPSMsg msg)\r
-    throws COPSPdpException {\r
-        COPSReportMsg repMsg = (COPSReportMsg) msg;\r
-        // COPSHandle handle = repMsg.getClientHandle();\r
-        // COPSHeader header = repMsg.getHeader();\r
-\r
-        // Support\r
-        if (repMsg.getIntegrity() != null) {\r
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            logger.warn("No state manager found with ID - " + repMsg.getClientHandle().getId().str());\r
-        } else {\r
-            man.processReport(repMsg);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Method handleSyncComplete\r
-     *\r
-     * @param    conn                a  Socket\r
-     * @param    msg                 a  COPSMsg\r
-     *\r
-     */\r
-    private void handleSyncComplete(Socket conn, COPSMsg msg)\r
-    throws COPSPdpException {\r
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
-        // COPSHandle handle = cMsg.getClientHandle();\r
-        // COPSHeader header = cMsg.getHeader();\r
-\r
-        // Support\r
-        if (cMsg.getIntegrity() != null) {\r
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
-        }\r
-\r
-        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
-        if (man == null) {\r
-            logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());\r
-        } else {\r
-            man.processSyncComplete(cMsg);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Requests a COPS sync from the PEP\r
-     * @throws COPSException\r
-     * @throws COPSPdpException\r
-     */\r
-    protected void syncAllRequestState() throws COPSException, COPSPdpException {\r
-        for (final COPSPdpReqStateMan man : _managerMap.values()) {\r
-            man.syncRequestState();\r
-        }\r
-    }\r
-\r
-    private void notifyCloseAllReqStateMan() throws COPSPdpException {\r
-        for (final COPSPdpReqStateMan man : _managerMap.values()) {\r
-            man.processClosedConnection(_error);\r
-        }\r
-    }\r
-\r
-    private void notifyNoKAAllReqStateMan() throws COPSPdpException {\r
-        for (final COPSPdpReqStateMan man : _managerMap.values()) {\r
-            man.processNoKAConnection();\r
-        }\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.*;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Class for managing an provisioning connection at the PDP side.
+ */
+public class COPSPdpConnection implements Runnable {
+
+    public final static Logger logger = LoggerFactory.getLogger(COPSPdpConnection.class);
+
+    /**
+        Socket connected to PEP
+     */
+    private Socket _sock;
+
+    /**
+        PEP identifier
+    */
+    private COPSPepId _pepId;
+
+    /**
+        Time of the latest keep-alive sent
+     */
+    private Date _lastKa;
+
+    /**
+     *  Time of the latest keep-alive received
+     */
+    protected Date _lastRecKa;
+
+    /**
+        Maps a Client Handle to a Handler
+     */
+    protected final Map<String, COPSPdpReqStateMan> _managerMap;
+
+    /**
+     *  PDP policy data processor class
+     */
+    protected COPSPdpDataProcess _process;
+
+    /**
+        Accounting timer value (secs)
+     */
+    protected short _acctTimer;
+
+    /**
+        Keep-alive timer value (secs)
+     */
+    protected short _kaTimer;
+
+    /**
+        COPS error returned by PEP
+     */
+    protected COPSError _error;
+
+    /**
+     * Creates a new PDP connection
+     *
+     * @param pepId PEP-ID of the connected PEP
+     * @param sock  Socket connected to PEP
+     * @param process   Object for processing policy data
+     */
+    public COPSPdpConnection(COPSPepId pepId, Socket sock, COPSPdpDataProcess process) {
+        _sock = sock;
+        _pepId = pepId;
+
+        _lastKa = new Date();
+        _managerMap = new ConcurrentHashMap<>();
+
+        _kaTimer = 0;
+        _process = process;
+    }
+
+    /**
+     * Gets the time of that latest keep-alive sent
+     * @return Time of that latest keep-alive sent
+     */
+    public Date getLastKAlive() {
+        return _lastKa;
+    }
+
+    /**
+     * Sets the keep-alive timer value
+     * @param kaTimer Keep-alive timer value (secs)
+     */
+    public void setKaTimer(short kaTimer) {
+        _kaTimer = kaTimer;
+    }
+
+    /**
+     * Gets the keep-alive timer value
+     * @return Keep-alive timer value (secs)
+     */
+    public short getKaTimer() {
+        return _kaTimer;
+    }
+
+    /**
+     * Sets the accounting timer value
+     * @param acctTimer Accounting timer value (secs)
+     */
+    public void setAccTimer(short acctTimer) {
+        _acctTimer = acctTimer;
+    }
+
+    /**
+     * Gets the accounting timer value
+     * @return Accounting timer value (secs)
+     */
+    public short getAcctTimer() {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets the PEP-ID
+     * @return   The ID of the PEP, as a <tt>String</tt>
+     */
+    public String getPepId() {
+        return _pepId.getData().str();
+    }
+
+    /**
+     * Checks whether the socket to the PEP is closed or not
+     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise
+     */
+    public boolean isClosed() {
+        return _sock.isClosed();
+    }
+
+    /**
+     * Closes the socket to the PEP
+     * @throws IOException
+     */
+    protected void close()
+    throws IOException {
+        _sock.close();
+    }
+
+    /**
+     * Gets the socket to the PEP
+     * @return   Socket connected to the PEP
+     */
+    public Socket getSocket() {
+        return _sock;
+    }
+
+    /**
+     * Main loop
+     */
+    public void run () {
+        Date _lastSendKa = new Date();
+        _lastRecKa = new Date();
+        try {
+            while (!_sock.isClosed()) {
+                if (_sock.getInputStream().available() != 0) {
+                    processMessage(_sock);
+                    _lastRecKa = new Date();
+                }
+
+                // Keep Alive
+                if (_kaTimer > 0) {
+                    // Timeout at PDP
+                    int _startTime = (int) (_lastRecKa.getTime());
+                    int cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > _kaTimer*1000) {
+                        _sock.close();
+                        // Notify all Request State Managers
+                        notifyNoKAAllReqStateMan();
+                    }
+
+                    // Send to PEP
+                    _startTime = (int) (_lastSendKa.getTime());
+                    cTime = (int) (new Date().getTime());
+
+                    if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
+                        // TODO - what should the real clientType be here???
+                        final COPSKAMsg msg = new COPSKAMsg(null);
+                        COPSTransceiver.sendMsg(msg, _sock);
+                        _lastSendKa = new Date();
+                    }
+                }
+
+                try {
+                    Thread.sleep(500);
+                } catch (Exception e) {
+                    logger.error("Exception thrown while sleeping", e);
+                }
+
+            }
+        } catch (Exception e) {
+            logger.error("Error while processing socket messages", e);
+        }
+
+        // connection closed by server
+        try {
+            _sock.close();
+        } catch (IOException e) {
+            logger.error("Error closing socket", e);
+        }
+
+        // Notify all Request State Managers
+        try {
+            notifyCloseAllReqStateMan();
+        } catch (COPSPdpException e) {
+            logger.error("Error closing state managers");
+        }
+    }
+
+    /**
+     * Gets a COPS message from the socket and processes it
+     * @param    conn Socket connected to the PEP
+     */
+    private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
+        final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+        switch (msg.getHeader().getOpCode()) {
+            case CC:
+                handleClientCloseMsg(conn, msg);
+                break;
+            case KA:
+                handleKeepAliveMsg(conn, msg);
+                break;
+            case REQ:
+                handleRequestMsg(conn, msg);
+                break;
+            case RPT:
+                handleReportMsg(conn, msg);
+                break;
+            case DRQ:
+                handleDeleteRequestMsg(conn, msg);
+                break;
+            case SSC:
+                handleSyncComplete(conn, msg);
+                break;
+            default:
+                throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+        }
+    }
+
+    /**
+     * Handle Client Close Message, close the passed connection
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     *
+     * <Client-Close> ::= <Common Header>
+     *                      <Error>
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     */
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+        _error = cMsg.getError();
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            }
+            conn.close();
+        } catch (Exception unae) {
+            logger.error("Unexpected exception closing connection", unae);
+        }
+    }
+
+    /**
+     * Gets the occurred COPS Error
+     * @return   <tt>COPSError</tt> object
+     */
+    protected COPSError getError()  {
+        return _error;
+    }
+
+    /**
+     * Handle Keep Alive Message
+     *
+     * <Keep-Alive> ::= <Common Header>
+     *                  [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
+        COPSKAMsg cMsg = (COPSKAMsg) msg;
+
+        COPSKAMsg kaMsg = (COPSKAMsg) msg;
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            }
+            kaMsg.writeData(conn);
+        } catch (Exception unae) {
+            logger.error("Unexpected exception while writing COPS data", unae);
+        }
+    }
+
+    /**
+     * Handle Delete Request Message
+     *
+     * <Delete Request> ::= <Common Header>
+     *                      <Client Handle>
+     *                      <Reason>
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
+    throws COPSPdpException {
+        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
+
+        // Support
+        if (cMsg.getIntegrity() != null) {
+            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        // Delete clientHandler
+        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
+            // TODO - Do something here
+        }
+
+        COPSPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
+        if (man == null) {
+            logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
+        } else {
+            man.processDeleteRequestState(cMsg);
+        }
+
+    }
+
+    /**
+     * Handle Request Message
+     *
+     * <Request> ::= <Common Header>
+     *                  <Client Handle>
+     *                  <Context>
+     *                  *(<Named ClientSI>)
+     *                  [<Integrity>]
+     * <Named ClientSI> ::= <*(<PRID> <EPD>)>
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
+
+        final COPSReqMsg reqMsg = (COPSReqMsg) msg;
+//        final COPSContext cntxt = reqMsg.getContext();
+        final COPSHeader header = reqMsg.getHeader();
+        //short reqType = cntxt.getRequestType();
+        final short cType = header.getClientType();
+
+        // Support
+        if (reqMsg.getIntegrity() != null) {
+            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        COPSPdpReqStateMan man = _managerMap.get(reqMsg.getClientHandle().getId().str());
+        if (man == null) {
+
+            man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
+            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
+            man.setDataProcess(_process);
+            man.initRequestState(_sock);
+
+            // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
+            //    header.getClientType() + " msgType=" +
+            //    cntxt.getMessageType() + ", connId=" + conn.toString());
+        }
+
+        man.processRequest(reqMsg);
+    }
+
+    /**
+     * Handle Report Message
+     *
+     * <Report State> ::= <Common Header>
+     *                      <Client Handle>
+     *                      <Report Type>
+     *                      *(<Named ClientSI>)
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleReportMsg(Socket conn, COPSMsg msg)
+    throws COPSPdpException {
+        COPSReportMsg repMsg = (COPSReportMsg) msg;
+        // COPSHandle handle = repMsg.getClientHandle();
+        // COPSHeader header = repMsg.getHeader();
+
+        // Support
+        if (repMsg.getIntegrity() != null) {
+            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        final COPSPdpReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
+        if (man == null) {
+            logger.warn("No state manager found with ID - " + repMsg.getClientHandle().getId().str());
+        } else {
+            man.processReport(repMsg);
+        }
+    }
+
+    /**
+     * Method handleSyncComplete
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleSyncComplete(Socket conn, COPSMsg msg)
+    throws COPSPdpException {
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
+        // COPSHandle handle = cMsg.getClientHandle();
+        // COPSHeader header = cMsg.getHeader();
+
+        // Support
+        if (cMsg.getIntegrity() != null) {
+            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+        if (man == null) {
+            logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
+        } else {
+            man.processSyncComplete(cMsg);
+        }
+    }
+
+    /**
+     * Requests a COPS sync from the PEP
+     * @throws COPSException
+     * @throws COPSPdpException
+     */
+    protected void syncAllRequestState() throws COPSException, COPSPdpException {
+        for (final COPSPdpReqStateMan man : _managerMap.values()) {
+            man.syncRequestState();
+        }
+    }
+
+    private void notifyCloseAllReqStateMan() throws COPSPdpException {
+        for (final COPSPdpReqStateMan man : _managerMap.values()) {
+            man.processClosedConnection(_error);
+        }
+    }
+
+    private void notifyNoKAAllReqStateMan() throws COPSPdpException {
+        for (final COPSPdpReqStateMan man : _managerMap.values()) {
+            man.processNoKAConnection();
+        }
+    }
+
+}
+
index 849177427e874d5450ee6a5843360d2c6c9c65f0..14f31426ecf7a1447167a5c2429cf06aa1c2d9f2 100644 (file)
@@ -1,83 +1,84 @@
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-import java.util.Hashtable;\r
-\r
-import org.umu.cops.stack.COPSError;\r
-\r
-/**\r
- * Abstract class for implementing policy data processing classes for provisioning PDPs.\r
- */\r
-abstract public class COPSPdpDataProcess {\r
-    /**\r
-     * Gets the policies to be uninstalled\r
-     * @param man   The associated request state manager\r
-     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
-     */\r
-    abstract public Hashtable getRemovePolicy(COPSPdpReqStateMan man);\r
-    /**\r
-     * Gets the policies to be installed\r
-     * @param man   The associated request state manager\r
-     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
-     */\r
-    abstract public Hashtable getInstallPolicy(COPSPdpReqStateMan man);\r
-    /**\r
-     * Makes a decision from the supplied request data\r
-     * @param man   The associated request state manager\r
-     * @param reqSIs    Client specific data suppplied in the COPS request\r
-     */\r
-    abstract public void setClientData(COPSPdpReqStateMan man, Hashtable reqSIs);\r
-    /**\r
-     * Builds a failure report\r
-     * @param man   The associated request state manager\r
-     * @param reportSIs Report data\r
-     */\r
-    abstract public void failReport (COPSPdpReqStateMan man, Hashtable reportSIs);\r
-    /**\r
-     * Builds a success report\r
-     * @param man   The associated request state manager\r
-     * @param reportSIs Report data\r
-     */\r
-    abstract public void successReport (COPSPdpReqStateMan man, Hashtable reportSIs);\r
-    /**\r
-     * Builds an accounting report\r
-     * @param man   The associated request state manager\r
-     * @param reportSIs Report data\r
-     */\r
-    abstract public void acctReport (COPSPdpReqStateMan man, Hashtable reportSIs);\r
-    /**\r
-     * Notifies that no accounting report has been received\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void notifyNoAcctReport (COPSPdpReqStateMan man);\r
-\r
-    /**\r
-     * Notifies a keep-alive timeout\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void notifyNoKAliveReceived (COPSPdpReqStateMan man);\r
-\r
-    /**\r
-      * Notifies that the connection has been closed\r
-      * @param man  The associated request state manager\r
-      * @param error Reason\r
-      */\r
-    public abstract void notifyClosedConnection (COPSPdpReqStateMan man, COPSError error);\r
-\r
-    /**\r
-     * Notifies that a request state has been deleted\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void notifyDeleteRequestState (COPSPdpReqStateMan man);\r
-\r
-    /**\r
-     * Notifies that a request state has been closed\r
-     * @param man   The associated request state manager\r
-     */\r
-    public abstract void closeRequestState(COPSPdpReqStateMan man);\r
-}\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.umu.cops.stack.COPSError;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * Abstract class for implementing policy data processing classes for provisioning PDPs.
+ */
+public interface COPSPdpDataProcess {
+    /**
+     * Gets the policies to be uninstalled
+     * @param man   The associated request state manager
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled
+     */
+    public Hashtable getRemovePolicy(COPSPdpReqStateMan man);
+    /**
+     * Gets the policies to be installed
+     * @param man   The associated request state manager
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled
+     */
+    public Hashtable getInstallPolicy(COPSPdpReqStateMan man);
+    /**
+     * Makes a decision from the supplied request data
+     * @param man   The associated request state manager
+     * @param reqSIs    Client specific data suppplied in the COPS request
+     */
+    public void setClientData(COPSPdpReqStateMan man, Map<String, String> reqSIs);
+    /**
+     * Builds a failure report
+     * @param man   The associated request state manager
+     * @param reportSIs Report data
+     */
+    public void failReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+    /**
+     * Builds a success report
+     * @param man   The associated request state manager
+     * @param reportSIs Report data
+     */
+    public void successReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+    /**
+     * Builds an accounting report
+     * @param man   The associated request state manager
+     * @param reportSIs Report data
+     */
+    public void acctReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+    /**
+     * Notifies that no accounting report has been received
+     * @param man   The associated request state manager
+     */
+    public void notifyNoAcctReport (COPSPdpReqStateMan man);
+
+    /**
+     * Notifies a keep-alive timeout
+     * @param man   The associated request state manager
+     */
+    public void notifyNoKAliveReceived (COPSPdpReqStateMan man);
+
+    /**
+      * Notifies that the connection has been closed
+      * @param man  The associated request state manager
+      * @param error Reason
+      */
+    public void notifyClosedConnection (COPSPdpReqStateMan man, COPSError error);
+
+    /**
+     * Notifies that a request state has been deleted
+     * @param man   The associated request state manager
+     */
+    public void notifyDeleteRequestState (COPSPdpReqStateMan man);
+
+    /**
+     * Notifies that a request state has been closed
+     * @param man   The associated request state manager
+     */
+    public void closeRequestState(COPSPdpReqStateMan man);
+}
index 956af9ce05e6fbb076d8a2a2eaca47d5e10ee9e7..87c24ac6b487333c4862e823ff55b9cc226d00d0 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-\r
-/**\r
- * COPS message transceiver class for provisioning connections at the PDP side.\r
- *\r
- * TODO - Need to continue refactoring by removing all instances of Hashtable (change to Map<>)\r
- */\r
-public class COPSPdpMsgSender {\r
-\r
-    /**\r
-     * Socket connected to PEP\r
-     */\r
-    protected Socket _sock;\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
-     * Creates a COPSPepMsgSender\r
-     *\r
-     * @param clientType        COPS client-type\r
-     * @param clientHandle      Client handle\r
-     * @param sock              Socket to the PEP\r
-     */\r
-    public COPSPdpMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
-        // COPS Handle\r
-        _handle = clientHandle;\r
-        _clientType = clientType;\r
-\r
-        _sock = sock;\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
-     * Sends a decision message\r
-     * @param removeDecs    Decisions to be removed\r
-     * @param installDecs   Decisions to be installed\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendDecision(Hashtable removeDecs, Hashtable installDecs)\r
-    throws COPSPdpException {\r
-        /* <Decision Message> ::= <Common Header: Flag SOLICITED>\r
-         *                          <Client Handle>\r
-         *                          *(<Decision>) | <Error>\r
-         *                          [<Integrity>]\r
-         * <Decision> ::= <Context>\r
-         *                  <Decision: Flags>\r
-         *                  [<Named Decision Data: Provisioning>]\r
-         * <Decision: Flags> ::= <Command-Code> NULLFlag\r
-         * <Command-Code> ::= NULLDecision | Install | Remove\r
-         * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
-         * <Install Decision> ::= *(<PRID> <EPD>)\r
-         * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
-         *\r
-         * Very important, this is actually being treated like this:\r
-         * <Install Decision> ::= <PRID> | <EPD>\r
-         * <Remove Decision> ::= <PRID> | <PPRID>\r
-         *\r
-        */\r
-\r
-        // Common Header with the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-        hdr.setFlag(COPSHeader.COPS_FLAG_SOLICITED);\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(handle);\r
-\r
-            // Decisions (no flags supplied)\r
-            //  <Context>\r
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-\r
-            // Remove Decisions\r
-            //  <Decision: Flags>\r
-            if (removeDecs.size() > 0) {\r
-                COPSDecision rdec1 = new COPSDecision();\r
-                rdec1.setCmdCode(COPSDecision.DEC_REMOVE);\r
-\r
-                decisionMsg.addDecision(rdec1, cntxt);\r
-\r
-                for (Enumeration e = removeDecs.keys() ; e.hasMoreElements() ;) {\r
-                    String strprid = (String) e.nextElement();\r
-                    String strepd = (String) removeDecs.get(strprid);\r
-\r
-                    //  <Named Decision Data: Provisioning> (PRID)\r
-                    COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                    COPSPrID prid = new COPSPrID();\r
-                    prid.setData(new COPSData(strprid));\r
-                    dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-                    //  <Named Decision Data: Provisioning> (EPD)\r
-                    COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                    COPSPrEPD epd = new COPSPrEPD();\r
-                    epd.setData(new COPSData(strepd));\r
-                    dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                    decisionMsg.addDecision(dec2, cntxt);\r
-                    decisionMsg.addDecision(dec3, cntxt);\r
-                }\r
-            }\r
-\r
-            // Install Decisions\r
-            //  <Decision: Flags>\r
-            if (installDecs.size() > 0) {\r
-                COPSDecision idec1 = new COPSDecision();\r
-                idec1.setCmdCode(COPSDecision.DEC_INSTALL);\r
-\r
-                decisionMsg.addDecision(idec1, cntxt);\r
-\r
-                for (Enumeration e = installDecs.keys() ; e.hasMoreElements() ;) {\r
-                    String strprid = (String) e.nextElement();\r
-                    String strepd = (String) installDecs.get(strprid);\r
-\r
-                    //  <Named Decision Data: Provisioning> (PRID)\r
-                    COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                    COPSPrID prid = new COPSPrID();\r
-                    prid.setData(new COPSData(strprid));\r
-                    dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-                    //  <Named Decision Data: Provisioning> (EPD)\r
-                    COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                    COPSPrEPD epd = new COPSPrEPD();\r
-                    epd.setData(new COPSData(strepd));\r
-                    dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                    decisionMsg.addDecision(dec2, cntxt);\r
-                    decisionMsg.addDecision(dec3, cntxt);\r
-                }\r
-\r
-                /**\r
-                COPSIntegrity intr = new COPSIntegrity();\r
-                intr.setKeyId(19);\r
-                intr.setSeqNum(9);\r
-                intr.setKeyDigest(new COPSData("KEY DIGEST"));\r
-                decisionMsg.add(intr);\r
-                /**/\r
-            }\r
-        } catch (COPSException e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        //** Send the decision\r
-        //**\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a decision message which was not requested by the PEP\r
-     * @param removeDecs    Decisions to be removed\r
-     * @param installDecs   Decisions to be installed\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendUnsolicitedDecision(Hashtable removeDecs, Hashtable installDecs)\r
-    throws COPSPdpException {\r
-        //** Example of an UNSOLICITED decision\r
-        //**\r
-\r
-        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
-         *                          <Client Handle>\r
-         *                          *(<Decision>) | <Error>\r
-         *                          [<Integrity>]\r
-         * <Decision> ::= <Context>\r
-         *                  <Decision: Flags>\r
-         *                  [<Named Decision Data: Provisioning>]\r
-         * <Decision: Flags> ::= <Command-Code> NULLFlag\r
-         * <Command-Code> ::= NULLDecision | Install | Remove\r
-         * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
-         * <Install Decision> ::= *(<PRID> <EPD>)\r
-         * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
-         *\r
-         * Very important, this is actually being treated like this:\r
-         * <Install Decision> ::= <PRID> | <EPD>\r
-         * <Remove Decision> ::= <PRID> | <PPRID>\r
-         *\r
-        */\r
-\r
-        // Common Header with the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle handle = new COPSHandle(getClientHandle().getId());\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(handle);\r
-\r
-            // Decisions (no flags supplied)\r
-            //  <Context>\r
-            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-\r
-            // Remove Decisions\r
-            //  <Decision: Flags>\r
-            COPSDecision rdec1 = new COPSDecision();\r
-            rdec1.setCmdCode(COPSDecision.DEC_REMOVE);\r
-\r
-            decisionMsg.addDecision(rdec1, cntxt);\r
-\r
-            for (Enumeration e = removeDecs.keys() ; e.hasMoreElements() ;) {\r
-                String strprid = (String) e.nextElement();\r
-                String strepd = (String) removeDecs.get(strprid);\r
-\r
-                //  <Named Decision Data: Provisioning> (PRID)\r
-                COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                COPSPrID prid = new COPSPrID();\r
-                prid.setData(new COPSData(strprid));\r
-                dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-                //  <Named Decision Data: Provisioning> (EPD)\r
-                COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                COPSPrEPD epd = new COPSPrEPD();\r
-                epd.setData(new COPSData(strepd));\r
-                dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                decisionMsg.addDecision(dec2, cntxt);\r
-                decisionMsg.addDecision(dec3, cntxt);\r
-            }\r
-\r
-            // Install Decisions\r
-            //  <Decision: Flags>\r
-            COPSDecision idec1 = new COPSDecision();\r
-            idec1.setCmdCode(COPSDecision.DEC_INSTALL);\r
-\r
-            decisionMsg.addDecision(idec1, cntxt);\r
-\r
-            for (Enumeration e = installDecs.keys() ; e.hasMoreElements() ;) {\r
-                String strprid = (String) e.nextElement();\r
-                String strepd = (String) installDecs.get(strprid);\r
-\r
-                //  <Named Decision Data: Provisioning> (PRID)\r
-                COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                COPSPrID prid = new COPSPrID();\r
-                prid.setData(new COPSData(strprid));\r
-                dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-                //  <Named Decision Data: Provisioning> (EPD)\r
-                COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
-                COPSPrEPD epd = new COPSPrEPD();\r
-                epd.setData(new COPSData(strepd));\r
-                dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                decisionMsg.addDecision(dec2, cntxt);\r
-                decisionMsg.addDecision(dec3, cntxt);\r
-            }\r
-\r
-            /**\r
-            COPSIntegrity intr = new COPSIntegrity();\r
-            intr.setKeyId(19);\r
-            intr.setSeqNum(9);\r
-            intr.setKeyDigest(new COPSData("KEY DIGEST"));\r
-            decisionMsg.add(intr);\r
-            /**/\r
-        } catch (COPSException e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        //** Send the decision\r
-        //**\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a message asking that the request state be deleted\r
-     * @throws   COPSPdpException\r
-     */\r
-    public void sendDeleteRequestState()\r
-    throws COPSPdpException {\r
-        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
-         *                          <Client Handle>\r
-         *                          *(<Decision>)\r
-         *                          [<Integrity>]\r
-         * <Decision> ::= <Context>\r
-         *                  <Decision: Flags>\r
-         * <Decision: Flags> ::= Remove Request-State\r
-         *\r
-        */\r
-\r
-        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());\r
-\r
-        // Decisions\r
-        //  <Context>\r
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-        //  <Decision: Flags>\r
-        COPSDecision dec = new COPSDecision();\r
-        dec.setCmdCode(COPSDecision.DEC_REMOVE);\r
-        dec.setFlags(COPSDecision.F_REQSTATE);\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(clienthandle);\r
-            decisionMsg.addDecision(dec, cntxt);\r
-        } catch (COPSException e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a request asking that a new request state be created\r
-     * @throws   COPSPdpException\r
-     */\r
-    public void sendOpenNewRequestState()\r
-    throws COPSPdpException {\r
-        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
-         *                          <Client Handle>\r
-         *                          *(<Decision>)\r
-         *                          [<Integrity>]\r
-         * <Decision> ::= <Context>\r
-         *                  <Decision: Flags>\r
-         * <Decision: Flags> ::= Install Request-State\r
-         *\r
-        */\r
-\r
-        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());\r
-\r
-        // Decisions\r
-        //  <Context>\r
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
-        //  <Decision: Flags>\r
-        COPSDecision dec = new COPSDecision();\r
-        dec.setCmdCode(COPSDecision.DEC_INSTALL);\r
-        dec.setFlags(COPSDecision.F_REQSTATE);\r
-\r
-        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
-        try {\r
-            decisionMsg.add(hdr);\r
-            decisionMsg.add(clienthandle);\r
-            decisionMsg.addDecision(dec, cntxt);\r
-        } catch (COPSException e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            decisionMsg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Sends a message asking for a COPS sync operation\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sendSyncRequestState()\r
-    throws COPSPdpException {\r
-        /* <Synchronize State Request>  ::= <Common Header>\r
-         *                                  [<Client Handle>]\r
-         *                                  [<Integrity>]\r
-         */\r
-\r
-        // Common Header with the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSQ, getClientType());\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        final COPSHandle clienthandle = new COPSHandle(_handle.getId());\r
-\r
-        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
-        try {\r
-            msg.add(hdr);\r
-            msg.add(clienthandle);\r
-        } catch (Exception e) {\r
-            throw new COPSPdpException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-}\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * COPS message transceiver class for provisioning connections at the PDP side.
+ *
+ * TODO - Need to continue refactoring by removing all instances of Hashtable (change to Map<>)
+ */
+public class COPSPdpMsgSender {
+
+    /**
+     * Socket connected to PEP
+     */
+    protected final Socket _sock;
+
+    /**
+     * COPS client-type that identifies the policy client
+     */
+    protected final short _clientType;
+
+    /**
+     * COPS client handle used to uniquely identify a particular
+     * PEP's request for a client-type
+     */
+    protected final COPSHandle _handle;
+
+    /**
+     * Creates a COPSPepMsgSender
+     *
+     * @param clientType        COPS client-type
+     * @param clientHandle      Client handle
+     * @param sock              Socket to the PEP
+     */
+    public COPSPdpMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
+        // COPS Handle
+        _handle = clientHandle;
+        _clientType = clientType;
+
+        _sock = sock;
+    }
+
+    /**
+     * Gets the client handle
+     * @return   Client's <tt>COPSHandle</tt>
+     */
+    public COPSHandle getClientHandle() {
+        return _handle;
+    }
+
+    /**
+     * Gets the client-type
+     * @return   Client-type value
+     */
+    public short getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Sends a decision message
+     * @param removeDecs    Decisions to be removed
+     * @param installDecs   Decisions to be installed
+     * @throws COPSPdpException
+     */
+    public void sendDecision(final Map<String, String> removeDecs, Map<String, String> installDecs)
+            throws COPSPdpException {
+        /* <Decision Message> ::= <Common Header: Flag SOLICITED>
+         *                          <Client Handle>
+         *                          *(<Decision>) | <Error>
+         *                          [<Integrity>]
+         * <Decision> ::= <Context>
+         *                  <Decision: Flags>
+         *                  [<Named Decision Data: Provisioning>]
+         * <Decision: Flags> ::= <Command-Code> NULLFlag
+         * <Command-Code> ::= NULLDecision | Install | Remove
+         * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
+         * <Install Decision> ::= *(<PRID> <EPD>)
+         * <Remove Decision> ::= *(<PRID> | <PPRID>)
+         *
+         * Very important, this is actually being treated like this:
+         * <Install Decision> ::= <PRID> | <EPD>
+         * <Remove Decision> ::= <PRID> | <PPRID>
+         *
+        */
+
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+
+        // Decisions (no flags supplied)
+        //  <Context>
+        final COPSContext cntxt = new COPSContext(RType.CONFIG, (short)0);
+
+        // Remove Decisions
+        //  <Decision: Flags>
+        final COPSDecision rdec1 = new COPSDecision(Command.REMOVE);
+
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(rdec1);
+        decisionMap.put(cntxt, decisionSet);
+
+        for (final Map.Entry<String, String> entry : removeDecs.entrySet()) {
+            //  <Named Decision Data: Provisioning> (PRID)
+            final COPSPrID prid = new COPSPrID();
+            prid.setData(new COPSData(entry.getKey()));
+            final COPSDecision decisionPrid = new COPSDecision(CType.NAMED,
+                    new COPSData(prid.getDataRep(), 0, prid.getDataLength()));
+
+            decisionMap.get(cntxt).add(decisionPrid);
+
+            final COPSPrEPD epd = new COPSPrEPD();
+            final COPSDecision decisionPrepd = new COPSDecision(CType.NAMED,
+                    new COPSData(epd.getDataRep(), 0, epd.getDataLength()));
+
+            decisionMap.get(cntxt).add(decisionPrepd);
+        }
+
+        // Install Decisions
+        //  <Decision: Flags>
+        final COPSDecision idec1 = new COPSDecision(Command.INSTALL);
+        decisionMap.get(cntxt).add(idec1);
+
+        for (final Map.Entry<String, String> entry : installDecs.entrySet()) {
+            //  <Named Decision Data: Provisioning> (PRID)
+            final COPSPrID prid = new COPSPrID();
+            prid.setData(new COPSData(entry.getKey()));
+            final COPSDecision decisionPrid2 = new COPSDecision(CType.NAMED,
+                    new COPSData(prid.getDataRep(), 0, prid.getDataLength()));
+
+            decisionMap.get(cntxt).add(decisionPrid2);
+        }
+
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
+                decisionMap, null);
+
+        //** Send the decision
+        //**
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a decision message which was not requested by the PEP
+     * @param removeDecs    Decisions to be removed
+     * @param installDecs   Decisions to be installed
+     * @throws COPSPdpException
+     */
+    public void sendUnsolicitedDecision(final Map<String, String> removeDecs, final Map<String, String> installDecs)
+            throws COPSPdpException {
+        //** Example of an UNSOLICITED decision
+        //**
+
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
+         *                          <Client Handle>
+         *                          *(<Decision>) | <Error>
+         *                          [<Integrity>]
+         * <Decision> ::= <Context>
+         *                  <Decision: Flags>
+         *                  [<Named Decision Data: Provisioning>]
+         * <Decision: Flags> ::= <Command-Code> NULLFlag
+         * <Command-Code> ::= NULLDecision | Install | Remove
+         * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
+         * <Install Decision> ::= *(<PRID> <EPD>)
+         * <Remove Decision> ::= *(<PRID> | <PPRID>)
+         *
+         * Very important, this is actually being treated like this:
+         * <Install Decision> ::= <PRID> | <EPD>
+         * <Remove Decision> ::= <PRID> | <PPRID>
+         *
+        */
+
+        // Common Header with the same ClientType as the request
+        // Client Handle with the same clientHandle as the request
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        // Decisions (no flags supplied)
+        //  <Context>
+        final COPSContext cntxt = new COPSContext(RType.CONFIG, (short)0);
+
+        // Remove Decisions
+        //  <Decision: Flags>
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(Command.REMOVE));
+        decisionMap.put(cntxt, decisionSet);
+
+        for (final Map.Entry<String, String> entry : removeDecs.entrySet()) {
+            //  <Named Decision Data: Provisioning> (PRID)
+            final COPSPrID prid = new COPSPrID();
+            prid.setData(new COPSData(entry.getKey()));
+            decisionMap.get(cntxt).add(new COPSDecision(CType.NAMED,
+                    new COPSData(prid.getDataRep(), 0, prid.getDataLength())));
+
+            //  <Named Decision Data: Provisioning> (EPD)
+            final COPSPrEPD epd = new COPSPrEPD();
+            epd.setData(new COPSData(entry.getValue()));
+            decisionMap.get(cntxt).add(
+                    new COPSDecision(CType.NAMED, new COPSData(epd.getDataRep(), 0, epd.getDataLength())));
+        }
+
+        // Install Decisions
+        //  <Decision: Flags>
+        decisionMap.get(cntxt).add(new COPSDecision(Command.INSTALL));
+
+        for (final Map.Entry<String, String> entry : installDecs.entrySet()) {
+            //  <Named Decision Data: Provisioning> (PRID)
+            final COPSPrID prid = new COPSPrID();
+            prid.setData(new COPSData(entry.getKey()));
+            decisionMap.get(cntxt).add(new COPSDecision(CType.NAMED,
+                    new COPSData(prid.getDataRep(), 0, prid.getDataLength())));
+
+            final COPSPrEPD epd = new COPSPrEPD();
+            epd.setData(new COPSData(entry.getValue()));
+            decisionMap.get(cntxt).add(
+                    new COPSDecision(CType.NAMED, new COPSData(epd.getDataRep(), 0, epd.getDataLength())));
+        }
+
+        /**
+        COPSIntegrity intr = new COPSIntegrity();
+        intr.setKeyId(19);
+        intr.setSeqNum(9);
+        intr.setKeyDigest(new COPSData("KEY DIGEST"));
+        decisionMsg.add(intr);
+        /**/
+
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
+                decisionMap, null);
+
+        //** Send the decision
+        //**
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a message asking that the request state be deleted
+     * @throws   COPSPdpException
+     */
+    public void sendDeleteRequestState() throws COPSPdpException {
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
+         *                          <Client Handle>
+         *                          *(<Decision>)
+         *                          [<Integrity>]
+         * <Decision> ::= <Context>
+         *                  <Decision: Flags>
+         * <Decision: Flags> ::= Remove Request-State
+         *
+        */
+
+        // Decisions
+        //  <Context>
+        //  <Decision: Flags>
+        final COPSDecision dec = new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE);
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(dec);
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
+                decisionMap, null);
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a request asking that a new request state be created
+     * @throws   COPSPdpException
+     */
+    public void sendOpenNewRequestState()
+    throws COPSPdpException {
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
+         *                          <Client Handle>
+         *                          *(<Decision>)
+         *                          [<Integrity>]
+         * <Decision> ::= <Context>
+         *                  <Decision: Flags>
+         * <Decision: Flags> ::= Install Request-State
+         *
+        */
+
+        //  <Decision: Flags>
+        final COPSDecision dec = new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE);
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(dec);
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(_handle.getId()),
+                decisionMap, null);
+
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a message asking for a COPS sync operation
+     * @throws COPSPdpException
+     */
+    public void sendSyncRequestState()
+    throws COPSPdpException {
+        /* <Synchronize State Request>  ::= <Common Header>
+         *                                  [<Client Handle>]
+         *                                  [<Integrity>]
+         */
+
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, new COPSHandle(_handle.getId()), null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());
+        }
+    }
+}
index 2de386c3d01b02eb92c2044e1337f81f513ea694..2c60428f0a273e586bf9368541f113e3cce89762 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-import org.umu.cops.stack.*;\r
-\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-import java.util.Vector;\r
-\r
-/**\r
- * State manager class for provisioning requests, at the PDP side.\r
- */\r
-public class COPSPdpReqStateMan {\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 COPSPdpDataProcess _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 COPSPdpMsgSender _sender;\r
-\r
-    /**\r
-     * Creates a request state manager\r
-     * @param clientType    Client-type\r
-     * @param clientHandle  Client handle\r
-     */\r
-    public COPSPdpReqStateMan(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 COPSPdpDataProcess 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(COPSPdpDataProcess 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 COPSPdpMsgSender(_clientType, _handle, sock);\r
-\r
-        // Initial state\r
-        _status = ST_INIT;\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
-        // Report Type\r
-        COPSReportType rtypemsg = msg.getReport();\r
-\r
-        // Named ClientSI\r
-        Vector clientSIs = msg.getClientSI();\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
-                strobjprid = obj.getData().str();\r
-                break;\r
-            case 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
-                break;\r
-            }\r
-        }\r
-\r
-        //** Here we must act in accordance with\r
-        //** the report received\r
-        if (rtypemsg.isSuccess()) {\r
-            _status = ST_REPORT;\r
-            _process.successReport(this, repSIs);\r
-        } else if (rtypemsg.isFailure()) {\r
-            _status = ST_REPORT;\r
-            _process.failReport(this, repSIs);\r
-        } else if (rtypemsg.isAccounting()) {\r
-            _status = ST_ACCT;\r
-            _process.acctReport(this, repSIs);\r
-        }\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
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.umu.cops.stack.*;
+
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * State manager class for provisioning requests, at the PDP side.
+ */
+public class 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;
+
+    /**
+     * Object for performing policy data processing
+     */
+    protected COPSPdpDataProcess _process;
+
+    /**
+     *  Current state of the request being managed
+     */
+    protected short _status;
+
+    /** COPS message transceiver used to send COPS messages */
+    protected COPSPdpMsgSender _sender;
+
+    /**
+     * Creates a request state manager
+     * @param clientType    Client-type
+     * @param clientHandle  Client handle
+     */
+    public COPSPdpReqStateMan(short clientType, 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 COPSPdpDataProcess getDataProcess() {
+        return _process;
+    }
+
+    /**
+     * Sets the policy data processing object
+     * @param   process Policy data processing object
+     */
+    public void setDataProcess(COPSPdpDataProcess 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 COPSPdpMsgSender(_clientType, _handle, sock);
+
+        // Initial state
+        _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;
+        */
+    }
+
+    /**
+     * Processes a report
+     * @param msg   Report message from the PEP
+     * @throws COPSPdpException
+     */
+    protected void processReport(final COPSReportMsg msg) throws COPSPdpException {
+
+        //** Analyze the report
+        //**
+
+        /*
+         * <Report State> ::= <Common Header>
+         *                      <Client Handle>
+         *                      <Report Type>
+         *                      *(<Named ClientSI>)
+         *                      [<Integrity>]
+         * <Named ClientSI: Report> ::= <[<GPERR>] *(<report>)>
+         * <report> ::= <ErrorPRID> <CPERR> *(<PRID><EPD>)
+         *
+         * Important, <Named ClientSI> is not parsed
+        */
+
+        // COPSHeader hdrmsg = msg.getHeader();
+        // COPSHandle handlemsg = msg.getClientHandle();
+
+        if (msg.getClientSI() != null) {
+            // Report Type
+            final COPSReportType rtypemsg = msg.getReport();
+
+            // Named ClientSI
+            //        final Set<COPSClientSI> clientSIs = msg.getClientSI();
+            final Map<String, String> repSIs = new HashMap<>();
+            String strobjprid = "";
+            //        for (final COPSClientSI clientSI : clientSIs) {
+            final COPSPrObjBase obj = new COPSPrObjBase(msg.getClientSI().getData().getData());
+            switch (obj.getSNum()) {
+                case COPSPrObjBase.PR_PRID:
+                    strobjprid = obj.getData().str();
+                    break;
+                case COPSPrObjBase.PR_EPD:
+                    repSIs.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 act in accordance with
+            //** the report received
+            switch (rtypemsg.getReportType()) {
+                case SUCCESS:
+                    _status = ST_REPORT;
+                    _process.successReport(this, repSIs);
+                    break;
+                case FAILURE:
+                    _status = ST_REPORT;
+                    _process.failReport(this, repSIs);
+                    break;
+                case ACCOUNTING:
+                    _status = ST_ACCT;
+                    _process.acctReport(this, repSIs);
+                    break;
+            }
+        }
+
+
+    }
+
+    /**
+     * 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 = ST_DEL;
+    }
+
+}
index 343d40ca9bce0b4a43d3187870b4ac2f1da648c5..e57823ece6afe3fe02b8bc0ac93711b1cff4d3ad 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpep;\r
-\r
-import java.io.IOException;\r
-import java.net.InetAddress;\r
-import java.net.Socket;\r
-import java.net.UnknownHostException;\r
-import java.util.Hashtable;\r
-\r
-import org.umu.cops.stack.COPSAcctTimer;\r
-import org.umu.cops.stack.COPSClientAcceptMsg;\r
-import org.umu.cops.stack.COPSClientCloseMsg;\r
-import org.umu.cops.stack.COPSClientOpenMsg;\r
-import org.umu.cops.stack.COPSData;\r
-import org.umu.cops.stack.COPSError;\r
-import org.umu.cops.stack.COPSException;\r
-import org.umu.cops.stack.COPSHeader;\r
-import org.umu.cops.stack.COPSKATimer;\r
-import org.umu.cops.stack.COPSMsg;\r
-import org.umu.cops.stack.COPSPepId;\r
-import org.umu.cops.stack.COPSTransceiver;\r
-\r
-/**\r
- * This is a provisioning COPS PEP. Responsible for making\r
- * connection to the PDP and maintaining it\r
- */\r
-public class COPSPepAgent {\r
-\r
-    /**\r
-        PEP's Identifier\r
-     */\r
-    private String _pepID;\r
-\r
-    /**\r
-        PEP's client-type\r
-     */\r
-    private short _clientType;\r
-\r
-    /**\r
-        PDP host name\r
-     */\r
-    private String _psHost;\r
-\r
-    /**\r
-        PDP port\r
-     */\r
-    private int _psPort;\r
-\r
-    /**\r
-        PEP-PDP connection manager\r
-     */\r
-    private COPSPepConnection _conn;\r
-\r
-    /**\r
-        COPS error returned by PDP\r
-     */\r
-    private COPSError _error;\r
-\r
-    /**\r
-     * Creates a PEP agent\r
-     * @param    pepID              PEP-ID\r
-     * @param    clientType         Client-type\r
-     */\r
-    public COPSPepAgent(String pepID, short clientType) {\r
-        _pepID = pepID;\r
-        _clientType = clientType;\r
-    }\r
-\r
-    /**\r
-     * Creates a PEP agent with a PEP-ID equal to "noname"\r
-     * @param    clientType         Client-type\r
-     */\r
-    public COPSPepAgent(short clientType) {\r
-\r
-        // PEPId\r
-        try {\r
-            _pepID = InetAddress.getLocalHost().getHostName();\r
-        } catch (Exception e) {\r
-            _pepID = "noname";\r
-        }\r
-\r
-        _clientType = clientType;\r
-    }\r
-\r
-    /**\r
-     * Gets the identifier of the PEP\r
-     * @return  PEP-ID\r
-     */\r
-    public String getPepID() {\r
-        return _pepID;\r
-    }\r
-\r
-    /**\r
-     * Gets the COPS client-type\r
-     * @return  PEP's client-type\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Gets PDP host name\r
-     * @return  PDP host name\r
-     */\r
-    public String getPDPName() {\r
-        return _psHost;\r
-    }\r
-\r
-    /**\r
-     * Gets the port of the PDP\r
-     * @return  PDP port\r
-     */\r
-    public int getPDPPort() {\r
-        return _psPort;\r
-    }\r
-\r
-    /**\r
-     * Connects to a PDP\r
-     * @param    psHost              PDP host name\r
-     * @param    psPort              PDP port\r
-     * @return   <tt>true</tt> if PDP accepts the connection; <tt>false</tt> otherwise\r
-     * @throws   java.net.UnknownHostException\r
-     * @throws   java.io.IOException\r
-     * @throws   COPSException\r
-     * @throws   COPSPepException\r
-     */\r
-    public boolean connect(String psHost, int psPort)\r
-    throws UnknownHostException, IOException, COPSException, COPSPepException {\r
-\r
-        // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");\r
-        _psHost = psHost;\r
-        _psPort = psPort;\r
-\r
-        // Check whether it already exists\r
-        if (_conn == null)\r
-            _conn = processConnection(psHost,psPort);\r
-        else {\r
-            // Check if it's closed\r
-            if (_conn.isClosed()) {\r
-                _conn = processConnection(psHost,psPort);\r
-            } else {\r
-                disconnect(null);\r
-                _conn = processConnection(psHost,psPort);\r
-            }\r
-        }\r
-\r
-        return (_conn != null);\r
-    }\r
-\r
-    /**\r
-     * Gets the connection manager\r
-     * @return  PEP-PDP connection manager object\r
-     */\r
-    public COPSPepConnection getConnection () {\r
-        return (_conn);\r
-    }\r
-\r
-    /**\r
-     * Gets the COPS error returned by the PDP\r
-     * @return   <tt>COPSError</tt> returned by PDP\r
-     */\r
-    public COPSError getConnectionError()   {\r
-        return _error;\r
-    }\r
-\r
-    /**\r
-     * Disconnects from the PDP\r
-     * @param error Reason\r
-     * @throws COPSException\r
-     * @throws IOException\r
-     */\r
-    public void disconnect(COPSError error)\r
-    throws COPSException, IOException {\r
-\r
-        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
-        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-        closeMsg.add(cHdr);\r
-        if (error != null)\r
-            closeMsg.add(error);\r
-\r
-        closeMsg.writeData(_conn.getSocket());\r
-        _conn.close();\r
-        _conn = null;\r
-    }\r
-\r
-    /**\r
-     * Adds a request state to the connection manager.\r
-     * @return  The newly created connection manager\r
-     * @throws COPSPepException\r
-     * @throws COPSException\r
-     */\r
-    public COPSPepReqStateMan addRequestState (String handle, COPSPepDataProcess process)\r
-    throws COPSPepException, COPSException {\r
-        if (_conn != null) {\r
-            return _conn.addRequestState(handle, process);\r
-        }\r
-        return null;\r
-    }\r
-\r
-\r
-    /**\r
-     * Queries the connection manager to delete a request state\r
-     * @param man   Request state manager\r
-     * @throws COPSPepException\r
-     * @throws COPSException\r
-     */\r
-    public void deleteRequestState (COPSPepReqStateMan man)\r
-    throws COPSPepException, COPSException {\r
-        if (_conn != null)\r
-            _conn.deleteRequestState(man);\r
-    }\r
-\r
-    /**\r
-     * Gets all the request state managers\r
-     * @return  A <tt>Hashtable</tt> holding all active request state managers\r
-     */\r
-    public Hashtable getReqStateMans() {\r
-        if (_conn != null)\r
-            return _conn.getReqStateMans();\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * Establish connection to PDP's IP address\r
-     *\r
-     * <Client-Open> ::= <Common Header>\r
-     *                  <PEPID>\r
-     *                  [<ClientSI>]\r
-     *                  [<LastPDPAddr>]\r
-     *                  [<Integrity>]\r
-     *\r
-     * Not support [<ClientSI>], [<LastPDPAddr>], [<Integrity>]\r
-     *\r
-     * <Client-Accept> ::= <Common Header>\r
-     *                      <KA Timer>\r
-     *                      [<ACCT Timer>]\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not send [<Integrity>]\r
-     *\r
-     * <Client-Close> ::= <Common Header>\r
-     *                      <Error>\r
-     *                      [<PDPRedirAddr>]\r
-     *                      [<Integrity>]\r
-     *\r
-     * Not send [<PDPRedirAddr>], [<Integrity>]\r
-     *\r
-     * @throws   UnknownHostException\r
-     * @throws   IOException\r
-     * @throws   COPSException\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    private COPSPepConnection processConnection(String psHost, int psPort)\r
-    throws UnknownHostException, IOException, COPSException, COPSPepException {\r
-        // Build OPN\r
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, _clientType);\r
-\r
-        COPSPepId pepId = new COPSPepId();\r
-        COPSData d = new COPSData(_pepID);\r
-        pepId.setData(d);\r
-\r
-        COPSClientOpenMsg msg = new COPSClientOpenMsg();\r
-        msg.add(hdr);\r
-        msg.add(pepId);\r
-\r
-        // Create Socket and send OPN\r
-        InetAddress addr = InetAddress.getByName(psHost);\r
-        Socket socket = new Socket(addr,psPort);\r
-        msg.writeData(socket);\r
-\r
-        // Receive the response\r
-        COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);\r
-\r
-        if (recvmsg.getHeader().isAClientAccept()) {\r
-            COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;\r
-\r
-            // Support\r
-            if (cMsg.getIntegrity() != null) {\r
-                throw new COPSPepException("Unsupported object (Integrity)");\r
-            }\r
-\r
-            // Mandatory KATimer\r
-            COPSKATimer kt = cMsg.getKATimer();\r
-            if (kt == null)\r
-                throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");\r
-            short _kaTimeVal = kt.getTimerVal();\r
-\r
-            // ACTimer\r
-            COPSAcctTimer at = cMsg.getAcctTimer();\r
-            short _acctTimer = 0;\r
-            if (at != null)\r
-                _acctTimer = at.getTimerVal();\r
-\r
-            // Create the connection manager\r
-            COPSPepConnection conn = new COPSPepConnection(_clientType, socket);\r
-            conn.setKaTimer(_kaTimeVal);\r
-            conn.setAcctTimer(_acctTimer);\r
-            new Thread(conn).start();\r
-\r
-            return conn;\r
-        } else if (recvmsg.getHeader().isAClientClose()) {\r
-            COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;\r
-            _error = cMsg.getError();\r
-            socket.close();\r
-            return null;\r
-        } else { // messages of other types are not expected\r
-            throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpep;
+
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * This is a provisioning COPS PEP. Responsible for making
+ * connection to the PDP and maintaining it
+ */
+public class COPSPepAgent {
+
+    /**
+        PEP's Identifier
+     */
+    private String _pepID;
+
+    /**
+        PEP's client-type
+     */
+    private short _clientType;
+
+    /**
+        PDP host name
+     */
+    private String _psHost;
+
+    /**
+        PDP port
+     */
+    private int _psPort;
+
+    /**
+        PEP-PDP connection manager
+     */
+    private COPSPepConnection _conn;
+
+    /**
+        COPS error returned by PDP
+     */
+    private COPSError _error;
+
+    /**
+     * Creates a PEP agent
+     * @param    pepID              PEP-ID
+     * @param    clientType         Client-type
+     */
+    public COPSPepAgent(final String pepID, final short clientType) {
+        _pepID = pepID;
+        _clientType = clientType;
+    }
+
+    /**
+     * Creates a PEP agent with a PEP-ID equal to "noname"
+     * @param    clientType         Client-type
+     */
+    public COPSPepAgent(final short clientType) {
+
+        // PEPId
+        try {
+            _pepID = InetAddress.getLocalHost().getHostName();
+        } catch (Exception e) {
+            _pepID = "noname";
+        }
+
+        _clientType = clientType;
+    }
+
+    /**
+     * Gets the identifier of the PEP
+     * @return  PEP-ID
+     */
+    public String getPepID() {
+        return _pepID;
+    }
+
+    /**
+     * Gets the COPS client-type
+     * @return  PEP's client-type
+     */
+    public short getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Gets PDP host name
+     * @return  PDP host name
+     */
+    public String getPDPName() {
+        return _psHost;
+    }
+
+    /**
+     * Gets the port of the PDP
+     * @return  PDP port
+     */
+    public int getPDPPort() {
+        return _psPort;
+    }
+
+    /**
+     * Connects to a PDP
+     * @param    psHost              PDP host name
+     * @param    psPort              PDP port
+     * @return   <tt>true</tt> if PDP accepts the connection; <tt>false</tt> otherwise
+     * @throws   java.io.IOException
+     * @throws   COPSException
+     * @throws   COPSPepException
+     */
+    public boolean connect(String psHost, int psPort) throws IOException, COPSException, COPSPepException {
+
+        // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");
+        _psHost = psHost;
+        _psPort = psPort;
+
+        // Check whether it already exists
+        if (_conn == null)
+            _conn = processConnection(psHost,psPort);
+        else {
+            // Check if it's closed
+            if (_conn.isClosed()) {
+                _conn = processConnection(psHost,psPort);
+            } else {
+                disconnect(null);
+                _conn = processConnection(psHost,psPort);
+            }
+        }
+
+        return (_conn != null);
+    }
+
+    /**
+     * Gets the connection manager
+     * @return  PEP-PDP connection manager object
+     */
+    public COPSPepConnection getConnection () {
+        return (_conn);
+    }
+
+    /**
+     * Gets the COPS error returned by the PDP
+     * @return   <tt>COPSError</tt> returned by PDP
+     */
+    public COPSError getConnectionError()   {
+        return _error;
+    }
+
+    /**
+     * Disconnects from the PDP
+     * @param error Reason
+     * @throws COPSException
+     * @throws IOException
+     */
+    public void disconnect(final COPSError error) throws COPSException, IOException {
+        final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
+        closeMsg.writeData(_conn.getSocket());
+        _conn.close();
+    }
+
+    /**
+     * Adds a request state to the connection manager.
+     * @return  The newly created connection manager
+     * @throws COPSPepException
+     * @throws COPSException
+     */
+    public COPSPepReqStateMan addRequestState(final String handle, final COPSPepDataProcess process)
+            throws COPSPepException, COPSException {
+        if (_conn != null) {
+            return _conn.addRequestState(handle, process);
+        }
+        return null;
+    }
+
+
+    /**
+     * Queries the connection manager to delete a request state
+     * @param man   Request state manager
+     * @throws COPSPepException
+     * @throws COPSException
+     */
+    public void deleteRequestState(final COPSPepReqStateMan man)
+    throws COPSPepException, COPSException {
+        if (_conn != null)
+            _conn.deleteRequestState(man);
+    }
+
+    /**
+     * Establish connection to PDP's IP address
+     *
+     * <Client-Open> ::= <Common Header>
+     *                  <PEPID>
+     *                  [<ClientSI>]
+     *                  [<LastPDPAddr>]
+     *                  [<Integrity>]
+     *
+     * Not support [<ClientSI>], [<LastPDPAddr>], [<Integrity>]
+     *
+     * <Client-Accept> ::= <Common Header>
+     *                      <KA Timer>
+     *                      [<ACCT Timer>]
+     *                      [<Integrity>]
+     *
+     * Not send [<Integrity>]
+     *
+     * <Client-Close> ::= <Common Header>
+     *                      <Error>
+     *                      [<PDPRedirAddr>]
+     *                      [<Integrity>]
+     *
+     * Not send [<PDPRedirAddr>], [<Integrity>]
+     *
+     * @throws   UnknownHostException
+     * @throws   IOException
+     * @throws   COPSException
+     * @throws   COPSPepException
+     *
+     */
+    private COPSPepConnection processConnection(String psHost, int psPort)
+            throws IOException, COPSException, COPSPepException {
+        // Build OPN
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, new COPSPepId(new COPSData(_pepID)),
+                null, null, null);
+
+        // Create Socket and send OPN
+        final InetAddress addr = InetAddress.getByName(psHost);
+        final Socket socket = new Socket(addr,psPort);
+        msg.writeData(socket);
+
+        // Receive the response
+        final COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
+
+        if (recvmsg.getHeader().getOpCode().equals(OPCode.CAT)) {
+            final COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
+
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                throw new COPSPepException("Unsupported object (Integrity)");
+            }
+
+            // Mandatory KATimer
+            final COPSKATimer kt = cMsg.getKATimer();
+            if (kt == null)
+                throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");
+            short _kaTimeVal = kt.getTimerVal();
+
+            // ACTimer
+            final COPSAcctTimer at = cMsg.getAcctTimer();
+            short _acctTimer = 0;
+            if (at != null)
+                _acctTimer = at.getTimerVal();
+
+            // Create the connection manager
+            final COPSPepConnection conn = new COPSPepConnection(_clientType, socket);
+            conn.setKaTimer(_kaTimeVal);
+            conn.setAcctTimer(_acctTimer);
+            new Thread(conn).start();
+
+            return conn;
+        } else if (recvmsg.getHeader().getOpCode().equals(OPCode.CC)) {
+            final COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
+            _error = cMsg.getError();
+            socket.close();
+            return null;
+        } else { // messages of other types are not expected
+            throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());
+        }
+    }
+}
+
+
+
index 89943ddc250cfcb038980d13da035452a8bfc8cb..f51109fdd398cf406acb7d122bf476406a66cc03 100644 (file)
@@ -9,10 +9,15 @@ package org.umu.cops.prpep;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSHeader.OPCode;
 
 import java.io.IOException;
 import java.net.Socket;
-import java.util.*;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -47,16 +52,10 @@ public class COPSPepConnection implements Runnable {
      */
     protected Date _lastRecKa;
 
-    /**
-        Opcode of the latest message sent
-    */
-    protected byte _lastmessage;
-
     /**
         Maps a COPS Client Handle to a Request State Manager
      */
     protected final Map<String, COPSPepReqStateMan> _managerMap;
-    // map < String(COPSHandle), COPSPepReqStateMan>;
 
     /**
         COPS error returned by PDP
@@ -68,7 +67,7 @@ public class COPSPepConnection implements Runnable {
      * @param clientType    PEP's client-type
      * @param sock          Socket connected to PDP
      */
-    public COPSPepConnection(short clientType, Socket sock) {
+    public COPSPepConnection(final short clientType, final Socket sock) {
 
         _clientType = clientType;
         _sock = sock;
@@ -77,8 +76,6 @@ public class COPSPepConnection implements Runnable {
         _acctTimer = 0;
         _kaTimer = 0;
         _responseTime = 10000;
-        _lastmessage = COPSHeader.COPS_OP_CAT;
-
         _managerMap = new ConcurrentHashMap<>();
     }
 
@@ -114,14 +111,6 @@ public class COPSPepConnection implements Runnable {
         return _acctTimer;
     }
 
-    /**
-     * Gets all request state managers
-     * @return  A <tt>Hashatable</tt> holding all request state managers
-     */
-    protected Hashtable getReqStateMans() {
-        return new Hashtable(_managerMap);
-    }
-
     /**
      * Checks whether the socket to the PDP is closed or not
      * @return  <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise
@@ -140,14 +129,6 @@ public class COPSPepConnection implements Runnable {
         _sock.close();
     }
 
-    /**
-     * Gets the opcode of the lastest message sent
-     * @return  Message opcode
-     */
-    public byte getLastmessage() {
-        return _lastmessage;
-    }
-
     /**
      * Sets response time
      * @param respTime  Response time value (msecs)
@@ -182,7 +163,7 @@ public class COPSPepConnection implements Runnable {
         try {
             while (!_sock.isClosed()) {
                 if (_sock.getInputStream().available() != 0) {
-                    _lastmessage = processMessage(_sock);
+                    processMessage(_sock);
                     _lastRecKa = new Date();
                 }
 
@@ -203,11 +184,7 @@ public class COPSPepConnection implements Runnable {
                     cTime = (int) (new Date().getTime());
 
                     if ((cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {
-                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);
-                        COPSKAMsg msg = new COPSKAMsg();
-
-                        msg.add(hdr);
-
+                        final COPSKAMsg msg = new COPSKAMsg(null);
                         COPSTransceiver.sendMsg(msg, _sock);
                         _lastSendKa = new Date();
                     }
@@ -259,24 +236,24 @@ public class COPSPepConnection implements Runnable {
      * @throws COPSException
      * @throws IOException
      */
-    protected byte processMessage(Socket conn)
-    throws COPSPepException, COPSException, IOException {
-        COPSMsg msg = COPSTransceiver.receiveMsg(conn);
-
-        if (msg.getHeader().isAClientClose()) {
-            handleClientCloseMsg(conn, msg);
-            return COPSHeader.COPS_OP_CC;
-        } else if (msg.getHeader().isADecision()) {
-            handleDecisionMsg(conn, msg);
-            return COPSHeader.COPS_OP_DEC;
-        } else if (msg.getHeader().isASyncStateReq()) {
-            handleSyncStateReqMsg(conn, msg);
-            return COPSHeader.COPS_OP_SSQ;
-        } else if (msg.getHeader().isAKeepAlive()) {
-            handleKeepAliveMsg(conn, msg);
-            return COPSHeader.COPS_OP_KA;
-        } else {
-            throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+    protected byte processMessage(final Socket conn) throws COPSPepException, COPSException, IOException {
+        final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+
+        switch (msg.getHeader().getOpCode()) {
+            case CC:
+                handleClientCloseMsg(conn, msg);
+                return (byte)OPCode.CC.ordinal();
+            case DEC:
+                handleDecisionMsg(conn, msg);
+                return (byte)OPCode.DEC.ordinal();
+            case SSQ:
+                handleSyncStateReqMsg(conn, msg);
+                return (byte)OPCode.SSQ.ordinal();
+            case KA:
+                handleKeepAliveMsg(conn, msg);
+                return (byte)OPCode.KA.ordinal();
+            default:
+                throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
         }
     }
 
@@ -377,29 +354,22 @@ public class COPSPepConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleDecisionMsg(Socket conn, COPSMsg msg)
-    throws COPSPepException {
-        COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
-        COPSHandle handle = dMsg.getClientHandle();
-        Hashtable decisions = dMsg.getDecisions();
-
-        for (Enumeration e = decisions.keys() ; e.hasMoreElements() ;) {
-
-            COPSContext context = (COPSContext) e.nextElement();
-            Vector v = (Vector) decisions.get(context);
-
-            Enumeration ee = v.elements();
-            if (ee.hasMoreElements()) {
-                COPSDecision decision = (COPSDecision) ee.nextElement();
+    private void handleDecisionMsg(final Socket conn, final COPSMsg msg) throws COPSPepException {
+        final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+        final COPSHandle handle = dMsg.getClientHandle();
+        final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
 
+        for (final Set<COPSDecision> copsDecisions: decisions.values()) {
+            for (final COPSDecision decision : copsDecisions) {
                 // Get the associated manager
-                COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
+                final COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
                 if (manager == null)
                     logger.warn("Unable to find state manager with key - " + handle.getId().str());
 
                 // Check message type
-                if (decision.getFlags() == COPSDecision.F_REQSTATE) {
-                    if (decision.isRemoveDecision())
+                // TODO FIXME - Use of manager object could result in a NPE
+                if (decision.getFlag().equals(DecisionFlag.REQSTATE)) {
+                    if (decision.getCommand().equals(Command.REMOVE))
                         // Delete Request State
                         manager.processDeleteRequestState(dMsg);
                     else
@@ -420,13 +390,13 @@ public class COPSPepConnection implements Runnable {
      * @param    handle              a  COPSHandle
      *
      */
-    private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle)
-    throws COPSPepException {
+    private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle) throws COPSPepException {
 
         COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
         if (manager == null)
             logger.warn("Unable to find state manager with key - " + handle.getId().str());
 
+        // TODO FIXME - Use of manager object could result in a NPE
         manager.processOpenNewRequestState();
     }
 
@@ -441,18 +411,15 @@ public class COPSPepConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg)
-    throws COPSPepException {
+    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
         COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
-        // COPSHandle handle = cMsg.getClientHandle();
-        // COPSHeader header = cMsg.getHeader();
 
         // Support
         if (cMsg.getIntegrity() != null) {
             logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
         }
 
-        COPSPepReqStateMan manager = (COPSPepReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+        COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
         if (manager == null) {
             logger.warn("Unable to find state manager with key - " + cMsg.getClientHandle().getId().str());
         } else {
@@ -472,9 +439,9 @@ public class COPSPepConnection implements Runnable {
      * @throws   COPSPepException
      *
      */
-    protected COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process)
-    throws COPSException, COPSPepException {
-        COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType,clientHandle);
+    protected COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process) throws COPSException,
+            COPSPepException {
+        COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
         if (_managerMap.get(clientHandle) != null)
             throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
 
@@ -493,8 +460,7 @@ public class COPSPepConnection implements Runnable {
      * @throws   COPSPepException
      *
      */
-    protected void deleteRequestState(COPSPepReqStateMan manager)
-    throws COPSException, COPSPepException {
+    protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException, COPSPepException {
         manager.finalizeRequestState();
     }
 
index 45d11ddb7b188e9add660ee10d95029ca05ca51c..9bda235f9347336ff6f9cbdc65d73c1c70c81ebe 100644 (file)
@@ -6,10 +6,10 @@
 
 package org.umu.cops.prpep;
 
-import java.util.Hashtable;
-
 import org.umu.cops.stack.COPSError;
 
+import java.util.Map;
+
 /**
  * COPSPepDataProcess process policy data and events.
  *
@@ -21,52 +21,52 @@ public abstract class COPSPepDataProcess {
     /**
      * Establish PDP decisions
      *
-     * @param removeDecs
-     * @param installDecs
-     * @param errorDecs
+     * @param man - the state manager
+     * @param removeDecs - the remove decisions
+     * @param installDecs - the install decisions
+     * @param errorDecs - the error decisions
      */
 
-       public abstract void setDecisions(COPSPepReqStateMan man, Hashtable removeDecs, Hashtable installDecs, Hashtable errorDecs);
+       public abstract void setDecisions(COPSPepReqStateMan man, Map<String, String> removeDecs,
+                                      Map<String, String> installDecs, Map<String, String> errorDecs);
 
     /**
      *  If the report is fail, return true
      *
-     * @return
+     * @return - t/f
      */
     public abstract boolean isFailReport(COPSPepReqStateMan man);
 
     /**
      * Return Report Data
      *
-     * @return
+     * @return - the report data
      */
-    public abstract Hashtable getReportData(COPSPepReqStateMan man);
+    public abstract Map<String, String> getReportData(COPSPepReqStateMan man);
 
     /**
      * Return Client Data
      *
-     * @return
+     * @return - the client data
      */
-    public abstract Hashtable getClientData(COPSPepReqStateMan man);
+    public abstract Map<String, String> getClientData(COPSPepReqStateMan man);
 
     /**
-     * Return Accouting Data
+     * Return Accounting Data
      *
-     * @return
+     * @return - the accounting data
      */
-    public abstract Hashtable getAcctData(COPSPepReqStateMan man);
+    public abstract Map<String, String> getAcctData(COPSPepReqStateMan man);
 
     /**
      * Notify the connection closed
-     *
-     * @param error
      */
-    public abstract void notifyClosedConnection (COPSPepReqStateMan man, COPSError error);
+    public abstract void notifyClosedConnection(COPSPepReqStateMan man, COPSError error);
 
     /**
      * Notify the KAlive timeout
      */
-    public abstract void notifyNoKAliveReceived (COPSPepReqStateMan man);
+    public abstract void notifyNoKAliveReceived(COPSPepReqStateMan man);
 
     /**
      * Process a PDP request to close a Request State
@@ -78,7 +78,7 @@ public abstract class COPSPepDataProcess {
     /**
      * Process a PDP request to open a new Request State
      *
-     * @param man
+     * @param man       Request State Manager
      */
     public abstract void newRequestState(COPSPepReqStateMan man);
 }
index 010560ccb468f763e671972779d2180b0276c4bf..17a03b1c1a7e2d0f5593fbdcc5dfbe0c9422e5e4 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpep;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-\r
-import org.umu.cops.stack.COPSClientSI;\r
-import org.umu.cops.stack.COPSContext;\r
-import org.umu.cops.stack.COPSData;\r
-import org.umu.cops.stack.COPSDeleteMsg;\r
-import org.umu.cops.stack.COPSException;\r
-import org.umu.cops.stack.COPSHandle;\r
-import org.umu.cops.stack.COPSHeader;\r
-import org.umu.cops.stack.COPSPrEPD;\r
-import org.umu.cops.stack.COPSPrID;\r
-import org.umu.cops.stack.COPSReason;\r
-import org.umu.cops.stack.COPSReportMsg;\r
-import org.umu.cops.stack.COPSReportType;\r
-import org.umu.cops.stack.COPSReqMsg;\r
-import org.umu.cops.stack.COPSSyncStateMsg;\r
-\r
-/**\r
- * COPSPepMsgSender sends COPS messages to PDP.\r
- *\r
- * @version COPSPepMsgSender.java, v 2.00 2004\r
- *\r
- */\r
-public class COPSPepMsgSender {\r
-\r
-    /**\r
-     * Socket connection to PDP\r
-     */\r
-    protected Socket _sock;\r
-\r
-    /**\r
-     * The client-type identifies the policy client\r
-     */\r
-    protected short _clientType;\r
-\r
-    /**\r
-     * The client handle is used to uniquely identify a particular\r
-     * PEP's request for a client-type\r
-     */\r
-    protected COPSHandle _handle;\r
-\r
-    /**\r
-     * Create a COPSPepMsgSender\r
-     *\r
-     * @param clientType        client-type\r
-     * @param clientHandle      client handle\r
-     * @param sock              socket of PDP connection\r
-     */\r
-    public COPSPepMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
-        // COPS Handle\r
-        _handle = clientHandle;\r
-        _clientType = clientType;\r
-\r
-        _sock = sock;\r
-    }\r
-\r
-    /**\r
-     * Return client handle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _handle;\r
-    }\r
-\r
-    /**\r
-     * Return client-type\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Send Request to PDP.\r
-     *   The PEP establishes a request state client handle for which the\r
-     *   remote PDP may maintain state.\r
-     *\r
-     * @param    clientSIs              a  Hashtable\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    public void sendRequest(Hashtable clientSIs)\r
-    throws COPSPepException {\r
-        // Create COPS Message\r
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_REQ, _clientType);\r
-        COPSContext cntxt = new COPSContext(COPSContext.CONFIG , (short) 0);\r
-\r
-        COPSHandle handle = _handle;\r
-\r
-        // Add the clientSIs\r
-        COPSReqMsg msg = new COPSReqMsg();\r
-        try {\r
-            msg.add(hdr) ;\r
-            msg.add(handle) ;\r
-            msg.add(cntxt) ;\r
-\r
-            if (clientSIs.size() > 0) {\r
-                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
-                    String strprid = (String) e.nextElement();\r
-                    String strepd = (String) clientSIs.get(strprid);\r
-\r
-                    //  (PRID)\r
-                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrID prid = new COPSPrID();\r
-                    prid.setData(new COPSData(strprid));\r
-                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-\r
-                    //  (EPD)\r
-                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrEPD epd = new COPSPrEPD();\r
-                    epd.setData(new COPSData(strepd));\r
-                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                    msg.add(cSi);\r
-                    msg.add(cSi2);\r
-                }\r
-            }\r
-\r
-        } catch (COPSException e) {\r
-            throw new COPSPepException("Error making Request Msg, reason: " + e.getMessage());\r
-        }\r
-\r
-        // Send message\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Send Fail Report to PDP.\r
-     *    The RPT message is used by the PEP to communicate to the PDP its\r
-     *    success or failure in carrying out the PDP's decision, or to report\r
-     *    an accounting related change in state.\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    public void sendFailReport(Hashtable clientSIs)\r
-    throws COPSPepException {\r
-        COPSReportMsg msg = new COPSReportMsg();\r
-        // Report FAIL\r
-        try {\r
-            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
-            COPSHandle hnd = _handle;\r
-\r
-            COPSReportType report = new COPSReportType(COPSReportType.FAILURE);\r
-\r
-            msg.add(hdr);\r
-            msg.add(hnd);\r
-            msg.add(report);\r
-            if (clientSIs.size() > 0) {\r
-                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
-                    String strprid = (String) e.nextElement();\r
-                    String strepd = (String) clientSIs.get(strprid);\r
-\r
-                    //  (PRID)\r
-                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrID prid = new COPSPrID();\r
-                    prid.setData(new COPSData(strprid));\r
-                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-\r
-                    //  (EPD)\r
-                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrEPD epd = new COPSPrEPD();\r
-                    epd.setData(new COPSData(strepd));\r
-                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                    msg.add(cSi);\r
-                    msg.add(cSi2);\r
-                }\r
-            }\r
-\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Send Succes Report to PDP.\r
-     *    The RPT message is used by the PEP to communicate to the PDP its\r
-     *    success or failure in carrying out the PDP's decision, or to report\r
-     *    an accounting related change in state.\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    public void sendSuccessReport(Hashtable clientSIs)\r
-    throws COPSPepException {\r
-        COPSReportMsg msg = new COPSReportMsg();\r
-        // Report SUCESS\r
-        try {\r
-            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
-            COPSHandle hnd = _handle;\r
-\r
-            COPSReportType report = new COPSReportType(COPSReportType.SUCCESS);\r
-\r
-            msg.add(hdr);\r
-            msg.add(hnd);\r
-            msg.add(report);\r
-\r
-            if (clientSIs.size() > 0) {\r
-                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
-                    String strprid = (String) e.nextElement();\r
-                    String strepd = (String) clientSIs.get(strprid);\r
-\r
-                    //  (PRID)\r
-                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrID prid = new COPSPrID();\r
-                    prid.setData(new COPSData(strprid));\r
-                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-\r
-                    //  (EPD)\r
-                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrEPD epd = new COPSPrEPD();\r
-                    epd.setData(new COPSData(strepd));\r
-                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                    msg.add(cSi);\r
-                    msg.add(cSi2);\r
-                }\r
-            }\r
-\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    public void sendAcctReport(Hashtable clientSIs)\r
-    throws COPSPepException {\r
-        COPSReportMsg msg = new COPSReportMsg();\r
-        // Report SUCESS\r
-        try {\r
-            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
-            COPSHandle hnd = _handle;\r
-\r
-            COPSReportType report = new COPSReportType(COPSReportType.ACCT);\r
-\r
-            msg.add(hdr);\r
-            msg.add(hnd);\r
-            msg.add(report);\r
-\r
-            if (clientSIs.size() > 0) {\r
-                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
-                    String strprid = (String) e.nextElement();\r
-                    String strepd = (String) clientSIs.get(strprid);\r
-\r
-                    //  (PRID)\r
-                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrID prid = new COPSPrID();\r
-                    prid.setData(new COPSData(strprid));\r
-                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
-\r
-                    //  (EPD)\r
-                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
-                    COPSPrEPD epd = new COPSPrEPD();\r
-                    epd.setData(new COPSData(strepd));\r
-                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
-\r
-                    msg.add(cSi);\r
-                    msg.add(cSi2);\r
-                }\r
-            }\r
-\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Send Sync State Complete to PDP.\r
-     *   The Synchronize State Complete is sent by the PEP to the PDP after\r
-     *   the PDP sends a synchronize state request to the PEP and the PEP has\r
-     *   finished synchronization.\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    public void sendSyncComplete()\r
-    throws COPSPepException {\r
-        // Common Header with the same ClientType as the request\r
-        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSC, _clientType);\r
-\r
-        // Client Handle with the same clientHandle as the request\r
-        COPSHandle clienthandle = _handle;\r
-\r
-        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
-        try {\r
-            msg.add(hdr);\r
-            msg.add(clienthandle);\r
-        } catch (Exception e) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Send Delete Request to PDP.\r
-     * When sent from the PEP this message indicates to the remote PDP that\r
-     * the state identified by the client handle is no longer\r
-     * available/relevant.\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    public void sendDeleteRequest()\r
-    throws COPSPepException {\r
-        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DRQ, _clientType);\r
-        COPSHandle handle = _handle;\r
-\r
-        // *** TODO: send a real reason\r
-        COPSReason reason = new COPSReason((short) 234, (short) 345);\r
-\r
-        COPSDeleteMsg msg = new COPSDeleteMsg();\r
-        try {\r
-            msg.add(hdr);\r
-            msg.add(handle);\r
-            msg.add(reason);\r
-        } catch (COPSException ex) {\r
-            throw new COPSPepException("Error making Msg");\r
-        }\r
-        try {\r
-            msg.writeData(_sock);\r
-        } catch (IOException e) {\r
-            throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpep;
+
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSClientSI.CSIType;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSReason.ReasonCode;
+import org.umu.cops.stack.COPSReportType.ReportType;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * COPSPepMsgSender sends COPS messages to PDP.
+ *
+ * @version COPSPepMsgSender.java, v 2.00 2004
+ *
+ */
+public class COPSPepMsgSender {
+
+    /**
+     * Socket connection to PDP
+     */
+    protected Socket _sock;
+
+    /**
+     * The client-type identifies the policy client
+     */
+    protected short _clientType;
+
+    /**
+     * The client handle is used to uniquely identify a particular
+     * PEP's request for a client-type
+     */
+    protected COPSHandle _handle;
+
+    /**
+     * Create a COPSPepMsgSender
+     *
+     * @param clientType        client-type
+     * @param clientHandle      client handle
+     * @param sock              socket of PDP connection
+     */
+    public COPSPepMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {
+        // COPS Handle
+        _handle = clientHandle;
+        _clientType = clientType;
+
+        _sock = sock;
+    }
+
+    /**
+     * Return client handle
+     *
+     * @return   a COPSHandle
+     *
+     */
+    public COPSHandle getClientHandle() {
+        return _handle;
+    }
+
+    /**
+     * Return client-type
+     *
+     * @return   a short
+     *
+     */
+    public int getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Send Request to PDP.
+     *   The PEP establishes a request state client handle for which the
+     *   remote PDP may maintain state.
+     *
+     * @param    clientSIs              a  Hashtable
+     *
+     * @throws   COPSPepException
+     *
+     */
+    public void sendRequest(final Map<String, String> clientSIs) throws COPSPepException {
+        final Set<COPSClientSI> clientSISet = new HashSet<>();
+        // Add the clientSIs
+        for (final Map.Entry<String, String> entry : clientSIs.entrySet()) {
+            //  (PRID)
+            final COPSPrID prid = new COPSPrID();
+            prid.setData(new COPSData(entry.getKey()));
+            clientSISet.add(new COPSClientSI(CSIType.NAMED, new COPSData(prid.getDataRep(), 0, prid.getDataLength())));
+
+            //  (EPD)
+            final COPSPrEPD epd = new COPSPrEPD();
+            epd.setData(new COPSData(entry.getValue()));
+            clientSISet.add(new COPSClientSI(CSIType.NAMED, new COPSData(epd.getDataRep(), 0, epd.getDataLength())));
+        }
+        final COPSReqMsg msg = new COPSReqMsg(_clientType, _handle, new COPSContext(RType.CONFIG, (short)0),
+                null, null, null, clientSISet, null);
+
+        // Send message
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the request, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Send Fail Report to PDP.
+     *    The RPT message is used by the PEP to communicate to the PDP its
+     *    success or failure in carrying out the PDP's decision, or to report
+     *    an accounting related change in state.
+     *
+     * @throws   COPSPepException
+     *
+     */
+    public void sendFailReport(final Map<String, String> clientSIs) throws COPSPepException {
+        sendReport(clientSIs, new COPSReportType(ReportType.FAILURE));
+    }
+
+    /**
+     * Send Succes Report to PDP.
+     *    The RPT message is used by the PEP to communicate to the PDP its
+     *    success or failure in carrying out the PDP's decision, or to report
+     *    an accounting related change in state.
+     *
+     * @throws   COPSPepException
+     *
+     */
+    public void sendSuccessReport(final Map<String, String> clientSIs) throws COPSPepException {
+        sendReport(clientSIs, new COPSReportType(ReportType.SUCCESS));
+    }
+
+    public void sendAcctReport(final Map<String, String> clientSIs) throws COPSPepException {
+        sendReport(clientSIs, new COPSReportType(ReportType.ACCOUNTING));
+    }
+
+    private void sendReport(final Map<String, String> clientSIs, final COPSReportType reportType)
+            throws COPSPepException {
+        // Report SUCESS
+        for (final Map.Entry<String, String> entry : clientSIs.entrySet()) {
+            //  (PRID)
+            final COPSPrID prid = new COPSPrID();
+            prid.setData(new COPSData(entry.getKey()));
+
+            final COPSReportMsg pridMsg = new COPSReportMsg(_clientType, _handle, reportType,
+                    new COPSClientSI(CSIType.NAMED, new COPSData(prid.getDataRep(), 0, prid.getDataLength())), null);
+            try {
+                pridMsg.writeData(_sock);
+            } catch (IOException e) {
+                throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());
+            }
+
+            //  (EPD)
+            final COPSPrEPD epd = new COPSPrEPD();
+            epd.setData(new COPSData(entry.getValue()));
+            final COPSReportMsg epdMsg = new COPSReportMsg(_clientType, _handle, reportType,
+                    new COPSClientSI(CSIType.NAMED, new COPSData(epd.getDataRep(), 0, epd.getDataLength())), null);
+            try {
+                pridMsg.writeData(_sock);
+            } catch (IOException e) {
+                throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Send Sync State Complete to PDP.
+     *   The Synchronize State Complete is sent by the PEP to the PDP after
+     *   the PDP sends a synchronize state request to the PEP and the PEP has
+     *   finished synchronization.
+     *
+     * @throws   COPSPepException
+     *
+     */
+    public void sendSyncComplete() throws COPSPepException {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Send Delete Request to PDP.
+     * When sent from the PEP this message indicates to the remote PDP that
+     * the state identified by the client handle is no longer
+     * available/relevant.
+     *
+     * @throws   COPSPepException
+     *
+     */
+    public void sendDeleteRequest() throws COPSPepException {
+        // *** TODO: send a real reason
+        final COPSReason reason = new COPSReason(ReasonCode.UNSPECIFIED, ReasonCode.NA);
+        final COPSDeleteMsg msg = new COPSDeleteMsg(_clientType, _handle, reason, null);
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());
+        }
+    }
+}
+
+
+
+
index 5d09425ab134045c6378288105d94fb9d68f2a91..dc0e1d834f46743b3a15b822e5b9694674185109 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpep;\r
-\r
-import org.umu.cops.stack.*;\r
-\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-import java.util.Vector;\r
-\r
-/**\r
- * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)\r
- * in PEP.\r
- *\r
- *   The client handle is used to identify a unique request state for a\r
- *   single PEP per client-type. Client handles are chosen by the PEP and\r
- *   are opaque to the PDP. The PDP simply uses the request handle to\r
- *   uniquely identify the request state for a particular Client-Type over\r
- *   a particular TCP connection and generically tie its decisions to a\r
- *   corresponding request. Client handles are initiated in request\r
- *   messages and are then used by subsequent request, decision, and\r
- *   report messages to reference the same request state. When the PEP is\r
- *   ready to remove a local request state, it will issue a delete message\r
- *   to the PDP for the corresponding client handle. A handle MUST be\r
- *   explicitly deleted by the PEP before it can be used by the PEP to\r
- *   identify a new request state. Handles referring to different request\r
- *   states MUST be unique within the context of a particular TCP\r
- *   connection and client-type.\r
- *\r
- * @version COPSPepReqStateMan.java, v 2.00 2004\r
- *\r
- */\r
-public class COPSPepReqStateMan {\r
-\r
-    /**\r
-     * Request State created\r
-     */\r
-    public final static short ST_CREATE = 1;\r
-    /**\r
-     * Request sent\r
-     */\r
-    public final static short ST_INIT = 2;\r
-    /**\r
-     * Decisions received\r
-     */\r
-    public final static short ST_DECS = 3;\r
-    /**\r
-     * Report sent\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 received\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
-     * KAlive Time out\r
-     */\r
-    public final static short ST_NOKA = 11;\r
-    /**\r
-     * ACCT Time out\r
-     */\r
-    public final static short ST_ACCT = 12;\r
-\r
-    /**\r
-     * The client-type identifies the policy client\r
-     */\r
-    protected short _clientType;\r
-\r
-    /**\r
-     *  The client handle is used to uniquely identify a particular\r
-     *  PEP's request for a client-type\r
-     */\r
-    protected COPSHandle _handle;\r
-\r
-    /**\r
-        The PolicyDataProcess is used to process policy data in the PEP\r
-     */\r
-    protected COPSPepDataProcess _process;\r
-\r
-    /**\r
-     *  State Request State\r
-     */\r
-    protected short _status;\r
-\r
-    /**\r
-        The Msg Sender is used to send COPS messages\r
-     */\r
-    protected COPSPepMsgSender _sender;\r
-\r
-    /**\r
-     * Sync State\r
-     */\r
-    protected boolean _syncState;\r
-\r
-    /**\r
-     * Create a State Request Manager\r
-     *\r
-     * @param    clientHandle                a Client Handle\r
-     *\r
-     */\r
-    public COPSPepReqStateMan(short clientType, String clientHandle) {\r
-        _handle = new COPSHandle(new COPSData(clientHandle));\r
-        _clientType = clientType;\r
-        _syncState = true;\r
-        _status = ST_CREATE;\r
-    }\r
-\r
-    /**\r
-     * Return client handle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _handle;\r
-    }\r
-\r
-    /**\r
-     * Return client-type\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Return Request State status\r
-     *\r
-     * @return      s short\r
-     */\r
-    public short getStatus() {\r
-        return _status;\r
-    }\r
-\r
-    /**\r
-     * Return the Policy Data Process\r
-     *\r
-     * @return   a PolicyConfigure\r
-     *\r
-     */\r
-    public COPSPepDataProcess getDataProcess() {\r
-        return _process;\r
-    }\r
-\r
-    /**\r
-     * Establish the Policy Data Process\r
-     *\r
-     * @param    process              a  PolicyConfigure\r
-     *\r
-     */\r
-    public void setDataProcess(COPSPepDataProcess process) {\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Init Request State\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void initRequestState(Socket sock)\r
-    throws COPSPepException {\r
-        // Inits an object for sending COPS messages to the PDP\r
-        _sender = new COPSPepMsgSender(_clientType, _handle, sock);\r
-\r
-        // If an object for retrieving PEP features exists,\r
-        // use it for retrieving them\r
-        Hashtable clientSIs;\r
-        if (_process != null)\r
-            clientSIs = _process.getClientData(this);\r
-        else\r
-            clientSIs = null;\r
-\r
-        // Send the request\r
-        _sender.sendRequest(clientSIs);\r
-\r
-        // Initial state\r
-        _status = ST_INIT;\r
-    }\r
-\r
-    /**\r
-     * Finalize Request State\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void finalizeRequestState()\r
-    throws COPSPepException {\r
-        _sender.sendDeleteRequest();\r
-        _status = ST_FINAL;\r
-    }\r
-\r
-    /**\r
-     * Process the message Decision\r
-     *\r
-     * @param    dMsg                a  COPSDecisionMsg\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void processDecision(COPSDecisionMsg dMsg)\r
-    throws COPSPepException {\r
-        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());\r
-\r
-        // COPSHandle handle = dMsg.getClientHandle();\r
-        Hashtable decisions = dMsg.getDecisions();\r
-\r
-        Hashtable removeDecs = new Hashtable(40);\r
-        Hashtable installDecs = new Hashtable(40);\r
-        Hashtable errorDecs = new Hashtable(40);\r
-        for (Enumeration e = decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) decisions.get(context);\r
-            Enumeration ee = v.elements();\r
-            COPSDecision cmddecision = (COPSDecision) ee.nextElement();\r
-\r
-            // cmddecision --> we must check whether it is an error!\r
-\r
-            if (cmddecision.isInstallDecision()) {\r
-                String prid = new String();\r
-                for (; ee.hasMoreElements() ;) {\r
-                    COPSDecision decision = (COPSDecision) ee.nextElement();\r
-\r
-                    COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());\r
-                    switch (obj.getSNum()) {\r
-                    case COPSPrObjBase.PR_PRID:\r
-                        prid = obj.getData().str();\r
-                        break;\r
-                    case COPSPrObjBase.PR_EPD:\r
-                        installDecs.put(prid, obj.getData().str());\r
-                        break;\r
-                    default:\r
-                        break;\r
-                    }\r
-                }\r
-            }\r
-\r
-            if (cmddecision.isRemoveDecision()) {\r
-\r
-                String prid = new String();\r
-                for (; ee.hasMoreElements() ;) {\r
-                    COPSDecision decision = (COPSDecision) ee.nextElement();\r
-\r
-                    COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());\r
-                    switch (obj.getSNum()) {\r
-                    case COPSPrObjBase.PR_PRID:\r
-                        prid = obj.getData().str();\r
-                        break;\r
-                    case COPSPrObjBase.PR_EPD:\r
-                        removeDecs.put(prid, obj.getData().str());\r
-                        break;\r
-                    default:\r
-                        break;\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        //** Apply decisions to the configuration\r
-        _process.setDecisions(this, removeDecs, installDecs, errorDecs);\r
-        _status = ST_DECS;\r
-\r
-\r
-        if (_process.isFailReport(this)) {\r
-            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");\r
-            _sender.sendFailReport(_process.getReportData(this));\r
-        } else {\r
-            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");\r
-            _sender.sendSuccessReport(_process.getReportData(this));\r
-        }\r
-        _status = ST_REPORT;\r
-\r
-        if (!_syncState) {\r
-            _sender.sendSyncComplete();\r
-            _syncState = true;\r
-            _status = ST_SYNCALL;\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Process the message NewRequestState\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void processOpenNewRequestState()\r
-    throws COPSPepException {\r
-\r
-        if (_process != null)\r
-            _process.newRequestState(this);\r
-\r
-        _status = ST_NEW;\r
-    }\r
-\r
-    /**\r
-     * Process the message DeleteRequestState\r
-     *\r
-     * @param    dMsg                a  COPSDecisionMsg\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void processDeleteRequestState(COPSDecisionMsg dMsg)\r
-    throws COPSPepException {\r
-        if (_process != null)\r
-            _process.closeRequestState(this);\r
-\r
-        _status = ST_DEL;\r
-    }\r
-\r
-    /**\r
-     * Process the message SycnStateRequest.\r
-     * The message SycnStateRequest indicates that the remote PDP\r
-     * wishes the client (which appears in the common header)\r
-     * to re-send its state.\r
-     *\r
-     * @param    ssMsg               a  COPSSyncStateMsg\r
-     *\r
-     * @throws   COPSPepException\r
-     *\r
-     */\r
-    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)\r
-    throws COPSPepException {\r
-        _syncState = false;\r
-        // If an object for retrieving PEP features exists,\r
-        // use it for retrieving them\r
-        Hashtable clientSIs;\r
-        if (_process != null)\r
-            clientSIs = _process.getClientData(this);\r
-        else\r
-            clientSIs = null;\r
-\r
-        // Send request\r
-        _sender.sendRequest(clientSIs);\r
-\r
-        _status = ST_SYNC;\r
-    }\r
-\r
-    protected void processClosedConnection(COPSError error)\r
-    throws COPSPepException {\r
-        if (_process != null)\r
-            _process.notifyClosedConnection(this, error);\r
-\r
-        _status = ST_CCONN;\r
-    }\r
-\r
-    protected void processNoKAConnection()\r
-    throws COPSPepException {\r
-        if (_process != null)\r
-            _process.notifyNoKAliveReceived(this);\r
-\r
-        _status = ST_NOKA;\r
-    }\r
-\r
-    protected void processAcctReport()\r
-    throws COPSPepException {\r
-\r
-        Hashtable report = new Hashtable();\r
-        if (_process != null)\r
-            report = _process.getAcctData(this);\r
-\r
-        _sender.sendAcctReport(report);\r
-\r
-        _status = ST_ACCT;\r
-    }\r
-\r
-}\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpep;
+
+import org.umu.cops.stack.*;
+
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
+ * in PEP.
+ *
+ *   The client handle is used to identify a unique request state for a
+ *   single PEP per client-type. Client handles are chosen by the PEP and
+ *   are opaque to the PDP. The PDP simply uses the request handle to
+ *   uniquely identify the request state for a particular Client-Type over
+ *   a particular TCP connection and generically tie its decisions to a
+ *   corresponding request. Client handles are initiated in request
+ *   messages and are then used by subsequent request, decision, and
+ *   report messages to reference the same request state. When the PEP is
+ *   ready to remove a local request state, it will issue a delete message
+ *   to the PDP for the corresponding client handle. A handle MUST be
+ *   explicitly deleted by the PEP before it can be used by the PEP to
+ *   identify a new request state. Handles referring to different request
+ *   states MUST be unique within the context of a particular TCP
+ *   connection and client-type.
+ *
+ * @version COPSPepReqStateMan.java, v 2.00 2004
+ *
+ */
+public class COPSPepReqStateMan {
+
+    /**
+     * Request State created
+     */
+    public final static short ST_CREATE = 1;
+    /**
+     * Request sent
+     */
+    public final static short ST_INIT = 2;
+    /**
+     * Decisions received
+     */
+    public final static short ST_DECS = 3;
+    /**
+     * Report sent
+     */
+    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 received
+     */
+    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;
+    /**
+     * KAlive Time out
+     */
+    public final static short ST_NOKA = 11;
+    /**
+     * ACCT Time out
+     */
+    public final static short ST_ACCT = 12;
+
+    /**
+     * The client-type identifies the policy client
+     */
+    protected short _clientType;
+
+    /**
+     *  The client handle is used to uniquely identify a particular
+     *  PEP's request for a client-type
+     */
+    protected COPSHandle _handle;
+
+    /**
+        The PolicyDataProcess is used to process policy data in the PEP
+     */
+    protected COPSPepDataProcess _process;
+
+    /**
+     *  State Request State
+     */
+    protected short _status;
+
+    /**
+        The Msg Sender is used to send COPS messages
+     */
+    protected COPSPepMsgSender _sender;
+
+    /**
+     * Sync State
+     */
+    protected boolean _syncState;
+
+    /**
+     * Create a State Request Manager
+     *
+     * @param    clientHandle                a Client Handle
+     *
+     */
+    public COPSPepReqStateMan(final short clientType, final String clientHandle) {
+        _handle = new COPSHandle(new COPSData(clientHandle));
+        _clientType = clientType;
+        _syncState = true;
+        _status = ST_CREATE;
+    }
+
+    /**
+     * Return client handle
+     *
+     * @return   a COPSHandle
+     *
+     */
+    public COPSHandle getClientHandle() {
+        return _handle;
+    }
+
+    /**
+     * Return client-type
+     *
+     * @return   a short
+     *
+     */
+    public int getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Return Request State status
+     *
+     * @return      s short
+     */
+    public short getStatus() {
+        return _status;
+    }
+
+    /**
+     * Return the Policy Data Process
+     *
+     * @return   a PolicyConfigure
+     *
+     */
+    public COPSPepDataProcess getDataProcess() {
+        return _process;
+    }
+
+    /**
+     * Establish the Policy Data Process
+     *
+     * @param    process              a  PolicyConfigure
+     *
+     */
+    public void setDataProcess(COPSPepDataProcess process) {
+        _process = process;
+    }
+
+    /**
+     * Init Request State
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void initRequestState(Socket sock)
+    throws COPSPepException {
+        // Inits an object for sending COPS messages to the PDP
+        _sender = new COPSPepMsgSender(_clientType, _handle, sock);
+
+        // If an object for retrieving PEP features exists,
+        // use it for retrieving them
+        final Map<String, String> clientSIs;
+        if (_process != null)
+            clientSIs = _process.getClientData(this);
+        else
+            clientSIs = new HashMap<>();
+
+        // Send the request
+        // TODO - do we really want to send when this is empty???
+        _sender.sendRequest(clientSIs);
+
+        // Initial state
+        _status = ST_INIT;
+    }
+
+    /**
+     * Finalize Request State
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void finalizeRequestState()
+    throws COPSPepException {
+        _sender.sendDeleteRequest();
+        _status = ST_FINAL;
+    }
+
+    /**
+     * Process the message Decision
+     *
+     * @param    dMsg                a  COPSDecisionMsg
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void processDecision(COPSDecisionMsg dMsg)
+    throws COPSPepException {
+        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
+
+        // COPSHandle handle = dMsg.getClientHandle();
+        final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
+
+        final Map<String, String> removeDecs = new HashMap<>();
+        final Map<String, String> installDecs = new HashMap<>();
+
+        for (Set<COPSDecision> copsDecisions: decisions.values()) {
+            final COPSDecision cmddecision = copsDecisions.iterator().next();
+            String prid = "";
+            switch (cmddecision.getCommand()) {
+                case INSTALL:
+                    for (final COPSDecision decision : copsDecisions) {
+                        final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                        switch (obj.getSNum()) {
+                            case COPSPrObjBase.PR_PRID:
+                                prid = obj.getData().str();
+                                break;
+                            case COPSPrObjBase.PR_EPD:
+                                installDecs.put(prid, obj.getData().str());
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                    break;
+                case REMOVE:
+                    for (final COPSDecision decision : copsDecisions) {
+                        final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                        switch (obj.getSNum()) {
+                            case COPSPrObjBase.PR_PRID:
+                                prid = obj.getData().str();
+                                break;
+                            case COPSPrObjBase.PR_EPD:
+                                removeDecs.put(prid, obj.getData().str());
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                    break;
+            }
+
+        }
+
+        //** Apply decisions to the configuration
+        // TODO - why is this collection never getting populated???
+        final Map<String, String> errorDecs = new HashMap<>();
+        _process.setDecisions(this, removeDecs, installDecs, errorDecs);
+        _status = ST_DECS;
+
+
+        if (_process.isFailReport(this)) {
+            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
+            _sender.sendFailReport(_process.getReportData(this));
+        } else {
+            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
+            _sender.sendSuccessReport(_process.getReportData(this));
+        }
+        _status = ST_REPORT;
+
+        if (!_syncState) {
+            _sender.sendSyncComplete();
+            _syncState = true;
+            _status = ST_SYNCALL;
+        }
+    }
+
+    /**
+     * Process the message NewRequestState
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void processOpenNewRequestState()
+    throws COPSPepException {
+
+        if (_process != null)
+            _process.newRequestState(this);
+
+        _status = ST_NEW;
+    }
+
+    /**
+     * Process the message DeleteRequestState
+     *
+     * @param    dMsg                a  COPSDecisionMsg
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void processDeleteRequestState(COPSDecisionMsg dMsg)
+    throws COPSPepException {
+        if (_process != null)
+            _process.closeRequestState(this);
+
+        _status = ST_DEL;
+    }
+
+    /**
+     * Process the message SycnStateRequest.
+     * The message SycnStateRequest indicates that the remote PDP
+     * wishes the client (which appears in the common header)
+     * to re-send its state.
+     *
+     * @param    ssMsg               a  COPSSyncStateMsg
+     *
+     * @throws   COPSPepException
+     *
+     */
+    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)
+    throws COPSPepException {
+        _syncState = false;
+        // If an object for retrieving PEP features exists,
+        // use it for retrieving them
+        final Map<String, String> clientSIs;
+        if (_process != null)
+            clientSIs = _process.getClientData(this);
+        else
+            clientSIs = new HashMap<>();
+
+        // Send request
+        // TODO - do we really want to send the request when the map is empty???
+        _sender.sendRequest(clientSIs);
+
+        _status = ST_SYNC;
+    }
+
+    protected void processClosedConnection(COPSError error)
+    throws COPSPepException {
+        if (_process != null)
+            _process.notifyClosedConnection(this, error);
+
+        _status = ST_CCONN;
+    }
+
+    protected void processNoKAConnection()
+    throws COPSPepException {
+        if (_process != null)
+            _process.notifyNoKAliveReceived(this);
+
+        _status = ST_NOKA;
+    }
+
+    protected void processAcctReport()
+    throws COPSPepException {
+
+        final Map<String, String> report;
+        if (_process != null) report = _process.getAcctData(this);
+        else report = new HashMap<>();
+
+        // TODO - do we really want to send when the map is empty???
+        _sender.sendAcctReport(report);
+
+        _status = ST_ACCT;
+    }
+
+}
index e6a733aa9ba0b64b911897e6c83f555373e3f01f..fe5dadfb3ab2c69135388dd1514ff61184d203f3 100644 (file)
@@ -1,47 +1,88 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-/**\r
- * COPS Accounting Timer Object\r
- *\r
- * @version COPSAcctTimer.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSAcctTimer extends COPSTimer {\r
-\r
-    public COPSAcctTimer() {\r
-        super(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), (short) 1);\r
-    }\r
-\r
-    ///\r
-    public COPSAcctTimer(short timeVal) {\r
-        super(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), timeVal);\r
-    }\r
-\r
-    ///\r
-    /**\r
-     * Method isAcctTimer\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAcctTimer() {\r
-        return true;\r
-    }\r
-\r
-    ///\r
-    protected COPSAcctTimer(byte[] dataPtr) {\r
-        super (dataPtr);\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS Accounting Timer Object (RFC 2748)
+ *
+ * Times are encoded as 2 octet integer values and are in units of
+ * seconds.  The timer value is treated as a delta.
+ *
+ * C-Num = 15,
+ * C-Type = 1, Accounting timer value
+ *
+ * Optional timer value used to determine the minimum interval between
+ * periodic accounting type reports. It is used by the PDP to describe
+ * to the PEP an acceptable interval between unsolicited accounting
+ * updates via Report messages where applicable. It provides a method
+ * for the PDP to control the amount of accounting traffic seen by the
+ * network. The range of finite time values is 1 to 65535 seconds
+ * represented as an unsigned two-octet integer. A value of zero means
+ * there SHOULD be no unsolicited accounting updates.
+ */
+public class COPSAcctTimer extends COPSTimer {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param timeVal - the timer value
+     * @throws java.lang.IllegalArgumentException when the id parameter is null
+     */
+    public COPSAcctTimer(final short timeVal) {
+        this((short)0, timeVal);
+    }
+
+    /**
+     * Constructor generally used for sending messages with some reserved value
+     * @param reserved - ???
+     * @param timeVal - the timer value
+     * @throws java.lang.IllegalArgumentException when the id parameter is null
+     */
+    protected COPSAcctTimer(final short reserved, final short timeVal) {
+        this(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), reserved, timeVal);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param header - the object header
+     * @param reserved - ???
+     * @param timeVal - the timer value
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSAcctTimer(final COPSObjHeader header, final short reserved, final short timeVal) {
+        super(header, reserved, timeVal);
+        if (!header.getCNum().equals(CNum.ACCT_TIMER))
+            throw new IllegalArgumentException("Invalid CNum value. Must be " + CNum.ACCT_TIMER);
+        if (!header.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Invalid CType value. Must be " + CType.DEF);
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSAcctTimer parse(final COPSObjHeaderData objHdrData, byte[] dataPtr) {
+        short reserved = 0;
+        reserved |= ((short) dataPtr[4]) << 8;
+        reserved |= ((short) dataPtr[5]) & 0xFF;
+
+        short timerValue = 0;
+        timerValue |= ((short) dataPtr[6]) << 8;
+        timerValue |= ((short) dataPtr[7]) & 0xFF;
+
+        return new COPSAcctTimer(objHdrData.header, reserved, timerValue);
+    }
+
+}
+
index dde0963ba2dab611de2b72c6266ec6bb8bb70b49..c8784f2c7d9cdd373f73a77b00d4ade8244df5f3 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- *     COPS Client Accept Message\r
- *\r
- * @version COPSClientAcceptMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSClientAcceptMsg extends COPSMsg {\r
-\r
-    /* COPSHeader coming from base class */\r
-    private COPSKATimer _kaTimer;\r
-    private COPSAcctTimer _acctTimer;\r
-    private COPSIntegrity _integrity;\r
-\r
-    ///Constructor\r
-    public COPSClientAcceptMsg() {\r
-        _kaTimer = null;\r
-        _acctTimer = null;\r
-        _integrity = null;\r
-    }\r
-\r
-    ///Create object from data\r
-    protected COPSClientAcceptMsg(byte[] data) throws COPSException {\r
-        parse(data);\r
-    }\r
-\r
-    /** Checks the sanity of COPS message and throw an\r
-      * COPSBadDataException when data is bad.\r
-      */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_kaTimer == null))\r
-            throw new COPSException("Bad message format");\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_CAT)\r
-            throw new COPSException ("Error Header (no COPS_OP_CAT)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Timer object to the message\r
-     *\r
-     * @param    timer               a  COPSTimer\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSTimer timer) throws COPSException {\r
-        if (timer.isKATimer()) {\r
-            _kaTimer = (COPSKATimer) timer;\r
-        } else {\r
-            _acctTimer = (COPSAcctTimer) timer;\r
-        }\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Integrity objects\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Method getKATimer\r
-     *\r
-     * @return   a COPSKATimer\r
-     *\r
-     */\r
-    public COPSKATimer getKATimer() {\r
-        return _kaTimer;\r
-    };\r
-\r
-    /**\r
-     * Returns true if has a account timer object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasAcctTimer() {\r
-        return (_acctTimer != null);\r
-    };\r
-\r
-    /**\r
-     * Should check hasAcctTimer() before calling\r
-     *\r
-     * @return   a COPSAcctTimer\r
-     *\r
-     */\r
-    public COPSAcctTimer getAcctTimer() {\r
-        return (_acctTimer);\r
-    }\r
-\r
-    /**\r
-     * Returns true if has a Integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    };\r
-\r
-    /**\r
-     * Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return (_integrity);\r
-    }\r
-\r
-    /**\r
-     * Writes data to a given socket id\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_kaTimer != null) _kaTimer.writeData(id);\r
-        if (_acctTimer != null) _acctTimer.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case KA:\r
-                    _kaTimer = new COPSKATimer(buf);\r
-                    _dataStart += _kaTimer.getDataLength();\r
-                    break;\r
-                case ACCT_TIMER:\r
-                    _acctTimer = new COPSAcctTimer(buf);\r
-                    _dataStart += _acctTimer.getDataLength();\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default:\r
-                    throw new COPSException("Bad Message format");\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_CAT)\r
-            throw new COPSException("Error Header");\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength() throws COPSException {\r
-        short len = 0;\r
-        if (_kaTimer != null) len += _kaTimer.getDataLength();\r
-        if (_acctTimer != null) len += _acctTimer.getDataLength();\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_kaTimer != null)\r
-            _kaTimer.dump(os);\r
-\r
-        if (_acctTimer != null)\r
-            _acctTimer.dump(os);\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Client-Accept (CAT)  PDP -> PEP (RFC 2748 pag. 26)
+ *
+ * The Client-Accept message is used to positively respond to the
+ * Client-Open message. This message will return to the PEP a timer
+ * object indicating the maximum time interval between keep-alive
+ * messages. Optionally, a timer specifying the minimum allowed interval
+ * between accounting report messages may be included when applicable.
+ *
+ * <Client-Accept>  ::= <Common Header>
+ * <KA Timer>
+ * [<ACCT Timer>]
+ * [<Integrity>]
+ *
+ * If the PDP refuses the client, it will instead issue a Client-Close
+ * message.
+ *
+ * The KA Timer corresponds to maximum acceptable intermediate time
+ * between the generation of messages by the PDP and PEP. The timer
+ * value is determined by the PDP and is specified in seconds. A timer
+ * value of 0 implies no secondary connection verification is necessary.
+ *
+ * The optional ACCT Timer allows the PDP to indicate to the PEP that
+ * periodic accounting reports SHOULD NOT exceed the specified timer
+ * interval per client handle. This allows the PDP to control the rate
+ * at which accounting reports are sent by the PEP (when applicable).
+ *
+ * In general, accounting type Report messages are sent to the PDP when
+ * determined appropriate by the PEP. The accounting timer merely is
+ * used by the PDP to keep the rate of such updates in check (i.e.
+ * Preventing the PEP from blasting the PDP with accounting reports).
+ * Not including this object implies there are no PDP restrictions on
+ * the rate at which accounting updates are generated.
+ *
+ * If the PEP receives a malformed Client-Accept message it MUST
+ * generate a Client-Close message specifying the appropriate error
+ * code.
+ */
+public class COPSClientAcceptMsg extends COPSMsg {
+
+    // Required
+    private final COPSKATimer _kaTimer;
+
+    // Optional
+    private final COPSAcctTimer _acctTimer;
+    private final COPSIntegrity _integrity;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message (required)
+     * @param kaTimer - the Keep alive timer (required)
+     * @param acctTimer - the account timer (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSClientAcceptMsg(final short clientType, final COPSKATimer kaTimer, final COPSAcctTimer acctTimer,
+                               final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.CAT, clientType), kaTimer, acctTimer, integrity);
+    }
+
+    /**
+     * Constructor (generally used for sending messages).
+     * @param version - the supported PCMM Version
+     * @param flag - the flag...
+     * @param clientType - the type of client that created the message (required)
+     * @param kaTimer - the Keep alive timer (required)
+     * @param acctTimer - the account timer (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSClientAcceptMsg(final int version, final Flag flag, final short clientType,
+                               final COPSKATimer kaTimer, final COPSAcctTimer acctTimer, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.CAT, clientType), kaTimer, acctTimer, integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header
+     * @param kaTimer - the Keep alive timer (required)
+     * @param acctTimer - the account timer (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSClientAcceptMsg(final COPSHeader hdr, final COPSKATimer kaTimer, final COPSAcctTimer acctTimer,
+                               final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.CAT))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.CAT);
+        if (kaTimer == null) throw new IllegalArgumentException("Keep alive timer must not be null");
+        _kaTimer = kaTimer;
+        _acctTimer = acctTimer;
+        _integrity = integrity;
+    }
+
+    // Getters
+    public COPSKATimer getKATimer() {
+        return _kaTimer;
+    }
+    public COPSAcctTimer getAcctTimer() {
+        return (_acctTimer);
+    }
+    public COPSIntegrity getIntegrity() {
+        return (_integrity);
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _kaTimer.writeData(socket);
+        if (_acctTimer != null) _acctTimer.writeData(socket);
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = _kaTimer.getDataLength() + _kaTimer.getHeader().getHdrLength();
+        if (_acctTimer != null) out += _acctTimer.getDataLength() + _acctTimer.getHeader().getHdrLength();
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        _kaTimer.dump(os);
+        if (_acctTimer != null) _acctTimer.dump(os);
+        if (_integrity != null)  _integrity.dump(os);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSClientAcceptMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSClientAcceptMsg acceptMsg = (COPSClientAcceptMsg) o;
+
+        return !(_acctTimer != null ? !_acctTimer.equals(acceptMsg._acctTimer) : acceptMsg._acctTimer != null) &&
+                !(_integrity != null ? !_integrity.equals(acceptMsg._integrity) : acceptMsg._integrity != null) &&
+                _kaTimer.equals(acceptMsg._kaTimer);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _kaTimer.hashCode();
+        result = 31 * result + (_acctTimer != null ? _acctTimer.hashCode() : 0);
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSDecisionMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSClientAcceptMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSKATimer kaTimer = null;
+        COPSAcctTimer acctTimer = null;
+        COPSIntegrity integrity = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case KA:
+                    kaTimer = COPSKATimer.parse(objHdrData, buf);
+                    break;
+                case ACCT_TIMER:
+                    acctTimer = COPSAcctTimer.parse(objHdrData, buf);
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSClientAcceptMsg(hdrData.header, kaTimer, acctTimer, integrity);
+    }
+
+}
+
index 87f113a9a992388a25d227f93b65e47cf10d9f84..af1fad1bf7e172a86dd8549383ea70cf950db555 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Client Close Message\r
- *\r
- * @version COPSClientCloseMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSClientCloseMsg extends COPSMsg {\r
-\r
-    /* COPSHeader coming from base class */\r
-    private COPSError _error;\r
-    private COPSIntegrity _integrity;\r
-\r
-\r
-    public COPSClientCloseMsg() {\r
-        _error = null;\r
-        _integrity = null;\r
-    }\r
-\r
-    protected COPSClientCloseMsg(byte[] data) throws COPSException {\r
-        parse (data);\r
-    }\r
-\r
-    /** Checks the sanity of COPS message and throw an\r
-      * COPSBadDataException when data is bad.\r
-      */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_error == null))\r
-            throw new COPSException("Bad message format");\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_CC)\r
-            throw new COPSException ("Error Header (no COPS_OP_CC)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Error object\r
-     *\r
-     * @param    error               a  COPSError\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSError error) throws COPSException {\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_error != null)\r
-            throw new COPSException ("No null Error");\r
-        _error = error;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Integrity objects\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Method getError\r
-     *\r
-     * @return   a COPSError\r
-     *\r
-     */\r
-    public COPSError getError() {\r
-        return (_error);\r
-    }\r
-\r
-    /**\r
-     * Returns true If it has integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    };\r
-\r
-    /**\r
-     * Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return (_integrity);\r
-    }\r
-\r
-    /**\r
-     * Write object data to given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_error != null) _error.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-            case ERROR:\r
-                _error = new COPSError(buf);\r
-                _dataStart += _error.getDataLength();\r
-                break;\r
-            case MSG_INTEGRITY:\r
-                _integrity = new COPSIntegrity(buf);\r
-                _dataStart += _integrity.getDataLength();\r
-                break;\r
-            default:\r
-                throw new COPSException("Bad Message format");\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_CC)\r
-            throw new COPSException("Error Header");\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength() throws COPSException {\r
-        int len = 0;\r
-        if (_error != null) len += _error.getDataLength();\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_error != null)\r
-            _error.dump(os);\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Client Close Message (RFC 2748 pg. 27)
+ *
+ * The Client-Close message can be issued by either the PDP or PEP to
+ * notify the other that a particular type of client is no longer being
+ * supported.
+ *
+ * <Client-Close>  ::= <Common Header>
+ * <Error>
+ * [<PDPRedirAddr>]
+ * [<Integrity>]
+ *
+ * The Error object is included to describe the reason for the close
+ * (e.g. the requested client-type is not supported by the remote PDP or
+ * client failure).
+ *
+ * A PDP MAY optionally include a PDP Redirect Address object in order
+ * to inform the PEP of the alternate PDP it SHOULD use for the client-
+ * type specified in the common header.
+ */
+public class COPSClientCloseMsg extends COPSMsg {
+
+    // Required
+    private final COPSError _error;
+
+    // Optional
+    private final COPSPdpAddress _redirAddr;
+    private final COPSIntegrity _integrity;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message (required)
+     * @param error - the error (required)
+     * @param redirAddr - the redirect address (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSClientCloseMsg(final short clientType, final COPSError error, final COPSPdpAddress redirAddr,
+                              final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.CC, clientType), error, redirAddr, integrity);
+    }
+
+    /**
+     * Constructor (generally used for sending messages).
+     * @param version - the supported PCMM Version
+     * @param flag - the flag...
+     * @param clientType - the type of client that created the message (required)
+     * @param error - the error (required)
+     * @param redirAddr - the redirect address (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSClientCloseMsg(final int version, final Flag flag, final short clientType, final COPSError error,
+                              final COPSPdpAddress redirAddr, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.CC, clientType), error, redirAddr, integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header
+     * @param error - the error (required)
+     * @param redirAddr - the redirect address (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSClientCloseMsg(final COPSHeader hdr, final COPSError error, final COPSPdpAddress redirAddr,
+                              final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.CC))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.CAT);
+        if (error == null) throw new IllegalArgumentException("Error object must not be null");
+        this._error = error;
+        this._redirAddr = redirAddr;
+        this._integrity = integrity;
+    }
+
+    // Getters
+    public COPSError getError() {
+        return (_error);
+    }
+    public COPSPdpAddress getRedirAddr() {
+        return (_redirAddr);
+    }
+    public COPSIntegrity getIntegrity() {
+        return (_integrity);
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _error.writeData(socket);
+        if (_redirAddr != null) _redirAddr.writeData(socket);
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = _error.getDataLength() + _error.getHeader().getHdrLength();
+        if (_redirAddr != null) out += _redirAddr.getDataLength() + _redirAddr.getHeader().getHdrLength();
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+
+    @Override
+    protected void dumpBody(OutputStream os) throws IOException {
+        _error.dump(os);
+        if (_redirAddr != null) _redirAddr.dump(os);
+        if (_integrity != null) _integrity.dump(os);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSClientCloseMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSClientCloseMsg closeMsg = (COPSClientCloseMsg) o;
+
+        return _error.equals(closeMsg._error) &&
+                !(_integrity != null ? !_integrity.equals(closeMsg._integrity) : closeMsg._integrity != null) &&
+                !(_redirAddr != null ? !_redirAddr.equals(closeMsg._redirAddr) : closeMsg._redirAddr != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _error.hashCode();
+        result = 31 * result + (_redirAddr != null ? _redirAddr.hashCode() : 0);
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSDecisionMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSClientCloseMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSError error = null;
+        COPSPdpAddress redirAddr = null;
+        COPSIntegrity integrity = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case ERROR:
+                    error = COPSError.parse(objHdrData, buf);
+                    break;
+                case PDP_REDIR:
+                    redirAddr = COPSPdpAddress.parse(objHdrData, buf);
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSClientCloseMsg(hdrData.header, error, redirAddr, integrity);
+    }
+
+}
+
index 20faf0cf2627235c19edba4f815470e2d532b649..f634476cb255b5a27f997057818bddac1e584789 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Client Open Message\r
- *\r
- * @version COPSClientOpenMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSClientOpenMsg extends COPSMsg {\r
-\r
-    private COPSPepId _pepId;\r
-    private COPSClientSI _clientSI;\r
-    private COPSPdpAddress _pdpAddress;\r
-    private COPSIntegrity _integrity;\r
-\r
-    public COPSClientOpenMsg() {\r
-        _pepId = null;\r
-        _clientSI = null;\r
-        _pdpAddress = null;\r
-        _integrity = null;\r
-        _hdr = null;\r
-    }\r
-\r
-    protected COPSClientOpenMsg(byte[] data) throws COPSException {\r
-        _pepId = null;\r
-        _clientSI = null;\r
-        _pdpAddress = null;\r
-        _integrity = null;\r
-        _hdr = null;\r
-        parse(data);\r
-    }\r
-\r
-    /**\r
-     * Method writeData\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null)_hdr.writeData(id);\r
-        if (_pepId != null) _pepId.writeData(id);\r
-        if (_clientSI != null) _clientSI.writeData(id);\r
-        if (_pdpAddress != null) _pdpAddress.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_OPN)\r
-            throw new COPSException ("Error Header (no COPS_OP_OPN)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add PEP Identification Object\r
-     *\r
-     * @param    pepid               a  COPSPepId\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSPepId pepid) throws COPSException {\r
-        if (pepid == null)\r
-            throw new COPSException ("Null COPSPepId");\r
-        if (!pepid.isPepId())\r
-            throw new COPSException ("Error COPSPepId");\r
-        _pepId = pepid;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Client Specific Information Object\r
-     *\r
-     * @param    clientSI            a  COPSClientSI\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSClientSI clientSI) throws COPSException {\r
-        if (clientSI == null)\r
-            throw new COPSException ("Null COPSClientSI");\r
-        if (!clientSI.isClientSI())\r
-            throw new COPSException ("Error COPSClientSI");\r
-        _clientSI = clientSI;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add PDP Address\r
-     *\r
-     * @param    pdpAddr             a  COPSPdpAddress\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSPdpAddress pdpAddr) throws COPSException {\r
-        if (pdpAddr == null)\r
-            throw new COPSException ("Null COPSPdpAddress");\r
-        if (!pdpAddr.isLastPdpAddress())\r
-            throw new COPSException ("Error COPSPdpAddress");\r
-        _pdpAddress = pdpAddr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Integrity object\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /** Checks the sanity of COPS message and throw an\r
-          * COPSBadDataException when data is bad.\r
-    */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_pepId == null))\r
-            throw new COPSException("Bad message format");\r
-    }\r
-\r
-    /**\r
-     * Method getPepId\r
-     *\r
-     * @return   a COPSPepId\r
-     *\r
-     */\r
-    public COPSPepId getPepId() {\r
-        return _pepId;\r
-    }\r
-\r
-    /**\r
-     * Method hasClientSI\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasClientSI() {\r
-        return (_clientSI != null);\r
-    }\r
-\r
-    /**\r
-     * Method getClientSI\r
-     *\r
-     * @return   a COPSClientSI\r
-     *\r
-     */\r
-    public COPSClientSI getClientSI() {\r
-        return (_clientSI);\r
-    }\r
-\r
-    /**\r
-     * Method hasPdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasPdpAddress() {\r
-        return (_pdpAddress != null);\r
-    }\r
-\r
-    /**\r
-     * Method getPdpAddress\r
-     *\r
-     * @return   a COPSPdpAddress\r
-     *\r
-     */\r
-    public COPSPdpAddress getPdpAddress() {\r
-        return _pdpAddress;\r
-    }\r
-\r
-    /**\r
-     * Method hasIntegrity\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    }\r
-\r
-    /**\r
-     * Method getIntegrity\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return _integrity;\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    private void setMsgLength() throws COPSException {\r
-        short len = 0;\r
-        if (_pepId != null) len += _pepId.getDataLength();\r
-        if (_clientSI != null) len += _clientSI.getDataLength();\r
-        if (_pdpAddress != null) len += _pdpAddress.getDataLength();\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        parseHeader(data);\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case PEPID:\r
-                    _pepId = new COPSPepId(buf);\r
-                    _dataStart += _pepId.getDataLength();\r
-                    break;\r
-                case LAST_PDP_ADDR:\r
-                    if (objHdr.getCType().ordinal() == 1) {\r
-                        _pdpAddress = new COPSIpv4LastPdpAddr(buf);\r
-                    } else if (objHdr.getCType().ordinal() == 2) {\r
-                        _pdpAddress = new COPSIpv6LastPdpAddr(buf);\r
-                    }\r
-                    _dataStart += _pdpAddress.getDataLength();\r
-                    break;\r
-                case CSI:\r
-                    _clientSI = new COPSClientSI(buf);\r
-                    _dataStart += _clientSI.getDataLength();\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default:\r
-                    throw new COPSException("Bad Message format");\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_OPN)\r
-            throw new COPSException("Error Header");\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_pepId != null)\r
-            _pepId.dump(os);\r
-\r
-        if (_clientSI != null)\r
-            _clientSI.dump(os);\r
-\r
-        if (_pdpAddress != null)\r
-            _pdpAddress.dump(os);\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Client Open Message (RFC 2748 page. 26)
+ *
+ * The Client-Open message can be used by the PEP to specify to the PDP
+ * the client-types the PEP can support, the last PDP to which the PEP
+ * connected for the given client-type, and/or client specific feature
+ * negotiation. A Client-Open message can be sent to the PDP at any time
+ * and multiple Client-Open messages for the same client-type are
+ * allowed (in case of global state changes).
+ *
+ * <Client-Open>  ::= <Common Header>
+ * <PEPID>
+ * [<ClientSI>]
+ * [<LastPDPAddr>]
+ * [<Integrity>]
+ *
+ * The PEPID is a symbolic, variable length name that uniquely
+ * identifies the specific client to the PDP (see Section 2.2.11).
+ *
+ * A named ClientSI object can be included for relaying additional
+ * global information about the PEP to the PDP when required (as
+ * specified in the appropriate extensions document for the client-
+ * type).
+ *
+ * The PEP may also provide a Last PDP Address object in its Client-Open
+ * message specifying the last PDP (for the given client-type) for which
+ * it is still caching decisions since its last reboot. A PDP can use
+ * this information to determine the appropriate synchronization
+ * behavior (See section 2.5).
+ *
+ * If the PDP receives a malformed Client-Open message it MUST generate
+ * a Client-Close message specifying the appropriate error code.
+ */
+public class COPSClientOpenMsg extends COPSMsg {
+
+    private final COPSPepId _pepId;
+    private final COPSClientSI _clientSI;
+    private final COPSPdpAddress _pdpAddress;
+    private final COPSIntegrity _integrity;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message (required)
+     * @param pepId - the PEP ID (required)
+     * @param clientSI - the COPS Client SI (optional)
+     * @param pdpAddress - the COPS PDP Address (optional)
+     * @param integrity - the COPS Integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSClientOpenMsg(final short clientType, final COPSPepId pepId, final COPSClientSI clientSI,
+                             final COPSPdpAddress pdpAddress, final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.OPN, clientType), pepId, clientSI, pdpAddress, integrity);
+    }
+
+    /**
+     * Recommended constructor generally for use by a client sending messages.
+     * @param version - the supported PCMM Version (required)
+     * @param flag - the flag...  (required)
+     * @param clientType - the type of client that created the message (required)
+     * @param pepId - the PEP ID (required)
+     * @param clientSI - the COPS Client SI (optional)
+     * @param pdpAddress - the COPS PDP Address (optional)
+     * @param integrity - the COPS Integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSClientOpenMsg(final int version, final Flag flag, final short clientType, final COPSPepId pepId,
+                             final COPSClientSI clientSI, final COPSPdpAddress pdpAddress,
+                             final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.OPN, clientType), pepId, clientSI, pdpAddress, integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header (required)
+     * @param pepId - the PEP ID (required)
+     * @param clientSI - the COPS Client SI (optional)
+     * @param pdpAddress - the COPS PDP Address (optional)
+     * @param integrity - the COPS Integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSClientOpenMsg(final COPSHeader hdr, final COPSPepId pepId, final COPSClientSI clientSI,
+                             final COPSPdpAddress pdpAddress, final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.OPN))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.OPN);
+        if (pepId == null) throw new IllegalArgumentException("Pep ID must not be null");
+        // TODO - considering adding some validation on the PDP Address and the client type
+        this._pepId = pepId;
+        this._clientSI = clientSI;
+        this._pdpAddress = pdpAddress;
+        this._integrity = integrity;
+    }
+
+    // Getters
+    public COPSPepId getPepId() {
+        return _pepId;
+    }
+    public COPSClientSI getClientSI() {
+        return (_clientSI);
+    }
+    public COPSPdpAddress getPdpAddress() {
+        return _pdpAddress;
+    }
+    public COPSIntegrity getIntegrity() {
+        return _integrity;
+    }
+
+    /**
+     * Method writeData
+     * @param    socket                  a  Socket
+     * @throws   IOException
+     */
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _pepId.writeData(socket);
+        if (_clientSI != null) _clientSI.writeData(socket);
+        if (_pdpAddress != null) _pdpAddress.writeData(socket);
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = _pepId.getDataLength() + _pepId.getHeader().getHdrLength();
+        if (_clientSI != null) out += _clientSI.getDataLength() + _clientSI.getHeader().getHdrLength();
+        if (_pdpAddress != null) out += _pdpAddress.getDataLength() + _pdpAddress.getHeader().getHdrLength();
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        _pepId.dump(os);
+        if (_clientSI != null) _clientSI.dump(os);
+        if (_pdpAddress != null) _pdpAddress.dump(os);
+        if (_integrity != null)  _integrity.dump(os);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSClientOpenMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSClientOpenMsg that = (COPSClientOpenMsg) o;
+
+        return !(_clientSI != null ? !_clientSI.equals(that._clientSI) : that._clientSI != null) &&
+                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null) &&
+                !(_pdpAddress != null ? !_pdpAddress.equals(that._pdpAddress) : that._pdpAddress != null) &&
+                _pepId.equals(that._pepId);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _pepId.hashCode();
+        result = 31 * result + (_clientSI != null ? _clientSI.hashCode() : 0);
+        result = 31 * result + (_pdpAddress != null ? _pdpAddress.hashCode() : 0);
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSReqMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSClientOpenMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSPepId pepId = null;
+        COPSClientSI clientSI = null;
+        COPSPdpAddress pdpAddress = null;
+        COPSIntegrity integrity = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case PEPID:
+                    pepId = COPSPepId.parse(objHdrData, buf);
+                    break;
+                case CSI:
+                    clientSI = COPSClientSI.parse(objHdrData, buf);
+                    break;
+                case LAST_PDP_ADDR:
+                    pdpAddress = COPSPdpAddress.parse(objHdrData, buf);
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSClientOpenMsg(hdrData.header, pepId, clientSI, pdpAddress, integrity);
+    }
+
+}
+
+
+
index 8b6bf23ab04ba282df681aeaa626dd3a4f81208b..e25fb91624924f15aee678956a9f439163b2ffc4 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Client Specific Information Object\r
- *\r
- * @version COPSClientSI.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSClientSI extends COPSObjBase {\r
-    public final static byte CSI_SIGNALED = 1;\r
-    public final static byte CSI_NAMED = 2;\r
-\r
-    private COPSObjHeader _objHdr;\r
-    private COPSData _data;\r
-    private COPSData _padding;\r
-\r
-    ///\r
-    public COPSClientSI(byte type) {\r
-        _objHdr = new COPSObjHeader(CNum.CSI, COPSObjHeader.VAL_TO_CTYPE.get((int)type));\r
-    }\r
-\r
-    public COPSClientSI(byte cnum, byte ctype) {\r
-        _objHdr = new COPSObjHeader(COPSObjHeader.VAL_TO_CNUM.get((int)cnum), COPSObjHeader.VAL_TO_CTYPE.get((int)ctype));\r
-    }\r
-\r
-    /**\r
-     Parse the data and create a ClientSI object\r
-     */\r
-    protected COPSClientSI(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        //Get the length of data following the obj header\r
-        short dLen = (short) (_objHdr.getDataLength() - 4);\r
-        COPSData d = new COPSData(dataPtr, 4, dLen);\r
-        setData(d);\r
-    }\r
-\r
-    /**\r
-     * Method setData\r
-     *\r
-     * @param    data                a  COPSData\r
-     *\r
-     */\r
-    public void setData(COPSData data) {\r
-        _data = data;\r
-        if (_data.length() % 4 != 0) {\r
-            int padLen = 4 - _data.length() % 4;\r
-            _padding = getPadding(padLen);\r
-        }\r
-        _objHdr.setDataLength((short) _data.length());\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        int lpadding = 0;\r
-        if (_padding != null) lpadding = _padding.length();\r
-        return (short) (_objHdr.getDataLength() + lpadding);\r
-    }\r
-\r
-    /**\r
-     * Method getData\r
-     *\r
-     * @return   a COPSData\r
-     *\r
-     */\r
-    public COPSData getData() {\r
-        return _data;\r
-    };\r
-\r
-    /**\r
-     * Method isClientSI\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isClientSI() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Write data on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-        COPSUtil.writeData(id, _data.getData(), _data.length());\r
-        if (_padding != null) {\r
-            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("client-SI: " + _data.str() + "\n").getBytes());\r
-    }\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Client Specific Information Object (RFC 2748)
+ *
+ * The various types of this object are required for requests, and used
+ * in reports and opens when required. It contains client-type specific
+ * information.
+ *
+ * C-Num = 9,
+ *
+ * C-Type = 1, Signaled ClientSI.
+ *
+ * Variable-length field. All objects/attributes specific to a client's
+ * signaling protocol or internal state are encapsulated within one or
+ * more signaled Client Specific Information Objects. The format of the
+ * data encapsulated in the ClientSI object is determined by the
+ * client-type.
+ *
+ * C-Type = 2, Named ClientSI.
+ *
+ * Variable-length field. Contains named configuration information
+ * useful for relaying specific information about the PEP, a request, or
+ * configured state to the PDP server.
+ */
+public class COPSClientSI extends COPSObjBase {
+
+    private final static Map<Integer, CSIType> VAL_TO_CSI = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_CSI.put(CSIType.NA.ordinal(), CSIType.NA);
+        VAL_TO_CSI.put(CSIType.SIGNALED.ordinal(), CSIType.SIGNALED);
+        VAL_TO_CSI.put(CSIType.NAMED.ordinal(), CSIType.NAMED);
+    }
+
+    /**
+     * This value is not being used here but stored only for clarity as it is being mapped directly to the
+     * ordinal value of the CType
+     */
+    private final CSIType _csiType;
+
+    /**
+     * The payload data
+     */
+    private final COPSData _data;
+
+    /**
+     * Bytes to add to outbound payload to ensure the length is divisible by 4 bytes
+     */
+    private final COPSData _padding;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param csitype - the CSIType
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSClientSI(final CSIType csitype, final COPSData data) {
+        /* The CSIType does not map directly to the CType, therefore the hook to map to a CType below is
+           required to ensure the header value outputs the correct value when streamed
+         */
+        this(new COPSObjHeader(CNum.CSI, COPSObjHeader.VAL_TO_CTYPE.get(csitype.ordinal())), data);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSClientSI(final COPSObjHeader hdr, final COPSData data) {
+        super(hdr);
+        _csiType = VAL_TO_CSI.get(hdr.getCType().ordinal());
+
+        if (!hdr.getCNum().equals(CNum.CSI))
+            throw new IllegalArgumentException("CNum must be equal to " + CNum.CSI);
+        if (_csiType == null || _csiType.equals(CSIType.NA))
+            throw new IllegalArgumentException("Invalid CSIType");
+        if (_csiType.ordinal() != hdr.getCType().ordinal())
+            throw new IllegalArgumentException("Error mapping CSIType " + _csiType + " to CType" + hdr.getCType());
+        if (data == null) throw new IllegalArgumentException("Data must not be null");
+
+        _data = data;
+        if ((_data.length() % 4) != 0) {
+            final int padLen = 4 - (_data.length() % 4);
+            _padding = COPSObjectParser.getPadding(padLen);
+        } else {
+            _padding = new COPSData();
+        }
+    }
+
+    /**
+     * Returns the CSIType
+     * @return - the type
+     */
+    public CSIType getCsiType() { return _csiType; }
+
+    /**
+     * Returns the data
+     * @return - the data
+     */
+    public COPSData getData() { return _data; }
+
+    @Override
+    /* The super says protected but this needs to be public due to usage in COPSDecisionMsgEX.java which is currently
+       calling this method. */
+    public int getDataLength() {
+        return _data.length() + _padding.length();
+    }
+
+    @Override
+    public void writeBody(final Socket socket) throws IOException {
+        COPSUtil.writeData(socket, _data.getData(), _data.length());
+        COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("CSI-type: " + _csiType + "\n").getBytes());
+        os.write(("client-SI: " + _data.str() + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSClientSI)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSClientSI that = (COPSClientSI) o;
+        return _data.equals(that._data) && _padding.equals(that._padding) ||
+                COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (_data != null ? _data.hashCode() : 0);
+        result = 31 * result + (_padding != null ? _padding.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Parses bytes to return a COPSClientSI object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSClientSI parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        short dLen = (short) (objHdrData.msgByteCount - 4);
+        return new COPSClientSI(objHdrData.header, new COPSData(dataPtr, 4, dLen));
+    }
+
+    /**
+     * The different CSI types. NA does not exist but is a placeholder for 0 as the ordinal values will be used
+     * to determine which type for marshalling
+     */
+    public enum CSIType {
+        NA, SIGNALED, NAMED
+    }
+}
+
index 4aa1821682d726b7b4d1d797971ce1a8973830b7..333da4f8ca12826f80623ba9ff28f317f1471d5f 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Context Object\r
- *\r
- * @version COPSContext.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSContext extends COPSObjBase {\r
-\r
-    public final static byte IN_ADMIN = 0x01;\r
-    public final static byte RES_ALLOC = 0x02;\r
-    public final static byte OUT = 0x04;\r
-    public final static byte CONFIG = 0x08;\r
-\r
-    private COPSObjHeader _objHdr;\r
-    private short _rType;\r
-    private short _mType;\r
-\r
-    ///\r
-    public COPSContext(short rType, short mType ) {\r
-        _objHdr = new COPSObjHeader(CNum.CONTEXT, CType.DEF);\r
-        _rType = rType;\r
-        _mType = mType;\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-          Parse the data and create a Context object\r
-     */\r
-    protected COPSContext(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        _rType |= ((short) dataPtr[4]) << 8;\r
-        _rType |= ((short) dataPtr[5]) & 0xFF;\r
-\r
-        _mType |= ((short) dataPtr[6]) << 8;\r
-        _mType |= ((short) dataPtr[7]) & 0xFF;\r
-\r
-        _objHdr.setDataLength( (short) 4);\r
-    }\r
-\r
-    /**\r
-     * Write object in network byte order to a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-\r
-        buf[0] = (byte) (_rType >> 8);\r
-        buf[1] = (byte) _rType;\r
-\r
-        buf[2] = (byte) (_mType >> 8);\r
-        buf[3] = (byte) _mType;\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    /**\r
-     * Returns the detail description of the request type\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String getDescription() {\r
-        String retStr = new String();\r
-        if ((_rType & 0x01) != 0) {\r
-            retStr += (retStr.length() != 0) ? "," : "";\r
-            retStr += "Incoming Message/Admission Control";\r
-        }\r
-        if ((_rType & 0x02) != 0) {\r
-            retStr += (retStr.length() != 0) ? "," : "";\r
-            retStr += "Resource allocation";\r
-        }\r
-        if ((_rType & 0x04) != 0) {\r
-            retStr += (retStr.length() != 0) ? "," : "";\r
-            retStr += "Outgoing message";\r
-        }\r
-        if ((_rType & 0x08) != 0) {\r
-            retStr += (retStr.length() != 0) ? "," : "";\r
-            retStr += "Configuration";\r
-        }\r
-        return retStr;\r
-    }\r
-\r
-    /**\r
-     * Method isIncomingMessage\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIncomingMessage() {\r
-        return (_rType & IN_ADMIN) != 0;\r
-    };\r
-\r
-    /**\r
-     * Method isAdminControl\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAdminControl() {\r
-        return (_rType & IN_ADMIN) != 0;\r
-    };\r
-\r
-    /**\r
-     * Method isResourceAllocationReq\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isResourceAllocationReq() {\r
-        return (_rType & RES_ALLOC) != 0;\r
-    };\r
-\r
-    /**\r
-     * Method isOutgoingMessage\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isOutgoingMessage() {\r
-        return (_rType & OUT) != 0;\r
-    };\r
-\r
-    /**\r
-     * Method isConfigRequest\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isConfigRequest() {\r
-        return (_rType & CONFIG) != 0;\r
-    };\r
-\r
-    /**\r
-     * Method getMessageType\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getMessageType() {\r
-        return (_mType) ;\r
-    };\r
-\r
-    /**\r
-     * Method getRequestType\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getRequestType() {\r
-        return (_rType);\r
-    };\r
-\r
-    /**\r
-     * Method isContext\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isContext() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("context: " + getDescription() + "," + _mType + "\n").getBytes());\r
-    }\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Context Object (RFC 2748)
+ *
+ * Specifies the type of event(s) that triggered the query. Required for
+ * request messages. Admission control, resource allocation, and
+ * forwarding requests are all amenable to client-types that outsource
+ * their decision making facility to the PDP. For applicable client-
+ * types a PEP can also make a request to receive named configuration
+ * information from the PDP. This named configuration data may be in a
+ * form useful for setting system attributes on a PEP, or it may be in
+ * the form of policy rules that are to be directly verified by the PEP.
+ *
+ * Multiple flags can be set for the same request. This is only allowed,
+ * however, if the set of client specific information in the combined
+ * request is identical to the client specific information that would be
+ * specified if individual requests were made for each specified flag.
+ *
+ * C-num = 2, C-Type = 1
+ *
+ * R-Type (Request Type Flag)
+ *
+ * 0x01 = Incoming-Message/Admission Control request
+ * 0x02 = Resource-Allocation request
+ * 0x04 = Outgoing-Message request
+ * 0x08 = Configuration request
+ *
+ * M-Type (Message Type)
+ *
+ * Client Specific 16 bit values of protocol message types
+ */
+public class COPSContext extends COPSObjBase {
+
+    /**
+     * A Map containing each RType by the byte value
+     */
+    public final static Map<Integer, RType> VAL_TO_RTYPE = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_RTYPE.put(1, RType.IN_ADMIN);
+        VAL_TO_RTYPE.put(2, RType.RES_ALLOC);
+        VAL_TO_RTYPE.put(4, RType.OUT);
+        VAL_TO_RTYPE.put(8, RType.CONFIG);
+    }
+
+    /**
+     * A Map containing the byte value by RType
+     */
+    private final static Map<RType, Integer> RTYPE_TO_VAL = new ConcurrentHashMap<>();
+    static {
+        for (final Map.Entry<Integer, RType> entry : VAL_TO_RTYPE.entrySet()) {
+            RTYPE_TO_VAL.put(entry.getValue(), entry.getKey());
+        }
+    }
+
+    /**
+     * The request type
+     */
+    private final RType _rType;
+
+    /**
+     * The message type
+     * Cannot find a list of types in order to make this an enumeration
+     */
+    private short _mType;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param rType - the type of request
+     * @param mType - the type of message
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSContext(final RType rType, final short mType ) {
+        this(new COPSObjHeader(CNum.CONTEXT, CType.DEF), rType, mType);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param rType - the type of request
+     * @param mType - the type of message
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSContext(final COPSObjHeader objHdr, final RType rType, final short mType ) {
+        super(objHdr);
+
+        if (!objHdr.getCNum().equals(CNum.CONTEXT))
+            throw new IllegalArgumentException("CNum must be equal to " + CNum.CONTEXT);
+        if (!objHdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Invalid CType value. Must be " + CType.DEF);
+        if (rType == null) throw new IllegalArgumentException("Must have a valid RType");
+
+        _rType = rType;
+        _mType = mType;
+    }
+
+    @Override
+    public void writeBody(final Socket socket) throws IOException {
+        byte[] buf = new byte[4];
+
+        final int rType = RTYPE_TO_VAL.get(_rType);
+        buf[0] = (byte)((byte)rType >> 8);
+        buf[1] = (byte)rType;
+
+        buf[2] = (byte)(_mType >> 8);
+        buf[3] = (byte)_mType;
+
+        COPSUtil.writeData(socket, buf, 4);
+    }
+
+    @Override
+    public int getDataLength() {
+        return 4;
+    }
+
+    /**
+     * Returns the detail description of the request type
+     * @return   a String
+     */
+    public String getDescription() {
+        switch (_rType) {
+            case IN_ADMIN: return "Incoming Message/Admission Control";
+            case RES_ALLOC: return "Resource allocation";
+            case OUT: return "Outgoing message";
+            case CONFIG: return "Configuration";
+            default: return "";
+        }
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("context: " + getDescription() + "," + _mType + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSContext)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSContext that = (COPSContext) o;
+
+        return _mType == that._mType && _rType == that._rType;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _rType.hashCode();
+        result = 31 * result + (int) _mType;
+        return result;
+    }
+
+    /**
+     * Parses bytes to return a COPSContext object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSContext parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        short rType = 0;
+        rType |= ((short) dataPtr[4]) << 8;
+        rType |= ((short) dataPtr[5]) & 0xFF;
+
+        short mType = 0;
+        mType |= ((short) dataPtr[6]) << 8;
+        mType |= ((short) dataPtr[7]) & 0xFF;
+
+        return new COPSContext(objHdrData.header, VAL_TO_RTYPE.get((int)rType), mType);
+    }
+
+    /**
+     * The request type
+     */
+    public enum RType {
+        IN_ADMIN, RES_ALLOC, OUT, CONFIG,
+    }
+
+}
+
+
index 6b05a043033ba31144601404f7fb632f7dc462dd..560c6bfcb02585c758a743dd3acb32378ba15730 100644 (file)
@@ -33,7 +33,7 @@ public class COPSData {
      * Default constructor\r
      */\r
     public COPSData() {\r
-        _dataBuf = null;\r
+        _dataBuf = new byte[0];\r
         _dLen = 0;\r
     }\r
 \r
index a572342e19e1238aab1b26bb831b995916f80114..4e152bc890995425c84ab9ad913b075841de1b21 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Decision\r
- *\r
- * @version COPSDecision.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSDecision extends COPSObjBase {\r
-\r
-    // CType\r
-    @Deprecated public final static byte DEC_DEF = 1;\r
-    @Deprecated public final static byte DEC_STATELESS = 2;\r
-    @Deprecated public final static byte DEC_REPL = 3;\r
-    @Deprecated public final static byte DEC_CSI = 4;\r
-    @Deprecated public final static byte DEC_NAMED = 5;\r
-\r
-    // Command\r
-    @Deprecated public final static byte DEC_NULL = 0;\r
-    @Deprecated public final static byte DEC_INSTALL = 1;\r
-    @Deprecated public final static byte DEC_REMOVE = 2;\r
-\r
-    // Flags\r
-    @Deprecated public final static byte F_REQERROR = 0x1;\r
-    @Deprecated public final static byte F_REQSTATE = 0x2;\r
-\r
-    protected COPSObjHeader _objHdr;\r
-    private COPSData _data;\r
-    private short _cmdCode;\r
-    private short _flags;\r
-    private COPSData _padding;\r
-\r
-    /**\r
-      Constructor to create a Decision object. By default creates\r
-      a decision object which is of fixed length.\r
-     */\r
-    public COPSDecision(byte cType) {\r
-        _objHdr = new COPSObjHeader(CNum.DEC, COPSObjHeader.VAL_TO_CTYPE.get((int)cType));\r
-        _cmdCode = 0;\r
-        _flags = 0;\r
-        if (cType == CType.DEF.ordinal()) _objHdr.setDataLength( (short) 4);\r
-    }\r
-\r
-    public COPSDecision() {\r
-        _objHdr = new COPSObjHeader(CNum.DEC, CType.DEF);\r
-        _cmdCode = 0;\r
-        _flags = 0;\r
-        _objHdr.setDataLength( (short) 4);\r
-    }\r
-\r
-    /**\r
-          Initialize the decision object with values from COPSObj header\r
-     */\r
-    protected COPSDecision(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        _cmdCode = 0;\r
-        _flags = 0;\r
-        if (_objHdr.getCType().equals(CType.DEF)) {\r
-            _cmdCode |= ((short) dataPtr[4]) << 8;\r
-            _cmdCode |= ((short) dataPtr[5]) & 0xFF;\r
-            _flags |= ((short) dataPtr[6]) << 8;\r
-            _flags |= ((short) dataPtr[7]) & 0xFF;\r
-\r
-            _objHdr.setDataLength((short) 4);\r
-        } else {\r
-            int dLen = _objHdr.getDataLength() - 4;\r
-            COPSData d = new COPSData(dataPtr, 4, dLen);\r
-            setData(d);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Method getDataLength\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        int lpadding = 0;\r
-        if (_padding != null) lpadding = _padding.length();\r
-        return ((short) (_objHdr.getDataLength() + lpadding));\r
-    }\r
-\r
-\r
-\r
-    /**\r
-     * Get the associated data if decision object is of cType 2 or higher\r
-     *\r
-     * @return   a COPSData\r
-     *\r
-     */\r
-    public COPSData getData() {\r
-        return (_data);\r
-    }\r
-\r
-    /**\r
-     * Set the decision data if decision object is of cType 2 or higher\r
-     *\r
-     * @param    data                a  COPSData\r
-     *\r
-     */\r
-    public void setData(COPSData data) {\r
-        if (data.length() % 4 != 0) {\r
-            int padLen = 4 - data.length() % 4;\r
-            _padding = getPadding(padLen);\r
-        }\r
-        _data = data;\r
-        _objHdr.setDataLength((short) data.length());\r
-    }\r
-\r
-    /**\r
-     * Retruns true if cType = 1\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isFlagSet() {\r
-        return ( _objHdr.getCType().ordinal() == 1);\r
-    };\r
-\r
-    /**\r
-     * If cType == 1 , get the flags associated\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getFlags() {\r
-        return (_flags);\r
-    };\r
-\r
-    /**\r
-     * If cType == 1 ,set the cmd code\r
-     *\r
-     * @param    cCode               a  byte\r
-     *\r
-     */\r
-    public void setCmdCode(byte cCode) {\r
-        _cmdCode = (short) cCode;\r
-    }\r
-\r
-    /**\r
-     * If cType == 1 ,set the cmd flags\r
-     *\r
-     * @param    flags               a  short\r
-     *\r
-     */\r
-    public void setFlags(short flags) {\r
-        _flags = flags;\r
-    }\r
-\r
-    /**\r
-     * Method isNullDecision\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isNullDecision() {\r
-        return ( _cmdCode == 0);\r
-    };\r
-\r
-    /**\r
-     * Method isInstallDecision\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isInstallDecision() {\r
-        return ( _cmdCode == 1);\r
-    };\r
-\r
-    /**\r
-     * Method isRemoveDecision\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isRemoveDecision() {\r
-        return ( _cmdCode == 2);\r
-    };\r
-\r
-    /**\r
-     * Method getTypeStr\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String getTypeStr() {\r
-        switch (_objHdr.getCType()) {\r
-            case DEF:\r
-                return "Default";\r
-            case STATELESS:\r
-                return "Stateless data";\r
-            case REPL:\r
-                return "Replacement data";\r
-            case CSI:\r
-                return "Client specific decision data";\r
-            case NAMED:\r
-                return "Named decision data";\r
-            default:\r
-                return "Unknown";\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Method isDecision\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isDecision() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Method isLocalDecision\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isLocalDecision() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Writes data to a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-\r
-        if (_objHdr.getCType().ordinal() >= 2) {\r
-            COPSUtil.writeData(id, _data.getData(), _data.length());\r
-            if (_padding != null) {\r
-                COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
-            }\r
-        } else {\r
-            byte[] buf = new byte[4];\r
-            buf[0] = (byte) (_cmdCode >> 8);\r
-            buf[1] = (byte) _cmdCode;\r
-            buf[2] = (byte) (_flags >> 8);\r
-            buf[3] = (byte) _flags;\r
-            COPSUtil.writeData(id, buf, 4);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-\r
-        if (_objHdr.getCType().ordinal() == 1) {\r
-            os.write(new String("Decision (" + getTypeStr() + ")\n").getBytes());\r
-            os.write(new String("Command code: " + _cmdCode + "\n").getBytes());\r
-            os.write(new String("Command flags: " + _flags + "\n").getBytes());\r
-        } else {\r
-            os.write(new String("Decision (" + getTypeStr() + ")\n").getBytes());\r
-            os.write(new String("Data: " + _data.str() + "\n").getBytes());\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Decision (RFC 2748)
+ *
+ * Decision made by the PDP. Appears in replies. The specific non-
+ * mandatory decision objects required in a decision to a particular
+ * request depend on the type of client.
+ *
+ * C-Num = 6
+ * C-Type = 1, Decision Flags (Mandatory)
+ *
+ * Commands:
+ * 0 = NULL Decision (No configuration data available)
+ * 1 = Install (Admit request/Install configuration)
+ * 2 = Remove (Remove request/Remove configuration)
+ *
+ * Flags:
+ * 0x01 = Trigger Error (Trigger error message if set)
+ * Note: Trigger Error is applicable to client-types that
+ * are capable of sending error notifications for signaled
+ * messages.
+ *
+ * Flag values not applicable to a given context's R-Type or
+ * client-type MUST be ignored by the PEP.
+ *
+ * C-Type = 2, Stateless Data
+ *
+ * This type of decision object carries additional stateless
+ * information that can be applied by the PEP locally. It is a
+ * variable length object and its internal format SHOULD be
+ * specified in the relevant COPS extension document for the given
+ * client-type. This object is optional in Decision messages and is
+ * interpreted relative to a given context.
+ *
+ * It is expected that even outsourcing PEPs will be able to make
+ * some simple stateless policy decisions locally in their LPDP. As
+ * this set is well known and implemented ubiquitously, PDPs are
+ * aware of it as well (either universally, through configuration,
+ * or using the Client-Open message). The PDP may also include this
+ * information in its decision, and the PEP MUST apply it to the
+ * resource allocation event that generated the request.
+ *
+ * C-Type = 3, Replacement Data
+ *
+ * This type of decision object carries replacement data that is to
+ * replace existing data in a signaled message. It is a variable
+ * length object and its internal format SHOULD be specified in the
+ * relevant COPS extension document for the given client-type. It is
+ * optional in Decision messages and is interpreted relative to a
+ * given context.
+ *
+ * C-Type = 4, Client Specific Decision Data
+ *
+ * Additional decision types can be introduced using the Client
+ * Specific Decision Data Object. It is a variable length object and
+ * its internal format SHOULD be specified in the relevant COPS
+ * extension document for the given client-type. It is optional in
+ * Decision messages and is interpreted relative to a given context.
+ *
+ * C-Type = 5, Named Decision Data
+ *
+ * Named configuration information is encapsulated in this version
+ * of the decision object in response to configuration requests. It
+ * is a variable length object and its internal format SHOULD be
+ * specified in the relevant COPS extension document for the given
+ * client-type. It is optional in Decision messages and is
+ * interpreted relative to both a given context and decision flags.
+ */
+public class COPSDecision extends COPSObjBase {
+
+    static Map<Integer, Command> VAL_TO_CMD = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_CMD.put(Command.NULL.ordinal(), Command.NULL);
+        VAL_TO_CMD.put(Command.INSTALL.ordinal(), Command.INSTALL);
+        VAL_TO_CMD.put(Command.REMOVE.ordinal(), Command.REMOVE);
+    }
+
+    static Map<Integer, DecisionFlag> VAL_TO_FLAG = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_FLAG.put(DecisionFlag.NA.ordinal(), DecisionFlag.NA);
+        VAL_TO_FLAG.put(DecisionFlag.REQERROR.ordinal(), DecisionFlag.REQERROR);
+        VAL_TO_FLAG.put(DecisionFlag.REQSTATE.ordinal(), DecisionFlag.REQSTATE);
+    }
+
+    /**
+     * All CTypes are supported except NA
+     */
+    private final Command _cmdCode;
+    private final DecisionFlag _flags;
+    private final COPSData _data;
+    private final COPSData _padding;
+
+    /**
+     * Constructor generally used for sending messages without any extra data
+     * @param cmdCode - the command
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSDecision(final Command cmdCode) {
+        this(CType.DEF, cmdCode, DecisionFlag.NA, new COPSData());
+    }
+
+    /**
+     * Constructor generally used for sending messages with a specific CType and extra data and a NA decision flag
+     * @param cType - the CType
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSDecision(final CType cType, final COPSData data) {
+        this(cType, Command.NULL, DecisionFlag.NA, data);
+    }
+
+    /**
+     * Constructor generally used for sending messages with a specific Command and DecisionFlag
+     * @param cmdCode - the command
+     * @param flags - the flags
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSDecision(final Command cmdCode, final DecisionFlag flags) {
+        this(CType.DEF, cmdCode, flags, new COPSData());
+    }
+
+    /**
+     * Constructor generally used for sending messages with a specific, CType, Command and DecisionFlag
+     * @param cType - the CType
+     * @param cmdCode - the command
+     * @param flags - the flags
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSDecision(final CType cType, final Command cmdCode, final DecisionFlag flags) {
+        this(cType, cmdCode, flags, new COPSData());
+    }
+
+    /**
+     * Constructor generally used for sending messages with a specific, CType, Command, DecisionFlag and data
+     * @param cType - the CType
+     * @param cmdCode - the command
+     * @param flags - the flags
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSDecision(final CType cType, final Command cmdCode, final DecisionFlag flags,
+                        final COPSData data) {
+        this(new COPSObjHeader(CNum.DEC, cType), cmdCode, flags, data);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param cmdCode - the command
+     * @param flags - the flags
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSDecision(final COPSObjHeader hdr, final Command cmdCode, final DecisionFlag flags,
+                           final COPSData data) {
+        super(hdr);
+        // TODO - find a better way to make this check
+        if (this.getClass().getName().equals("org.umu.cops.stack.COPSDecision") && !hdr.getCNum().equals(CNum.DEC))
+            throw new IllegalArgumentException("CNum must be equal to " + CNum.DEC);
+
+        if (hdr.getCType().equals(CType.NA)) throw new IllegalArgumentException("CType must not be " + CType.NA);
+        if (cmdCode == null) throw new IllegalArgumentException("Command code must not be null");
+        if (flags == null) throw new IllegalArgumentException("Flags must not be null");
+        if (data == null) throw new IllegalArgumentException("Data object must not be null");
+
+        _cmdCode = cmdCode;
+        _flags = flags;
+        _data = data;
+
+        if ((_data.length() % 4) != 0) {
+            final int padLen = 4 - (_data.length() % 4);
+            _padding = COPSObjectParser.getPadding(padLen);
+        } else {
+            _padding = new COPSData();
+        }
+    }
+
+    /**
+     * Returns the command
+     * @return - the command
+     */
+    public Command getCommand() { return _cmdCode; }
+
+    @Override
+    public int getDataLength() {
+        return 4 + _data.length() + _padding.length();
+    }
+
+    /**
+     * Get the associated data if decision object is of cType 2 or higher
+     * @return   a COPSData
+     */
+    public COPSData getData() {
+        return (_data);
+    }
+
+    /**
+     * If cType == 1 , get the flags associated
+     * @return   a short
+     */
+    public DecisionFlag getFlag() {
+        return _flags;
+    }
+
+    /**
+     * Method getTypeStr
+     * @return   a String
+     */
+    public String getTypeStr() {
+        switch (this.getHeader().getCType()) {
+            case DEF:
+                return "Default";
+            case STATELESS:
+                return "Stateless data";
+            case REPL:
+                return "Replacement data";
+            case CSI:
+                return "Client specific decision data";
+            case NAMED:
+                return "Named decision data";
+            default:
+                return "Unknown";
+        }
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        final byte[] buf = new byte[4];
+        buf[0] = (byte) (_cmdCode.ordinal() >> 8);
+        buf[1] = (byte) _cmdCode.ordinal();
+        buf[2] = (byte) (_flags.ordinal() >> 8);
+        buf[3] = (byte) _flags.ordinal();
+        COPSUtil.writeData(socket, buf, 4);
+
+        COPSUtil.writeData(socket, _data.getData(), _data.length());
+        if (_padding != null) {
+            COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+        }
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        if (this.getHeader().getCType().equals(CType.DEF)) {
+            os.write(("Decision (" + getTypeStr() + ")\n").getBytes());
+            os.write(("Command code: " + _cmdCode + "\n").getBytes());
+            os.write(("Command flags: " + _flags + "\n").getBytes());
+        } else {
+            os.write(("Decision (" + getTypeStr() + ")\n").getBytes());
+            os.write(("Data: " + _data.str() + "\n").getBytes());
+        }
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSDecision)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSDecision that = (COPSDecision) o;
+
+        return _cmdCode == that._cmdCode && _flags == that._flags && _data.equals(that._data) &&
+                _padding.equals(that._padding) ||
+                COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _data.hashCode();
+        result = 31 * result + _cmdCode.hashCode();
+        result = 31 * result + _flags.hashCode();
+        result = 31 * result + _padding.hashCode();
+        return result;
+    }
+
+    /**
+     * Parses bytes to return a COPSDecision object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSDecision parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        int _cmdCode = 0;
+        _cmdCode |= ((short) dataPtr[4]) << 8;
+        _cmdCode |= ((short) dataPtr[5]) & 0xFF;
+
+        int _flags = 0;
+        _flags |= ((short) dataPtr[6]) << 8;
+        _flags |= ((short) dataPtr[7]) & 0xFF;
+
+        final COPSData d;
+        if (objHdrData.header.getCType().equals(CType.DEF)) {
+            d = null;
+        } else {
+            d = new COPSData(dataPtr, 8, objHdrData.msgByteCount - 8);
+        }
+        return new COPSDecision(objHdrData.header, COPSDecision.VAL_TO_CMD.get(_cmdCode),
+                COPSDecision.VAL_TO_FLAG.get(_flags), d);
+    }
+
+    /**
+     * Supported command types
+     */
+    public enum Command {
+        NULL,    // No configuration data available
+        INSTALL, // Admit request/install configuration
+        REMOVE   // Remove request/remove configuration
+    }
+
+    public enum DecisionFlag {
+        NA,
+        REQERROR, // = Trigger error
+        REQSTATE, // = ???
+    }
+
+}
index 1b85cf71ca6bccf0a7eebdca30b68b485f51ac39..3bb81fbf997b763bbe8700ec9cf4ba0f5d860b70 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-import java.util.Vector;\r
-\r
-/**\r
- * COPS Decision Message\r
- *\r
- * @version COPSDecisionMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSDecisionMsg extends COPSMsg {\r
-\r
-    /* COPSHeader coming from base class */\r
-    private COPSHandle _clientHandle;\r
-    private COPSError _error;\r
-    private Hashtable _decisions;\r
-    private COPSIntegrity _integrity;\r
-    private COPSContext _decContext;\r
-    private COPSClientSI _decSI;\r
-\r
-    ///\r
-    public COPSDecisionMsg() {\r
-        _clientHandle = null;\r
-        _error = null;\r
-        _decisions = new Hashtable(20);\r
-        _integrity = null;\r
-        _decContext = null;\r
-        _decSI = null;\r
-    }\r
-\r
-    /** Checks the sanity of COPS message and throw an\r
-      * COPSBadDataException when data is bad.\r
-      */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_clientHandle == null) || ( (_error == null) && (_decisions.size() == 0))) {\r
-            throw new COPSException("Bad message format");\r
-        }\r
-    }\r
-\r
-    ///\r
-    protected COPSDecisionMsg(byte[] data) throws COPSException  {\r
-        _decisions = new Hashtable(20);\r
-        _clientHandle = null;\r
-        _error = null;\r
-        _integrity = null;\r
-        _decContext = null;\r
-        _decSI = null;\r
-\r
-        parse(data);\r
-    }\r
-\r
-    /**\r
-     * Parses the data and fills COPSDecisionMsg with its constituents\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        super.parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case HANDLE:\r
-                    _clientHandle = new COPSHandle(buf);\r
-                    _dataStart += _clientHandle.getDataLength();\r
-                    break;\r
-                case CONTEXT:\r
-                    //dec context\r
-                    _decContext = new COPSContext(buf);\r
-                    _dataStart += _decContext.getDataLength();\r
-                    break;\r
-                case ERROR:\r
-                    _error = new COPSError(buf);\r
-                    _dataStart += _error.getDataLength();\r
-                    break;\r
-                case DEC:\r
-                    COPSDecision decs = new COPSDecision(buf);\r
-                    _dataStart += decs.getDataLength();\r
-                    addDecision(decs, _decContext);\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default: {\r
-                    throw new COPSException("Bad Message format, unknown object type");\r
-                }\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Parses the data and fills that follows the header hdr and fills COPSDecisionMsg\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC)\r
-            throw new COPSException ("Error Header (no COPS_OP_DEC)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add client handle to the message\r
-     *\r
-     * @param    handle              a  COPSHandle\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHandle handle) throws COPSException {\r
-        if (handle == null)\r
-            throw new COPSException ("Null Handle");\r
-        _clientHandle = handle;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add an Error object\r
-     *\r
-     * @param    error               a  COPSError\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSError error) throws COPSException {\r
-        if (_decisions.size() != 0)\r
-            throw new COPSException ("No null decisions");\r
-        if (_error != null)\r
-            throw new COPSException ("No null error");\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_integrity != null)\r
-            throw new COPSException ("No null integrity");\r
-        _error = error;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add one or more local decision object for a given decision context\r
-     * the context is optional, if null all decision object are tided to\r
-     * message context\r
-     *\r
-     * @param    decision            a  COPSDecision\r
-     * @param    context             a  COPSContext\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void addDecision(COPSDecision decision, COPSContext context)  throws COPSException {\r
-        //Either error or decision can be added\r
-        //If error is aleady there assert\r
-        if (_error != null)\r
-            throw new COPSException ("No null error");\r
-\r
-        if (decision.isLocalDecision())\r
-            throw new COPSException ("Is local decision");\r
-\r
-        Vector v = (Vector) _decisions.get(context);\r
-        if (v == null) v = new Vector();\r
-\r
-        if (decision.isFlagSet()) {//Commented out as advised by Felix\r
-            //if (v.size() != 0)\r
-            //{\r
-            //Only one set of decision flags is allowed\r
-            //for each context\r
-            //     throw new COPSException ("Bad Message format, only one set of decision flags is allowed.");\r
-            //}\r
-        } else {\r
-            if (v.size() == 0) {\r
-                //The flags decision must precede any other\r
-                //decision message, since the decision is not\r
-                //flags throw exception\r
-                throw new COPSException ("Bad Message format, flags decision must precede any other decision object.");\r
-            }\r
-        }\r
-        v.add(decision);\r
-        _decisions.put(context,v);\r
-\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add integrity object\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity)  throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-    /**\r
-     * Add clientSI object\r
-     *\r
-     * @param    clientSI           a  COPSClientSI\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSClientSI clientSI)  throws COPSException {\r
-        if (clientSI == null)\r
-            throw new COPSException ("Null clientSI");\r
-        /*\r
-                  if (!integrity.isMessageIntegrity())\r
-                       throw new COPSException ("Error Integrity");\r
-        */\r
-        _decSI = clientSI;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_clientHandle != null) _clientHandle.writeData(id);\r
-        if (_error != null) _error.writeData(id);\r
-\r
-        //Display decisions\r
-        //Display any local decisions\r
-        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) _decisions.get(context);\r
-            context.writeData(id);\r
-\r
-            for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {\r
-                COPSDecision decision = (COPSDecision) ee.nextElement();\r
-                decision.writeData(id);\r
-            }\r
-        }\r
-\r
-        if (_decSI != null) _decSI.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Method getHeader\r
-     *\r
-     * @return   a COPSHeader\r
-     *\r
-     */\r
-    public COPSHeader getHeader() {\r
-        return _hdr;\r
-    }\r
-\r
-    /**\r
-     * Method getClientHandle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _clientHandle;\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has error object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasError() {\r
-        return (_error != null);\r
-    };\r
-\r
-    /**\r
-     * Should check hasError() before calling\r
-     *\r
-     * @return   a COPSError\r
-     *\r
-     */\r
-    public COPSError getError() {\r
-        return _error;\r
-    };\r
-\r
-    /**\r
-     * Returns a map of decision for which is an arry of context and vector\r
-     * of associated decision object.\r
-     *\r
-     * @return   a Hashtable\r
-     *\r
-     */\r
-    public Hashtable getDecisions() {\r
-        return _decisions;\r
-    };\r
-\r
-    /**\r
-     * Returns true if it has integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    };\r
-\r
-    /**\r
-     * Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return _integrity;\r
-    };\r
-\r
-    /**\r
-     * Method setMsgLength\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength()  throws COPSException {\r
-        short len = 0;\r
-        if (_clientHandle != null)\r
-            len += _clientHandle.getDataLength();\r
-        if (_error != null)\r
-            len += _error.getDataLength();\r
-\r
-        //Display any local decisions\r
-        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) _decisions.get(context);\r
-            len += context.getDataLength();\r
-\r
-            for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {\r
-                COPSDecision decision = (COPSDecision) ee.nextElement();\r
-                len += decision.getDataLength();\r
-            }\r
-        }\r
-        if (_decSI != null) {\r
-            len += _decSI.getDataLength();\r
-        }\r
-        if (_integrity != null) {\r
-            len += _integrity.getDataLength();\r
-        }\r
-\r
-        _hdr.setMsgLength((int) len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_clientHandle != null)\r
-            _clientHandle.dump(os);\r
-        if (_error != null)\r
-            _error.dump(os);\r
-\r
-        //Display any local decisions\r
-        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) _decisions.get(context);\r
-            context.dump(os);\r
-\r
-            for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {\r
-                COPSDecision decision = (COPSDecision) ee.nextElement();\r
-                decision.dump(os);\r
-            }\r
-        }\r
-        if (_decSI != null) {\r
-            _decSI.dump(os);\r
-        }\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.*;
+
+/**
+ * COPS Decision Message  (RFC 2748 page. 23)
+ *
+ * The PDP responds to the REQ with a DEC message that includes the
+ * associated client handle and one or more decision objects grouped
+ * relative to a Context object and Decision Flags object type pair. If
+ * there was a protocol error an error object is returned instead.
+ *
+ * It is required that the first decision message for a new/updated
+ * request will have the solicited message flag set (value = 1) in the
+ * COPS header. This avoids the issue of keeping track of which updated
+ * request (that is, a request reissued for the same handle) a
+ * particular decision corresponds. It is important that, for a given
+ * handle, there be at most one outstanding solicited decision per
+ * request. This essentially means that the PEP SHOULD NOT issue more
+ * than one REQ (for a given handle) before it receives a corresponding
+ * DEC with the solicited message flag set. The PDP MUST always issue
+ * decisions for requests on a particular handle in the order they
+ * arrive and all requests MUST have a corresponding decision.
+ *
+ * To avoid deadlock, the PEP can always timeout after issuing a request
+ * that does not receive a decision. It MUST then delete the timed-out
+ * handle, and may try again using a new handle.
+ *
+ * The format of the Decision message is as follows:
+ *
+ * <Decision Message> ::= <Common Header>
+ * <Client Handle>
+ * <Decision(s)> | <Error>
+ * [<Integrity>]
+ *
+ * <Decision(s)> ::= <Decision> | <Decision(s)> <Decision>
+ *
+ * <Decision> ::= <Context>
+ * <Decision: Flags>
+ * [<Decision: Stateless Data>]
+ * [<Decision: Replacement Data>]
+ * [<Decision: ClientSI Data>]
+ * [<Decision: Named Data>]
+ *
+ * The Decision message may include either an Error object or one or
+ * more context plus associated decision objects. COPS protocol problems
+ * are reported in the Error object (e.g. an error with the format of
+ * the original request including malformed request messages, unknown
+ * COPS objects in the Request, etc.). The applicable Decision object(s)
+ * depend on the context and the type of client. The only ordering
+ * requirement for decision objects is that the required Decision Flags
+ * object type MUST precede the other Decision object types per context
+ * binding.
+ */
+public class COPSDecisionMsg extends COPSMsg {
+
+    // Required
+    private final COPSHandle _clientHandle;
+
+    // Optional
+    private final COPSError _error;
+    private final Map<COPSContext, Set<COPSDecision>> _decisions;
+    private final COPSIntegrity _integrity;
+
+    /**
+     * Constructor for Decision messages containing a COPS Error.
+     * As this has been deprecated, the constructor containing the version and Flag should be used going forward.
+     * @param clientType - the client type (required)
+     * @param clientHandle - the handle (required)
+     * @param error - the error (required)
+     * @param integrity - the integrity (optional)
+     */
+    @Deprecated
+    public COPSDecisionMsg(final short clientType, final COPSHandle clientHandle,
+                           final COPSError error, final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.DEC, clientType), clientHandle, error, null, integrity);
+    }
+
+    /**
+     * Constructor for Decision messages containing a COPS Error.
+     * @param clientType - the client type (required)
+     * @param clientHandle - the handle (required)
+     * @param error - the error (required)
+     * @param integrity - the integrity (optional)
+     */
+    public COPSDecisionMsg(final int version, final Flag flag, final short clientType, final COPSHandle clientHandle,
+                           final COPSError error, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, error, null, integrity);
+    }
+
+    /**
+     * Constructor for Decision messages containing decisions
+     * As this has been deprecated, the constructor containing the version and Flag should be used going forward.
+     * @param clientType - the client type (required)
+     * @param clientHandle - the handle (required)
+     * @param decisions - the decisions (required)
+     * @param integrity - the integrity (optional)
+     */
+    @Deprecated
+    public COPSDecisionMsg(final short clientType, final COPSHandle clientHandle,
+                           final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.DEC, clientType), clientHandle, null, decisions, integrity);
+    }
+
+    /**
+     * Constructor for Decision messages containing decisions
+     * @param clientType - the client type (required)
+     * @param clientHandle - the handle (required)
+     * @param decisions - the decisions (required)
+     * @param integrity - the integrity (optional)
+     */
+    public COPSDecisionMsg(final int version, final Flag flag, final short clientType, final COPSHandle clientHandle,
+                           final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, null, decisions, integrity);
+    }
+
+    /**
+     * Constructor generally designed for Decision messages being parsed from a byte array.
+     * @param hdr - the header
+     * @param clientHandle - the handle
+     * @param error - the error (if null, decisions must not be null or empty)
+     * @param decisions - the decisions (must be empty or null if error is not)
+     * @param integrity - the integrity (optional)
+     */
+    protected COPSDecisionMsg(final COPSHeader hdr, final COPSHandle clientHandle,
+                           final COPSError error, final Map<COPSContext, Set<COPSDecision>> decisions,
+                           final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.DEC))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.DEC);
+        if (clientHandle == null) throw new IllegalArgumentException("Client handle must not be null");
+        if (error == null && (decisions == null || decisions.isEmpty()))
+            throw new IllegalArgumentException("Must contain either an COPSError or at least one decision");
+        if (error != null && (decisions != null && !decisions.isEmpty()))
+            throw new IllegalArgumentException("Must not contain a COPSError and decisions");
+
+        if(decisions == null) _decisions = Collections.unmodifiableMap(new HashMap<COPSContext, Set<COPSDecision>>());
+        else _decisions = Collections.unmodifiableMap(decisions);
+
+        for (Set<COPSDecision> decSet: _decisions.values()) {
+            if (decSet == null || decSet.isEmpty())
+                throw new IllegalArgumentException("Decisions are empty");
+        }
+
+        _clientHandle = clientHandle;
+        _error = error;
+        _integrity = integrity;
+
+    }
+
+    // Getters
+    public COPSHandle getClientHandle() {
+        return _clientHandle;
+    }
+    public COPSError getError() {
+        return _error;
+    }
+    public Map<COPSContext, Set<COPSDecision>> getDecisions() {
+        return _decisions;
+    }
+    public COPSIntegrity getIntegrity() {
+        return _integrity;
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = 0;
+        out += _clientHandle.getDataLength() + _clientHandle.getHeader().getHdrLength();
+        if (_error != null) out += _error.getDataLength() + _error.getHeader().getHdrLength();
+
+        for (final Map.Entry<COPSContext, Set<COPSDecision>> entry : _decisions.entrySet()) {
+            out += entry.getKey().getDataLength() + entry.getKey().getHeader().getHdrLength();
+            for (final COPSDecision decision : entry.getValue()) {
+                out += decision.getDataLength() + decision.getHeader().getHdrLength();
+            }
+        }
+
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+
+        return out;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _clientHandle.writeData(socket);
+        if (_error != null) _error.writeData(socket);
+
+        //Display decisions
+        //Display any local decisions
+        for (final Map.Entry<COPSContext, Set<COPSDecision>> entry : _decisions.entrySet()) {
+            entry.getKey().writeData(socket);
+            for (final COPSDecision decision : entry.getValue()) {
+                decision.writeData(socket);
+            }
+        }
+
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        if (_clientHandle != null)
+            _clientHandle.dump(os);
+        if (_error != null)
+            _error.dump(os);
+
+        //Display any local decisions
+        for (final Map.Entry<COPSContext, Set<COPSDecision>> entry : _decisions.entrySet()) {
+            entry.getKey().dump(os);
+            for (final COPSDecision decision : entry.getValue()) {
+                decision.dump(os);
+            }
+        }
+        if (_integrity != null) {
+            _integrity.dump(os);
+        }
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSDecisionMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSDecisionMsg that = (COPSDecisionMsg) o;
+
+        for (final Map.Entry<COPSContext, Set<COPSDecision>> entry : this._decisions.entrySet()) {
+            final Set<COPSDecision> thatDecisions = that._decisions.get(entry.getKey());
+            if (thatDecisions == null) return false;
+
+            for (final COPSDecision thisDecision : entry.getValue()) {
+                boolean found = false;
+                for (final COPSDecision thatDecision: thatDecisions) {
+                    if (thisDecision.equals(thatDecision)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (! found) return false;
+            }
+        }
+
+        return _clientHandle.equals(that._clientHandle) &&
+                !(_error != null ? !_error.equals(that._error) : that._error != null) &&
+                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _clientHandle.hashCode();
+        result = 31 * result + (_error != null ? _error.hashCode() : 0);
+        result = 31 * result + _decisions.hashCode();
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSDecisionMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSDecisionMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSHandle clientHandle = null;
+        COPSContext context = null;
+        COPSError error = null;
+        COPSIntegrity integrity = null;
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case HANDLE:
+                    clientHandle = COPSHandle.parse(objHdrData, buf);
+                    break;
+                case CONTEXT:
+                    if (context == null) {
+                        context = COPSContext.parse(objHdrData, buf);
+                    } else context = COPSContext.parse(objHdrData, buf);
+                    break;
+                case ERROR:
+                    error = COPSError.parse(objHdrData, buf);
+                    break;
+                case DEC:
+                    if (decisionMap.get(context) != null)
+                        decisionMap.get(context).add(COPSDecision.parse(objHdrData, buf));
+                    else {
+                        final Set<COPSDecision> decisions = new HashSet<>();
+                        decisions.add(COPSDecision.parse(objHdrData, buf));
+                        decisionMap.put(context, decisions);
+                    }
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSDecisionMsg(hdrData.header, clientHandle, error, decisionMap, integrity);
+    }
+
+}
\ No newline at end of file
index 2022d1dbc21a84d2a34401b5952b6262ef4434b7..bbcdb39e1de888e4d0151519af9d2ab707d33590 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Delete Message (RFC 2748 pag. 24)\r
- *\r
- *    When sent from the PEP this message indicates to the remote PDP that\r
- *    the state identified by the client handle is no longer\r
- *    available/relevant. This information will then be used by the remote\r
- *    PDP to initiate the appropriate housekeeping actions. The reason code\r
- *    object is interpreted with respect to the client-type and signifies\r
- *    the reason for the removal.\r
- *\r
- *    The format of the Delete Request State message is as follows:\r
- *\r
- *               <Delete Request>  ::= <Common Header>\r
- *                                     <Client Handle>\r
- *                                     <Reason>\r
- *                                     [<Integrity>]\r
- *\r
- *\r
- * @version COPSDeleteMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSDeleteMsg extends COPSMsg {\r
-    /* COPSHeader coming from base class */\r
-    private COPSHandle  _clientHandle;\r
-    private COPSReason _reason;\r
-    private COPSIntegrity _integrity;\r
-\r
-    public COPSDeleteMsg() {\r
-        _clientHandle = null;\r
-        _reason = null;\r
-        _integrity = null;\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSDeleteMsg object\r
-     */\r
-    protected COPSDeleteMsg(byte[] data) throws COPSException {\r
-        _clientHandle = null;\r
-        _reason = null;\r
-        _integrity = null;\r
-        parse(data);\r
-    }\r
-\r
-    /**\r
-     * Checks the sanity of COPS message and throw an\r
-     * COPSException when data is bad.\r
-     *\r
-     */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_clientHandle == null) || (_reason == null))\r
-            throw new COPSException("Bad message format");\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_DRQ)\r
-            throw new COPSException ("Error Header (no COPS_OP_DRQ)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Reason object to the message\r
-     *\r
-     * @param    reason              a  COPSReason\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSReason reason) throws COPSException {\r
-        if (_reason != null)\r
-            throw new COPSException ("No null Reason");\r
-\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_integrity != null)\r
-            throw new COPSException ("No null Integrity");\r
-        _reason = reason;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Handle object\r
-     *\r
-     * @param    handle              a  COPSHandle\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHandle handle) throws COPSException {\r
-        if (handle == null)\r
-            throw new COPSException ("Null Handle");\r
-        _clientHandle = handle;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Integrity object\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Get Client Handle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _clientHandle;\r
-    };\r
-\r
-    /**\r
-     * Get Reason\r
-     *\r
-     * @return   a COPSReason\r
-     *\r
-     */\r
-    public COPSReason getReason() {\r
-        return _reason;\r
-    };\r
-\r
-    /**\r
-     * Returns true if it has integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    };\r
-\r
-    /**\r
-     * Get Integrity. Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return (_integrity);\r
-    }\r
-\r
-    /**\r
-     * Writes data to given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_clientHandle != null) _clientHandle.writeData(id);\r
-        if (_reason != null) _reason.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Parse data\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        super.parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case HANDLE:\r
-                    _clientHandle = new COPSHandle(buf);\r
-                    _dataStart += _clientHandle.getDataLength();\r
-                    break;\r
-                case REASON_CODE:\r
-                    _reason = new COPSReason(buf);\r
-                    _dataStart += _reason.getDataLength();\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default:\r
-                    throw new COPSException("Bad Message format, unknown object type");\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Parse data\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_DRQ)\r
-            throw new COPSException("Error Header");\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength()  throws COPSException  {\r
-        short len = 0;\r
-        if (_clientHandle != null) len += _clientHandle.getDataLength();\r
-        if (_reason != null) len += _reason.getDataLength();\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_clientHandle != null)\r
-            _clientHandle.dump(os);\r
-\r
-        if (_reason != null)\r
-            _reason.dump(os);\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Delete Message (RFC 2748 pag. 24)
+ *
+ *    When sent from the PEP this message indicates to the remote PDP that
+ *    the state identified by the client handle is no longer
+ *    available/relevant. This information will then be used by the remote
+ *    PDP to initiate the appropriate housekeeping actions. The reason code
+ *    object is interpreted with respect to the client-type and signifies
+ *    the reason for the removal.
+ *
+ *    The format of the Delete Request State message is as follows:
+ *
+ *               <Delete Request>  ::= <Common Header>
+ *                                     <Client Handle>
+ *                                     <Reason>
+ *                                     [<Integrity>]
+ *
+ *
+ * @version COPSDeleteMsg.java, v 1.00 2003
+ *
+ */
+public class COPSDeleteMsg extends COPSMsg {
+    // Required
+    private final COPSHandle  _clientHandle;
+    private final COPSReason _reason;
+
+    // Optional
+    private final COPSIntegrity _integrity;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message (required)
+     * @param handle - the COPS Handle (required)
+     * @param reason - the reason (required)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSDeleteMsg(final short clientType, final COPSHandle handle, final COPSReason reason,
+                         final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.DRQ, clientType), handle, reason, integrity);
+    }
+
+    /**
+     * Constructor (generally used for sending messages).
+     * @param version - the supported PCMM Version
+     * @param flag - the flag...
+     * @param clientType - the type of client that created the message (required)
+     * @param handle - the COPS Handle (required)
+     * @param reason - the reason (required)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSDeleteMsg(final int version, final Flag flag, final short clientType, final COPSHandle handle,
+                         final COPSReason reason, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.DRQ, clientType), handle, reason, integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header
+     * @param handle - the COPS Handle (required)
+     * @param reason - the reason (required)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSDeleteMsg(final COPSHeader hdr, final COPSHandle handle, final COPSReason reason,
+                         final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.DRQ))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.DRQ);
+        if (handle == null) throw new IllegalArgumentException("COPSHandle must not be null");
+        if (reason == null) throw new IllegalArgumentException("COPSReason must not be null");
+
+        _clientHandle = handle;
+        _reason = reason;
+        _integrity = integrity;
+    }
+
+    // Getters
+    public COPSHandle getClientHandle() {
+        return _clientHandle;
+    }
+    public COPSReason getReason() {
+        return _reason;
+    }
+    public COPSIntegrity getIntegrity() {
+        return (_integrity);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = _clientHandle.getDataLength() + _clientHandle.getHeader().getHdrLength();
+        out += _reason.getDataLength() + _reason.getHeader().getHdrLength();
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _clientHandle.writeData(socket);
+        _reason.writeData(socket);
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        _clientHandle.dump(os);
+        _reason.dump(os);
+        if (_integrity != null) {
+            _integrity.dump(os);
+        }
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSDeleteMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSDeleteMsg that = (COPSDeleteMsg) o;
+
+        return _clientHandle.equals(that._clientHandle) &&
+                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null) &&
+                _reason.equals(that._reason);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _clientHandle.hashCode();
+        result = 31 * result + _reason.hashCode();
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSDecisionMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSDeleteMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSHandle clientHandle = null;
+        COPSReason reason = null;
+        COPSIntegrity integrity = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case HANDLE:
+                    clientHandle = COPSHandle.parse(objHdrData, buf);
+                    break;
+                case REASON_CODE:
+                    reason = COPSReason.parse(objHdrData, buf);
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSDeleteMsg(hdrData.header, clientHandle, reason, integrity);
+    }
+}
+
+
+
+
index 06b09c3593157a9f32b3858707b4a6d831f29cd9..38986533795e436b8ec96d11da597ff3ae6399a3 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Error\r
- *\r
- * @version COPSError.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSError extends COPSObjBase {\r
-\r
-    public final static byte COPS_ERR_BAD_HANDLE = 1;\r
-    public final static byte COPS_ERR_BAD_HANDLE_REF = 2;\r
-    public final static byte COPS_ERR_BAD_MSG_FORMAT = 3;\r
-    public final static byte COPS_ERR_FAIL_PROCESS = 4;\r
-    public final static byte COPS_ERR_MISSING_INFO = 5;\r
-    public final static byte COPS_ERR_UNSUPPORTED_CLIENT_TYPE = 6;\r
-    public final static byte COPS_ERR_MANDATORY_OBJECT_MISSING = 7;\r
-    public final static byte COPS_ERR_CLIENT_FAILURE = 8;\r
-    public final static byte COPS_ERR_COMM_FAILURE = 9;\r
-    public final static byte COPS_ERR_UNKNOWN = 10;\r
-    public final static byte COPS_ERR_SHUTTING_DOWN = 11;\r
-    public final static byte COPS_ERR_PDP_REDIRECT = 12;\r
-    public final static byte COPS_ERR_UNKNOWN_OBJECT = 13;\r
-    public final static byte COPS_ERR_AUTH_FAILURE = 14;\r
-    public final static byte COPS_ERR_AUTH_REQUIRED = 15;\r
-    public final static byte COPS_ERR_MA = 16;\r
-\r
-    private final static String G_errmsgArray[] = {\r
-        "Unknown.",\r
-        "Bad handle.",\r
-        "Invalid handle reference.",\r
-        "Bad message format (Malformed message).",\r
-        "Unable to process.",\r
-        "Mandatory client-specific info missing.",\r
-        "Unsupported client-type",\r
-        "Mandatory COPS object missing.",\r
-        "Client failure.",\r
-        "Communication failure.",\r
-        "Unknown.",\r
-        "Shutting down.",\r
-        "Redirect to preferred server.",\r
-        "Unknown COPS object",\r
-        "Authentication failure.",\r
-        "Authentication required.",\r
-    };\r
-\r
-    private COPSObjHeader _objHdr;\r
-    private short _errCode;\r
-    private short _errSubCode;\r
-\r
-    public COPSError(short errCode, short subCode) {\r
-        _objHdr = new COPSObjHeader(CNum.ERROR, CType.DEF);\r
-        _errCode = errCode;\r
-        _errSubCode = subCode;\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    protected COPSError(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-        _errCode |= ((short) dataPtr[4]) << 8;\r
-        _errCode |= ((short) dataPtr[5]) & 0xFF;\r
-        _errSubCode |= ((short) dataPtr[6]) << 8;\r
-        _errSubCode |= ((short) dataPtr[7]) & 0xFF;\r
-\r
-        // _objHdr.setDataLength(sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    public short getErrCode() {\r
-               return _errCode;\r
-       }\r
-    \r
-    public short getErrSubCode() {\r
-               return _errSubCode;\r
-       }\r
-    /**\r
-     * Returns size in number of octects\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        return (_objHdr.getDataLength());\r
-    };\r
-\r
-    /**\r
-     * Method getDescription\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String getDescription() {\r
-        String errStr1;\r
-        String errStr2;\r
-\r
-        ///Get the details from the error code\r
-        errStr1 = G_errmsgArray[_errCode];\r
-        //TODO - define error sub-codes\r
-        errStr2 = "";\r
-        return (errStr1 + ":" + errStr2);\r
-    }\r
-\r
-    /**\r
-     * Method isError\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isError() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Writes object to given network socket in network byte order\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-\r
-        buf[0] = (byte) (_errCode >> 8);\r
-        buf[1] = (byte) _errCode;\r
-        buf[2] = (byte) (_errSubCode >> 8);\r
-        buf[3] = (byte) _errSubCode;\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Error Code: " + _errCode + "\n").getBytes());\r
-        os.write(new String("Error Sub Code: " + _errSubCode + "\n").getBytes());\r
-    }\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Error (RFC 2748)
+ *
+ * This object is used to identify a particular COPS protocol error.
+ * The error sub-code field contains additional detailed client specific
+ * error codes. The appropriate Error Sub-codes for a particular
+ * client-type SHOULD be specified in the relevant COPS extensions
+ * document.
+ *
+ * C-Num = 8, C-Type = 1
+ *
+ * Error-Code:
+ *
+ * 1 = Bad handle
+ * 2 = Invalid handle reference
+ * 3 = Bad message format (Malformed Message)
+ * 4 = Unable to process (server gives up on query)
+ * 5 = Mandatory client-specific info missing
+ * 6 = Unsupported client-type
+ * 7 = Mandatory COPS object missing
+ * 8 = Client Failure
+ * 9 = Communication Failure
+ * 10= Unspecified
+ * 11= Shutting down
+ * 12= Redirect to Preferred Server
+ * 13= Unknown COPS Object:
+ * Sub-code (octet 2) contains unknown object's C-Num
+ * and (octet 3) contains unknown object's C-Type.
+ * 14= Authentication Failure
+ * 15= Authentication Required
+ */
+public class COPSError extends COPSObjBase {
+
+    public final static Map<Integer, ErrorTypes> ERROR_CODE_TO_TYPE = new ConcurrentHashMap<>();
+    static {
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.NA.ordinal(), ErrorTypes.NA);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.BAD_HANDLE.ordinal(), ErrorTypes.BAD_HANDLE);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.BAD_HANDLE_REF.ordinal(), ErrorTypes.BAD_HANDLE_REF);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.BAD_MSG_FORMAT.ordinal(), ErrorTypes.BAD_MSG_FORMAT);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.FAIL_PROCESS.ordinal(), ErrorTypes.FAIL_PROCESS);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.MISSING_INFO.ordinal(), ErrorTypes.MISSING_INFO);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.UNSUPPORTED_CLIENT_TYPE.ordinal(), ErrorTypes.UNSUPPORTED_CLIENT_TYPE);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.MANDATORY_OBJECT_MISSING.ordinal(), ErrorTypes.MANDATORY_OBJECT_MISSING);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.CLIENT_FAILURE.ordinal(), ErrorTypes.CLIENT_FAILURE);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.COMM_FAILURE.ordinal(), ErrorTypes.COMM_FAILURE);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.UNKNOWN.ordinal(), ErrorTypes.UNKNOWN);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.SHUTTING_DOWN.ordinal(), ErrorTypes.SHUTTING_DOWN);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.PDP_REDIRECT.ordinal(), ErrorTypes.PDP_REDIRECT);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.UNKNOWN_OBJECT.ordinal(), ErrorTypes.UNKNOWN_OBJECT);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.AUTH_FAILURE.ordinal(), ErrorTypes.AUTH_FAILURE);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.AUTH_REQUIRED.ordinal(), ErrorTypes.AUTH_REQUIRED);
+        ERROR_CODE_TO_TYPE.put(ErrorTypes.MA.ordinal(), ErrorTypes.MA);
+    }
+
+    private final static Map<ErrorTypes, String> ERROR_TYPE_TO_STRING = new ConcurrentHashMap<>();
+    static {
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.NA, "Unknown.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.BAD_HANDLE, "Bad handle.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.BAD_HANDLE_REF, "Invalid handle reference.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.BAD_MSG_FORMAT, "Bad message format (Malformed message).");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.FAIL_PROCESS, "Unable to process.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.MISSING_INFO, "Mandatory client-specific info missing.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, "Unsupported client-type");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.MANDATORY_OBJECT_MISSING, "Mandatory COPS object missing.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.CLIENT_FAILURE, "Client failure.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.COMM_FAILURE, "Communication failure.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.UNKNOWN, "Unknown.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.SHUTTING_DOWN, "Shutting down.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.PDP_REDIRECT, "Redirect to preferred server.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.UNKNOWN_OBJECT, "Unknown COPS object");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.AUTH_FAILURE, "Authentication failure.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.AUTH_REQUIRED, "Authentication required.");
+        ERROR_TYPE_TO_STRING.put(ErrorTypes.MA, "Authentication required.");
+    }
+
+    /**
+     * The error code
+     */
+    private ErrorTypes _errCode;
+
+    /**
+     * Additional detailed client specific error codes
+     */
+    private ErrorTypes _errSubCode;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param errCode - the error code
+     * @param subCode - the type of message
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSError(final ErrorTypes errCode, final ErrorTypes subCode) {
+        this(new COPSObjHeader(CNum.ERROR, CType.DEF), errCode, subCode);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param errCode - the error code
+     * @param subCode - the type of message
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSError(final COPSObjHeader hdr, final ErrorTypes errCode, final ErrorTypes subCode) {
+        super(hdr);
+        if (!hdr.getCNum().equals(CNum.ERROR))
+            throw new IllegalArgumentException("Must have a CNum value of " + CNum.ERROR);
+        if (!hdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.DEF);
+        if (errCode == null || subCode == null) throw new IllegalArgumentException("Error codes must not be null");
+        if (errCode.equals(ErrorTypes.NA))
+            throw new IllegalArgumentException("Error code must not be of type " + ErrorTypes.NA);
+
+        _errCode = errCode;
+        _errSubCode = subCode;
+    }
+
+    public ErrorTypes getErrCode() {
+        return _errCode;
+    }
+
+    public ErrorTypes getErrSubCode() {
+        return _errSubCode;
+    }
+
+    @Override
+    public int getDataLength() {
+        return 4;
+    }
+
+    /**
+     * Method getDescription
+     * @return   a String
+     */
+    public String getDescription() {
+        String errStr1;
+        String errStr2;
+
+        ///Get the details from the error code
+        errStr1 = ERROR_TYPE_TO_STRING.get(_errCode);
+        //TODO - define error sub-codes
+        errStr2 = "";
+        return (errStr1 + ":" + errStr2);
+    }
+
+    @Override
+    public void writeBody(final Socket socket) throws IOException {
+        final byte[] buf = new byte[4];
+
+        buf[0] = (byte) ((byte)_errCode.ordinal() >> 8);
+        buf[1] = (byte)_errCode.ordinal();
+        buf[2] = (byte) ((byte)_errSubCode.ordinal() >> 8);
+        buf[3] = (byte)_errSubCode.ordinal();
+
+        COPSUtil.writeData(socket, buf, 4);
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("Error Code: " + _errCode + "\n").getBytes());
+        os.write(("Error Sub Code: " + _errSubCode + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSError)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSError copsError = (COPSError) o;
+
+        return _errCode == copsError._errCode && _errSubCode == copsError._errSubCode;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (_errCode != null ? _errCode.hashCode() : 0);
+        result = 31 * result + (_errSubCode != null ? _errSubCode.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSError parse(final COPSObjHeaderData objHdrData, byte[] dataPtr) {
+        int errCode = 0;
+        errCode |= ((short) dataPtr[4]) << 8;
+        errCode |= ((short) dataPtr[5]) & 0xFF;
+
+        int errSubCode = 0;
+        errSubCode |= ((short) dataPtr[6]) << 8;
+        errSubCode |= ((short) dataPtr[7]) & 0xFF;
+
+        return new COPSError(objHdrData.header, ERROR_CODE_TO_TYPE.get(errCode), ERROR_CODE_TO_TYPE.get(errSubCode));
+    }
+
+    /**
+     * The different error types and the ordinal value will be serialized
+     */
+    public enum ErrorTypes {
+        NA,
+        BAD_HANDLE,
+        BAD_HANDLE_REF,
+        BAD_MSG_FORMAT,
+        FAIL_PROCESS,
+        MISSING_INFO,
+        UNSUPPORTED_CLIENT_TYPE,
+        MANDATORY_OBJECT_MISSING,
+        CLIENT_FAILURE,
+        COMM_FAILURE,
+        UNKNOWN,
+        SHUTTING_DOWN,
+        PDP_REDIRECT,
+        UNKNOWN_OBJECT,
+        AUTH_FAILURE,
+        AUTH_REQUIRED,
+        MA
+    }
+
+}
+
index 127ce617a9a81c5d62ce0f7f2109754559f4bfa5..0dea15afd2084e8944ac48b1fdb2a10c4bcbc0f2 100644 (file)
@@ -27,6 +27,10 @@ public class COPSException extends Exception {
         rc = retCode;\r
     }\r
 \r
+    public COPSException(String msg, Throwable t) {\r
+        super(msg, t);\r
+    }\r
+\r
     /**\r
      * Method returnCode\r
      *\r
index b4bc14f099f93a881a219eb256e0400f3a043b27..676360eefe872054f9e71d718b3103cb73b550df 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Handle Object (RFC 2748 pag. 9)\r
- *\r
- *   The Handle Object encapsulates a unique value that identifies an\r
- *   installed state. This identification is used by most COPS operations.\r
- *\r
- *           C-Num = 1\r
- *\r
- *           C-Type = 1, Client Handle.\r
- *\r
- *   Variable-length field, no implied format other than it is unique from\r
- *   other client handles from the same PEP (a.k.a. COPS TCP connection)\r
- *   for a particular client-type. It is always initially chosen by the\r
- *   PEP and then deleted by the PEP when no longer applicable. The client\r
- *   handle is used to refer to a request state initiated by a particular\r
- *   PEP and installed at the PDP for a client-type. A PEP will specify a\r
- *   client handle in its Request messages, Report messages and Delete\r
- *   messages sent to the PDP. In all cases, <b>the client handle is used to\r
- *   uniquely identify a particular PEP's request for a client-type</b>.\r
- *\r
- *   The client handle value is set by the PEP and is opaque to the PDP.\r
- *   The PDP simply performs a byte-wise comparison on the value in this\r
- *   object with respect to the handle object values of other currently\r
- *   installed requests.\r
- *\r
- * @version COPSHandle.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSHandle extends COPSObjBase {\r
-\r
-    private final COPSObjHeader _objHdr;\r
-    private final COPSData _id;\r
-    private final COPSData _padding;\r
-\r
-    /**\r
-     * Constructor\r
-     * @param id - the identifier (must not be null)\r
-     * @throws java.lang.IllegalArgumentException when the id parameter is null\r
-     */\r
-    public COPSHandle(final COPSData id) {\r
-        if (id == null) throw new IllegalArgumentException("COPSData must not be null");\r
-        _objHdr = new COPSObjHeader(CNum.HANDLE, CType.DEF);\r
-        _id = id;\r
-        if ((_id.length() % 4) != 0) {\r
-            final int padLen = 4 - (_id.length() % 4);\r
-            _padding = getPadding(padLen);\r
-        } else {\r
-            _padding = new COPSData();\r
-        }\r
-        _objHdr.setDataLength((short) _id.length());\r
-    }\r
-\r
-    /**\r
-     * Constructor\r
-     * @param dataPtr - the data to parse for setting this object's attributes\r
-     */\r
-    protected COPSHandle(final byte[] dataPtr) {\r
-        if (dataPtr == null || dataPtr.length < 5)\r
-            throw new IllegalArgumentException("Data cannot be null or fewer than 5 bytes");\r
-\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        //Get the length of data following the obj header\r
-        final int dLen = _objHdr.getDataLength() - 4;\r
-        _id = new COPSData(dataPtr, 4, dLen);\r
-        if ((_id.length() % 4) != 0) {\r
-            final int padLen = 4 - (_id.length() % 4);\r
-            _padding = getPadding(padLen);\r
-        } else {\r
-            _padding = new COPSData();\r
-        }\r
-        _objHdr.setDataLength((short) _id.length());\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     * @return   a short\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        final int lpadding;\r
-        if (_padding != null) lpadding = _padding.length();\r
-        else lpadding = 0;\r
-        return ((short) (_objHdr.getDataLength() + lpadding));\r
-    }\r
-\r
-    /**\r
-     * Get handle value\r
-     * @return   a COPSData\r
-     */\r
-    public COPSData getId() {\r
-        return _id;\r
-    }\r
-\r
-    @Override\r
-    public boolean isClientHandle() {\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public void writeData(final Socket socket) throws IOException {\r
-        _objHdr.writeData(socket);\r
-\r
-        COPSUtil.writeData(socket, _id.getData(), _id.length());\r
-        if (_padding != null) {\r
-            COPSUtil.writeData(socket, _padding.getData(), _padding.length());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     * @param    os                  an OutputStream\r
-     * @throws   IOException\r
-     */\r
-    public void dump(final OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(("client-handle: " + _id.str() + "\n").getBytes());\r
-    }\r
-\r
-    @Override\r
-    public boolean equals(Object o) {\r
-        if (this == o) {\r
-            return true;\r
-        }\r
-        if (!(o instanceof COPSHandle)) {\r
-            return false;\r
-        }\r
-        final COPSHandle that = (COPSHandle) o;\r
-        return _id.equals(that._id) && _objHdr.equals(that._objHdr);\r
-    }\r
-\r
-    @Override\r
-    public int hashCode() {\r
-        int result = _objHdr.hashCode();\r
-        result = 31 * result + _id.hashCode();\r
-        return result;\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Handle Object (RFC 2748 pag. 9)
+ *
+ *   The Handle Object encapsulates a unique value that identifies an
+ *   installed state. This identification is used by most COPS operations.
+ *
+ *           C-Num = 1
+ *
+ *           C-Type = 1, Client Handle.
+ *
+ *   Variable-length field, no implied format other than it is unique from
+ *   other client handles from the same PEP (a.k.a. COPS TCP connection)
+ *   for a particular client-type. It is always initially chosen by the
+ *   PEP and then deleted by the PEP when no longer applicable. The client
+ *   handle is used to refer to a request state initiated by a particular
+ *   PEP and installed at the PDP for a client-type. A PEP will specify a
+ *   client handle in its Request messages, Report messages and Delete
+ *   messages sent to the PDP. In all cases, <b>the client handle is used to
+ *   uniquely identify a particular PEP's request for a client-type</b>.
+ *
+ *   The client handle value is set by the PEP and is opaque to the PDP.
+ *   The PDP simply performs a byte-wise comparison on the value in this
+ *   object with respect to the handle object values of other currently
+ *   installed requests.
+ *
+ */
+public class COPSHandle extends COPSObjBase {
+
+    /**
+     * The payload data
+     */
+    private final COPSData _data;
+
+    /**
+     * Bytes to add to outbound payload to ensure the length is divisible by 4 bytes
+     */
+    private final COPSData _padding;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param id - the identifier (must not be null)
+     * @throws java.lang.IllegalArgumentException when the id parameter is null
+     */
+    public COPSHandle(final COPSData id) {
+        this(new COPSObjHeader(CNum.HANDLE, CType.DEF), id);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param data - the ID
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSHandle(final COPSObjHeader objHdr, final COPSData data) {
+        super(objHdr);
+        if (!objHdr.getCNum().equals(CNum.HANDLE))
+            throw new IllegalArgumentException("CNum on header must be of type HANDLE");
+        if (!objHdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Invalid CType value. Must be " + CType.DEF);
+        if (data == null) throw new IllegalArgumentException("COPSData must not be null");
+
+        _data = data;
+
+        if ((_data.length() % 4) != 0) {
+            final int padLen = 4 - (_data.length() % 4);
+            _padding = COPSObjectParser.getPadding(padLen);
+        } else {
+            _padding = new COPSData();
+        }
+    }
+
+    @Override
+    public int getDataLength() {
+        return _data.length() + _padding.length();
+    }
+
+    /**
+     * Get handle value
+     * @return   a COPSData
+     */
+    public COPSData getId() {
+        return _data;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        COPSUtil.writeData(socket, _data.getData(), _data.length());
+        COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("client-handle: " + _data.str() + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSHandle)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSHandle that = (COPSHandle) o;
+
+        return _data.equals(that._data) && _padding.equals(that._padding) ||
+                COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _data.hashCode();
+        result = 31 * result + _padding.hashCode();
+        return result;
+    }
+
+    /**
+     * Parses bytes to return a COPSHandle object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSHandle parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        if (dataPtr == null || dataPtr.length < 5)
+            throw new IllegalArgumentException("Data cannot be null or fewer than 5 bytes");
+
+        //Get the length of data following the obj header
+        final COPSData id = new COPSData(dataPtr, 4, objHdrData.msgByteCount - objHdrData.header.getHdrLength());
+        return new COPSHandle(objHdrData.header, id);
+    }
+
+}
+
index 90a0a630b2b0844360d737f59990abf0085d569b..65542603836b4c0529dbc14a9dbfc9f15babed60 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Header (RFC 2748 pag. 6)\r
- *\r
- *   Each COPS message consists of the COPS header followed by a number of\r
- *   typed objects.\r
- *\r
- *             0              1              2              3\r
- *     +--------------+--------------+--------------+--------------+\r
- *     |Version| Flags|    Op Code   |       Client-type           |\r
- *     +--------------+--------------+--------------+--------------+\r
- *     |                      Message Length                       |\r
- *     +--------------+--------------+--------------+--------------+\r
- *\r
- *     Global note: //// implies field is reserved, set to 0.\r
- *\r
- *       The fields in the header are:\r
- *         Version: 4 bits\r
- *             COPS version number. Current version is 1.\r
- *\r
- *         Flags: 4 bits\r
- *             Defined flag values (all other flags MUST be set to 0):\r
- *               0x1 Solicited Message Flag Bit\r
- *                This flag is set when the message is solicited by\r
- *                another COPS message. This flag is NOT to be set\r
- *                (value=0) unless otherwise specified.\r
- *\r
- *         Op Code: 8 bits\r
- *            The COPS operations:\r
- *              1 = Request                 (REQ)\r
- *              2 = Decision                (DEC)\r
- *              3 = Report State            (RPT)\r
- *              4 = Delete Request State    (DRQ)\r
- *              5 = Synchronize State Req   (SSQ)\r
- *              6 = Client-Open             (OPN)\r
- *              7 = Client-Accept           (CAT)\r
- *              8 = Client-Close            (CC)\r
- *              9 = Keep-Alive              (KA)\r
- *              10= Synchronize Complete    (SSC)\r
- *\r
- *       Client-type: 16 bits\r
- *\r
- *\r
- * @version COPSHeader.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSHeader {\r
-\r
-    public final static byte COPS_OP_REQ = 1;\r
-    public final static byte COPS_OP_DEC = 2;\r
-    public final static byte COPS_OP_RPT = 3;\r
-    public final static byte COPS_OP_DRQ = 4;\r
-    public final static byte COPS_OP_SSQ = 5;\r
-    public final static byte COPS_OP_OPN = 6;\r
-    public final static byte COPS_OP_CAT = 7;\r
-    public final static byte COPS_OP_CC = 8;\r
-    public final static byte COPS_OP_KA = 9;\r
-    public final static byte COPS_OP_SSC = 10;\r
-\r
-    public final static byte COPS_FLAG_NULL = 0;\r
-    public final static byte COPS_FLAG_SOLICITED = 1;\r
-\r
-    private byte _versionNflg;\r
-    private byte _opCode;\r
-    private short _cType;\r
-    private int _msgLength;\r
-\r
-    public COPSHeader() {\r
-        _versionNflg = 0x10;\r
-        _opCode = 0;\r
-        _cType = 0;\r
-        _msgLength = 0;\r
-    }\r
-\r
-    public COPSHeader(byte opCode, short clientType) {\r
-        _versionNflg = 0x10;\r
-        _opCode = opCode;\r
-        _cType = clientType;\r
-        _msgLength = 0;\r
-        if (isAKeepAlive()) _cType = 0;\r
-    }\r
-\r
-    public COPSHeader(byte opCode) {\r
-        _versionNflg = 0x10;\r
-        _opCode = opCode;\r
-        _cType = 0;\r
-        _msgLength = 0;\r
-        if (isAKeepAlive()) _cType = 0;\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSHeader object\r
-     */\r
-    public COPSHeader(byte[] buf) {\r
-        _versionNflg = (byte) buf[0];\r
-        _opCode = (byte) buf[1];\r
-        _cType |= ((short) buf[2]) << 8;\r
-        _cType |= ((short) buf[3]) & 0xFF;\r
-        _msgLength |= ((short) buf[4]) << 24;\r
-        _msgLength |= ((short) buf[5]) << 16;\r
-        _msgLength |= ((short) buf[6]) << 8;\r
-        _msgLength |= ((short) buf[7]) & 0xFF;\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message Request, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isARequest() {\r
-        return (_opCode == COPS_OP_REQ);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message Decision, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isADecision() {\r
-        return (_opCode == COPS_OP_DEC);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message Report, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAReport() {\r
-        return (_opCode == COPS_OP_RPT);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message DeleteRequest, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isADeleteReq() {\r
-        return (_opCode == COPS_OP_DRQ);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message SyncStateReq, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isASyncStateReq() {\r
-        return (_opCode == COPS_OP_SSQ);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message ClientOpen, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAClientOpen() {\r
-        return (_opCode == COPS_OP_OPN);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message ClientAccept, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAClientAccept() {\r
-        return (_opCode == COPS_OP_CAT);\r
-    }\r
-\r
-    /**\r
-     * If operation code corresponds with a message ClientClose, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAClientClose() {\r
-        return (_opCode == COPS_OP_CC);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message KeepAlive, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAKeepAlive() {\r
-        return (_opCode == COPS_OP_KA);\r
-    }\r
-\r
-    /**\r
-     * If the operation code corresponds with a message SSC, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isASyncComplete() {\r
-        return (_opCode == COPS_OP_SSC);\r
-    }\r
-\r
-    /**\r
-     * Get message length\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getMsgLength() {\r
-        return _msgLength;\r
-    }\r
-\r
-    /**\r
-     * Get header length\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getHdrLength() {\r
-        // return (sizeof(u_int32_t) * 2);\r
-        return ( 8 );\r
-    }\r
-\r
-    /**\r
-     * Get Operation Code\r
-     *\r
-     * @return   a byte\r
-     *\r
-     */\r
-    public byte getOpCode() {\r
-        return _opCode;\r
-    }\r
-\r
-    /**\r
-     * Set the solicitation flag\r
-     *\r
-     * @param    flg                 a  byte\r
-     *\r
-     */\r
-    public void setFlag(byte flg) {\r
-        _versionNflg &= 0x10;\r
-        _versionNflg |= flg;\r
-    }\r
-\r
-    /**\r
-     * Returns the flags field\r
-     * @return aByte     Flags field in header\r
-     */\r
-    public byte getFlags() { //OJO\r
-        return (byte) (_versionNflg & 0x0f);\r
-    }\r
-\r
-    /**\r
-     * Set the client-type\r
-     *\r
-     * @param    cType               a  short\r
-     *\r
-     */\r
-    public void setClientType(short cType) {\r
-        _cType = cType;\r
-    };\r
-\r
-    /**\r
-     * Set the message length\r
-     *\r
-     * @param    len                 an int\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void setMsgLength(int len) throws COPSException {\r
-        if ((len % 4) != 0)\r
-            throw new COPSException ("Message is not aligned on 32 bit intervals");\r
-        _msgLength = len + 8;\r
-    }\r
-\r
-    /**\r
-     * Get client-type\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getClientType() {\r
-        return (_cType);\r
-    };\r
-\r
-    /**\r
-     * Always return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isCOPSHeader() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Writes object to given network socket in network byte order\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        byte buf[] = new byte[8];\r
-\r
-        buf[0] = (byte) _versionNflg;\r
-        buf[1] = (byte) _opCode;\r
-        buf[2] = (byte) (_cType >> 8);\r
-        buf[3] = (byte) _cType;\r
-        buf[4] = (byte) (_msgLength >> 24);\r
-        buf[5] = (byte) (_msgLength >> 16);\r
-        buf[6] = (byte) (_msgLength >> 8);\r
-        buf[7] = (byte) _msgLength;\r
-\r
-        COPSUtil.writeData(id, buf, 8);\r
-    }\r
-\r
-    /**\r
-     * Get an object textual description\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String toString() {\r
-        String str = new String();\r
-\r
-        str += "**MSG HEADER** \n";\r
-        str += "Version: " + (_versionNflg >> 4) + "\n";\r
-        str += "Flags: " + (_versionNflg & 0x01) + "\n";\r
-        str += "OpCode: " + _opCode + "\n";\r
-        str += "Client-type: " + _cType + "\n";\r
-        str += "Message-length(bytes): " + _msgLength + "\n";\r
-        return str;\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        os.write(new String("**MSG HEADER**" + "\n").getBytes());\r
-        os.write(new String("Version: " + (_versionNflg >> 4) + "\n").getBytes());\r
-        os.write(new String("Flags: " + (_versionNflg & 0x01) + "\n").getBytes());\r
-        os.write(new String("OpCode: " + _opCode + "\n").getBytes());\r
-        os.write(new String("Client-type: " + _cType + "\n").getBytes());\r
-        os.write(new String("Message-length(bytes): " + _msgLength + "\n").getBytes());\r
-    }\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Header (RFC 2748 pag. 6)
+ *
+ *   Each COPS message consists of the COPS header followed by a number of
+ *   typed objects.
+ *
+ *             0              1              2              3
+ *     +--------------+--------------+--------------+--------------+
+ *     |Version| Flags|    Op Code   |       Client-type           |
+ *     +--------------+--------------+--------------+--------------+
+ *     |                      Message Length                       |
+ *     +--------------+--------------+--------------+--------------+
+ *
+ *     Global note: //// implies field is reserved, set to 0.
+ *
+ *       The fields in the header are:
+ *         Version: 4 bits
+ *             COPS version number. Current version is 1.
+ *
+ *         Flags: 4 bits
+ *             Defined flag values (all other flags MUST be set to 0):
+ *               0x1 Solicited Message Flag Bit
+ *                This flag is set when the message is solicited by
+ *                another COPS message. This flag is NOT to be set
+ *                (value=0) unless otherwise specified.
+ *
+ *         Op Code: 8 bits
+ *            The COPS operations:
+ *              1 = Request                 (REQ)
+ *              2 = Decision                (DEC)
+ *              3 = Report State            (RPT)
+ *              4 = Delete Request State    (DRQ)
+ *              5 = Synchronize State Req   (SSQ)
+ *              6 = Client-Open             (OPN)
+ *              7 = Client-Accept           (CAT)
+ *              8 = Client-Close            (CC)
+ *              9 = Keep-Alive              (KA)
+ *              10= Synchronize Complete    (SSC)
+ *
+ *       Client-type: 16 bits
+ *
+ *
+ * @version COPSHeader.java, v 1.00 2003
+ *
+ */
+public class COPSHeader {
+
+    /**
+     * Map allowing for the quick retrieval of the operation based on the numeric value coming in via the
+     * COPS payload.
+     */
+    final static Map<Integer, OPCode> VAL_TO_OP = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_OP.put(OPCode.NA.ordinal(), OPCode.NA);
+        VAL_TO_OP.put(OPCode.REQ.ordinal(), OPCode.REQ);
+        VAL_TO_OP.put(OPCode.DEC.ordinal(), OPCode.DEC);
+        VAL_TO_OP.put(OPCode.RPT.ordinal(), OPCode.RPT);
+        VAL_TO_OP.put(OPCode.DRQ.ordinal(), OPCode.DRQ);
+        VAL_TO_OP.put(OPCode.SSQ.ordinal(), OPCode.SSQ);
+        VAL_TO_OP.put(OPCode.OPN.ordinal(), OPCode.OPN);
+        VAL_TO_OP.put(OPCode.CAT.ordinal(), OPCode.CAT);
+        VAL_TO_OP.put(OPCode.CC.ordinal(), OPCode.CC);
+        VAL_TO_OP.put(OPCode.KA.ordinal(), OPCode.KA);
+        VAL_TO_OP.put(OPCode.SSC.ordinal(), OPCode.SSC);
+    }
+
+    /**
+     * Represents the PCMM version number of the message
+     * Holds the first nibble of the COPS message
+     */
+    private final int _pcmmVersion;
+
+    /**
+     * Represents the second nibble of the message where solicited decisions will be set to 1 else 0
+     * Values 0 = UNSOLICITED | 1 = SOLICITED
+     */
+    private final Flag _flag;
+
+    /**
+     * Represents the type of operation which will be used to determine the type of COPSMsg this header will be a
+     * part of.
+     * Uses the byte value contained in the second byte of the message and inbound messages should use the constant
+     * Map VAL_TO_CT during construction
+     */
+    private final OPCode _opCode;
+
+    /**
+     * Represents client type which there are currently 3 types supported.
+     * Uses the 3rd byte of the message and inbound messages should use the constant Map VAL_TO_OP during construction
+     */
+    private final short _cType;
+
+    /**
+     * Easy constructor that implies version 1 and UNSOLICITED flag.
+     *
+     * User should leverage the main constructor below and set the version and flags.
+     *
+     * @param opCode - the Operation code denoting the type of message
+     * @param clientType - the client type generally denotes if it is an Ipv4 (TYPE_1) else Ipv6
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSHeader(final OPCode opCode, final short clientType) {
+        this(1, Flag.UNSOLICITED, opCode, clientType);
+    }
+
+    /**
+     * Should be the main constructor.
+     * @param version - PCMM Version
+     * @param flag - the header flag
+     * @param opCode - the COPS operation code
+     * @param clientType - the type of client interfacing
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSHeader(final int version, final Flag flag, final OPCode opCode, final short clientType) {
+        if(version < 1) throw new IllegalArgumentException("Invalid version number - " + version);
+        if(flag == null) throw new IllegalArgumentException("Flag is null");
+        if(opCode == null) throw new IllegalArgumentException("OPCode is null");
+        _pcmmVersion = version;
+        _flag = flag;
+        _opCode = opCode;
+        _cType = clientType;
+
+        // TODO - Determine why this??? - remove until this makes some sense
+//        if (opCode.equals(OPCode.KA)) _cType = ClientType.NA;
+//        else _cType = clientType;
+    }
+
+    // Getters
+    public int getPcmmVersion() { return _pcmmVersion; }
+    public Flag getFlag() { return _flag; }
+
+    /**
+     * Get header length
+     * @return   an int
+     */
+    public int getHdrLength() {
+        return 8;
+    }
+
+    /**
+     * Get Operation Code
+     * @return   a byte
+     */
+    public OPCode getOpCode() {
+        return _opCode;
+    }
+
+    /**
+     * Get client-type
+     * @return   a short
+     */
+    public short getClientType() {
+        return _cType;
+    }
+
+    /**
+     * Writes object to given network socket in network byte order
+     * @param    socket                  a  Socket
+     * @throws   IOException
+     */
+    public void writeData(final Socket socket, final int msgLength) throws IOException {
+        byte buf[] = new byte[8];
+        buf[0] = (byte) COPSMsgParser.combineNibbles((byte)_pcmmVersion, (byte) _flag.ordinal());
+        buf[1] = (byte) _opCode.ordinal();
+
+        final byte[] cTypeBytes = COPSMsgParser.shortToBytes(_cType);
+        buf[2] = cTypeBytes[0];
+        buf[3] = cTypeBytes[1];
+        buf[4] = (byte) (msgLength >> 24);
+        buf[5] = (byte) (msgLength >> 16);
+        buf[6] = (byte) (msgLength >> 8);
+        buf[7] = (byte) msgLength;
+        COPSUtil.writeData(socket, buf, 8);
+    }
+
+    @Override
+    public String toString() {
+        return "**MSG HEADER** \n"
+                + "Version: " + _pcmmVersion + "\n"
+                + "Flags: " + _flag + "\n"
+                + "OpCode: " + _opCode + "\n"
+                + "Client-type: " + _cType + "\n";
+    }
+
+    /**
+     * Write an object textual description in the output stream
+     * @param    os                  an OutputStream
+     * @throws   IOException
+     */
+    public void dump(OutputStream os) throws IOException {
+        os.write(("**MSG HEADER**" + "\n").getBytes());
+        os.write(("Version: " + _pcmmVersion + "\n").getBytes());
+        os.write(("Flags: " + _flag + "\n").getBytes());
+        os.write(("OpCode: " + _opCode + "\n").getBytes());
+        os.write(("Client-type: " + _cType + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSHeader)) {
+            return false;
+        }
+
+        final COPSHeader header = (COPSHeader) o;
+
+        return _pcmmVersion == header._pcmmVersion && _cType == header._cType && _flag == header._flag &&
+                _opCode == header._opCode;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = _pcmmVersion;
+        result = 31 * result + _flag.hashCode();
+        result = 31 * result + _opCode.hashCode();
+        result = 31 * result + _cType;
+        return result;
+    }
+
+    /**
+     * Represents the COPS Operation code and byte value corresponds to the item's ordinal value
+     *            The COPS operations:
+     *              0 = N/A - placeholder for the invalid value of 0
+     *              1 = Request                 (REQ)
+     *              2 = Decision                (DEC)
+     *              3 = Report State            (RPT)
+     *              4 = Delete Request State    (DRQ)
+     *              5 = Synchronize State Req   (SSQ)
+     *              6 = Client-Open             (OPN)
+     *              7 = Client-Accept           (CAT)
+     *              8 = Client-Close            (CC)
+     *              9 = Keep-Alive              (KA)
+     *              10= Synchronize Complete    (SSC)
+     */
+    public enum OPCode {
+        NA, REQ, DEC, RPT, DRQ, SSQ, OPN, CAT, CC, KA, SSC
+    }
+
+    /**
+     * Represents the COPS flags value where the inbound nibble value maps to the ordinal values.
+     */
+    public enum Flag {
+        UNSOLICITED, SOLICITED
+    }
+
+}
+
+
+
+
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeaderData.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeaderData.java
new file mode 100644 (file)
index 0000000..7dac959
--- /dev/null
@@ -0,0 +1,30 @@
+package org.umu.cops.stack;
+
+/**
+ * Class designed for simply containing the COPSHeader and the total message's byte count.
+ *
+ * No need to test as this class will be tested implicitly via other tests and this does not contain or need
+ * any domain specific logic
+ */
+class COPSHeaderData {
+
+    /**
+     * The actual header to be injected into the appropriate COPSMsg object
+     */
+    final COPSHeader header;
+
+    /**
+     * The total number of bytes contained within the inbound message being parsed.
+     */
+    final int msgByteCount;
+
+    /**
+     * Constructor
+     * @param hdr - the COPS message header
+     * @param numBytes - the total number of bytes contained within the message envelope
+     */
+    public COPSHeaderData(final COPSHeader hdr, final int numBytes) {
+        this.header = hdr;
+        this.msgByteCount = numBytes;
+    }
+}
index b5e6d4128d96f1cd1641ca2d32dc3a17c38c93dc..53fc2ad5b54a5bd3d910b4f045196c6ce77ae014 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Integrity Object\r
- *\r
- * @version COPSIntegrity.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIntegrity extends COPSObjBase {\r
-    private COPSObjHeader _objHdr;\r
-    private int _keyId;\r
-    private int _seqNum;\r
-    private COPSData _keyDigest;\r
-    private COPSData _padding;\r
-\r
-    public COPSIntegrity() {\r
-        _objHdr = new COPSObjHeader(CNum.MSG_INTEGRITY, CType.DEF);\r
-        _keyId = 0;\r
-        _seqNum = 0;\r
-    }\r
-\r
-    public COPSIntegrity(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        _keyId |= ((short) dataPtr[4]) << 24;\r
-        _keyId |= ((short) dataPtr[5]) << 16;\r
-        _keyId |= ((short) dataPtr[6]) << 8;\r
-        _keyId |= ((short) dataPtr[7]) & 0xFF;\r
-        _seqNum |= ((short) dataPtr[8]) << 24;\r
-        _seqNum |= ((short) dataPtr[9]) << 16;\r
-        _seqNum |= ((short) dataPtr[10]) << 8;\r
-        _seqNum |= ((short) dataPtr[11]) & 0xFF;\r
-\r
-        int dLen = _objHdr.getDataLength() - 12;\r
-        COPSData d = new COPSData(dataPtr, 12, dLen);\r
-        setKeyDigest(d);\r
-    }\r
-\r
-    /**\r
-     * Method setKeyId\r
-     *\r
-     * @param    keyId               an int\r
-     *\r
-     */\r
-    public void setKeyId(int keyId) {\r
-        _keyId = keyId;\r
-    };\r
-\r
-    /**\r
-     * Method setSeqNum\r
-     *\r
-     * @param    seqNum              an int\r
-     *\r
-     */\r
-    public void setSeqNum(int seqNum) {\r
-        _seqNum = seqNum;\r
-    };\r
-\r
-    /**\r
-     * Method setKeyDigest\r
-     *\r
-     * @param    keyDigest           a  COPSData\r
-     *\r
-     */\r
-    public void setKeyDigest(COPSData keyDigest) {\r
-        _keyDigest = keyDigest;\r
-        if (_keyDigest.length() % 4 != 0) {\r
-            int padLen = 4 - _keyDigest.length() % 4;\r
-            _padding = getPadding(padLen);\r
-        }\r
-        // _objHdr.setDataLength(sizeof(u_int32_t)\r
-        //                           + sizeof(u_int32_t) + _keyDigest.length());\r
-        _objHdr.setDataLength((short) (8 + _keyDigest.length()));\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        int lpadding = 0;\r
-        if (_padding != null) lpadding = _padding.length();\r
-        return ((short) (_objHdr.getDataLength() + lpadding));\r
-    }\r
-\r
-    /**\r
-     * Method getKeyId\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getKeyId() {\r
-        return _keyId;\r
-    };\r
-\r
-    /**\r
-     * Method getSeqNum\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getSeqNum() {\r
-        return _seqNum;\r
-    };\r
-\r
-    /**\r
-     * Method getKeyDigest\r
-     *\r
-     * @return   a COPSData\r
-     *\r
-     */\r
-    public COPSData getKeyDigest() {\r
-        return _keyDigest;\r
-    };\r
-\r
-    /**\r
-     * Method isMessageIntegrity\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isMessageIntegrity() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Write data on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-\r
-        byte[] buf = new byte[8];\r
-        buf[0] = (byte) (_keyId >> 24);\r
-        buf[1] = (byte) (_keyId >> 16);\r
-        buf[2] = (byte) (_keyId >> 8);\r
-        buf[3] = (byte) _keyId;\r
-        buf[4] = (byte) (_seqNum >> 24);\r
-        buf[5] = (byte) (_seqNum >> 16);\r
-        buf[6] = (byte) (_seqNum >> 8);\r
-        buf[7] = (byte) _seqNum;\r
-        COPSUtil.writeData(id, buf, 8);\r
-\r
-        COPSUtil.writeData(id, _keyDigest.getData(), _keyDigest.length());\r
-        if (_padding != null) {\r
-            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Key Id: " + _keyId + "\n").getBytes());\r
-        os.write(new String("Sequence: " + _seqNum + "\n").getBytes());\r
-        os.write(new String("Key digest: " + _keyDigest.str() + "\n").getBytes());\r
-    }\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Integrity Object (RFC 2748)
+ *
+ * The integrity object includes a sequence number and a message digest
+ * useful for authenticating and validating the integrity of a COPS
+ * message. When used, integrity is provided at the end of a COPS
+ * message as the last COPS object. The digest is then computed over all
+ * of a particular COPS message up to but not including the digest value
+ * itself. The sender of a COPS message will compute and fill in the
+ * digest portion of the Integrity object. The receiver of a COPS
+ * message will then compute a digest over the received message and
+ * verify it matches the digest in the received Integrity object.
+ *
+ * C-Num = 16,
+ *
+ * C-Type = 1, HMAC digest
+ *
+ * The HMAC integrity object employs HMAC (Keyed-Hashing for Message
+ * Authentication) [HMAC] to calculate the message digest based on a key
+ * shared between the PEP and its PDP.
+ *
+ * This Integrity object specifies a 32-bit Key ID used to identify a
+ * specific key shared between a particular PEP and its PDP and the
+ * cryptographic algorithm to be used. The Key ID allows for multiple
+ * simultaneous keys to exist on the PEP with corresponding keys on the
+ * PDP for the given PEPID. The key identified by the Key ID was used to
+ * compute the message digest in the Integrity object. All
+ * implementations, at a minimum, MUST support HMAC-MD5-96, which is
+ * HMAC employing the MD5 Message-Digest Algorithm [MD5] truncated to
+ * 96-bits to calculate the message digest.
+ *
+ * This object also includes a sequence number that is a 32-bit unsigned
+ * integer used to avoid replay attacks. The sequence number is
+ * initiated during an initial Client-Open Client-Accept message
+ * exchange and is then incremented by one each time a new message is
+ * sent over the TCP connection in the same direction. If the sequence
+ * number reaches the value of 0xFFFFFFFF, the next increment will
+ * simply rollover to a value of zero.
+ *
+ * The variable length digest is calculated over a COPS message starting
+ * with the COPS Header up to the Integrity Object (which MUST be the
+ * last object in a COPS message) INCLUDING the Integrity object's
+ * header, Key ID, and Sequence Number. The Keyed Message Digest field
+ * is not included as part of the digest calculation. In the case of
+ * HMAC-MD5-96, HMAC-MD5 will produce a 128-bit digest that is then to
+ * be truncated to 96-bits before being stored in or verified against
+ * the Keyed Message Digest field as specified in [HMAC]. The Keyed
+ * Message Digest MUST be 96-bits when HMAC-MD5-96 is used.
+ */
+public class COPSIntegrity extends COPSObjBase {
+
+    private final int _keyId;
+    private final int _seqNum;
+    private final COPSData _keyDigest;
+    private final COPSData _padding;
+
+    /**
+     * Constructor generally used for sending messages
+     * // TODO - why aren't any classes requiring injection of the keyId, seqNum, or keyDigest members???
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIntegrity() {
+        this(0, 0, new COPSData());
+    }
+
+    public COPSIntegrity(final int keyId, final int seqNum, final COPSData keyDigest) {
+        this(new COPSObjHeader(CNum.MSG_INTEGRITY, CType.DEF), keyId, seqNum, keyDigest);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param keyId - the keyId
+     * @param seqNum - the sequence number
+     * @param keyDigest - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIntegrity(final COPSObjHeader hdr, final int keyId, final int seqNum, final COPSData keyDigest) {
+        super(hdr);
+        if (!hdr.getCNum().equals(CNum.MSG_INTEGRITY))
+            throw new IllegalArgumentException("CNum must be of type - " + CNum.MSG_INTEGRITY);
+        if (!hdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("CType must be of type - " + CType.DEF);
+
+        _keyId = keyId;
+        _seqNum = seqNum;
+
+        if (keyDigest == null) _keyDigest = new COPSData();
+        else _keyDigest = keyDigest;
+        if ((_keyDigest.length() % 4) != 0) {
+            final int padLen = 4 - (_keyDigest.length() % 4);
+            _padding = COPSObjectParser.getPadding(padLen);
+        } else {
+            _padding = new COPSData();
+        }
+    }
+
+    // Getters
+    public int getKeyId() { return _keyId; }
+    public int getSeqNum() { return _seqNum; }
+    public COPSData getKeyDigest() { return _keyDigest; }
+
+    @Override
+    public int getDataLength() {
+        return 8 + _keyDigest.length() + _padding.length();
+    }
+
+    @Override
+    public void writeBody(final Socket socket) throws IOException {
+        final byte[] buf = new byte[8];
+        buf[0] = (byte) (_keyId >> 24);
+        buf[1] = (byte) (_keyId >> 16);
+        buf[2] = (byte) (_keyId >> 8);
+        buf[3] = (byte) _keyId;
+        buf[4] = (byte) (_seqNum >> 24);
+        buf[5] = (byte) (_seqNum >> 16);
+        buf[6] = (byte) (_seqNum >> 8);
+        buf[7] = (byte) _seqNum;
+        COPSUtil.writeData(socket, buf, 8);
+
+        COPSUtil.writeData(socket, _keyDigest.getData(), _keyDigest.length());
+        if (_padding != null) {
+            COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+        }
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("Key Id: " + _keyId + "\n").getBytes());
+        os.write(("Sequence: " + _seqNum + "\n").getBytes());
+        os.write(("Key digest: " + _keyDigest.str() + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSIntegrity)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSIntegrity integrity = (COPSIntegrity) o;
+
+        if (_keyId != integrity._keyId) {
+            return false;
+        }
+        if (_seqNum != integrity._seqNum) {
+            return false;
+        }
+        if (_keyDigest.equals(integrity._keyDigest) && _padding.equals(integrity._padding)) return true;
+        else
+            return COPSUtil.copsDataPaddingEquals(this._keyDigest, this._padding,
+                    integrity._keyDigest, integrity._padding);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _keyId;
+        result = 31 * result + _seqNum;
+        result = 31 * result + _keyDigest.hashCode();
+        result = 31 * result + _padding.hashCode();
+        return result;
+    }
+
+    /**
+     * Parses bytes to return a COPSIntegrity object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSIntegrity parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        int keyId = 0;
+        keyId |= ((short) dataPtr[4]) << 24;
+        keyId |= ((short) dataPtr[5]) << 16;
+        keyId |= ((short) dataPtr[6]) << 8;
+        keyId |= ((short) dataPtr[7]) & 0xFF;
+
+        int seqNum = 0;
+        seqNum |= ((short) dataPtr[8]) << 24;
+        seqNum |= ((short) dataPtr[9]) << 16;
+        seqNum |= ((short) dataPtr[10]) << 8;
+        seqNum |= ((short) dataPtr[11]) & 0xFF;
+
+        final int usedBytes = objHdrData.header.getHdrLength() + 8;
+        if (objHdrData.msgByteCount > usedBytes)
+            return new COPSIntegrity(objHdrData.header, keyId, seqNum,
+                    new COPSData(dataPtr, usedBytes, objHdrData.msgByteCount - usedBytes));
+        else return new COPSIntegrity(objHdrData.header, keyId, seqNum, new COPSData());
+    }
+
+}
+
+
index 7d6b746933aa8d2bd0dd9fe52e8b6051092bca0b..44b92e58171a8c47d88bd42c7c3dcc1700eb4f9a 100644 (file)
@@ -1,67 +1,92 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-\r
-\r
-/**\r
- * COPS Interface\r
- *\r
- * @version COPSInterface.java, v 1.00 2003\r
- *\r
- */\r
-abstract class COPSInterface extends COPSObjBase {\r
-    /**\r
-     * Method isIpv4Address\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    protected boolean isIpv4Address() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isIpv6Address\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    protected boolean isIpv6Address() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isInInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    protected boolean isInInterface() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isOutInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    protected boolean isOutInterface() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    protected boolean isInterface() {\r
-        return true;\r
-    }\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Abstract COPS Interface for extension of all COPS interface types
+ */
+abstract class COPSInterface extends COPSObjBase {
+
+    /**
+     * The associated address object for a given COPS Interfaace
+     */
+    protected final COPSIpAddress _addr;
+
+    /**
+     * The interface on which the protocol message was received
+     */
+    protected final int _ifindex;
+
+    /**
+     * Constructor
+     * @param objHdr - the object's header
+     * @param ifindex - the interface value
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSInterface(final COPSObjHeader objHdr, final COPSIpAddress addr, final int ifindex) {
+        super(objHdr);
+        if (addr == null) throw new IllegalArgumentException("Address object cannot be null");
+        _addr = addr;
+        _ifindex = ifindex;
+    }
+
+    public abstract boolean isInInterface();
+    public abstract boolean isIPv6();
+
+    @Override
+    protected int getDataLength() {
+        return _addr.getDataLength() + 4;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _addr.writeData(socket);
+        final byte[] buf = new byte[4];
+        buf[0] = (byte) (_ifindex >> 24);
+        buf[1] = (byte) (_ifindex >> 16);
+        buf[2] = (byte) (_ifindex >> 8);
+        buf[3] = (byte) _ifindex;
+        COPSUtil.writeData(socket, buf, 4);
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        os.write(("Address: " + _addr.getIpName() + "\n").getBytes());
+        os.write(("ifindex: " + _ifindex + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSInterface)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSInterface that = (COPSInterface) o;
+
+        return _ifindex == that._ifindex && _addr.equals(that._addr);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _addr.hashCode();
+        result = 31 * result + _ifindex;
+        return result;
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpAddress.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpAddress.java
new file mode 100644 (file)
index 0000000..2093fff
--- /dev/null
@@ -0,0 +1,87 @@
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+/**
+ * Abstract superclass for all COPS IP Addresses.
+ */
+public abstract class COPSIpAddress {
+
+    /**
+     * The byte array representation of an IP address
+     */
+    protected final byte[] _addr;
+
+    /**
+     * Creates an address for a given host
+     * @param hostName - the host name
+     * @throws java.net.UnknownHostException
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpAddress(final String hostName) throws UnknownHostException {
+        if (hostName == null) throw new IllegalArgumentException("Hostname must not be null");
+        _addr = deriveIpAddress(hostName);
+    }
+
+    protected COPSIpAddress(final byte[] addr) {
+        if (addr == null) throw new IllegalArgumentException("The addr parameter must not be null");
+        _addr = addr;
+    }
+
+    protected byte[] getAddressBytes() { return _addr; }
+
+    /**
+     * Derives the IP address in a byte array from the host name
+     * @param    hostName            a  String
+     * @throws   UnknownHostException
+     */
+    protected abstract byte[] deriveIpAddress(final String hostName) throws UnknownHostException;
+
+    /**
+     * Method getIpName
+     * @return   a String
+     * @throws   UnknownHostException
+     */
+    public abstract String getIpName() throws UnknownHostException;
+
+    /**
+     * Returns the number of bytes that will be written
+     * @return   a short
+     */
+    public int getDataLength() {
+        return _addr.length;
+    }
+
+    /**
+     * Write data on a given network socket
+     * @param    socket                  a  Socket
+     * @throws   IOException
+     */
+    public void writeData(Socket socket) throws IOException {
+        COPSUtil.writeData(socket, _addr, _addr.length);
+    }
+
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSIpAddress)) {
+            return false;
+        }
+
+        final COPSIpAddress that = (COPSIpAddress) o;
+
+        return Arrays.equals(_addr, that._addr);
+
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(_addr);
+    }
+}
index 2bb7d873ef4dba8f2b27a30cbba29245fe5e60e4..3ed9397ab98f10549967ed0b6bb9b0f876657478 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.ByteArrayInputStream;\r
-import java.io.IOException;\r
-import java.net.InetAddress;\r
-import java.net.Socket;\r
-import java.net.UnknownHostException;\r
-\r
-/**\r
- * COPS IPv4 Address\r
- *\r
- * @version COPSIpv4Address.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv4Address {\r
-\r
-    private byte[] _addr;\r
-\r
-    public COPSIpv4Address() {\r
-        _addr = new byte[4];\r
-    }\r
-\r
-    public COPSIpv4Address(String hostName) throws UnknownHostException {\r
-        setIpAddress(hostName);\r
-    }\r
-\r
-    /**\r
-     * Method setIpAddress\r
-     *\r
-     * @param    hostName            a  String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public void setIpAddress(String hostName) throws UnknownHostException {\r
-        _addr = InetAddress.getByName(hostName).getAddress();\r
-    }\r
-\r
-    /**\r
-     * Method getIpName\r
-     *\r
-     * @return   a String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public String getIpName() throws UnknownHostException {\r
-        return InetAddress.getByAddress(_addr).getHostName();\r
-    }\r
-\r
-    /**\r
-     * Method getIpAddress\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getIpAddress() {\r
-        int ipaddr = 0;\r
-\r
-        ipaddr |= ((int) _addr[0]) << 24;\r
-        ipaddr |= ((int) _addr[1]) << 16;\r
-        ipaddr |= ((int) _addr[2]) << 8;\r
-        ipaddr |= ((int) _addr[3]) & 0xFF;\r
-\r
-        return ipaddr;\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    dataPtr             a  byte[]\r
-     *\r
-     */\r
-    public void parse(byte[] dataPtr) {\r
-        new ByteArrayInputStream(dataPtr).read(_addr,0,4);\r
-    }\r
-\r
-    /**\r
-     * Method getDataLength\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        return (4);\r
-    }\r
-\r
-    /**\r
-     * Write data on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        COPSUtil.writeData(id, _addr, 4);\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * COPS IPv4 Address
+ */
+public class COPSIpv4Address extends COPSIpAddress {
+
+    /**
+     * Creates an address for a given host
+     * @param hostName - the host name
+     * @throws UnknownHostException
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv4Address(final String hostName) throws UnknownHostException {
+        super(hostName);
+    }
+
+    /**
+     * Creates an address for a given IP address contained within a byte array
+     * @param addr - the host name
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv4Address(final byte[] addr) {
+        super(addr);
+        if (addr.length != 4) throw new IllegalArgumentException("The address must be 4 bytes");
+    }
+
+    @Override
+    protected byte[] deriveIpAddress(final String hostName) throws UnknownHostException {
+        final InetAddress[] addrs = Inet4Address.getAllByName(hostName);
+        for (final InetAddress addr : addrs) {
+            if (addr instanceof Inet4Address) {
+                return addr.getAddress();
+            }
+        }
+        throw new UnknownHostException("InetAddress could not be found");
+    }
+
+    @Override
+    public String getIpName() throws UnknownHostException {
+        return Inet4Address.getByAddress(_addr).getHostName();
+    }
+
+}
+
index e243dc7ea6e4b013847a1a76b300e08a364ed0fb..7c20f41dfdc79c10b806054e69ac66d172278d89 100644 (file)
@@ -1,60 +1,86 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS IPv4 Input Address\r
- *\r
- * @version COPSIpv4InInterface.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv4InInterface extends COPSIpv4Interface {\r
-    public COPSIpv4InInterface() {\r
-        super(new COPSObjHeader(CNum.ININTF, CType.DEF));\r
-    }\r
-\r
-    public COPSIpv4InInterface(byte[] dataPtr) {\r
-        super(dataPtr);\r
-    }\r
-\r
-    /**\r
-     * Method className\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String className() {\r
-        return "COPSIpv4InInterface";\r
-    }\r
-\r
-    /**\r
-     * Method isInInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isInInterface() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-    }\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS IPv4 Input Address (RFC 2748)
+ *
+ * The In-Interface Object is used to identify the incoming interface on
+ * which a particular request applies and the address where the received
+ * message originated. For flows or messages generated from the PEP's
+ * local host, the loop back address and ifindex are used.
+ *
+ * This Interface object is also used to identify the incoming
+ * (receiving) interface via its ifindex. The ifindex may be used to
+ * differentiate between sub-interfaces and unnumbered interfaces (see
+ * RSVP's LIH for an example). When SNMP is supported by the PEP, this
+ * ifindex integer MUST correspond to the same integer value for the
+ * interface in the SNMP MIB-II interface index table.
+ *
+ * Note: The ifindex specified in the In-Interface is typically relative
+ * to the flow of the underlying protocol messages. The ifindex is the
+ * interface on which the protocol message was received.
+ *
+ * C-Num = 3
+ *
+ * C-Type = 1, IPv4 Address + Interface
+ *
+ * 0             1              2             3
+ * +--------------+--------------+--------------+--------------+
+ * |                   IPv4 Address format                     |
+ * +--------------+--------------+--------------+--------------+
+ * |                          ifindex                          |
+ * +--------------+--------------+--------------+--------------+
+ *
+ * For this type of the interface object, the IPv4 address specifies the
+ * IP address that the incoming message came from.
+ */
+public class COPSIpv4InInterface extends COPSIpv4Interface {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param ifindex - the interface value
+     * @param addr - the IPv4 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv4InInterface(final COPSIpv4Address addr, final int ifindex) {
+        this(new COPSObjHeader(CNum.ININTF, CType.DEF), addr, ifindex);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param ifindex - the interface value
+     * @param addr - the IPv4 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4InInterface(final COPSObjHeader objHdr, final COPSIpv4Address addr, final int ifindex) {
+        super(objHdr, addr, ifindex);
+        if (!objHdr.getCNum().equals(CNum.ININTF))
+            throw new IllegalArgumentException("CNum must be of type - " + CNum.ININTF);
+        if (!objHdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("CType must be of type - " + CType.DEF);
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSIpv4InInterface parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        return new COPSIpv4InInterface(objHdrData.header, COPSIpv4Interface.parseAddress(dataPtr),
+                COPSIpv4Interface.parseIfIndex(dataPtr));
+    }
+
+    public boolean isInInterface() { return true; }
+}
index a9fbc3b8be6ca7ecb50eab6c8266a01b1578e98b..86ff35fb908bb60a2e22dc1caf1908a09b845bd9 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.net.UnknownHostException;\r
-\r
-/**\r
- * COPS IPv4 Interface\r
- *\r
- * @version COPSIpv4Interface.java, v 1.00 2003\r
- *\r
- */\r
-public abstract class COPSIpv4Interface extends COPSInterface {\r
-\r
-    protected COPSObjHeader _objHdr;\r
-    private COPSIpv4Address _addr;\r
-    private int _ifindex;\r
-\r
-\r
-    /**\r
-     * Method isIpv4Address\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIpv4Address() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Method setIpAddress\r
-     *\r
-     * @param    hostName            a  String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public void setIpAddress(String hostName) throws UnknownHostException {\r
-        _addr.setIpAddress(hostName);\r
-    }\r
-\r
-    /**\r
-     * Method getIpName\r
-     *\r
-     * @return   a String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public String getIpName() throws UnknownHostException {\r
-        return (_addr.getIpName());\r
-    }\r
-\r
-    /**\r
-     * Method getIpAddress\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getIpAddress() {\r
-        return (_addr.getIpAddress());\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    protected COPSIpv4Interface(COPSObjHeader hdr) {\r
-        _objHdr = hdr;\r
-//        _objHdr.setCType((byte) 1);\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    protected COPSIpv4Interface(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        byte[] buf = new byte[4];\r
-        System.arraycopy(dataPtr,4,buf,0,4);\r
-\r
-        _addr.parse(buf);\r
-\r
-        _ifindex |= ((int) dataPtr[8]) << 24;\r
-        _ifindex |= ((int) dataPtr[9]) << 16;\r
-        _ifindex |= ((int) dataPtr[10]) << 8;\r
-        _ifindex |= ((int) dataPtr[11]) & 0xFF;\r
-\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+/**
+ * COPS IPv4 Interface
+ *
+ * @version COPSIpv4Interface.java, v 1.00 2003
+ *
+ */
+public abstract class COPSIpv4Interface extends COPSInterface {
+
+    /**
+     * Constructor
+     * @param objHdr - the header
+     * @param ifindex - the interface value
+     * @param addr - the address object
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4Interface(final COPSObjHeader objHdr, final COPSIpv4Address addr, final int ifindex) {
+        super(objHdr, addr, ifindex);
+    }
+
+    @Override
+    public boolean isIPv6() { return false; }
+
+    /**
+     * Creates a COPSIpv4Address object from a byte array.
+     * @param dataPtr - the byte array
+     * @return - the address
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected static COPSIpv4Address parseAddress(final byte[] dataPtr) {
+        byte[] buf = new byte[4];
+        buf[0] = dataPtr[4];
+        buf[1] = dataPtr[5];
+        buf[2] = dataPtr[6];
+        buf[3] = dataPtr[7];
+        return new COPSIpv4Address(buf);
+    }
+
+    /**
+     * Parses the ifindex value from a byte array.
+     * @param dataPtr - the byte array
+     * @return - the index value
+     */
+    protected static int parseIfIndex(final byte[] dataPtr) {
+        int ifindex = 0;
+        ifindex |= ((int) dataPtr[8]) << 24;
+        ifindex |= ((int) dataPtr[9]) << 16;
+        ifindex |= ((int) dataPtr[10]) << 8;
+        ifindex |= ((int) dataPtr[11]) & 0xFF;
+        return ifindex;
+    }
+
+}
+
+
+
+
index 25ee04f7b7b8b7c94e20e64f5dd191f715ddf197..f86e1fdd32ff74b68e494ceee80a5185a14b3bb8 100644 (file)
@@ -1,55 +1,64 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-\r
-/**\r
- * COPS IPv4 Last PDP Address\r
- *\r
- * @version COPSIpv4LastPdpAddr.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv4LastPdpAddr extends COPSIpv4PdpAddress {\r
-\r
-    public COPSIpv4LastPdpAddr() {\r
-        super(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF));\r
-    }\r
-\r
-    public COPSIpv4LastPdpAddr(byte[] dataPtr) {\r
-        super(dataPtr);\r
-    }\r
-\r
-    /**\r
-     * Method isLastPdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isLastPdpAddress() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Ipv4PdpAddress" + "\n").getBytes());\r
-        os.write(new String("Address: " + _addr.getIpName() + "\n").getBytes());\r
-        os.write(new String("Port: " + _tcpPort + "\n").getBytes());\r
-    }\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.UnknownHostException;
+
+/**
+ * Last PDP Address (RFC 2748)
+ *
+ * When a PEP sends a Client-Open message for a particular client-type
+ * the PEP SHOULD specify the last PDP it has successfully opened
+ * (meaning it received a Client-Accept) since the PEP last rebooted.
+ * If no PDP was used since the last reboot, the PEP will simply not
+ * include this object in the Client-Open message.
+ *
+ * C-Num = 14,
+ *
+ * C-Type = 1, IPv4 Address (Same format as PDPRedirAddr)
+ *
+ * C-Type = 2, IPv6 Address (Same format as PDPRedirAddr)
+ */
+public class COPSIpv4LastPdpAddr extends COPSIpv4PdpAddress {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param host - the host name
+     * @param port - the associated port
+     * @param reserved - ???
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv4LastPdpAddr(final String host, final int port, final short reserved) throws UnknownHostException {
+        super(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF), host, port, reserved);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param addr - the byte array representation of a host
+     * @param tcpPort - the associated port
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4LastPdpAddr(final COPSObjHeader objHdr, final byte[] addr, final int tcpPort,
+                                  final short reserved) {
+        super(objHdr, addr, tcpPort, reserved);
+        if (!objHdr.getCNum().equals(CNum.LAST_PDP_ADDR))
+            throw new IllegalArgumentException("CNum must be equal to - " + CNum.LAST_PDP_ADDR);
+    }
+
+    @Override
+    public void dumpBody(OutputStream os) throws IOException {
+        os.write(("Ipv4LastPdpAddress" + "\n").getBytes());
+        super.dumpBody(os);
+    }
+}
index 572e680fb0cf43a100a07e9d14bd720fbfb3dba8..b4360811324bb4514bf96896d5af836b19e6c1c7 100644 (file)
@@ -1,63 +1,86 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS IPv4 Output Interface\r
- *\r
- * @version COPSIpv4OutInterface.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv4OutInterface extends COPSIpv4Interface {\r
-    public COPSIpv4OutInterface() {\r
-        super(new COPSObjHeader(CNum.ININTF, CType.DEF));\r
-    }\r
-\r
-    public COPSIpv4OutInterface(byte[] dataPtr) {\r
-        super(dataPtr);\r
-    }\r
-\r
-    /**\r
-     * Method className\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String className() {\r
-        return "COPSIpv4OutInterface";\r
-    }\r
-\r
-    /**\r
-     * Method isInInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isInInterface() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-    }\r
-\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS IPv4 Output Interface (RFC 2748)
+ *
+ * The Out-Interface is used to identify the outgoing interface to which
+ * a specific request applies and the address for where the forwarded
+ * message is to be sent. For flows or messages destined to the PEP's
+ * local host, the loop back address and ifindex are used.  The Out-
+ * Interface has the same formats as the In-Interface Object.
+ *
+ * This Interface object is also used to identify the outgoing
+ * (forwarding) interface via its ifindex. The ifindex may be used to
+ * differentiate between sub-interfaces and unnumbered interfaces (see
+ * RSVP's LIH for an example). When SNMP is supported by the PEP, this
+ * ifindex integer MUST correspond to the same integer value for the
+ * interface in the SNMP MIB-II interface index table.
+ *
+ * Note: The ifindex specified in the Out-Interface is typically
+ * relative to the flow of the underlying protocol messages. The ifindex
+ * is the one on which a protocol message is about to be forwarded.
+ *
+ * C-Num = 4
+ *
+ * C-Type = 1, IPv4 Address + Interface
+ *
+ * Same C-Type format as the In-Interface object. The IPv4 address
+ * specifies the IP address to which the outgoing message is going. The
+ * ifindex is used to refer to the MIB-II defined local outgoing
+ * interface on the PEP.
+ * C-Type = 2, IPv6 Address + Interface
+ *
+ * Same C-Type format as the In-Interface object. For this type of the
+ * interface object, the IPv6 address specifies the IP address to which
+ * the outgoing message is going. The ifindex is used to refer to the
+ * MIB-II defined local outgoing interface on the PEP.
+ */
+public class COPSIpv4OutInterface extends COPSIpv4Interface {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param ifindex - the interface value
+     * @param addr - the IPv4 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv4OutInterface(final COPSIpv4Address addr, final int ifindex) {
+        this(new COPSObjHeader(CNum.OUTINTF, CType.DEF), addr, ifindex);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param ifindex - the interface value
+     * @param addr - the IPv4 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4OutInterface(final COPSObjHeader objHdr, final COPSIpv4Address addr, final int ifindex) {
+        super(objHdr, addr, ifindex);
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSIpv4OutInterface parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        return new COPSIpv4OutInterface(objHdrData.header, COPSIpv4Interface.parseAddress(dataPtr),
+                COPSIpv4Interface.parseIfIndex(dataPtr));
+    }
+
+    public boolean isInInterface() { return false; }
+}
+
+
index 98b0042173bcfc05ba652c9c981d2ea5e8168dde..f49a79c3fac35e1b6d9c69ab12edb832f3e06a4f 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.net.UnknownHostException;\r
-\r
-/**\r
- * COPS IPv4 PDP Address\r
- *\r
- * @version COPSIpv4PdpAddress.java, v 1.00 2003\r
- *\r
- */\r
-abstract public class COPSIpv4PdpAddress extends COPSPdpAddress {\r
-\r
-    protected COPSObjHeader _objHdr;\r
-    protected COPSIpv4Address _addr;\r
-    private short _reserved;\r
-    protected short _tcpPort;\r
-\r
-    protected COPSIpv4PdpAddress(COPSObjHeader hdr) {\r
-        _addr = new COPSIpv4Address();\r
-        _objHdr = hdr;\r
-//        _objHdr.setCType((byte) 1);\r
-        // _objHdr.setDataLength((short) _addr.getDataLength() + sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    protected COPSIpv4PdpAddress(byte[] dataPtr) {\r
-        _addr = new COPSIpv4Address();\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        byte[] buf = new byte[4];\r
-        System.arraycopy(dataPtr,2,buf,0,4);\r
-        _addr.parse(buf);\r
-\r
-        _reserved |= ((short) dataPtr[8]) << 8;\r
-        _reserved |= ((short) dataPtr[9]) & 0xFF;\r
-        _tcpPort |= ((short) dataPtr[10]) << 8;\r
-        _tcpPort |= ((short) dataPtr[11]) & 0xFF;\r
-\r
-        // _objHdr.setDataLength(_addr.getDataLength() + sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    /**\r
-     * Method setIpAddress\r
-     *\r
-     * @param    hostName            a  String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public void setIpAddress(String hostName) throws UnknownHostException  {\r
-        _addr.setIpAddress(hostName);\r
-    }\r
-\r
-    /**\r
-     * Method setTcpPort\r
-     *\r
-     * @param    port                a  short\r
-     *\r
-     */\r
-    public void setTcpPort(short port) {\r
-        _tcpPort = port;\r
-    }\r
-\r
-    /**\r
-     * Method getIpName\r
-     *\r
-     * @return   a String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public String getIpName() throws UnknownHostException {\r
-        return (_addr.getIpName());\r
-    }\r
-\r
-    /**\r
-     * Method getTcpPort\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    short getTcpPort() {\r
-        return _tcpPort;\r
-    };\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    /**\r
-     * Method isIpv6PdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIpv6PdpAddress() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Write data on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        //\r
-        _objHdr.writeData(id);\r
-        _addr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-        buf[0] = (byte) (_reserved & 0xFF);\r
-        buf[1] = (byte) (_reserved << 8);\r
-        buf[2] = (byte) (_tcpPort & 0xFF);\r
-        buf[3] = (byte) (_tcpPort << 8);\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.net.UnknownHostException;
+
+/**
+ * Super for IPv4 PDP Addresses
+ */
+abstract public class COPSIpv4PdpAddress extends COPSPdpAddress {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param host - the host name
+     * @param tcpPort - the associated port
+     * @param reserved - not in use
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4PdpAddress(final COPSObjHeader objHdr, final String host, final int tcpPort, final short reserved)
+            throws UnknownHostException {
+        super(objHdr, new COPSIpv4Address(host), tcpPort, reserved);
+        if (!objHdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.DEF);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param addr - the byte array representation of a host
+     * @param tcpPort - the associated port
+     * @param reserved - not in use
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4PdpAddress(final COPSObjHeader objHdr, final byte[] addr, final int tcpPort,
+                                 final short reserved) {
+        super(objHdr, new COPSIpv4Address(addr), tcpPort, reserved);
+        if (!objHdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.DEF);
+    }
+
+
+}
+
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpRedirectAddress.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpRedirectAddress.java
new file mode 100644 (file)
index 0000000..33bb1bc
--- /dev/null
@@ -0,0 +1,56 @@
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.UnknownHostException;
+
+/**
+ * PDP Redirect Address (RFC 2748 pg. 15)
+ *
+ * A PDP when closing a PEP session for a particular client-type may
+ optionally use this object to redirect the PEP to the specified PDP
+ server address and TCP port number:
+ *
+ * C-Num = 13,
+ *
+ * C-Type = 1, IPv4 Address (Same format as PDPRedirAddr)
+ *
+ * C-Type = 2, IPv6 Address (Same format as PDPRedirAddr)
+ */
+public class COPSIpv4PdpRedirectAddress extends COPSIpv4PdpAddress {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param host - the host name
+     * @param port - the associated port
+     * @param reserved - ???
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv4PdpRedirectAddress(final String host, final int port, final short reserved) throws UnknownHostException {
+        super(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF), host, port, reserved);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param addr - the byte array representation of a host
+     * @param tcpPort - the associated port
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv4PdpRedirectAddress(final COPSObjHeader objHdr, final byte[] addr, final int tcpPort,
+                                  final short reserved) {
+        super(objHdr, addr, tcpPort, reserved);
+        if (!objHdr.getCNum().equals(CNum.PDP_REDIR))
+            throw new IllegalArgumentException("CNum must be equal to - " + CNum.PDP_REDIR);
+    }
+
+    @Override
+    public void dumpBody(OutputStream os) throws IOException {
+        os.write(("Ipv4PdpRedirectAddress" + "\n").getBytes());
+        super.dumpBody(os);
+    }
+}
index 0364359f2c1a4fb6e03d63682e3af4bfd4a2a207..7d62b0b1a24286d9d9d324cefd2b90fa411e25d6 100644 (file)
@@ -1,90 +1,56 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.ByteArrayInputStream;\r
-import java.io.IOException;\r
-import java.net.InetAddress;\r
-import java.net.Socket;\r
-import java.net.UnknownHostException;\r
-\r
-/**\r
- * COPS IPv6 Address\r
- *\r
- * @version COPSIpv6Address.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv6Address {\r
-\r
-    private byte[] _addr;\r
-\r
-    public COPSIpv6Address() {\r
-        _addr = new byte[16];\r
-    }\r
-\r
-    public COPSIpv6Address(String hostName) throws UnknownHostException {\r
-        setIpAddress(hostName);\r
-    }\r
-\r
-    /**\r
-     * Method setIpAddress\r
-     *\r
-     * @param    hostName            a  String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public void setIpAddress(String hostName) throws UnknownHostException {\r
-        _addr = InetAddress.getByName(hostName).getAddress();\r
-    }\r
-\r
-    /**\r
-     * Method getIpName\r
-     *\r
-     * @return   a String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public String getIpName() throws UnknownHostException {\r
-        return InetAddress.getByAddress(_addr).getHostName();\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    dataPtr             a  byte[]\r
-     *\r
-     */\r
-    public void parse(byte[] dataPtr) {\r
-        new ByteArrayInputStream(dataPtr).read(_addr,0,16);\r
-    }\r
-\r
-    /**\r
-     * Method getDataLength\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        return (16);\r
-    }\r
-\r
-    /**\r
-     * Write data on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        COPSUtil.writeData(id, _addr, 16);\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * COPS IPv6 Address
+ */
+public class COPSIpv6Address extends COPSIpAddress {
+
+    /**
+     * Creates an address for a given host
+     * @param hostName - the host name
+     * @throws UnknownHostException
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv6Address(final String hostName) throws UnknownHostException {
+        super(hostName);
+    }
+
+    /**
+     * Creates an address for a given IP address contained within a byte array
+     * @param addr - the host name
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv6Address(final byte[] addr) {
+        super(addr);
+        if (addr.length != 16) throw new IllegalArgumentException("The address must be 16 bytes");
+    }
+
+
+    @Override
+    protected byte[] deriveIpAddress(final String hostName) throws UnknownHostException {
+        final InetAddress[] addrs = Inet4Address.getAllByName(hostName);
+        for (final InetAddress addr : addrs) {
+            if (addr instanceof Inet6Address) {
+                return addr.getAddress();
+            }
+        }
+        throw new UnknownHostException("InetAddress could not be found");
+    }
+
+    @Override
+    public String getIpName() throws UnknownHostException {
+        return Inet6Address.getByAddress(_addr).getHostName();
+    }
+}
+
index b49716bff00ded236eb9683f47113730dee8a269..51c93e0f8a8504f3b94bfe2141fa1e5c44c07dbb 100644 (file)
@@ -1,62 +1,94 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS IPv6 Input Interface\r
- *\r
- * @version COPSIpv6InInterface.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv6InInterface extends COPSIpv6Interface {\r
-    public COPSIpv6InInterface() {\r
-        super(new COPSObjHeader(CNum.ININTF, CType.STATELESS));\r
-    }\r
-\r
-    public COPSIpv6InInterface(byte[] dataPtr) {\r
-        super(dataPtr);\r
-    }\r
-\r
-    /**\r
-     * Method className\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String className() {\r
-        return "COPSIpv6InInterface";\r
-    }\r
-\r
-    /**\r
-     * Method isInInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isInInterface() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-    }\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS IPv6 Input Address (RFC 2748)
+ *
+ * The In-Interface Object is used to identify the incoming interface on
+ * which a particular request applies and the address where the received
+ * message originated. For flows or messages generated from the PEP's
+ * local host, the loop back address and ifindex are used.
+ *
+ * This Interface object is also used to identify the incoming
+ * (receiving) interface via its ifindex. The ifindex may be used to
+ * differentiate between sub-interfaces and unnumbered interfaces (see
+ * RSVP's LIH for an example). When SNMP is supported by the PEP, this
+ * ifindex integer MUST correspond to the same integer value for the
+ * interface in the SNMP MIB-II interface index table.
+ *
+ * Note: The ifindex specified in the In-Interface is typically relative
+ * to the flow of the underlying protocol messages. The ifindex is the
+ * interface on which the protocol message was received.
+ *
+ * C-Type = 2, IPv6 Address + Interface
+ *
+ * 0             1              2             3
+ * +--------------+--------------+--------------+--------------+
+ * |                                                           |
+ * +                                                           +
+ * |                                                           |
+ * +                    IPv6 Address format                    +
+ * |                                                           |
+ * +                                                           +
+ * |                                                           |
+ * +--------------+--------------+--------------+--------------+
+ * |                          ifindex                          |
+ * +--------------+--------------+--------------+--------------+
+ *
+ * For this type of the interface object, the IPv6 address specifies the
+ * IP address that the incoming message came from. The ifindex is used
+ * to refer to the MIB-II defined local incoming interface on the PEP as
+ * described above.
+ */
+public class COPSIpv6InInterface extends COPSIpv6Interface {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param ifindex - the interface value
+     * @param addr - the IPv6 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv6InInterface(final COPSIpv6Address addr, final int ifindex) {
+        super(new COPSObjHeader(CNum.ININTF, CType.STATELESS), addr, ifindex);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param ifindex - the interface value
+     * @param addr - the IPv6 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6InInterface(final COPSObjHeader objHdr, final COPSIpv6Address addr, final int ifindex) {
+        super(objHdr, addr, ifindex);
+        if (!objHdr.getCNum().equals(CNum.ININTF))
+            throw new IllegalArgumentException("CNum must be of type - " + CNum.ININTF);
+        if (!objHdr.getCType().equals(CType.STATELESS))
+            throw new IllegalArgumentException("CType must be of type - " + CType.STATELESS);
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSIpv6InInterface parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        return new COPSIpv6InInterface(objHdrData.header, COPSIpv6Interface.parseAddress(dataPtr),
+                COPSIpv6Interface.parseIfIndex(dataPtr));
+    }
+
+    public boolean isInInterface() { return true; }
+}
+
+
index 2165aee1c93955d0ed63e7cd7c33c75a6bf55c0d..9bff41383c04c4b5712ca283682f5ca2e0e3ea83 100644 (file)
@@ -1,95 +1,64 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.net.UnknownHostException;\r
-\r
-/**\r
- * COPS IPv6 Interface\r
- *\r
- * @version COPSIpv6Interface.java, v 1.00 2003\r
- *\r
- */\r
-public abstract class COPSIpv6Interface extends COPSInterface {\r
-\r
-    /**\r
-     * Method isIpv6Address\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIpv6Address() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Method setIpAddress\r
-     *\r
-     * @param    hostName            a  String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public void setIpAddress(String hostName) throws UnknownHostException {\r
-        _addr.setIpAddress(hostName);\r
-    }\r
-\r
-    /**\r
-     * Method getIpName\r
-     *\r
-     * @return   a String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public String getIpName() throws UnknownHostException {\r
-        return (_addr.getIpName());\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    protected COPSIpv6Interface(COPSObjHeader hdr) {\r
-        _objHdr = hdr;\r
-//        _objHdr.setCType((byte) 2);\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    protected COPSIpv6Interface(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-        _objHdr.parse(dataPtr);\r
-        // _objHdr.checkDataLength();\r
-\r
-        byte[] buf = new byte[4];\r
-        System.arraycopy(dataPtr,4,buf,0,16);\r
-\r
-        _addr.parse(buf);\r
-\r
-        _ifindex |= ((int) dataPtr[20]) << 24;\r
-        _ifindex |= ((int) dataPtr[21]) << 16;\r
-        _ifindex |= ((int) dataPtr[22]) << 8;\r
-        _ifindex |= ((int) dataPtr[23]) & 0xFF;\r
-\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    private COPSObjHeader _objHdr;\r
-    private COPSIpv6Address _addr;\r
-    private int _ifindex;\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * COPS IPv6 Interface
+ *
+ * @version COPSIpv6Interface.java, v 1.00 2003
+ *
+ */
+public abstract class COPSIpv6Interface extends COPSInterface {
+
+    /**
+     * Constructor
+     * @param objHdr - the header
+     * @param ifindex - the interface value
+     * @param addr - the address object
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6Interface(final COPSObjHeader objHdr, final COPSIpv6Address addr, final int ifindex) {
+        super(objHdr, addr, ifindex);
+    }
+
+    @Override
+    public boolean isIPv6() { return true; }
+
+    /**
+     * Creates a COPSIpv6Address object from a byte array.
+     * @param dataPtr - the byte array
+     * @return - the address
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected static COPSIpv6Address parseAddress(final byte[] dataPtr) {
+        byte[] buf = new byte[16];
+        System.arraycopy(dataPtr, 4, buf, 0, 16);
+        new ByteArrayInputStream(dataPtr).read(buf, 0, 16);
+        return new COPSIpv6Address(buf);
+    }
+
+    /**
+     * Parses the ifindex value from a byte array.
+     * @param dataPtr - the byte array
+     * @return - the index value
+     */
+    protected static int parseIfIndex(final byte[] dataPtr) {
+        int ifindex = 0;
+        ifindex |= ((int) dataPtr[20]) << 24;
+        ifindex |= ((int) dataPtr[21]) << 16;
+        ifindex |= ((int) dataPtr[22]) << 8;
+        ifindex |= ((int) dataPtr[23]) & 0xFF;
+        return ifindex;
+    }
+
+}
+
+
+
+
index 0840392b1e6d5450211a39e8a6eb5e30646b4fe8..81f3355c69755e0a23b5a03ccd6a74813a32c517 100644 (file)
@@ -1,54 +1,65 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-\r
-/**\r
- * COPS IPv6 Last PDP Address\r
- *\r
- * @version COPSIpv6LastPdpAddr.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv6LastPdpAddr extends COPSIpv6PdpAddress {\r
-\r
-    public COPSIpv6LastPdpAddr() {\r
-        super();\r
-        // TODO - FIXME later, currently not in use and the header is now immutable\r
-//        _objHdr.setCNum(COPSObjHeader.COPS_LAST_PDP_ADDR);\r
-    }\r
-\r
-    public COPSIpv6LastPdpAddr(byte[] dataPtr) {\r
-        super(dataPtr);\r
-    }\r
-\r
-    /**\r
-     * Method isLastPdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isLastPdpAddress() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Ipv6PdpAddress" + "\n").getBytes());\r
-        os.write(new String("Address: " + _addr.getIpName() + "\n").getBytes());\r
-        os.write(new String("Port: " + _tcpPort + "\n").getBytes());\r
-    }\r
-};\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.UnknownHostException;
+
+/**
+ * Last PDP Address (RFC 2748)
+ *
+ * When a PEP sends a Client-Open message for a particular client-type
+ * the PEP SHOULD specify the last PDP it has successfully opened
+ * (meaning it received a Client-Accept) since the PEP last rebooted.
+ * If no PDP was used since the last reboot, the PEP will simply not
+ * include this object in the Client-Open message.
+ *
+ * C-Num = 14,
+ *
+ * C-Type = 1, IPv4 Address (Same format as PDPRedirAddr)
+ *
+ * C-Type = 2, IPv6 Address (Same format as PDPRedirAddr)
+ */
+public class COPSIpv6LastPdpAddr extends COPSIpv6PdpAddress {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param host - the host name
+     * @param tcpPort - the associated port
+     * @param reserved - ???
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv6LastPdpAddr(final String host, final int tcpPort, final short reserved) throws UnknownHostException {
+        super(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), host, tcpPort, reserved);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param addr - the byte array representation of a host
+     * @param tcpPort - the associated port
+     * @param reserved - ???
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6LastPdpAddr(final COPSObjHeader objHdr, final byte[] addr, final int tcpPort, final short reserved) {
+        super(objHdr, addr, tcpPort, reserved);
+        if (!objHdr.getCNum().equals(CNum.LAST_PDP_ADDR))
+            throw new IllegalArgumentException("CNum must be equal to - " + CNum.LAST_PDP_ADDR);
+    }
+
+    @Override
+    public void dumpBody(OutputStream os) throws IOException {
+        os.write(("Ipv6LastPdpAddr" + "\n").getBytes());
+        super.dumpBody(os);
+    }
+
+}
index 1908874febbfc6f5717baceb9f4877bd5db4220d..94d420453b64a395f31270eebc14bdbc4b00edbd 100644 (file)
@@ -1,61 +1,84 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS IPv6 Output Interface\r
- *\r
- * @version COPSIpv6OutInterface.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSIpv6OutInterface extends COPSIpv6Interface {\r
-    public COPSIpv6OutInterface() {\r
-        super(new COPSObjHeader(CNum.ININTF, CType.STATELESS));\r
-    }\r
-\r
-    public COPSIpv6OutInterface(byte[] dataPtr) {\r
-        super(dataPtr);\r
-    }\r
-\r
-    /**\r
-     * Method className\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String className() {\r
-        return "COPSIpv6OutInterface";\r
-    }\r
-\r
-    /**\r
-     * Method isInInterface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isInInterface() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-    }\r
-\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS IPv6 Output Interface (RFC 2748)
+ *
+ * The Out-Interface is used to identify the outgoing interface to which
+ * a specific request applies and the address for where the forwarded
+ * message is to be sent. For flows or messages destined to the PEP's
+ * local host, the loop back address and ifindex are used.  The Out-
+ * Interface has the same formats as the In-Interface Object.
+ *
+ * This Interface object is also used to identify the outgoing
+ * (forwarding) interface via its ifindex. The ifindex may be used to
+ * differentiate between sub-interfaces and unnumbered interfaces (see
+ * RSVP's LIH for an example). When SNMP is supported by the PEP, this
+ * ifindex integer MUST correspond to the same integer value for the
+ * interface in the SNMP MIB-II interface index table.
+ *
+ * Note: The ifindex specified in the Out-Interface is typically
+ * relative to the flow of the underlying protocol messages. The ifindex
+ * is the one on which a protocol message is about to be forwarded.
+ *
+ * C-Num = 4
+ *
+ * C-Type = 1, IPv4 Address + Interface
+ *
+ * Same C-Type format as the In-Interface object. The IPv4 address
+ * specifies the IP address to which the outgoing message is going. The
+ * ifindex is used to refer to the MIB-II defined local outgoing
+ * interface on the PEP.
+ * C-Type = 2, IPv6 Address + Interface
+ *
+ * Same C-Type format as the In-Interface object. For this type of the
+ * interface object, the IPv6 address specifies the IP address to which
+ * the outgoing message is going. The ifindex is used to refer to the
+ * MIB-II defined local outgoing interface on the PEP.
+ */
+public class COPSIpv6OutInterface extends COPSIpv6Interface {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param ifindex - the interface value
+     * @param addr - the IPv6 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv6OutInterface(final COPSIpv6Address addr, final int ifindex) {
+        this(new COPSObjHeader(CNum.OUTINTF, CType.STATELESS), addr, ifindex);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param ifindex - the interface value
+     * @param addr - the IPv6 address
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6OutInterface(final COPSObjHeader objHdr, final COPSIpv6Address addr, final int ifindex) {
+        super(objHdr, addr, ifindex);
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSIpv6OutInterface parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        return new COPSIpv6OutInterface(objHdrData.header, COPSIpv6Interface.parseAddress(dataPtr),
+                COPSIpv6Interface.parseIfIndex(dataPtr));
+    }
+
+    public boolean isInInterface() { return false; }
+}
index 698e2eca146c62421e10217b041a45b1226bbdc4..2c3734fe3e9e4d6c62f4a7428a2807531ec31294 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.net.UnknownHostException;\r
-\r
-/**\r
- * COPS IPv6 PDP Address\r
- *\r
- * @version COPSIpv6PdpAddress.java, v 1.00 2003\r
- *\r
- */\r
-abstract public class COPSIpv6PdpAddress extends COPSPdpAddress {\r
-\r
-    protected COPSObjHeader _objHdr;\r
-    protected COPSIpv6Address _addr;\r
-    private short _reserved;\r
-    protected short _tcpPort;\r
-\r
-    protected COPSIpv6PdpAddress() {\r
-        _addr = new COPSIpv6Address();\r
-        _objHdr = new COPSObjHeader(CNum.NA, CType.STATELESS);\r
-        // _objHdr.setDataLength((short) _addr.getDataLength() + sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    protected COPSIpv6PdpAddress(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-        // _objHdr.checkDataLength();\r
-\r
-        byte[] buf = new byte[16];\r
-        System.arraycopy(dataPtr,2,buf,0,16);\r
-        _addr.parse(buf);\r
-\r
-        _reserved |= ((short) dataPtr[20]) << 8;\r
-        _reserved |= ((short) dataPtr[21]) & 0xFF;\r
-        _tcpPort |= ((short) dataPtr[22]) << 8;\r
-        _tcpPort |= ((short) dataPtr[23]) & 0xFF;\r
-\r
-        // _objHdr.setDataLength(_addr.getDataLength() + sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
-    }\r
-\r
-    /**\r
-     * Method setIpAddress\r
-     *\r
-     * @param    hostName            a  String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public void setIpAddress(String hostName) throws UnknownHostException  {\r
-        _addr.setIpAddress(hostName);\r
-    }\r
-\r
-    /**\r
-     * Method setTcpPort\r
-     *\r
-     * @param    port                a  short\r
-     *\r
-     */\r
-    public void setTcpPort(short port) {\r
-        _tcpPort = port;\r
-    }\r
-\r
-    /**\r
-     * Method getIpName\r
-     *\r
-     * @return   a String\r
-     *\r
-     * @throws   UnknownHostException\r
-     *\r
-     */\r
-    public String getIpName() throws UnknownHostException {\r
-        return (_addr.getIpName());\r
-    }\r
-\r
-    /**\r
-     * Method getTcpPort\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    short getTcpPort() {\r
-        return _tcpPort;\r
-    };\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    /**\r
-     * Method isIpv6PdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIpv6PdpAddress() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Write data on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        //\r
-        _objHdr.writeData(id);\r
-        _addr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-        buf[0] = (byte) (_reserved >> 8);\r
-        buf[1] = (byte) _reserved;\r
-        buf[2] = (byte) (_tcpPort >> 8);\r
-        buf[3] = (byte) _tcpPort ;\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.net.UnknownHostException;
+
+/**
+ * Super for IPv6 PDP Addresses
+ */
+abstract public class COPSIpv6PdpAddress extends COPSPdpAddress {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param host - the host name
+     * @param tcpPort - the associated port
+     * @param reserved - not in use
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6PdpAddress(final COPSObjHeader objHdr, final String host, final int tcpPort, final short reserved)
+            throws UnknownHostException {
+        super(objHdr, new COPSIpv6Address(host), tcpPort, reserved);
+        if (!objHdr.getCType().equals(CType.STATELESS))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.STATELESS);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param addr - the byte array representation of a host
+     * @param tcpPort - the associated port
+     * @param reserved - not in use
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6PdpAddress(final COPSObjHeader objHdr, final byte[] addr, final int tcpPort,
+                                 final short reserved) {
+        super(objHdr, new COPSIpv6Address(addr), tcpPort, reserved);
+        if (!objHdr.getCType().equals(CType.STATELESS))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.STATELESS);
+    }
+
+}
+
+
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpRedirectAddress.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpRedirectAddress.java
new file mode 100644 (file)
index 0000000..a5f2bc7
--- /dev/null
@@ -0,0 +1,57 @@
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.UnknownHostException;
+
+/**
+ * PDP Redirect Address (RFC 2748 pg. 15)
+ *
+ * A PDP when closing a PEP session for a particular client-type may
+ optionally use this object to redirect the PEP to the specified PDP
+ server address and TCP port number:
+ *
+ * C-Num = 13,
+ *
+ * C-Type = 1, IPv4 Address (Same format as PDPRedirAddr)
+ *
+ * C-Type = 2, IPv6 Address (Same format as PDPRedirAddr)
+ */
+public final class COPSIpv6PdpRedirectAddress extends COPSIpv6PdpAddress {
+
+    /**
+     * Constructor generally used for sending messages
+     * @param host - the host name
+     * @param port - the associated port
+     * @param reserved - ???
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSIpv6PdpRedirectAddress(final String host, final int port, final short reserved) throws UnknownHostException {
+        super(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), host, port, reserved);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param objHdr - the object header
+     * @param addr - the byte array representation of a host
+     * @param tcpPort - the associated port
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSIpv6PdpRedirectAddress(final COPSObjHeader objHdr, final byte[] addr, final int tcpPort,
+                                         final short reserved) {
+        super(objHdr, addr, tcpPort, reserved);
+        if (!objHdr.getCNum().equals(CNum.PDP_REDIR))
+            throw new IllegalArgumentException("CNum must be equal to - " + CNum.PDP_REDIR);
+    }
+
+    @Override
+    public void dumpBody(OutputStream os) throws IOException {
+        os.write(("Ipv6PdpRedirectAddress" + "\n").getBytes());
+        super.dumpBody(os);
+    }
+
+}
index a640be61bbfdc0bd731028d926e96500fc87e5e7..ab4ccbae49bf4a5a77712755edfb67e96b91885a 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Keep Alive Message\r
- *\r
- * @version COPSKAMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSKAMsg extends COPSMsg {\r
-\r
-    /* COPSHeader coming from base class */\r
-    private COPSIntegrity  _integrity;\r
-\r
-    public COPSKAMsg() {\r
-        _integrity = null;\r
-    }\r
-\r
-    protected COPSKAMsg(byte[] data) throws COPSException {\r
-        _integrity = null;\r
-        parse(data);\r
-    }\r
-\r
-    /** Checks the sanity of COPS message and throw an\r
-      * COPSBadDataException when data is bad.\r
-      */\r
-    public void checkSanity() throws COPSException {\r
-        //The client type in the header MUST always be set to 0\r
-        //as KA is used for connection verification.RFC 2748\r
-        if ((_hdr == null) && (_hdr.getClientType() != 0))\r
-            throw new COPSException("Bad message format");\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_KA)\r
-            throw new COPSException ("Error Header (no COPS_OP_KA)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Integrity objects\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has Integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    };\r
-\r
-    /**\r
-     * Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return (_integrity);\r
-    }\r
-\r
-    /**\r
-     * Writes data to given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        super.parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-            case MSG_INTEGRITY:\r
-                _integrity = new COPSIntegrity(buf);\r
-                _dataStart += _integrity.getDataLength();\r
-                break;\r
-            default: {\r
-                throw new COPSException("Bad Message format, unknown object type");\r
-            }\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data)     throws COPSException {\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_KA)\r
-            throw new COPSException("Error Header");\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    private void setMsgLength() throws COPSException {\r
-        short len = 0;\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Keep Alive Message (RFC 2748 pg. 27)
+ *
+ * The keep-alive message MUST be transmitted by the PEP within the
+ * period defined by the minimum of all KA Timer values specified in all
+ * received CAT messages for the connection. A KA message MUST be
+ * generated randomly between 1/4 and 3/4 of this minimum KA timer
+ * interval. When the PDP receives a keep-alive message from a PEP, it
+ * MUST echo a keep-alive back to the PEP. This message provides
+ * validation for each side that the connection is still functioning
+ * even when there is no other messaging.
+ *
+ * Note: The client-type in the header MUST always be set to 0 as the KA
+ * is used for connection verification (not per client session
+ * verification).
+ *
+ * <Keep-Alive>  ::= <Common Header>
+ * [<Integrity>]
+ * Both client and server MAY assume the TCP connection is insufficient
+ * for the client-type with the minimum time value (specified in the CAT
+ * message) if no communication activity is detected for a period
+ * exceeding the timer period. For the PEP, such detection implies the
+ * remote PDP or connection is down and the PEP SHOULD now attempt to
+ * use an alternative/backup PDP.
+ */
+public class COPSKAMsg extends COPSMsg {
+
+    // Optional
+    private final COPSIntegrity  _integrity;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSKAMsg(final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.KA, (short)0), integrity);
+    }
+
+    /**
+     * Constructor (generally used for sending messages).
+     * @param version - the supported PCMM Version
+     * @param flag - the flag...
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSKAMsg(final int version, final Flag flag, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.KA, (short)0), integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSKAMsg(final COPSHeader hdr, final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.KA))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.KA);
+        if (hdr.getClientType() != 0) throw new IllegalArgumentException("Client type must be 0");
+        _integrity = integrity;
+    }
+
+    // Getter
+    public COPSIntegrity getIntegrity() {
+        return (_integrity);
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected int getDataLength() {
+        if (_integrity != null) return _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        else return 0;
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        if (_integrity != null) _integrity.dump(os);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSKAMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSKAMsg copskaMsg = (COPSKAMsg) o;
+
+        return !(_integrity != null ? !_integrity.equals(copskaMsg._integrity) : copskaMsg._integrity != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSDecisionMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSKAMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSIntegrity integrity = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSKAMsg(hdrData.header, integrity);
+    }
+
+}
+
+
+
+
+
+
index 86db031157803842bf41a7fa26e91b72ac0d4468..afb24af306f35d896b4a8171b0cf78faf3262f27 100644 (file)
@@ -1,45 +1,81 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-/**\r
- * COPS Keep Alive Timer\r
- *\r
- * @version COPSKATimer.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSKATimer extends COPSTimer {\r
-\r
-    public COPSKATimer() {\r
-        super(new COPSObjHeader(CNum.KA, CType.DEF), (short) 1);\r
-    }\r
-\r
-    ///\r
-    public COPSKATimer(short timeVal) {\r
-        super(new COPSObjHeader(CNum.KA, CType.DEF), timeVal);\r
-    }\r
-\r
-    /**\r
-     * Method isKATimer\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isKATimer() {\r
-        return true;\r
-    }\r
-\r
-    protected COPSKATimer(byte[] dataPtr) {\r
-        super (dataPtr);\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS Keep Alive Timer (RFC 2748)
+ *
+ * Times are encoded as 2 octet integer values and are in units of
+ * seconds.  The timer value is treated as a delta.
+ *
+ * C-Num = 10,
+ *
+ * C-Type = 1, Keep-alive timer value
+ * Timer object used to specify the maximum time interval over which a
+ * COPS message MUST be sent or received. The range of finite timeouts
+ * is 1 to 65535 seconds represented as an unsigned two-octet integer.
+ * The value of zero implies infinity.
+ */
+public class COPSKATimer extends COPSTimer {
+
+    /**
+     * Constructor generally used for sending messages
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSKATimer(final short timeVal) {
+        this((short)0, timeVal);
+    }
+
+    /**
+     * Constructor to override the reserved member value from 0
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSKATimer(final short reserved, final short timeVal) {
+        this(new COPSObjHeader(CNum.KA, CType.DEF), reserved, timeVal);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param reserved - ???
+     * @param timeVal - the timer value
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSKATimer(final COPSObjHeader hdr, final short reserved, final short timeVal) {
+        super(hdr, reserved, timeVal);
+        if (!hdr.getCNum().equals(CNum.KA))
+            throw new IllegalArgumentException("Invalid CNum value. Must be " + CNum.KA);
+        if (!hdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Invalid CType value. Must be " + CType.DEF);
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSKATimer parse(final COPSObjHeaderData objHdrData, byte[] dataPtr) {
+        short reserved = 0;
+        reserved |= ((short) dataPtr[4]) << 8;
+        reserved |= ((short) dataPtr[5]) & 0xFF;
+
+        short timerValue = 0;
+        timerValue |= ((short) dataPtr[6]) << 8;
+        timerValue |= ((short) dataPtr[7]) & 0xFF;
+
+        return new COPSKATimer(objHdrData.header, reserved, timerValue);
+    }
+
+}
+
index 2fb4a5cda5ed865609e4dc8ab866c7ab944ee6a5..a06ed920faff5db2065fc8c039c9b4e2ee02d78a 100644 (file)
@@ -1,48 +1,69 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-\r
-\r
-/**\r
- * COPS LPDP Decision Object\r
- *\r
- * @version COPSLPDPDecision.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSLPDPDecision extends COPSDecision {\r
-\r
-    /**\r
-      Constructor to create a Local Decision object.\r
-     */\r
-    public COPSLPDPDecision(byte cType) {\r
-        super (cType);\r
-// TODO - FIXME later, currently not in use and the header is now immutable\r
-//        _objHdr.setCNum(COPSObjHeader.COPS_LPDP_DEC);\r
-    }\r
-\r
-    public COPSLPDPDecision() {\r
-        super ();\r
-// TODO - FIXME later, currently not in use and the header is now immutable\r
-//        _objHdr.setCNum(COPSObjHeader.COPS_LPDP_DEC);\r
-    }\r
-\r
-    /**\r
-     * Method isLocalDecision\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isLocalDecision() {\r
-        return true;\r
-    }\r
-\r
-    protected COPSLPDPDecision(byte[] data) {\r
-        super (data);\r
-    }\r
-\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+/**
+ * COPS LPDP Decision Object (local decision) (RFC 2748)
+ *
+ * Decision made by the PEP's local policy decision point (LPDP). May
+ * appear in requests. These objects correspond to and are formatted the
+ * same as the client specific decision objects defined above.
+ *
+ * C-Num = 7
+ *
+ * C-Type = (same C-Type as for Decision objects)
+ */
+public class COPSLPDPDecision extends COPSDecision {
+
+    /**
+     * Constructor generally used for sending messages with a specific, CType, Command and DecisionFlag
+     * @param cType - the CType
+     * @param cmdCode - the command
+     * @param flags - the flags
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSLPDPDecision(final CType cType, final Command cmdCode, final DecisionFlag flags, final COPSData data) {
+        this(new COPSObjHeader(CNum.LPDP_DEC, cType), cmdCode, flags, data);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param cmdCode - the command
+     * @param flags - the flags
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSLPDPDecision(final COPSObjHeader hdr, final Command cmdCode, final DecisionFlag flags,
+                               final COPSData data) {
+        super(hdr, cmdCode, flags, data);
+
+        if (!hdr.getCNum().equals(CNum.LPDP_DEC))
+            throw new IllegalArgumentException("Invalid CNum value. Must be " + CNum.LPDP_DEC);
+    }
+
+    /**
+     * Parses bytes to return a COPSLPDPDecision object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSLPDPDecision parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        final COPSObjHeader tempHdr = new COPSObjHeader(CNum.DEC, objHdrData.header.getCType());
+        final COPSObjHeaderData tempObjHdrData = new COPSObjHeaderData(tempHdr, objHdrData.msgByteCount);
+        final COPSDecision decision = COPSDecision.parse(tempObjHdrData, dataPtr);
+        return new COPSLPDPDecision(objHdrData.header, decision.getCommand(), decision.getFlag(), decision.getData());
+    }
+
+}
index 2c492f38a8eadc31e8093d72b8fc207822985982..ee7b10a2d39a04377aa568c7ce8e453a2ddb060d 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Message\r
- *\r
- * @version COPSMsg.java, v 1.00 2003\r
- *\r
- */\r
-abstract public class COPSMsg {\r
-\r
-    protected COPSHeader _hdr;\r
-    protected int _dataLength;\r
-    protected int _dataStart;\r
-\r
-    /**\r
-     * Method getHeader\r
-     *\r
-     * @return   a COPSHeader\r
-     *\r
-     */\r
-    public COPSHeader getHeader() {\r
-        return _hdr;\r
-    }\r
-\r
-    /**\r
-     * Method writeData\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public abstract void writeData(Socket id) throws IOException;\r
-\r
-    /**\r
-     * Method getMsgLength\r
-     *\r
-     * @return   an int\r
-     *\r
-     */\r
-    public int getMsgLength() {\r
-        return _hdr.getMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected abstract void parse(COPSHeader hdr, byte[] data) throws COPSException;\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected abstract void parse(byte[] data) throws COPSException;\r
-\r
-    /**\r
-     * Method parseHeader\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parseHeader(byte[] data) throws COPSException {\r
-        _dataLength = 0;\r
-        _dataStart = 0;\r
-        if (_hdr == null) {\r
-            // _hdr = new COPSHeader(COPSHeader.COPS_OP_CAT);\r
-            _hdr = new COPSHeader(data);\r
-            _dataStart += 8;\r
-            _dataLength = _hdr.getMsgLength();\r
-        } else {\r
-            //header is already read\r
-            _dataLength = _hdr.getMsgLength() - 8;\r
-        }\r
-\r
-        //validate the message length\r
-        //Should fill on the 32bit boundary\r
-        if ((_hdr.getMsgLength() % 4 != 0)) {\r
-            throw new COPSException("Bad message format: COPS message is not on 32 bit bounday");\r
-        }\r
-    }\r
-\r
-    /** Checks the sanity of COPS message and throw an\r
-         COPSBadDataException when data is bad.\r
-    */\r
-    public abstract void checkSanity()throws COPSException;\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        os.write(new String("COPS Message").getBytes());\r
-    }\r
-\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Represents messages coming from and going to a COPS device such as a CMTS
+ */
+abstract public class COPSMsg {
+
+    private static final Logger logger = LoggerFactory.getLogger(COPSMsg.class);
+
+    /**
+     * The COPS header that is associated with all COPS messages
+     */
+    private final COPSHeader _hdr;
+
+    /**
+     * Base constructor
+     * @param hdr - the header
+     */
+    public COPSMsg(final COPSHeader hdr) {
+        if (hdr == null) throw new IllegalArgumentException("Header must not be null");
+        this._hdr = hdr;
+    }
+    /**
+     * Returns the message header object
+     * @return   a COPSHeader
+     */
+    public COPSHeader getHeader() {
+        return _hdr;
+    }
+
+    /**
+     * Method writeData. Implementers should be calling super.writeData() for the header prior to writing out the rest.
+     * @param    socket                  a  Socket
+     * @throws   IOException
+     */
+    public final void writeData(final Socket socket) throws IOException {
+        logger.info("Writing data for OPCode - " + _hdr.getOpCode());
+        _hdr.writeData(socket, _hdr.getHdrLength() + getDataLength());
+        writeBody(socket);
+    }
+
+    /**
+     * Returns the number of bytes to be contained within the payload excluding the header
+     * @return - a positive value including the header size
+     */
+    protected abstract int getDataLength();
+
+    /**
+     * Writes out the body data over a socket
+     * @param socket - the socket to which to write
+     */
+    protected abstract void writeBody(Socket socket) throws IOException;
+
+    /**
+     * Write an object textual description in the output stream
+     * @param    os                  an OutputStream
+     * @throws   IOException
+     */
+    final public void dump(final OutputStream os) throws IOException {
+        _hdr.dump(os);
+        dumpBody(os);
+    }
+
+    /**
+     * Creates a string representation of this object and sends it to an output stream
+     * @param os - the output stream
+     * @throws IOException
+     */
+    protected abstract void dumpBody(final OutputStream os) throws IOException;
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSMsg)) {
+            return false;
+        }
+
+        final COPSMsg copsMsg = (COPSMsg) o;
+
+        return _hdr.equals(copsMsg._hdr);
+
+    }
+
+    @Override
+    public int hashCode() {
+        return _hdr.hashCode();
+    }
+}
index 04a4aff51c70be4196fc7be3d0de60f78b0029ae..84279912d9ee4b888db90f82c1f944ed09d836e3 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-/**\r
- * COPS Message Parser\r
- *\r
- * @version COPSMsgParser.java, v 1.00 2003\r
- *\r
- */\r
-\r
-// import org.umu.cops.common.COPSDebug;\r
-\r
-public class COPSMsgParser {\r
-    ///\r
-    public COPSMsgParser() {\r
-\r
-    }\r
-\r
-    /** Parses the given COPS data and returns a COPSMsg object\r
-     *     with COPS object filed in.The COPSMsg object is allocated in the\r
-     *     call and it is the responsibility of the caller to free the memory\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @return   a COPSMsg\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public COPSMsg parse(byte[] data) throws COPSException {\r
-        COPSHeader hdr = new COPSHeader(data);\r
-\r
-        byte[] buf = new byte[data.length - 8];\r
-        System.arraycopy(data,8,buf,0,data.length - 8);\r
-\r
-        return (parse(hdr, buf));\r
-    }\r
-\r
-    /**\r
-     * Parse the message with given header , the data is pointing\r
-     * to the data following the header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @return   a COPSMsg\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public COPSMsg parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        COPSMsg copsMsg = null;\r
-        short cCode = hdr.getOpCode();\r
-        switch (cCode) {\r
-        case COPSHeader.COPS_OP_REQ: {\r
-            // COPSDebug.out(getClass().getName(), "Creating REQ msg");\r
-            copsMsg = new COPSReqMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_DEC: {\r
-            // COPSDebug.out(getClass().getName(), "Creating DEC msg");\r
-            copsMsg = new COPSDecisionMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_RPT: {\r
-            // COPSDebug.out(getClass().getName(), "Creating RPT msg");\r
-            copsMsg = new COPSReportMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_DRQ: {\r
-            // COPSDebug.out(getClass().getName(), "Creating DRQ msg");\r
-            copsMsg = new COPSDeleteMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_OPN: {\r
-            // COPSDebug.out(getClass().getName(), "Creating Client-Open msg");\r
-            copsMsg = new COPSClientOpenMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_CAT: {\r
-            // COPSDebug.out(getClass().getName(), "Creating Client-Accept msg");\r
-            copsMsg = new COPSClientAcceptMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_CC: {\r
-            // COPSDebug.out(getClass().getName(), "Creating Client-Close msg");\r
-            copsMsg = new COPSClientCloseMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_KA: {\r
-            // COPSDebug.out(getClass().getName(), "Creating KA msg");\r
-            copsMsg = new COPSKAMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_SSQ: {\r
-            // COPSDebug.out(getClass().getName(), "Creating Sync-State Request msg");\r
-            copsMsg = new COPSSyncStateMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        case COPSHeader.COPS_OP_SSC: {\r
-            // COPSDebug.out(getClass().getName(), "Creating Sync-State Complete msg");\r
-            copsMsg = new COPSSyncStateMsg();\r
-            copsMsg.parse(hdr, data);\r
-        }\r
-        break;\r
-        default:\r
-            // COPSDebug.out(getClass().getName(), "Unknown message type");\r
-            break;\r
-        }\r
-\r
-\r
-        // if(copsMsg != null)\r
-        //     try { copsMsg.dump(COPSDebug.out); } catch (Exception e) {};\r
-\r
-        return copsMsg;\r
-    }\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.util.Date;
+
+/**
+ * Utility for parsing COPS messages obtained from a Socket connection
+ */
+
+public class COPSMsgParser {
+
+    public final static Logger logger = LoggerFactory.getLogger(COPSMsgParser.class);
+
+    /**
+     * Transforms a COPS message streaming in from a Socket connection into a COPSMsg object
+     * @param socket - the socket
+     * @return - an implementation of the abstract COPSMsg object
+     * @throws IOException
+     * @throws COPSException
+     */
+    public static COPSMsg parseMessage(final Socket socket) throws IOException, COPSException {
+        final COPSHeaderData hdrData = readHeader(socket);
+        return readBody(socket, hdrData);
+    }
+
+
+    /**
+     * Unmarshalls the COPS Header data from the bytes received on the Socket
+     * @param socket - the socket
+     * @return - the header data
+     * @throws IOException
+     */
+    private static COPSHeaderData readHeader(final Socket socket) throws IOException {
+        logger.info("Reading COPS Header");
+        final byte[] data = new byte[8];
+        final int bytesRead = readData(socket, data, 8);
+        if (bytesRead != 8) throw new IOException("Expected 8 bytes, read in " + bytesRead);
+
+        final byte[] vFlagsNibbles = splitByteToNibbles(data[0]);
+        byte version = vFlagsNibbles[0];
+        final Flag flag;
+        if (vFlagsNibbles[1] == 1) flag = Flag.SOLICITED; else flag = Flag.UNSOLICITED;
+
+        final OPCode opCode;
+        if (COPSHeader.VAL_TO_OP.get((int)data[1]) == null) opCode = OPCode.NA;
+        else opCode = COPSHeader.VAL_TO_OP.get((int)data[1]);
+
+        short cType = bytesToShort(data[2], data[3]);
+
+        int msgLength = ((short) data[4]) << 24;
+        msgLength |= ((short) data[5]) << 16;
+        msgLength |= ((short) data[6]) << 8;
+        msgLength |= ((short) data[7]) & 0xFF;
+
+        return new COPSHeaderData(new COPSHeader(version, flag, opCode, cType), msgLength);
+    }
+
+    /**
+     * Takes a short value and splits it into 2 bytes
+     * @param val - the value to split
+     * @return - a 2 byte array
+     */
+    public static byte[] shortToBytes(final short val) {
+        final byte[] out = new byte[2];
+        out[0] = (byte) (val >> 8);
+        out[1] = (byte) val;
+        return out;
+    }
+
+    /**
+     * Takes two bytes and concatenates the two into a short value
+     * @param byte1 - the first byte
+     * @param byte2 - the training byte
+     * @return - the short value
+     */
+    public static short bytesToShort(final byte byte1, final byte byte2) {
+        short out = 0;
+        out |= ((short) byte1) << 8;
+        out |= ((short) byte2) & 0xFF;
+        return out;
+    }
+
+    private static COPSMsg readBody(final Socket socket, final COPSHeaderData hdrData) throws IOException, COPSException {
+        logger.info("Reading COPS Body of type - " + hdrData.header.getOpCode());
+        final int expectedBytes = hdrData.msgByteCount - hdrData.header.getHdrLength();
+        final byte[] buffer = new byte[expectedBytes];
+        final int nread = readData(socket, buffer, expectedBytes);
+//        buffer[expectedBytes] = (byte) '\0';
+        if (nread != expectedBytes) {
+            throw new COPSException("Bad COPS message");
+        }
+        return parse(hdrData, buffer);
+    }
+
+    /**
+     * Reads nchar from a given sockets, blocks on read untill nchar are read of conenction has error
+     * bRead returns the bytes read.
+     * @param    socket              a  Socket
+     * @param    dataRead            a  byte[] - this array should be initialized to the proper size but is then
+     *                               populated by reference
+     * @param    nchar               an int
+     * @return   an int
+     * @throws   IOException
+     */
+    public static int readData(final Socket socket, final byte[] dataRead, final int nchar)  throws IOException {
+        final InputStream input = socket.getInputStream();
+        int nread = 0;
+        int startTime = (int) (new Date().getTime());
+        do {
+            if (input.available() != 0) {
+                nread += input.read(dataRead, nread, nchar-nread);
+                startTime = (int) (new Date().getTime());
+            } else {
+                int nowTime = (int) (new Date().getTime());
+                // Read Timeout - TODO - May want to make this configurable
+                if ((nowTime - startTime) > 2000)
+                    break;
+            }
+        } while (nread != nchar);
+        return nread;
+    }
+    /**
+     * Parse the message with given header , the data is pointing
+     * to the data following the header
+     * @param    hdrData - contains the header and the
+     * @param    data                a  byte[]
+     * @return   a COPSMsg
+     * @throws   COPSException
+     */
+    private static COPSMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        final OPCode cCode = hdrData.header.getOpCode();
+        switch (cCode) {
+            case REQ:
+                return COPSReqMsg.parse(hdrData, data);
+            case DEC:
+                return COPSDecisionMsg.parse(hdrData, data);
+            case RPT:
+                return COPSReportMsg.parse(hdrData, data);
+            case DRQ:
+                return COPSDeleteMsg.parse(hdrData, data);
+            case OPN:
+                return COPSClientOpenMsg.parse(hdrData, data);
+            case CAT:
+                return COPSClientAcceptMsg.parse(hdrData, data);
+            case CC:
+                return COPSClientCloseMsg.parse(hdrData, data);
+            case KA:
+                return COPSKAMsg.parse(hdrData, data);
+            case SSQ:
+            case SSC:
+                return COPSSyncStateMsg.parse(hdrData, data);
+            default:
+                throw new COPSException("Unsupported client code");
+        }
+    }
+
+    /**
+     * Builds two nibbles represented as bytes from a single byte. Each nibble returned must not be > 15
+     * @param b the byte to divide into nibbles
+     * @return two bytes where the first represents bits 1-4 and second represents bits 5-8
+     */
+    public static byte[] splitByteToNibbles(final byte b) {
+        return new byte[]{
+                //move the four high bits to the right,
+                //fill up with zeros
+                (byte)(b >>> 4 & 0xF),
+                //zero out the four high bits and leave
+                //the low bits untouched
+                (byte)(b & 0x0F)
+        };
+    }
+
+    /**
+     * Combines two bytes representing a nibble into a single byte
+     * @param byte1 - nibble #1 (0-15)
+     * @param byte2 - nibble #2 (0-15)
+     * @return - one byte representing both nibbles
+     * @throws java.lang.IllegalArgumentException if either value is < 0 || > 15
+     */
+    public static int combineNibbles(final byte byte1, final byte byte2) {
+        if (byte1 > 15 || byte1 < 0 || byte2 > 15 || byte2 < 0)
+            throw new IllegalArgumentException("Each byte representing a nibble shall not exceed 15 (0xf)");
+        return (byte1 << 4) | byte2;
+    }
+
+}
+
+
index ecdd39a75ce14718f9a38182bd537aaab8a5d515..220a273c265b46e187fdd0a22516f0b8f58820f3 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-import java.util.Arrays;\r
-\r
-/**\r
- * COPS Object\r
- *\r
- * TODO - this should be an interface and all of these default return values can be dangerous\r
- * @version COPSObjBase.java, v 1.00 2003\r
- *\r
- */\r
-public abstract class COPSObjBase {\r
-    /**\r
-     * Add padding in the data, if the data does not fall on 32-bit boundary\r
-     * @param    len                 an int\r
-     * @return   a COPSData\r
-     */\r
-    static COPSData getPadding(final int len) {\r
-        byte[] padBuf = new byte[len];\r
-        Arrays.fill(padBuf, (byte) 0);\r
-        return new COPSData(padBuf, 0, len);\r
-    }\r
-\r
-    /**\r
-     * Writes data to a given network _socket\r
-     * @param    id                  a  Socket\r
-     * @throws   IOException\r
-     */\r
-    public abstract void writeData(Socket id) throws IOException;\r
-\r
-    /**\r
-     * Method getDataLength\r
-     * @return   a short\r
-     */\r
-    short getDataLength() {\r
-        return 0;\r
-    }\r
-\r
-    /**\r
-     * Method isCOPSHeader\r
-     * @return   a boolean\r
-     */\r
-    boolean isCOPSHeader() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isClientHandle\r
-     * @return   a boolean\r
-     */\r
-    boolean isClientHandle() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isContext\r
-     * @return   a boolean\r
-     */\r
-    boolean isContext() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isInterface\r
-     * @return   a boolean\r
-     */\r
-    boolean isInterface() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isDecision\r
-     * @return   a boolean\r
-     */\r
-    boolean isDecision() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isLocalDecision\r
-     * @return   a boolean\r
-     */\r
-    boolean isLocalDecision() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isReport\r
-     * @return   a boolean\r
-     */\r
-    boolean isReport() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isError\r
-     * @return   a boolean\r
-     */\r
-    boolean isError() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isTimer\r
-     * @return   a boolean\r
-     */\r
-    boolean isTimer() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isPepId\r
-     * @return   a boolean\r
-     */\r
-    boolean isPepId() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isReason\r
-     * @return   a boolean\r
-     */\r
-    boolean isReason() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isPdpAddress\r
-     * @return   a boolean\r
-     */\r
-    boolean isPdpAddress() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isClientSI\r
-     * @return   a boolean\r
-     */\r
-    boolean isClientSI() {\r
-        return false;\r
-    }\r
-\r
-    /**\r
-     * Method isMessageIntegrity\r
-     * @return   a boolean\r
-     */\r
-    boolean isMessageIntegrity() {\r
-        return false;\r
-    }\r
-\r
-}\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Represents objects that can be contained within COPS messages.
+ */
+public abstract class COPSObjBase {
+
+    /**
+     * Generally used to determine the type of message
+     */
+    private final COPSObjHeader _objHdr;
+
+    /**
+     * The base object constructor
+     * @param objHdr - the header (required)
+     */
+    public COPSObjBase(final COPSObjHeader objHdr) {
+        if (objHdr == null) throw new IllegalArgumentException("Object header must not be null");
+        this._objHdr = objHdr;
+    }
+
+    /**
+     * Returns the header
+     * @return - the header
+     */
+    public COPSObjHeader getHeader() { return _objHdr; }
+
+    /**
+     * Writes data to a given network _socket
+     * @param    socket                  a  Socket
+     * @throws   IOException
+     */
+    final public void writeData(final Socket socket) throws IOException {
+        _objHdr.writeData(socket, getDataLength());
+        writeBody(socket);
+    }
+
+    protected abstract void writeBody(Socket socket) throws IOException;
+
+    /**
+     * Returns the length of the body data to be output (not including header)
+     * @return   a short
+     */
+    protected abstract int getDataLength();
+
+    /**
+     * Write an object textual description in the output stream
+     * @param    os                  an OutputStream
+     * @throws   IOException
+     */
+    final public void dump(final OutputStream os) throws IOException {
+        _objHdr.dump(os);
+        dumpBody(os);
+    }
+
+    protected abstract void dumpBody(OutputStream os) throws IOException;
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSObjBase)) {
+            return false;
+        }
+
+        final COPSObjBase that = (COPSObjBase) o;
+        return _objHdr.equals(that._objHdr);
+    }
+
+    @Override
+    public int hashCode() {
+        return _objHdr.hashCode();
+    }
+}
index d3b580e12403eeafec9a448e836af89266a40643..971c0b0ee999030507ac3e86c1750126da1c4e7d 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-import java.util.Map;\r
-import java.util.concurrent.ConcurrentHashMap;\r
-\r
-/**\r
- * COPS Object Header\r
- *\r
- * @version COPSObjHeader.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSObjHeader  {\r
-\r
-    static Map<Integer, CNum> VAL_TO_CNUM = new ConcurrentHashMap<>();\r
-    static {\r
-        VAL_TO_CNUM.put(CNum.NA.ordinal(), CNum.NA);\r
-        VAL_TO_CNUM.put(CNum.HANDLE.ordinal(), CNum.HANDLE);\r
-        VAL_TO_CNUM.put(CNum.CONTEXT.ordinal(), CNum.CONTEXT);\r
-        VAL_TO_CNUM.put(CNum.ININTF.ordinal(), CNum.ININTF);\r
-        VAL_TO_CNUM.put(CNum.OUTINTF.ordinal(), CNum.OUTINTF);\r
-        VAL_TO_CNUM.put(CNum.REASON_CODE.ordinal(), CNum.REASON_CODE);\r
-        VAL_TO_CNUM.put(CNum.DEC.ordinal(), CNum.DEC);\r
-        VAL_TO_CNUM.put(CNum.LPDP_DEC.ordinal(), CNum.LPDP_DEC);\r
-        VAL_TO_CNUM.put(CNum.ERROR.ordinal(), CNum.ERROR);\r
-        VAL_TO_CNUM.put(CNum.CSI.ordinal(), CNum.CSI);\r
-        VAL_TO_CNUM.put(CNum.KA.ordinal(), CNum.KA);\r
-        VAL_TO_CNUM.put(CNum.PEPID.ordinal(), CNum.PEPID);\r
-        VAL_TO_CNUM.put(CNum.RPT.ordinal(), CNum.RPT);\r
-        VAL_TO_CNUM.put(CNum.PDP_REDIR.ordinal(), CNum.PDP_REDIR);\r
-        VAL_TO_CNUM.put(CNum.LAST_PDP_ADDR.ordinal(), CNum.LAST_PDP_ADDR);\r
-        VAL_TO_CNUM.put(CNum.ACCT_TIMER.ordinal(), CNum.ACCT_TIMER);\r
-        VAL_TO_CNUM.put(CNum.MSG_INTEGRITY.ordinal(), CNum.MSG_INTEGRITY);\r
-    }\r
-\r
-    static Map<Integer, CType> VAL_TO_CTYPE = new ConcurrentHashMap<>();\r
-    static {\r
-        VAL_TO_CTYPE.put(CType.NA.ordinal(), CType.NA);\r
-        VAL_TO_CTYPE.put(CType.DEF.ordinal(), CType.DEF);\r
-        VAL_TO_CTYPE.put(CType.STATELESS.ordinal(), CType.STATELESS);\r
-        VAL_TO_CTYPE.put(CType.REPL.ordinal(), CType.REPL);\r
-        VAL_TO_CTYPE.put(CType.CSI.ordinal(), CType.CSI);\r
-        VAL_TO_CTYPE.put(CType.NAMED.ordinal(), CType.NAMED);\r
-    }\r
-\r
-    /**\r
-     * Denotes the type of COPSMsg\r
-     */\r
-    private final CNum _cNum;\r
-\r
-    /**\r
-     * Subtype or version of the information.\r
-     */\r
-    private final CType _cType;\r
-\r
-    /**\r
-     * TODO - remove this attribute as the body of the COPS message should return the body length\r
-     */\r
-    @Deprecated\r
-    private short _len;\r
-\r
-    /**\r
-     * Constructor\r
-     * @param cNum - the cNum value\r
-     * @param cType - the cType value\r
-     * @throws java.lang.IllegalArgumentException\r
-     */\r
-    public COPSObjHeader(final CNum cNum, final CType cType) {\r
-        if (cNum == null || cType == null) throw new IllegalArgumentException("CNum and CType must not be null");\r
-        _cNum = cNum;\r
-        _cType = cType;\r
-        _len = 4;\r
-    }\r
-\r
-    /**\r
-     * Get the data length in number of octets\r
-     * @return   a short\r
-     */\r
-    public short getHdrLength() {\r
-        return (short)4;\r
-    }\r
-\r
-    /**\r
-     * Get the class information identifier cNum\r
-     * @return   a byte\r
-     */\r
-\r
-    public CNum getCNum() {\r
-        return _cNum;\r
-    }\r
-\r
-    /**\r
-     * Get the type per cNum\r
-     * @return   a byte\r
-     */\r
-    public CType getCType() {\r
-        return _cType;\r
-    }\r
-\r
-    /**\r
-     * Get stringified CNum\r
-     * @return   a String\r
-     */\r
-    public String getStrCNum() {\r
-        switch (_cNum) {\r
-            case HANDLE:\r
-                return ("Client-handle");\r
-            case CONTEXT:\r
-                return ("Context");\r
-            case ININTF:\r
-                return ("In-Interface");\r
-            case OUTINTF:\r
-                return ("Out-Interface");\r
-            case REASON_CODE:\r
-                return ("Reason");\r
-            case DEC:\r
-                return ("Decision");\r
-            case LPDP_DEC:\r
-                return ("Local-Decision");\r
-            case ERROR:\r
-                return ("Error");\r
-            case CSI:\r
-                return ("Client-SI");\r
-            case KA:\r
-                return ("KA-timer");\r
-            case PEPID:\r
-                return ("PEP-id");\r
-            case RPT:\r
-                return ("Report");\r
-            case PDP_REDIR:\r
-                return ("Redirect PDP addr");\r
-            case LAST_PDP_ADDR:\r
-                return ("Last PDP addr");\r
-            case ACCT_TIMER:\r
-                return ("Account-Timer");\r
-            case MSG_INTEGRITY:\r
-                return ("Message-Integrity");\r
-            default:\r
-                return ("Unknown");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Set the obj length, the length is the length of the data following\r
-     * the object header.The length of the object header (4 bytes) is added\r
-     * to the length passed.\r
-     *\r
-     * TODO - The data length will be removed from the header in a subsequent patch\r
-     *\r
-     * @param    len                 a  short\r
-     */\r
-    @Deprecated\r
-    public void setDataLength(short len) {\r
-        //Add the length of the header also\r
-        _len = (short) (len + 4);\r
-    }\r
-\r
-    /**\r
-     * Get the data length in number of octets\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        return _len;\r
-    }\r
-\r
-    /**\r
-     * Writes data to a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        byte[] buf = new byte[4];\r
-\r
-        buf[0] = (byte) (_len >> 8);\r
-        buf[1] = (byte) _len;\r
-        buf[2] = (byte) _cNum.ordinal();\r
-        buf[3] = (byte) _cType.ordinal();\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     * @param    os                  an OutputStream\r
-     * @throws   IOException\r
-     */\r
-    public void dump(final OutputStream os) throws IOException {\r
-        os.write(("**" + getStrCNum() + "**" + "\n").getBytes());\r
-        os.write(("C-num: " + _cNum + "\n").getBytes());\r
-        os.write(("C-type: " + _cType + "\n").getBytes());\r
-    }\r
-\r
-    @Override\r
-    public boolean equals(Object o) {\r
-        if (this == o) {\r
-            return true;\r
-        }\r
-        if (!(o instanceof COPSObjHeader)) {\r
-            return false;\r
-        }\r
-\r
-        final COPSObjHeader header = (COPSObjHeader) o;\r
-\r
-        return _cNum == header._cNum && _cType == header._cType;\r
-\r
-    }\r
-\r
-    @Override\r
-    public int hashCode() {\r
-        int result = _cNum.hashCode();\r
-        result = 31 * result + _cType.hashCode();\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * Method parse\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     */\r
-    public final static COPSObjHeader parse(byte[] data) {\r
-        short len = 0;\r
-        len = 0;\r
-        len |= ((short) data[0]) << 8;\r
-        len |= ((short) data[1]) & 0xFF;\r
-\r
-        int cNum = 0;\r
-        cNum |= data[2];\r
-\r
-        int cType = 0;\r
-        cType |= data[3];\r
-\r
-        final COPSObjHeader hdr = new COPSObjHeader(VAL_TO_CNUM.get(cNum), VAL_TO_CTYPE.get(cType));\r
-        hdr.setDataLength(len);\r
-        return hdr;\r
-    }\r
-\r
-    public enum CNum {\r
-        NA,\r
-        HANDLE,\r
-        CONTEXT,\r
-        ININTF,\r
-        OUTINTF,\r
-        REASON_CODE,\r
-        DEC,\r
-        LPDP_DEC,\r
-        ERROR,\r
-        CSI,\r
-        KA,\r
-        PEPID,\r
-        RPT,\r
-        PDP_REDIR,\r
-        LAST_PDP_ADDR,\r
-        ACCT_TIMER,\r
-        MSG_INTEGRITY,\r
-    }\r
-\r
-    public enum CType {\r
-        NA,\r
-        DEF,\r
-        STATELESS,\r
-        REPL,\r
-        CSI,\r
-        NAMED\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Object Header
+ *
+ * @version COPSObjHeader.java, v 1.00 2003
+ *
+ */
+public class COPSObjHeader  {
+
+    static Map<Integer, CNum> VAL_TO_CNUM = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_CNUM.put(CNum.NA.ordinal(), CNum.NA);
+        VAL_TO_CNUM.put(CNum.HANDLE.ordinal(), CNum.HANDLE);
+        VAL_TO_CNUM.put(CNum.CONTEXT.ordinal(), CNum.CONTEXT);
+        VAL_TO_CNUM.put(CNum.ININTF.ordinal(), CNum.ININTF);
+        VAL_TO_CNUM.put(CNum.OUTINTF.ordinal(), CNum.OUTINTF);
+        VAL_TO_CNUM.put(CNum.REASON_CODE.ordinal(), CNum.REASON_CODE);
+        VAL_TO_CNUM.put(CNum.DEC.ordinal(), CNum.DEC);
+        VAL_TO_CNUM.put(CNum.LPDP_DEC.ordinal(), CNum.LPDP_DEC);
+        VAL_TO_CNUM.put(CNum.ERROR.ordinal(), CNum.ERROR);
+        VAL_TO_CNUM.put(CNum.CSI.ordinal(), CNum.CSI);
+        VAL_TO_CNUM.put(CNum.KA.ordinal(), CNum.KA);
+        VAL_TO_CNUM.put(CNum.PEPID.ordinal(), CNum.PEPID);
+        VAL_TO_CNUM.put(CNum.RPT.ordinal(), CNum.RPT);
+        VAL_TO_CNUM.put(CNum.PDP_REDIR.ordinal(), CNum.PDP_REDIR);
+        VAL_TO_CNUM.put(CNum.LAST_PDP_ADDR.ordinal(), CNum.LAST_PDP_ADDR);
+        VAL_TO_CNUM.put(CNum.ACCT_TIMER.ordinal(), CNum.ACCT_TIMER);
+        VAL_TO_CNUM.put(CNum.MSG_INTEGRITY.ordinal(), CNum.MSG_INTEGRITY);
+    }
+
+    static Map<Integer, CType> VAL_TO_CTYPE = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_CTYPE.put(CType.NA.ordinal(), CType.NA);
+        VAL_TO_CTYPE.put(CType.DEF.ordinal(), CType.DEF);
+        VAL_TO_CTYPE.put(CType.STATELESS.ordinal(), CType.STATELESS);
+        VAL_TO_CTYPE.put(CType.REPL.ordinal(), CType.REPL);
+        VAL_TO_CTYPE.put(CType.CSI.ordinal(), CType.CSI);
+        VAL_TO_CTYPE.put(CType.NAMED.ordinal(), CType.NAMED);
+    }
+
+    /**
+     * Denotes the type of COPSMsg
+     */
+    private final CNum _cNum;
+
+    /**
+     * Subtype or version of the information.
+     */
+    private final CType _cType;
+
+    /**
+     * Constructor
+     * @param cNum - the cNum value
+     * @param cType - the cType value
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSObjHeader(final CNum cNum, final CType cType) {
+        if (cNum == null || cType == null) throw new IllegalArgumentException("CNum and CType must not be null");
+        _cNum = cNum;
+        _cType = cType;
+    }
+
+    /**
+     * Get the data length in number of octets
+     * @return   a short
+     */
+    public short getHdrLength() {
+        return (short)4;
+    }
+
+    /**
+     * Get the class information identifier cNum
+     * @return   a byte
+     */
+
+    public CNum getCNum() {
+        return _cNum;
+    }
+
+    /**
+     * Get the type per cNum
+     * @return   a byte
+     */
+    public CType getCType() {
+        return _cType;
+    }
+
+    /**
+     * Get stringified CNum
+     * @return   a String
+     */
+    public String getStrCNum() {
+        switch (_cNum) {
+            case HANDLE:
+                return ("Client-handle");
+            case CONTEXT:
+                return ("Context");
+            case ININTF:
+                return ("In-Interface");
+            case OUTINTF:
+                return ("Out-Interface");
+            case REASON_CODE:
+                return ("Reason");
+            case DEC:
+                return ("Decision");
+            case LPDP_DEC:
+                return ("Local-Decision");
+            case ERROR:
+                return ("Error");
+            case CSI:
+                return ("Client-SI");
+            case KA:
+                return ("KA-timer");
+            case PEPID:
+                return ("PEP-id");
+            case RPT:
+                return ("Report");
+            case PDP_REDIR:
+                return ("Redirect PDP addr");
+            case LAST_PDP_ADDR:
+                return ("Last PDP addr");
+            case ACCT_TIMER:
+                return ("Account-Timer");
+            case MSG_INTEGRITY:
+                return ("Message-Integrity");
+            default:
+                return ("Unknown");
+        }
+    }
+
+    /**
+     * Writes data to a given network _socket
+     * @param    socket                  a  Socket
+     * @throws   IOException
+     */
+    public void writeData(final Socket socket, final int dataLength) throws IOException {
+        final int payloadSize = + getHdrLength() + dataLength;
+        final byte[] buf = new byte[4];
+        buf[0] = (byte) (payloadSize >> 8);
+        buf[1] = (byte) payloadSize;
+        buf[2] = (byte)_cNum.ordinal();
+        buf[3] = (byte)_cType.ordinal();
+
+        COPSUtil.writeData(socket, buf, 4);
+    }
+
+    /**
+     * Write an object textual description in the output stream
+     * @param    os                  an OutputStream
+     * @throws   IOException
+     */
+    public void dump(final OutputStream os) throws IOException {
+        os.write(("**" + getStrCNum() + "**" + "\n").getBytes());
+        os.write(("C-num: " + _cNum + "\n").getBytes());
+        os.write(("C-type: " + _cType + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSObjHeader)) {
+            return false;
+        }
+
+        final COPSObjHeader header = (COPSObjHeader) o;
+
+        return _cNum == header._cNum && _cType == header._cType;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = _cNum.hashCode();
+        result = 31 * result + _cType.hashCode();
+        return result;
+    }
+
+    public enum CNum {
+        NA,
+        HANDLE,
+        CONTEXT,
+        ININTF,
+        OUTINTF,
+        REASON_CODE,
+        DEC,
+        LPDP_DEC,
+        ERROR,
+        CSI,
+        KA,
+        PEPID,
+        RPT,
+        PDP_REDIR,
+        LAST_PDP_ADDR,
+        ACCT_TIMER,
+        MSG_INTEGRITY,
+    }
+
+    public enum CType {
+        NA,
+        DEF,
+        STATELESS,
+        REPL,
+        CSI,
+        NAMED
+    }
+
+}
+
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeaderData.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeaderData.java
new file mode 100644 (file)
index 0000000..e4947d6
--- /dev/null
@@ -0,0 +1,30 @@
+package org.umu.cops.stack;
+
+/**
+ * Class designed for simply containing the COPSHeader and the total message's byte count.
+ *
+ * No need to test as this class will be tested implicitly via other tests and this does not contain or need
+ * any domain specific logic
+ */
+public class COPSObjHeaderData {
+
+    /**
+     * The actual header to be injected into the appropriate COPSMsg object
+     */
+    final public COPSObjHeader header;
+
+    /**
+     * The total number of bytes contained within the inbound message being parsed.
+     */
+    final public int msgByteCount;
+
+    /**
+     * Constructor
+     * @param hdr - the COPS message header
+     * @param numBytes - the total number of bytes contained within the message envelope
+     */
+    public COPSObjHeaderData(final COPSObjHeader hdr, final int numBytes) {
+        this.header = hdr;
+        this.msgByteCount = numBytes;
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjectParser.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjectParser.java
new file mode 100644 (file)
index 0000000..4684ee3
--- /dev/null
@@ -0,0 +1,71 @@
+package org.umu.cops.stack;
+
+import java.util.Arrays;
+
+/**
+ * Static utilitarian methods for parsing COPS objects contained within COPS messages.
+ */
+public class COPSObjectParser {
+
+    /**
+     * Parses the header information for a COPSObjBase object.
+     * @param data - the data to parse
+     * @return - the header
+     */
+    public static COPSObjHeaderData parseObjHeader(final byte[] data) {
+        if (data == null || data.length < 4)
+            throw new IllegalArgumentException("Data cannot be null or fewer than 4 bytes");
+
+        // TODO - Determine what setting the _len value from the data buffer really means
+        int len = 0;
+        len |= ((short) data[0]) << 8;
+        len |= ((short) data[1]) & 0xFF;
+
+        int cNum = 0;
+        cNum |= data[2];
+
+        int cType = 0;
+        cType |= data[3];
+
+        return new COPSObjHeaderData(
+                new COPSObjHeader(COPSObjHeader.VAL_TO_CNUM.get(cNum), COPSObjHeader.VAL_TO_CTYPE.get(cType)), len);
+    }
+
+    /**
+     * Parses bytes to return a COPSInterface object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSInterface parseIpv4Interface(final COPSObjHeaderData objHdrData, final byte[] dataPtr,
+                                                   final boolean isIn) {
+        if (isIn) return COPSIpv4InInterface.parse(objHdrData, dataPtr);
+        else return COPSIpv4OutInterface.parse(objHdrData, dataPtr);
+    }
+
+    /**
+     * Parses bytes to return a COPSIpv6Interface object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSIpv6Interface parseIpv6Interface(final COPSObjHeaderData objHdrData, final byte[] dataPtr,
+                                                       final boolean isIn) {
+        if (isIn) return COPSIpv6InInterface.parse(objHdrData, dataPtr);
+        else return COPSIpv6OutInterface.parse(objHdrData, dataPtr);
+    }
+
+    /**
+     * Add padding in the data, if the data does not fall on 32-bit boundary
+     * @param    len                 an int
+     * @return   a COPSData
+     */
+    public static COPSData getPadding(final int len) {
+        byte[] padBuf = new byte[len];
+        Arrays.fill(padBuf, (byte) 0);
+        return new COPSData(padBuf, 0, len);
+    }
+
+}
index f20236482129fab5c3c652ff8912e3eec3578e7a..53f9f93506404721ca7178b53316bd04f21e13a7 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-\r
-/**\r
- * COPS PDP Address\r
- *\r
- * @version COPSPdpAddress.java, v 1.00 2003\r
- *\r
- */\r
-abstract public class COPSPdpAddress extends COPSObjBase {\r
-\r
-    /**\r
-     * Method isPdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isPdpAddress() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Method isIpv4PdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIpv4PdpAddress() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isIpv6PdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isIpv6PdpAddress() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isLastPdpAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isLastPdpAddress() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isPdpredirectAddress\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isPdpredirectAddress() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    abstract public void dump(OutputStream os) throws IOException;\r
-};\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Superclass for  all PDP Address classes for which we appear to only have 2 concrete implementations and 4
+ * subclasses meaning this class hierarchy is ripe for further refactoring.
+ */
+abstract public class COPSPdpAddress extends COPSObjBase {
+
+    /**
+     * The address
+     */
+    private COPSIpAddress _addr;
+
+    /**
+     * The port number
+     */
+    private final int _tcpPort;
+
+    /**
+     * Currently the space holding this value is not in use.
+     */
+    private final short _reserved;
+
+    /**
+     * Constructor
+     * @param objHdr - the object's header info
+     * @param tcpPort - the port associated with an IP device
+     * @param reserved - not in use
+     */
+    protected COPSPdpAddress(final COPSObjHeader objHdr, final COPSIpAddress addr, final int tcpPort,
+                             final short reserved) {
+        super(objHdr);
+        if (addr == null) throw new IllegalArgumentException("Address must not be null");
+        if (tcpPort < 1) throw new IllegalArgumentException("Invalid port number - " + tcpPort);
+        this._addr = addr;
+        this._tcpPort = tcpPort;
+        this._reserved = reserved;
+    }
+
+    public int getTcpPort() {
+        return _tcpPort;
+    }
+
+    public short getReserved() {
+        return _reserved;
+    }
+
+    /**
+     * Creates the correct object of this type from a byte array.
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSPdpAddress parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
+        short reserved = 0;
+        int tcpPort = 0;
+
+        switch (objHdrData.header.getCType()) {
+            case DEF:
+                final byte[] addr4 = new byte[4];
+                System.arraycopy(dataPtr, 4, addr4, 0, 4);
+                reserved |= ((short) dataPtr[8]) << 8;
+                reserved |= ((short) dataPtr[9]) & 0xFF;
+                tcpPort |= ((short) dataPtr[10]) << 8;
+                tcpPort |= ((short) dataPtr[11]) & 0xFF;
+
+                switch (objHdrData.header.getCNum()) {
+                    case LAST_PDP_ADDR:
+                        return new COPSIpv4LastPdpAddr(objHdrData.header, addr4, tcpPort, reserved);
+                    case PDP_REDIR:
+                        return new COPSIpv4PdpRedirectAddress(objHdrData.header, addr4, tcpPort, reserved);
+                    default:
+                        throw new IllegalArgumentException("Unsupported CNum - " + objHdrData.header.getCNum());
+                }
+            case STATELESS:
+                final byte[] addr6 = new byte[16];
+                System.arraycopy(dataPtr, 4, addr6, 0, 16);
+                reserved |= ((short) dataPtr[20]) << 8;
+                reserved |= ((short) dataPtr[21]) & 0xFF;
+                tcpPort |= ((short) dataPtr[22]) << 8;
+                tcpPort |= ((short) dataPtr[23]) & 0xFF;
+                switch (objHdrData.header.getCNum()) {
+                    case LAST_PDP_ADDR:
+                        return new COPSIpv6LastPdpAddr(objHdrData.header, addr6, tcpPort, reserved);
+                    case PDP_REDIR:
+                        return new COPSIpv6PdpRedirectAddress(objHdrData.header, addr6, tcpPort, reserved);
+                    default:
+                        throw new IllegalArgumentException("Unsupported CNum - " + objHdrData.header.getCNum());
+                }
+            default:
+                throw new IllegalArgumentException("CType was not DEF(1) or STATELESS (2)");
+        }
+    }
+
+    @Override
+    public int getDataLength() {
+        return _addr.getDataLength() + 4;
+    }
+
+    @Override
+    public void dumpBody(OutputStream os) throws IOException {
+        os.write(("Address: " + _addr.getIpName() + "\n").getBytes());
+        os.write(("Port: " + _tcpPort + "\n").getBytes());
+    }
+
+    @Override
+    public void writeBody(final Socket socket) throws IOException {
+        _addr.writeData(socket);
+
+        byte[] buf = new byte[4];
+        buf[0] = (byte) (_reserved >> 8);
+        buf[1] = (byte) _reserved;
+        buf[2] = (byte) (_tcpPort >> 8);
+        buf[3] = (byte) _tcpPort ;
+
+        COPSUtil.writeData(socket, buf, 4);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSPdpAddress)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSPdpAddress that = (COPSPdpAddress) o;
+
+        return _reserved == that._reserved && _tcpPort == that._tcpPort && _addr.equals(that._addr);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _addr.hashCode();
+        result = 31 * result + _tcpPort;
+        result = 31 * result + (int) _reserved;
+        return result;
+    }
+}
+
index 9f1df76144bcd8cceb9d65634d537a6778cbf261..21866a239acde03701b18ca51a7d7e68daa35f44 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS PEP Identification Object\r
- *\r
- * @version COPSPepId.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSPepId extends COPSObjBase {\r
-\r
-    COPSObjHeader _objHdr;\r
-    COPSData _data;\r
-    COPSData _padding;\r
-\r
-    public COPSPepId() {\r
-        _objHdr = new COPSObjHeader(CNum.PEPID, CType.DEF);\r
-    }\r
-\r
-    protected COPSPepId(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        //Get the length of data following the obj header\r
-        short dLen = (short) (_objHdr.getDataLength() - 4);\r
-        COPSData d = new COPSData (dataPtr, 4, dLen);\r
-        setData(d);\r
-    }\r
-\r
-    /**\r
-     * Method setData\r
-     *\r
-     * @param    data                a  COPSData\r
-     *\r
-     */\r
-    public void setData(COPSData data) {\r
-        _data = data;\r
-        if (_data.length() % 4 != 0) {\r
-            int padLen = 4 - _data.length() % 4;\r
-            _padding = getPadding(padLen);\r
-        }\r
-        _objHdr.setDataLength((short)_data.length());\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        int lpadding = 0;\r
-        if (_padding != null) lpadding = _padding.length();\r
-        return ((short) (_objHdr.getDataLength() + lpadding));\r
-    }\r
-\r
-    /**\r
-     * Method getData\r
-     *\r
-     * @return   a COPSData\r
-     *\r
-     */\r
-    public COPSData getData() {\r
-        return _data;\r
-    };\r
-\r
-    /**\r
-     * Method isPepId\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isPepId() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Write data to given netwrok socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-        COPSUtil.writeData(id, _data.getData(), _data.length());\r
-        if (_padding != null) {\r
-            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("PEPID: " + _data.str() + "\n").getBytes());\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS PEP Identification Object (RFC 2748)
+ *
+ * The PEP Identification Object is used to identify the PEP client to
+ * the remote PDP. It is required for Client-Open messages.
+ *
+ * C-Num = 11, C-Type = 1
+ *
+ * Variable-length field. It is a NULL terminated ASCII string that is
+ * also zero padded to a 32-bit word boundary (so the object length is a
+ * multiple of 4 octets). The PEPID MUST contain an ASCII string that
+ * uniquely identifies the PEP within the policy domain in a manner that
+ * is persistent across PEP reboots. For example, it may be the PEP's
+ * statically assigned IP address or DNS name. This identifier may
+ * safely be used by a PDP as a handle for identifying the PEP in its
+ * policy rules.
+ */
+public class COPSPepId extends COPSObjBase {
+
+    /**
+     * The payload data
+     */
+    final COPSData _data;
+
+    /**
+     * Bytes to add to outbound payload to ensure the length is divisible by 4 bytes
+     */
+    final COPSData _padding;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSPepId(final COPSData data) {
+        this(new COPSObjHeader(CNum.PEPID, CType.DEF), data);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSPepId(final COPSObjHeader hdr, final COPSData data) {
+        super(hdr);
+
+        if (!hdr.getCNum().equals(CNum.PEPID))
+            throw new IllegalArgumentException("CNum must be equal to " + CNum.PEPID);
+        if (!hdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("CType must be equal to " + CType.DEF);
+        if (data == null) throw new IllegalArgumentException("Data must not be null");
+
+        _data = data;
+        if ((_data.length() % 4) != 0) {
+            final int padLen = 4 - (_data.length() % 4);
+            _padding = COPSObjectParser.getPadding(padLen);
+        } else {
+            _padding = new COPSData();
+        }
+    }
+
+    @Override
+    protected int getDataLength() {
+        return _data.length() + _padding.length();
+    }
+
+    /**
+     * Method getData
+     * @return   a COPSData
+     */
+    public COPSData getData() {
+        return _data;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        COPSUtil.writeData(socket, _data.getData(), _data.length());
+        if (_padding != null) {
+            COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+        }
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        os.write(("PEPID: " + _data.str() + "\n").getBytes());
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSPepId)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSPepId that = (COPSPepId) o;
+
+        return _data.equals(that._data) && _padding.equals(that._padding) ||
+                COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _data.hashCode();
+        result = 31 * result + _padding.hashCode();
+        return result;
+    }
+
+    /**
+     * Parses bytes to return a COPSPepId object
+     * @param objHdrData - the associated header
+     * @param dataPtr - the data to parse
+     * @return - the object
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSPepId parse(final COPSObjHeaderData objHdrData, byte[] dataPtr) {
+        short dLen = (short)(objHdrData.msgByteCount - 4);
+        return new COPSPepId(objHdrData.header, new COPSData (dataPtr, 4, dLen));
+    }
+
+}
+
+
+
index f8530e0c6cdc6de70237abf65252aa08292980ff..4b1d60926d7a1565cd37b1bab0f5076ac0c32c59 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Reason Object (RFC 2748 pag. 12)\r
- *\r
- *   This object specifies the reason why the request state was deleted.\r
- *   It appears in the delete request (DRQ) message. The Reason Sub-code\r
- *   field is reserved for more detailed client-specific reason codes\r
- *   defined in the corresponding documents.\r
- *\r
- *           C-Num = 5, C-Type = 1\r
- *\r
- *               0             1              2             3\r
- *       +--------------+--------------+--------------+--------------+\r
- *       |         Reason-Code         |       Reason Sub-code       |\r
- *       +--------------+--------------+--------------+--------------+\r
- *\r
- *           Reason Code:\r
- *               1 = Unspecified\r
- *               2 = Management\r
- *               3 = Preempted (Another request state takes precedence)\r
- *               4 = Tear (Used to communicate a signaled state removal)\r
- *               5 = Timeout (Local state has timed-out)\r
- *               6 = Route Change (Change invalidates request state)\r
- *               7 = Insufficient Resources (No local resource available)\r
- *               8 = PDP's Directive (PDP decision caused the delete)\r
- *                9 = Unsupported decision (PDP decision not supported)\r
- *               10= Synchronize Handle Unknown\r
- *               11= Transient Handle (stateless event)\r
- *               12= Malformed Decision (could not recover)\r
- *               13= Unknown COPS Object from PDP:\r
- *                   Sub-code (octet 2) contains unknown object's C-Num\r
- *                   and (octet 3) contains unknown object's C-Type.\r
- *\r
- * @version COPSReason.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSReason extends COPSPrObjBase {\r
-\r
-    public final static String[] G_msgArray = {\r
-        "Unknown.",\r
-        "Unspecified.",\r
-        "Management.",\r
-        "Preempted (Another request state takes precedence).",\r
-        "Tear (Used to communicate a signaled state removal).",\r
-        "Timeout ( Local state has timed-out).",\r
-        "Route change (Change invalidates request state).",\r
-        "Insufficient Resources.",\r
-        "PDP's Directive.",\r
-        "Unsupported decision.",\r
-        "Synchronize handle unknown.",\r
-        "Transient handle.",\r
-        "Malformed decision.",\r
-        "Unknown COPS object from PDP.",\r
-    };\r
-\r
-    private COPSObjHeader _objHdr;\r
-    private short _reasonCode;\r
-    private short _reasonSubCode;\r
-\r
-    ///\r
-    public COPSReason(short reasonCode, short subCode) {\r
-        _objHdr = new COPSObjHeader(CNum.REASON_CODE, CType.DEF);\r
-        _reasonCode = reasonCode;\r
-        _reasonSubCode = subCode;\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSReason object\r
-     */\r
-    protected COPSReason(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        _reasonCode |= ((short) dataPtr[4]) << 8;\r
-        _reasonCode |= ((short) dataPtr[5]) & 0xFF;\r
-        _reasonSubCode |= ((short) dataPtr[6]) << 8;\r
-        _reasonSubCode |= ((short) dataPtr[7]) & 0xFF;\r
-\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    /**\r
-     * Get Reason description\r
-     *\r
-     * @return   a String\r
-     *\r
-     */\r
-    public String getDescription() {\r
-        String reasonStr1;\r
-        String reasonStr2;\r
-\r
-        ///Get the details from the error code\r
-        reasonStr1 = G_msgArray[_reasonCode];\r
-        //TODO - defind reason sub-codes\r
-        reasonStr2 = "";\r
-        return (reasonStr1 + ":" + reasonStr2);\r
-    }\r
-\r
-    /**\r
-     * Always return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isReason() {\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * Write object in network byte order to a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-\r
-        _objHdr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-\r
-        buf[0] = (byte) (_reasonCode >> 8);\r
-        buf[1] = (byte) _reasonCode;\r
-        buf[2] = (byte) (_reasonSubCode >> 8);\r
-        buf[3] = (byte) _reasonSubCode;\r
-\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Reason Code: " + _reasonCode + "\n").getBytes());\r
-        os.write(new String("Reason Sub Code: " + _reasonSubCode + "\n").getBytes());\r
-    }\r
-}\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Reason Object (RFC 2748 page. 12)
+ *
+ *   This object specifies the reason why the request state was deleted.
+ *   It appears in the delete request (DRQ) message. The Reason Sub-code
+ *   field is reserved for more detailed client-specific reason codes
+ *   defined in the corresponding documents.
+ *
+ *           C-Num = 5, C-Type = 1
+ *
+ *               0             1              2             3
+ *       +--------------+--------------+--------------+--------------+
+ *       |         Reason-Code         |       Reason Sub-code       |
+ *       +--------------+--------------+--------------+--------------+
+ *
+ *           Reason Code:
+ *               1 = Unspecified
+ *               2 = Management
+ *               3 = Preempted (Another request state takes precedence)
+ *               4 = Tear (Used to communicate a signaled state removal)
+ *               5 = Timeout (Local state has timed-out)
+ *               6 = Route Change (Change invalidates request state)
+ *               7 = Insufficient Resources (No local resource available)
+ *               8 = PDP's Directive (PDP decision caused the delete)
+ *                9 = Unsupported decision (PDP decision not supported)
+ *               10= Synchronize Handle Unknown
+ *               11= Transient Handle (stateless event)
+ *               12= Malformed Decision (could not recover)
+ *               13= Unknown COPS Object from PDP:
+ *                   Sub-code (octet 2) contains unknown object's C-Num
+ *                   and (octet 3) contains unknown object's C-Type.
+ *
+ * @version COPSReason.java, v 1.00 2003
+ *
+ */
+public class COPSReason extends COPSObjBase {
+
+    private final static Map<Integer, ReasonCode> VAL_TO_REASON = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_REASON.put(ReasonCode.NA.ordinal(), ReasonCode.NA);
+        VAL_TO_REASON.put(ReasonCode.UNSPECIFIED.ordinal(), ReasonCode.UNSPECIFIED);
+        VAL_TO_REASON.put(ReasonCode.MANAGEMENT.ordinal(), ReasonCode.MANAGEMENT);
+        VAL_TO_REASON.put(ReasonCode.PREEMPTED.ordinal(), ReasonCode.PREEMPTED);
+        VAL_TO_REASON.put(ReasonCode.TEAR.ordinal(), ReasonCode.TEAR);
+        VAL_TO_REASON.put(ReasonCode.TIMEOUT.ordinal(), ReasonCode.TIMEOUT);
+        VAL_TO_REASON.put(ReasonCode.ROUTE_CHANGE.ordinal(), ReasonCode.ROUTE_CHANGE);
+        VAL_TO_REASON.put(ReasonCode.INSUFF_RESOURCES.ordinal(), ReasonCode.INSUFF_RESOURCES);
+        VAL_TO_REASON.put(ReasonCode.PDP_DIRECTIVE.ordinal(), ReasonCode.PDP_DIRECTIVE);
+        VAL_TO_REASON.put(ReasonCode.UNSUPPORT_DEC.ordinal(), ReasonCode.UNSUPPORT_DEC);
+        VAL_TO_REASON.put(ReasonCode.SYNC_HANDLE.ordinal(), ReasonCode.SYNC_HANDLE);
+        VAL_TO_REASON.put(ReasonCode.TRANS_HANDLE.ordinal(), ReasonCode.TRANS_HANDLE);
+        VAL_TO_REASON.put(ReasonCode.MALFORMED_DEC.ordinal(), ReasonCode.MALFORMED_DEC);
+        VAL_TO_REASON.put(ReasonCode.UNKNOWN_COPS_OBJ.ordinal(), ReasonCode.UNKNOWN_COPS_OBJ);
+    }
+
+    private final static Map<ReasonCode, String> REASON_TO_STRING = new ConcurrentHashMap<>();
+    static {
+        REASON_TO_STRING.put(ReasonCode.NA, "Unknown.");
+        REASON_TO_STRING.put(ReasonCode.UNSPECIFIED, "Unspecified.");
+        REASON_TO_STRING.put(ReasonCode.MANAGEMENT, "Management.");
+        REASON_TO_STRING.put(ReasonCode.PREEMPTED, "Preempted (Another request state takes precedence).");
+        REASON_TO_STRING.put(ReasonCode.TEAR, "Tear (Used to communicate a signaled state removal).");
+        REASON_TO_STRING.put(ReasonCode.TIMEOUT, "Timeout ( Local state has timed-out).");
+        REASON_TO_STRING.put(ReasonCode.ROUTE_CHANGE, "Route change (Change invalidates request state).");
+        REASON_TO_STRING.put(ReasonCode.INSUFF_RESOURCES, "Insufficient Resources.");
+        REASON_TO_STRING.put(ReasonCode.PDP_DIRECTIVE, "PDP's Directive.");
+        REASON_TO_STRING.put(ReasonCode.UNSUPPORT_DEC, "Unsupported decision.");
+        REASON_TO_STRING.put(ReasonCode.SYNC_HANDLE, "Synchronize handle unknown.");
+        REASON_TO_STRING.put(ReasonCode.TRANS_HANDLE, "Transient handle.");
+        REASON_TO_STRING.put(ReasonCode.MALFORMED_DEC, "Malformed decision.");
+        REASON_TO_STRING.put(ReasonCode.UNKNOWN_COPS_OBJ, "Unknown COPS object from PDP.");
+    }
+
+    /**
+     * The reason
+     */
+    private final ReasonCode _reasonCode;
+
+    /**
+     * Reserved for more detailed client-specific reasons
+     */
+    private final ReasonCode _reasonSubCode;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param reasonCode - the reason code
+     * @param subCode - more detailed reasons
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSReason(final ReasonCode reasonCode, final ReasonCode subCode) {
+        this(new COPSObjHeader(CNum.REASON_CODE, CType.DEF), reasonCode, subCode);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param reasonCode - the reason code
+     * @param subCode - the type of message
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSReason(final COPSObjHeader hdr, final ReasonCode reasonCode, final ReasonCode subCode) {
+        super(hdr);
+        if (!hdr.getCNum().equals(CNum.REASON_CODE))
+            throw new IllegalArgumentException("Must have a CNum value of " + CNum.REASON_CODE);
+        if (!hdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.DEF);
+        if (reasonCode == null || subCode == null) throw new IllegalArgumentException("Error codes must not be null");
+        if (reasonCode.equals(ReasonCode.NA))
+            throw new IllegalArgumentException("Error code must not be of type " + ReasonCode.NA);
+
+        _reasonCode = reasonCode;
+        _reasonSubCode = subCode;
+    }
+
+    public ReasonCode getReasonCode() { return _reasonCode; }
+    public ReasonCode getReasonSubCode() { return _reasonSubCode; }
+
+    @Override
+    protected int getDataLength() {
+        return 4;
+    }
+
+    /**
+     * Get Reason description
+     * @return   a String
+     */
+    public String getDescription() {
+        return (REASON_TO_STRING.get(_reasonCode) + ":");
+    }
+
+    @Override
+    protected void writeBody(final Socket id) throws IOException {
+        final byte[] buf = new byte[4];
+        buf[0] = (byte) (_reasonCode.ordinal() >> 8);
+        buf[1] = (byte) _reasonCode.ordinal();
+        buf[2] = (byte) (_reasonSubCode.ordinal() >> 8);
+        buf[3] = (byte) _reasonSubCode.ordinal();
+        COPSUtil.writeData(id, buf, 4);
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("Reason Code: " + _reasonCode + "\n").getBytes());
+        os.write(("Reason Sub Code: " + _reasonSubCode + "\n").getBytes());
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSReason parse(final COPSObjHeaderData objHdrData, byte[] dataPtr) {
+        short reasonCode = 0;
+        reasonCode |= ((short) dataPtr[4]) << 8;
+        reasonCode |= ((short) dataPtr[5]) & 0xFF;
+
+        short reasonSubCode = 0;
+        reasonSubCode |= ((short) dataPtr[6]) << 8;
+        reasonSubCode |= ((short) dataPtr[7]) & 0xFF;
+
+        return new COPSReason(objHdrData.header, VAL_TO_REASON.get((int)reasonCode),
+                VAL_TO_REASON.get((int)reasonSubCode));
+    }
+
+    /**
+     * All of the supported reason codes
+     */
+    public enum ReasonCode {
+        NA, UNSPECIFIED, MANAGEMENT, PREEMPTED, TEAR, TIMEOUT, ROUTE_CHANGE, INSUFF_RESOURCES, PDP_DIRECTIVE,
+        UNSUPPORT_DEC, SYNC_HANDLE, TRANS_HANDLE, MALFORMED_DEC, UNKNOWN_COPS_OBJ
+    }
+
+}
+
+
index a474147d216f0d5cef72b844f28b88f927daa0e9..ec0865e2e2eddc033139413dc47d48b388037fae 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Vector;\r
-\r
-/**\r
- * COPS Report Message (RFC 2748 pag. 25)\r
- *\r
- *    The RPT message is used by the PEP to communicate to the PDP its\r
- *   success or failure in carrying out the PDP's decision, or to report\r
- *   an accounting related change in state. The Report-Type specifies the\r
- *   kind of report and the optional ClientSI can carry additional\r
- *   information per Client-Type.\r
- *\r
- *   For every DEC message containing a configuration context that is\r
- *   received by a PEP, the PEP MUST generate a corresponding Report State\r
- *   message with the Solicited Message flag set describing its success or\r
- *   failure in applying the configuration decision. In addition,\r
- *   outsourcing decisions from the PDP MAY result in a corresponding\r
- *   solicited Report State from the PEP depending on the context and the\r
- *   type of client. RPT messages solicited by decisions for a given\r
- *   Client Handle MUST set the Solicited Message flag and MUST be sent in\r
- *   the same order as their corresponding Decision messages were\r
- *   received. There MUST never be more than one Report State message\r
- *   generated with the Solicited Message flag set per Decision.\r
- *\r
- *   The Report State may also be used to provide periodic updates of\r
- *   client specific information for accounting and state monitoring\r
- *   purposes depending on the type of the client. In such cases the\r
- *   accounting report type should be specified utilizing the appropriate\r
- *   client specific information object.\r
- *\r
- *              <Report State> ::== <Common Header>\r
- *                                  <Client Handle>\r
- *                                  <Report-Type>\r
- *                                  [<ClientSI>]\r
- *                                  [<Integrity>]\r
- *\r
- * @version COPSReportMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSReportMsg extends COPSMsg {\r
-    /* COPSHeader coming from base class */\r
-    private COPSHandle _clientHandle;\r
-    private COPSReportType _report;\r
-    private Vector _clientSI;\r
-    private COPSIntegrity _integrity;\r
-\r
-    public COPSReportMsg() {\r
-        _clientHandle = null;\r
-        _report = null;\r
-        _integrity = null;\r
-        _clientSI = new Vector(20);\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSReportMsg object\r
-     */\r
-    protected COPSReportMsg (byte[] data) throws COPSException {\r
-        _clientHandle = null;\r
-        _report = null;\r
-        _integrity = null;\r
-        parse(data);\r
-    }\r
-\r
-    /**\r
-     * Checks the sanity of COPS message and throw an\r
-     * COPSException when data is bad.\r
-     */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_clientHandle == null) || (_report == null))\r
-            throw new COPSException("Bad message format");\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_RPT)\r
-            throw new COPSException ("Error Header (no COPS_OP_REQ)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Report object to the message\r
-     *\r
-     * @param    report              a  COPSReportType\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSReportType report) throws COPSException {\r
-        if (report == null)\r
-            throw new COPSException ("Null Handle");\r
-\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_integrity != null)\r
-            throw new COPSException ("No null Handle");\r
-\r
-        _report = report;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add client handle to the message\r
-     *\r
-     * @param    handle              a  COPSHandle\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHandle handle) throws COPSException {\r
-        if (handle == null)\r
-            throw new COPSException ("Null Handle");\r
-\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_integrity != null)\r
-            throw new COPSException ("No null Handle");\r
-\r
-        _clientHandle = handle;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add one or more clientSI objects\r
-     *\r
-     * @param    clientSI            a  COPSClientSI\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSClientSI clientSI) throws COPSException {\r
-        if (clientSI == null)\r
-            throw new COPSException ("Null ClientSI");\r
-        _clientSI.add(clientSI);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add integrity object\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Get client Handle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _clientHandle;\r
-    }\r
-\r
-    /**\r
-     * Get report type\r
-     *\r
-     * @return   a COPSReportType\r
-     *\r
-     */\r
-    public COPSReportType getReport() {\r
-        return _report;\r
-    }\r
-\r
-    /**\r
-     * Get clientSI\r
-     *\r
-     * @return   a Vector\r
-     *\r
-     */\r
-    public Vector getClientSI() {\r
-        return _clientSI;\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has Integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    }\r
-\r
-\r
-    /**\r
-     * Get Integrity. Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return (_integrity);\r
-    }\r
-\r
-    /**\r
-     * Writes data to given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        //checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_clientHandle != null) _clientHandle.writeData(id);\r
-        if (_report != null) _report.writeData(id);\r
-\r
-        for (Enumeration e = _clientSI.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-            clientSI.writeData(id);\r
-        }\r
-\r
-        if (_integrity != null) _integrity.writeData(id);\r
-    }\r
-\r
-    /**\r
-     * Parse data\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        super.parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case HANDLE:\r
-                    _clientHandle = new COPSHandle(buf);\r
-                    _dataStart += _clientHandle.getDataLength();\r
-                    break;\r
-                case RPT:\r
-                    _report = new COPSReportType(buf);\r
-                    _dataStart += _report.getDataLength();\r
-                    break;\r
-                case CSI:\r
-                    COPSClientSI csi = new COPSClientSI(buf);\r
-                    _dataStart += csi.getDataLength();\r
-                    _clientSI.add(csi);\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default:\r
-                    throw new COPSException("Bad Message format, unknown object type");\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Parse data\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_RPT)\r
-            throw new COPSException ("Null Header");\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength() throws COPSException {\r
-        short len = 0;\r
-        if (_clientHandle != null) len += _clientHandle.getDataLength();\r
-        if (_report != null) len += _report.getDataLength();\r
-\r
-        for (Enumeration e = _clientSI.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-            len += clientSI.getDataLength();\r
-        }\r
-\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_clientHandle != null)\r
-            _clientHandle.dump(os);\r
-\r
-        if (_report != null)\r
-            _report.dump(os);\r
-\r
-        for (Enumeration e = _clientSI.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-            clientSI.dump(os);\r
-        }\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Report Message (RFC 2748 pag. 25)
+ *
+ *    The RPT message is used by the PEP to communicate to the PDP its
+ *   success or failure in carrying out the PDP's decision, or to report
+ *   an accounting related change in state. The Report-Type specifies the
+ *   kind of report and the optional ClientSI can carry additional
+ *   information per Client-Type.
+ *
+ *   For every DEC message containing a configuration context that is
+ *   received by a PEP, the PEP MUST generate a corresponding Report State
+ *   message with the Solicited Message flag set describing its success or
+ *   failure in applying the configuration decision. In addition,
+ *   outsourcing decisions from the PDP MAY result in a corresponding
+ *   solicited Report State from the PEP depending on the context and the
+ *   type of client. RPT messages solicited by decisions for a given
+ *   Client Handle MUST set the Solicited Message flag and MUST be sent in
+ *   the same order as their corresponding Decision messages were
+ *   received. There MUST never be more than one Report State message
+ *   generated with the Solicited Message flag set per Decision.
+ *
+ *   The Report State may also be used to provide periodic updates of
+ *   client specific information for accounting and state monitoring
+ *   purposes depending on the type of the client. In such cases the
+ *   accounting report type should be specified utilizing the appropriate
+ *   client specific information object.
+ *
+ *              <Report State> ::== <Common Header>
+ *                                  <Client Handle>
+ *                                  <Report-Type>
+ *                                  [<ClientSI>]
+ *                                  [<Integrity>]
+ *
+ * @version COPSReportMsg.java, v 1.00 2003
+ *
+ */
+public class COPSReportMsg extends COPSMsg {
+    // Required
+    private final COPSHandle _clientHandle;
+    private final COPSReportType _report;
+    private final COPSIntegrity _integrity;
+
+    // TODO - Determine why previous implementation had a collection of Client SIs when the specification reads
+    // that there may be only one. May need to revert back to a Set<COPSClientSI>
+    // Optional
+    private final COPSClientSI _clientSI;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message (required)
+     * @param clientHandle - the COPS Handle (required)
+     * @param report - the report (required)
+     * @param clientSI - the client SI (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSReportMsg(final short clientType, final COPSHandle clientHandle, final COPSReportType report,
+                         final COPSClientSI clientSI, final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.RPT, clientType), clientHandle, report, clientSI, integrity);
+    }
+
+    /**
+     * Constructor (generally used for sending messages).
+     * @param version - the supported PCMM Version
+     * @param flag - the flag...
+     * @param clientType - the type of client that created the message (required)
+     * @param clientHandle - the COPS Handle (required)
+     * @param report - the report (required)
+     * @param clientSI - the client SI (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSReportMsg(final int version, final Flag flag, final short clientType, final COPSHandle clientHandle, final COPSReportType report,
+                         final COPSClientSI clientSI, final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.RPT, clientType), clientHandle, report, clientSI, integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header
+     * @param clientHandle - the COPS Handle (required)
+     * @param report - the report (required)
+     * @param clientSI - the client SI (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSReportMsg(final COPSHeader hdr, final COPSHandle clientHandle, final COPSReportType report,
+                         final COPSClientSI clientSI, final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.RPT))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.RPT);
+        if (clientHandle == null) throw new IllegalArgumentException("COPSHandle must not be null");
+        if (report == null) throw new IllegalArgumentException("COPSReportType must not be null");
+
+        _clientHandle = clientHandle;
+        _report = report;
+        _clientSI = clientSI;
+        _integrity = integrity;
+    }
+
+    // Getters
+    public COPSHandle getClientHandle() {
+        return _clientHandle;
+    }
+    public COPSReportType getReport() {
+        return _report;
+    }
+    public COPSClientSI getClientSI() {
+        return _clientSI;
+    }
+    public COPSIntegrity getIntegrity() {
+        return (_integrity);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = _clientHandle.getDataLength() + _clientHandle.getHeader().getHdrLength();
+        out += _report.getDataLength() + _report.getHeader().getHdrLength();
+        if (_clientSI != null) out += _clientSI.getDataLength() + _clientSI.getHeader().getHdrLength();
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _clientHandle.writeData(socket);
+        _report.writeData(socket);
+        if (_clientSI != null) _clientSI.writeData(socket);
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        _clientHandle.dump(os);
+        _report.dump(os);
+        if (_clientSI != null) _clientSI.dump(os);
+        if (_integrity != null) _integrity.dump(os);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSReportMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSReportMsg that = (COPSReportMsg) o;
+
+        return _clientHandle.equals(that._clientHandle) &&
+                !(_clientSI != null ? !_clientSI.equals(that._clientSI) : that._clientSI != null) &&
+                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null) &&
+                _report.equals(that._report);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _clientHandle.hashCode();
+        result = 31 * result + _report.hashCode();
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        result = 31 * result + (_clientSI != null ? _clientSI.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSDecisionMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSReportMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSHandle clientHandle = null;
+        COPSReportType report = null;
+        COPSIntegrity integrity = null;
+        COPSClientSI clientSI = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case HANDLE:
+                    clientHandle = COPSHandle.parse(objHdrData, buf);
+                    break;
+                case RPT:
+                    report = COPSReportType.parse(objHdrData, buf);
+                    break;
+                case CSI:
+                    clientSI = COPSClientSI.parse(objHdrData, buf);
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSReportMsg(hdrData.header, clientHandle, report, clientSI, integrity);
+    }
+}
+
+
+
index 504d34bbb099173260b7ce04b6b34ae91ef1809c..fb5cdd712dbd6175f88a07ba32b5494286adba41 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import org.umu.cops.stack.COPSObjHeader.CNum;\r
-import org.umu.cops.stack.COPSObjHeader.CType;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Report Type (RFC 2748 pag. 16\r
- *\r
- *   The Type of Report on the request state associated with a handle:\r
- *\r
- *           C-Num = 12, C-Type = 1\r
- *\r
- *               0             1              2             3\r
- *       +--------------+--------------+--------------+--------------+\r
- *       |         Report-Type         |        /////////////        |\r
- *       +--------------+--------------+--------------+--------------+\r
- *\r
- *           Report-Type:\r
- *               1 = Success   : Decision was successful at the PEP\r
- *               2 = Failure   : Decision could not be completed by PEP\r
- *               3 = Accounting: Accounting update for an installed state\r
- *\r
- *\r
- * @version COPSReportType.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSReportType extends COPSPrObjBase {\r
-\r
-    public final static String[] msgMap = {\r
-        "Unknown",\r
-        "Success",\r
-        "Failure",\r
-        "Accounting",\r
-    };\r
-\r
-    private COPSObjHeader _objHdr;\r
-    private short _rType;\r
-    private short _reserved;\r
-\r
-    public final static short SUCCESS = 1;\r
-    public final static short FAILURE = 2;\r
-    public final static short ACCT = 3;\r
-\r
-    public COPSReportType(short rType) {\r
-        _objHdr = new COPSObjHeader(CNum.RPT, CType.DEF);\r
-        _rType = rType;\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSReportType object\r
-     */\r
-    protected COPSReportType(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        _rType |= ((short) dataPtr[4]) << 8;\r
-        _rType |= ((short) dataPtr[5]) & 0xFF;\r
-        _reserved |= ((short) dataPtr[6]) << 8;\r
-        _reserved |= ((short) dataPtr[7]) & 0xFF;\r
-\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    /**\r
-     * If it is Success, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isSuccess() {\r
-        return (_rType == SUCCESS );\r
-    };\r
-\r
-    /**\r
-     * If it is Failure, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isFailure() {\r
-        return (_rType == FAILURE);\r
-    };\r
-\r
-    /**\r
-     * If it is Accounting, return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAccounting() {\r
-        return (_rType == ACCT);\r
-    };\r
-\r
-    /**\r
-     * Always return true\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isReport() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Write data in network byte order on a given network socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-\r
-        buf[0] = (byte) (_rType >> 8);\r
-        buf[1] = (byte) _rType;\r
-        buf[2] = (byte) (_reserved >> 8);\r
-        buf[3] = (byte) _reserved;\r
-\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Report: " + msgMap[_rType] + "\n").getBytes());\r
-    }\r
-}\r
-\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Report Type (RFC 2748 pg. 16)
+ *
+ *   The Type of Report on the request state associated with a handle:
+ *
+ *           C-Num = 12, C-Type = 1
+ *
+ *               0             1              2             3
+ *       +--------------+--------------+--------------+--------------+
+ *       |         Report-Type         |        /////////////        |
+ *       +--------------+--------------+--------------+--------------+
+ *
+ *           Report-Type:
+ *               1 = Success   : Decision was successful at the PEP
+ *               2 = Failure   : Decision could not be completed by PEP
+ *               3 = Accounting: Accounting update for an installed state
+ *
+ *
+ * @version COPSReportType.java, v 1.00 2003
+ *
+ */
+public class COPSReportType extends COPSObjBase {
+
+    private final static Map<Integer, ReportType> VAL_TO_RPT_TYPE = new ConcurrentHashMap<>();
+    static {
+        VAL_TO_RPT_TYPE.put(ReportType.NA.ordinal(), ReportType.NA);
+        VAL_TO_RPT_TYPE.put(ReportType.SUCCESS.ordinal(), ReportType.SUCCESS);
+        VAL_TO_RPT_TYPE.put(ReportType.FAILURE.ordinal(), ReportType.FAILURE);
+        VAL_TO_RPT_TYPE.put(ReportType.ACCOUNTING.ordinal(), ReportType.ACCOUNTING);
+    }
+
+    private final static Map<ReportType, String> RPT_TYPE_TO_STRING = new ConcurrentHashMap<>();
+    static {
+        RPT_TYPE_TO_STRING.put(ReportType.NA, "Unknown.");
+        RPT_TYPE_TO_STRING.put(ReportType.SUCCESS, "Success.");
+        RPT_TYPE_TO_STRING.put(ReportType.FAILURE, "Failure.");
+        RPT_TYPE_TO_STRING.put(ReportType.ACCOUNTING, "Accounting.");
+    }
+
+    /**
+     * The type of report
+     */
+    private final ReportType _rType;
+
+    /**
+     * What is this attribute used for???
+     */
+    private final short _reserved;
+
+    /**
+     * Constructor generally used for sending messages
+     * @param rType - the report type
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSReportType(final ReportType rType) {
+        this(new COPSObjHeader(CNum.RPT, CType.DEF), rType, (short)0);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param hdr - the object header
+     * @param rType - the report type
+     * @param reserved - ???
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSReportType(final COPSObjHeader hdr, final ReportType rType, final short reserved) {
+        super(hdr);
+        if (!hdr.getCNum().equals(CNum.RPT))
+            throw new IllegalArgumentException("Must have a CNum value of " + CNum.RPT);
+        if (!hdr.getCType().equals(CType.DEF))
+            throw new IllegalArgumentException("Must have a CType value of " + CType.DEF);
+        if (rType == null) throw new IllegalArgumentException("Report type must not be null");
+        if (rType.equals(ReportType.NA))
+            throw new IllegalArgumentException("Report type must not be of type " + ReportType.NA);
+
+        _rType = rType;
+        _reserved = reserved;
+    }
+
+    public ReportType getReportType() { return _rType; }
+
+    @Override
+    public int getDataLength() {
+        return 4;
+    }
+
+    @Override
+    protected void writeBody(final Socket id) throws IOException {
+        final byte[] buf = new byte[4];
+
+        buf[0] = (byte) (_rType.ordinal() >> 8);
+        buf[1] = (byte) _rType.ordinal();
+        buf[2] = (byte) (_reserved >> 8);
+        buf[3] = (byte) _reserved;
+
+        COPSUtil.writeData(id, buf, 4);
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        os.write(("Report: " + RPT_TYPE_TO_STRING.get(_rType) + "\n").getBytes());
+    }
+
+    /**
+     * Creates this object from a byte array
+     * @param objHdrData - the header
+     * @param dataPtr - the data to parse
+     * @return - a new Timer
+     * @throws java.lang.IllegalArgumentException
+     */
+    public static COPSReportType parse(final COPSObjHeaderData objHdrData, byte[] dataPtr) {
+        short rType = 0;
+        rType |= ((short) dataPtr[4]) << 8;
+        rType |= ((short) dataPtr[5]) & 0xFF;
+
+        short reserved = 0;
+        reserved |= ((short) dataPtr[6]) << 8;
+        reserved |= ((short) dataPtr[7]) & 0xFF;
+
+        return new COPSReportType(objHdrData.header, VAL_TO_RPT_TYPE.get((int)rType), reserved);
+    }
+
+    /**
+     * The supported report types
+     */
+    public enum ReportType {
+        NA, SUCCESS, FAILURE, ACCOUNTING
+    }
+
+}
+
+
+
+
+
index 6293abae13e72a2cdad082a736b901b82b6ce3e6..d5653288baf377ec3314112d086fdd37b90ca67d 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-import java.util.Vector;\r
-\r
-/**\r
- * COPS Request Message (RFC 2748 pag. 22)\r
- *\r
- *   The PEP establishes a request state client handle for which the\r
- *   remote PDP may maintain state. The remote PDP then uses this handle\r
- *   to refer to the exchanged information and decisions communicated over\r
- *   the TCP connection to a particular PEP for a given client-type.\r
- *\r
- *   Once a stateful handle is established for a new request, any\r
- *   subsequent modifications of the request can be made using the REQ\r
- *   message specifying the previously installed handle. The PEP is\r
- *   responsible for notifying the PDP whenever its local state changes so\r
- *   the PDP's state will be able to accurately mirror the PEP's state.\r
- *\r
- *   The format of the Request message is as follows:\r
- *\r
- *               <Request Message> ::=  <Common Header>\r
- *                                      <Client Handle>\r
- *                                      <Context>\r
- *                                      [<IN-Int>]\r
- *                                      [<OUT-Int>]\r
- *                                      [<ClientSI(s)>]\r
- *                                      [<LPDPDecision(s)>]\r
- *                                      [<Integrity>]\r
- *\r
- *               <ClientSI(s)> ::= <ClientSI> | <ClientSI(s)> <ClientSI>\r
- *\r
- *               <LPDPDecision(s)> ::= <LPDPDecision> |\r
- *                                     <LPDPDecision(s)> <LPDPDecision>\r
- *\r
- *               <LPDPDecision> ::= [<Context>]\r
- *                                  <LPDPDecision: Flags>\r
- *                                  [<LPDPDecision: Stateless Data>]\r
- *                                  [<LPDPDecision: Replacement Data>]\r
- *                                  [<LPDPDecision: ClientSI Data>]\r
- *                                  [<LPDPDecision: Named Data>]\r
- *\r
- *   The context object is used to determine the context within which all\r
- *   the other objects are to be interpreted. It also is used to determine\r
- *   the kind of decision to be returned from the policy server. This\r
- *   decision might be related to admission control, resource allocation,\r
- *   object forwarding and substitution, or configuration.\r
- *\r
- *   The interface objects are used to determine the corresponding\r
- *   interface on which a signaling protocol message was received or is\r
- *   about to be sent. They are typically used if the client is\r
- *   participating along the path of a signaling protocol or if the client\r
- *   is requesting configuration data for a particular interface.\r
- *\r
- *   ClientSI, the client specific information object, holds the client-\r
- *   type specific data for which a policy decision needs to be made. In\r
- *   the case of configuration, the Named ClientSI may include named\r
- *   information about the module, interface, or functionality to be\r
- *   configured. The ordering of multiple ClientSIs is not important.\r
- *\r
- *   Finally, LPDPDecision object holds information regarding the local\r
- *   decision made by the LPDP.\r
- *\r
- *   Malformed Request messages MUST result in the PDP specifying a\r
- *   Decision message with the appropriate error code.\r
- *\r
- * @version COPSReqMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSReqMsg extends COPSMsg {\r
-\r
-    /* COPSHeader coming from base class */\r
-    private COPSHandle _clientHandle;\r
-    private COPSContext _context;\r
-    private COPSInterface _inInterface;\r
-    private COPSInterface _outInterface;\r
-    private Vector _clientSIs;\r
-    private Hashtable _decisions;\r
-    private COPSIntegrity _integrity;\r
-    private COPSContext _lpdpContext;\r
-\r
-    public COPSReqMsg() {\r
-        _clientHandle = null;\r
-        _context = null;\r
-        _inInterface = null;\r
-        _outInterface = null;\r
-        _clientSIs = new Vector(20);\r
-        _decisions = new Hashtable();\r
-        _integrity = null;\r
-        _lpdpContext = null;\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSReqMsg object\r
-     */\r
-    protected COPSReqMsg(byte[] data) throws COPSException {\r
-        parse(data);\r
-    }\r
-\r
-    /**\r
-     * Checks the sanity of COPS message and throw an\r
-     * COPSBadDataException when data is bad.\r
-     */\r
-    public void checkSanity() throws COPSException {\r
-        if ((_hdr == null) || (_clientHandle == null) || (_context == null)) {\r
-            throw new COPSException("Bad message format");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Add an IN or OUT interface object\r
-     *\r
-     * @param    inter               a  COPSInterface\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSInterface inter) throws COPSException {\r
-        if (!(inter.isInInterface() || inter.isOutInterface()))\r
-            throw new COPSException ("No Interface");\r
-\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_integrity != null)\r
-            throw new COPSException ("Integrity should be the last one");\r
-\r
-        if (inter.isInInterface()) {\r
-            if (_inInterface != null)\r
-                throw new COPSException ("Object inInterface exits");\r
-\r
-            if (inter.isIpv4Address()) {\r
-                COPSIpv4InInterface inInter = (COPSIpv4InInterface) inter;\r
-                _inInterface = inInter;\r
-            } else {\r
-                COPSIpv6InInterface inInter = (COPSIpv6InInterface) inter;\r
-                _inInterface = inInter;\r
-            }\r
-        } else {\r
-            if (_outInterface != null)\r
-                throw new COPSException ("Object outInterface exits");\r
-\r
-            if (inter.isIpv4Address()) {\r
-                COPSIpv4OutInterface outInter = (COPSIpv4OutInterface) inter;\r
-                _outInterface = outInter;\r
-            } else {\r
-                COPSIpv6OutInterface outInter = (COPSIpv6OutInterface) inter;\r
-                _outInterface = outInter;\r
-            }\r
-        }\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add header to the message\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if (hdr.getOpCode() != COPSHeader.COPS_OP_REQ)\r
-            throw new COPSException ("Error Header (no COPS_OP_REQ)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add Context object to the message\r
-     *\r
-     * @param    context             a  COPSContext\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSContext context) throws COPSException {\r
-        if (context == null)\r
-            throw new COPSException ("Null Context");\r
-        _context = context;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add client handle to the message\r
-     *\r
-     * @param    handle              a  COPSHandle\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHandle handle) throws COPSException {\r
-        if (handle == null)\r
-            throw new COPSException ("Null Handle");\r
-        _clientHandle = handle;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add one or more clientSI objects\r
-     *\r
-     * @param    clientSI            a  COPSClientSI\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSClientSI clientSI) throws COPSException {\r
-        if (clientSI == null)\r
-            throw new COPSException ("Null ClientSI");\r
-        _clientSIs.add(clientSI);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add one or more local decision object for a given decision context\r
-     * the context is optional, if null all decision object are tided to\r
-     * message context\r
-     *\r
-     * @param    decision            a  COPSLPDPDecision\r
-     * @param    context             a  COPSContext\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void addLocalDecision(COPSLPDPDecision decision, COPSContext context) throws COPSException {\r
-        if (!decision.isLocalDecision())\r
-            throw new COPSException ("Local Decision");\r
-\r
-        Vector v = (Vector) _decisions.get(context);\r
-        if (decision.isFlagSet()) {\r
-            if (v.size() != 0) {\r
-                //Only one set of decision flags is allowed\r
-                //for each context\r
-                throw new COPSException ("Bad Message format, only one set of decision flags is allowed.");\r
-            }\r
-        } else {\r
-            if (v.size() == 0) {\r
-                //The flags decision must precede any other\r
-                //decision message, since the decision is not\r
-                //flags throw exception\r
-                throw new COPSException ("Bad Message format, flags decision must precede any other decision object.");\r
-            }\r
-        }\r
-        v.add(decision);\r
-        _decisions.put(context,v);\r
-\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add integrity object\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_clientHandle != null) _clientHandle.writeData(id);\r
-        if (_context != null) _context.writeData(id);\r
-\r
-        for (Enumeration e = _clientSIs.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-            clientSI.writeData(id);\r
-        }\r
-\r
-        //Display any local decisions\r
-        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) _decisions.get(context);\r
-            context.writeData(id);\r
-\r
-            for (Enumeration ee = v.elements() ; e.hasMoreElements() ;) {\r
-                COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();\r
-                decision.writeData(id);\r
-            }\r
-        }\r
-\r
-        if (_integrity != null) _integrity.writeData(id);\r
-\r
-    }\r
-\r
-    /**\r
-     * Return Header\r
-     *\r
-     * @return   a COPSHeader\r
-     *\r
-     */\r
-    public COPSHeader getHeader() {\r
-        return _hdr;\r
-    }\r
-\r
-    /**\r
-     * Return client Handle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _clientHandle;\r
-    }\r
-\r
-    /**\r
-     * Return Context\r
-     *\r
-     * @return   a COPSContext\r
-     *\r
-     */\r
-    public COPSContext getContext() {\r
-        return _context;\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has In Interface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasInInterface() {\r
-        return (_inInterface == null);\r
-    }\r
-\r
-    /**\r
-     * Should check hasInInterface() before calling\r
-     *\r
-     * @return   a COPSInterface\r
-     *\r
-     */\r
-    public COPSInterface getInInterface() {\r
-        return _inInterface;\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has Out interface\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasOutInterface() {\r
-        return (_outInterface == null);\r
-    }\r
-\r
-    /**\r
-     * Should check hasOutInterface() before calling\r
-     *\r
-     * @return   a COPSInterface\r
-     *\r
-     */\r
-    public COPSInterface getOutInterface() {\r
-        return _outInterface;\r
-    }\r
-\r
-    /**\r
-     * Returns a vector if ClientSI objects\r
-     *\r
-     * @return   a Vector\r
-     *\r
-     */\r
-    public Vector getClientSI() {\r
-        return _clientSIs;\r
-    }\r
-\r
-    /**\r
-     * Returns a HashTable of any local decisions\r
-     *\r
-     * @return   a Hashtable\r
-     *\r
-     */\r
-    public Hashtable getLpdpDecisions() {\r
-        return _decisions;\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has Integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity == null);\r
-    }\r
-\r
-    /**\r
-     * Get Integrity. Should check hasIntegrity() becfore calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return _integrity;\r
-    }\r
-\r
-    /**\r
-     * Parses the data and fills COPSReqMsg with its constituents\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        super.parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case HANDLE:\r
-                    _clientHandle = new COPSHandle(buf);\r
-                    _dataStart += _clientHandle.getDataLength();\r
-                    break;\r
-                case CONTEXT:\r
-                    if (_context == null) {\r
-                        //Message context\r
-                        _context = new COPSContext(buf);\r
-                        _dataStart += _context.getDataLength();\r
-                    } else {\r
-                        //lpdp context\r
-                        _lpdpContext = new COPSContext(buf);\r
-                        _dataStart += _lpdpContext.getDataLength();\r
-                    }\r
-                    break;\r
-                case ININTF:\r
-                    if (objHdr.getCType().ordinal() == 1) {\r
-                        _inInterface = new COPSIpv4InInterface(buf);\r
-                    } else {\r
-                        _inInterface = new COPSIpv6InInterface(buf);\r
-                    }\r
-                    _dataStart += _inInterface.getDataLength();\r
-                    break;\r
-                case OUTINTF:\r
-                    if (objHdr.getCType().ordinal() == 1) {\r
-                        _outInterface = new COPSIpv4OutInterface(buf);\r
-                    } else {\r
-                        _outInterface = new COPSIpv6OutInterface(buf);\r
-                    }\r
-                    _dataStart += _outInterface.getDataLength();\r
-                break;\r
-                case LPDP_DEC:\r
-                    COPSLPDPDecision lpdp = new COPSLPDPDecision(buf);\r
-                    _dataStart += lpdp.getDataLength();\r
-                    addLocalDecision(lpdp, _lpdpContext);\r
-                    break;\r
-                case CSI:\r
-                    COPSClientSI csi = new COPSClientSI (buf);\r
-                    _dataStart += csi.getDataLength();\r
-                    _clientSIs.add(csi);\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default:\r
-                    throw new COPSException("Bad Message format, unknown object type");\r
-            }\r
-        }\r
-        checkSanity();\r
-\r
-    }\r
-\r
-    /**\r
-     * Parses the data and fills that follows the header hdr and fills COPSReqMsg\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength() throws COPSException {\r
-        short len = 0;\r
-\r
-        if (_clientHandle != null)\r
-            len += _clientHandle.getDataLength();\r
-\r
-        if (_context != null)\r
-            len += _context.getDataLength();\r
-\r
-        for (Enumeration e = _clientSIs.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-            len += clientSI.getDataLength();\r
-        }\r
-\r
-        //Display any local decisions\r
-        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) _decisions.get(context);\r
-            len += context.getDataLength();\r
-\r
-            for (Enumeration ee = v.elements() ; e.hasMoreElements() ;) {\r
-                COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();\r
-                len += decision.getDataLength();\r
-            }\r
-        }\r
-\r
-        if (_integrity != null) {\r
-            len += _integrity.getDataLength();\r
-        }\r
-\r
-        _hdr.setMsgLength((int) len);\r
-\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_clientHandle != null)\r
-            _clientHandle.dump(os);\r
-\r
-        if (_context != null)\r
-            _context.dump(os);\r
-\r
-        for (Enumeration e = _clientSIs.elements() ; e.hasMoreElements() ;) {\r
-            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
-            clientSI.dump(os);\r
-        }\r
-\r
-        //Display any local decisions\r
-        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
-\r
-            COPSContext context = (COPSContext) e.nextElement();\r
-            Vector v = (Vector) _decisions.get(context);\r
-            context.dump(os);\r
-\r
-            for (Enumeration ee = v.elements() ; e.hasMoreElements() ;) {\r
-                COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();\r
-                decision.dump(os);\r
-            }\r
-        }\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.*;
+
+/**
+ * COPS Request Message (RFC 2748 page. 22)
+ *
+ *   The PEP establishes a request state client handle for which the
+ *   remote PDP may maintain state. The remote PDP then uses this handle
+ *   to refer to the exchanged information and decisions communicated over
+ *   the TCP connection to a particular PEP for a given client-type.
+ *
+ *   Once a stateful handle is established for a new request, any
+ *   subsequent modifications of the request can be made using the REQ
+ *   message specifying the previously installed handle. The PEP is
+ *   responsible for notifying the PDP whenever its local state changes so
+ *   the PDP's state will be able to accurately mirror the PEP's state.
+ *
+ *   The format of the Request message is as follows:
+ *
+ *               <Request Message> ::=  <Common Header>
+ *                                      <Client Handle>
+ *                                      <Context>
+ *                                      [<IN-Int>]
+ *                                      [<OUT-Int>]
+ *                                      [<ClientSI(s)>]
+ *                                      [<LPDPDecision(s)>]
+ *                                      [<Integrity>]
+ *
+ *               <ClientSI(s)> ::= <ClientSI> | <ClientSI(s)> <ClientSI>
+ *
+ *               <LPDPDecision(s)> ::= <LPDPDecision> |
+ *                                     <LPDPDecision(s)> <LPDPDecision>
+ *
+ *               <LPDPDecision> ::= [<Context>]
+ *                                  <LPDPDecision: Flags>
+ *                                  [<LPDPDecision: Stateless Data>]
+ *                                  [<LPDPDecision: Replacement Data>]
+ *                                  [<LPDPDecision: ClientSI Data>]
+ *                                  [<LPDPDecision: Named Data>]
+ *
+ *   The context object is used to determine the context within which all
+ *   the other objects are to be interpreted. It also is used to determine
+ *   the kind of decision to be returned from the policy server. This
+ *   decision might be related to admission control, resource allocation,
+ *   object forwarding and substitution, or configuration.
+ *
+ *   The interface objects are used to determine the corresponding
+ *   interface on which a signaling protocol message was received or is
+ *   about to be sent. They are typically used if the client is
+ *   participating along the path of a signaling protocol or if the client
+ *   is requesting configuration data for a particular interface.
+ *
+ *   ClientSI, the client specific information object, holds the client-
+ *   type specific data for which a policy decision needs to be made. In
+ *   the case of configuration, the Named ClientSI may include named
+ *   information about the module, interface, or functionality to be
+ *   configured. The ordering of multiple ClientSIs is not important.
+ *
+ *   Finally, LPDPDecision object holds information regarding the local
+ *   decision made by the LPDP.
+ *
+ *   Malformed Request messages MUST result in the PDP specifying a
+ *   Decision message with the appropriate error code.
+ *
+ * @version COPSReqMsg.java, v 1.00 2003
+ *
+ */
+public class COPSReqMsg extends COPSMsg {
+
+    // Required Attributes
+    private final COPSHandle _clientHandle;
+    private final COPSContext _context;
+
+    // Optional Attributes
+    private final COPSInterface _inInterface;
+    private final COPSInterface _outInterface;
+    private final COPSIntegrity _integrity;
+
+    // Collection Attributes (can be empty)
+    private final Set<COPSClientSI> _clientSIs;
+    private final Map<COPSContext, Set<COPSLPDPDecision>> _decisions;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message  (required)
+     * @param handle - the COPS Handle (required)
+     * @param context - the COPS Context  (required)
+     * @param integrity - the COPS Integrity (optional)
+     * @param inInterface - the In Interface (optional)
+     * @param outInterface - the Out interface (optional)
+     * @param clientSIs - the Client SIs (optional)
+     * @param decisions - the Decisions by context (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSReqMsg(final short clientType, final COPSHandle handle, final COPSContext context,
+                      final COPSIntegrity integrity, final COPSInterface inInterface, final COPSInterface outInterface,
+                      final Set<COPSClientSI> clientSIs, final Map<COPSContext, Set<COPSLPDPDecision>> decisions) {
+        this(1, Flag.UNSOLICITED, clientType, handle, context, integrity, inInterface, outInterface,
+                clientSIs, decisions);
+    }
+
+    /**
+     * Recommended constructor generally for use by a client sending messages.
+     * @param version - the supported PCMM Version (required)
+     * @param flag - the flag...  (required)
+     * @param clientType - the type of client that created the message  (required)
+     * @param handle - the COPS Handle  (required)
+     * @param context - the COPS Context  (required)
+     * @param integrity - the COPS Integrity (optional)
+     * @param inInterface - the In Interface (optional)
+     * @param outInterface - the Out interface (optional)
+     * @param clientSIs - the Client SIs (optional)
+     * @param decisions - the Decisions by context (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSReqMsg(final int version, final Flag flag, final short clientType, final COPSHandle handle,
+                      final COPSContext context, final COPSIntegrity integrity, final COPSInterface inInterface,
+                      final COPSInterface outInterface, final Set<COPSClientSI> clientSIs,
+                      final Map<COPSContext, Set<COPSLPDPDecision>> decisions) {
+        this(new COPSHeader(version, flag, OPCode.REQ, clientType), handle, context, integrity, inInterface,
+                outInterface, clientSIs, decisions);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header (required)
+     * @param handle - the COPS Handle (required)
+     * @param context - the COPS Context (required)
+     * @param integrity - the COPS Integrity (optional)
+     * @param inInterface - the In Interface (optional)
+     * @param outInterface - the Out interface (optional)
+     * @param clientSIs - the Client SIs (optional)
+     * @param decisions - the Decisions by context (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSReqMsg(final COPSHeader hdr, final COPSHandle handle, final COPSContext context,
+                      final COPSIntegrity integrity, final COPSInterface inInterface, final COPSInterface outInterface,
+                      final Set<COPSClientSI> clientSIs, final Map<COPSContext, Set<COPSLPDPDecision>> decisions) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.REQ))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.REQ);
+        if (handle == null) throw new IllegalArgumentException("COPSHandle must not be null");
+        if (context == null) throw new IllegalArgumentException("COPSContext must not be null");
+
+        _clientHandle = handle;
+        _context = context;
+        _integrity = integrity;
+        _inInterface = inInterface;
+        _outInterface = outInterface;
+
+        if (clientSIs == null) _clientSIs = Collections.unmodifiableSet(new HashSet<COPSClientSI>());
+        else _clientSIs = Collections.unmodifiableSet(clientSIs);
+
+        if (decisions == null) _decisions = Collections.unmodifiableMap(new HashMap<COPSContext, Set<COPSLPDPDecision>>());
+        else _decisions = Collections.unmodifiableMap(decisions);
+    }
+
+
+    // Getters of optional members - all can return null
+    public COPSIntegrity getIntegrity() { return _integrity; }
+    public COPSInterface getInInterface() { return _inInterface; }
+    public COPSInterface getOutInterface() { return _outInterface; }
+//    public COPSContext getLpdpContext() { return _lpdpContext; }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        _clientHandle.writeData(socket);
+        _context.writeData(socket);
+
+        if (_inInterface != null) _inInterface.writeData(socket);
+        if (_outInterface != null) _outInterface.writeData(socket);
+
+        for (final COPSClientSI clientSI : _clientSIs) {
+            clientSI.writeData(socket);
+        }
+
+        //Display any local decisions
+        for (final Map.Entry<COPSContext, Set<COPSLPDPDecision>> entry : _decisions.entrySet()) {
+            entry.getKey().writeData(socket);
+            for (final COPSDecision decision : entry.getValue()) {
+                decision.writeData(socket);
+            }
+        }
+
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = _context.getDataLength() + _context.getHeader().getHdrLength();
+        out += _clientHandle.getDataLength() + _clientHandle.getHeader().getHdrLength();
+        if (_inInterface != null) out += _inInterface.getDataLength() + _inInterface.getHeader().getHdrLength();
+        if (_outInterface != null) out += _outInterface.getDataLength() + _outInterface.getHeader().getHdrLength();
+
+        for (final COPSClientSI clientSI : _clientSIs) {
+            out += clientSI.getDataLength() + clientSI.getHeader().getHdrLength();
+        }
+
+        for (final Map.Entry<COPSContext, Set<COPSLPDPDecision>> entry : _decisions.entrySet()) {
+            out += entry.getKey().getDataLength() + entry.getKey().getHeader().getHdrLength();
+            for (final COPSDecision decision : entry.getValue()) {
+                out += decision.getDataLength() + decision.getHeader().getHdrLength();
+            }
+        }
+
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+
+    /**
+     * Return client Handle
+     * @return   a COPSHandle
+     */
+    public COPSHandle getClientHandle() {
+        return _clientHandle;
+    }
+
+    /**
+     * Return Context
+     * @return   a COPSContext
+     */
+    public COPSContext getContext() {
+        return _context;
+    }
+
+    /**
+     * Returns a Set of ClientSI objects
+     * @return not null but can be empty
+     */
+    public Set<COPSClientSI> getClientSI() {
+        return _clientSIs;
+    }
+
+    /**
+     * Returns a Map of COPSDecision objects
+     * @return not null but can be empty
+     */
+    public Map<COPSContext, Set<COPSLPDPDecision>> getDecisions() {
+        return _decisions;
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        if (_clientHandle != null)
+            _clientHandle.dump(os);
+
+        if (_context != null)
+            _context.dump(os);
+
+        for (final COPSClientSI clientSI : _clientSIs) {
+            clientSI.dump(os);
+        }
+
+        //Display any local decisions
+        for (final Map.Entry<COPSContext, Set<COPSLPDPDecision>> entry : _decisions.entrySet()) {
+            entry.getKey().dump(os);
+
+            for (final COPSDecision decision : entry.getValue()) {
+                decision.dump(os);
+            }
+        }
+
+        if (_integrity != null) {
+            _integrity.dump(os);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSReqMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSReqMsg that = (COPSReqMsg) o;
+
+        if (this._clientSIs.size() != that._clientSIs.size()) return false;
+        for (final COPSClientSI thisClientSI : this._clientSIs) {
+            boolean found = false;
+            for (final COPSClientSI thatClientSI: that._clientSIs) {
+                if (thisClientSI.equals(thatClientSI)) {
+                    found = true;
+                    break;
+                }
+            }
+            if (! found) return false;
+        }
+
+        for (final Map.Entry<COPSContext, Set<COPSLPDPDecision>> entry : this._decisions.entrySet()) {
+            final Set<COPSLPDPDecision> thatDecisions = that._decisions.get(entry.getKey());
+            if (thatDecisions == null) return false;
+
+            for (final COPSLPDPDecision thisDecision : entry.getValue()) {
+                boolean found = false;
+                for (final COPSLPDPDecision thatDecision: thatDecisions) {
+                    if (thisDecision.equals(thatDecision)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (! found) return false;
+            }
+        }
+
+        if (!this._clientHandle.equals(that._clientHandle)) return false;
+        if (!this._context.equals(that._context)) return false;
+
+        if (this._integrity == null && that._integrity != null) return false;
+        if (this._integrity != null && that._integrity == null) return false;
+        if (this._integrity != null && that._integrity != null)
+            if (!this._integrity.equals(that._integrity)) return false;
+
+        if (this._inInterface == null && that._inInterface != null) return false;
+        if (this._inInterface != null && that._inInterface == null) return false;
+        if (this._inInterface != null && that._inInterface != null)
+            if (!this._inInterface.equals(that._inInterface)) return false;
+
+        if (this._outInterface == null && that._outInterface != null) return false;
+        if (this._outInterface != null && that._outInterface == null) return false;
+        if (this._outInterface != null && that._outInterface != null)
+            if (!this._outInterface.equals(that._outInterface)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + _clientHandle.hashCode();
+        result = 31 * result + _context.hashCode();
+        result = 31 * result + (_inInterface != null ? _inInterface.hashCode() : 0);
+        result = 31 * result + (_outInterface != null ? _outInterface.hashCode() : 0);
+        result = 31 * result + _clientSIs.hashCode();
+        result = 31 * result + _decisions.hashCode();
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSReqMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSReqMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSHandle clientHandle = null;
+        COPSContext context = null;
+        COPSContext lpdpContext = null;
+        COPSIntegrity integrity = null;
+        COPSInterface inInterface = null;
+        COPSInterface outInterface = null;
+        Set<COPSClientSI> clientSIs = new HashSet<>();
+        Map<COPSContext, Set<COPSLPDPDecision>> localDecisions = new HashMap<>();
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case HANDLE:
+                    clientHandle = COPSHandle.parse(objHdrData, buf);
+                    break;
+                case CONTEXT:
+                    if (context == null) context = COPSContext.parse(objHdrData, buf);
+                    else lpdpContext = COPSContext.parse(objHdrData, buf);
+                    break;
+                case ININTF:
+                    if (objHdrData.header.getCType().equals(CType.DEF)) {
+                        inInterface = COPSObjectParser.parseIpv4Interface(objHdrData, buf, true);
+                    } else inInterface = COPSObjectParser.parseIpv6Interface(objHdrData, buf, true);
+                    break;
+                case OUTINTF:
+                    if (objHdrData.header.getCType().equals(CType.DEF)) {
+                        outInterface = COPSObjectParser.parseIpv4Interface(objHdrData, buf, false);
+                    } else  outInterface = COPSObjectParser.parseIpv6Interface(objHdrData, buf, false);
+                    break;
+                case LPDP_DEC:
+                    if (localDecisions.get(lpdpContext) != null)
+                        localDecisions.get(lpdpContext).add(COPSLPDPDecision.parse(objHdrData, buf));
+                    else {
+                        final Set<COPSLPDPDecision> decisions = new HashSet<>();
+                        decisions.add(COPSLPDPDecision.parse(objHdrData, buf));
+                        localDecisions.put(lpdpContext, decisions);
+                    }
+                    break;
+                case CSI:
+                    clientSIs.add(COPSClientSI.parse(objHdrData, buf));
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSReqMsg(hdrData.header, clientHandle, context, integrity, inInterface, outInterface,
+                clientSIs, localDecisions);
+    }
+
+}
+
index b9d352db325a9e22f0b0fbfa2af3942acc8fecf4..54509eef1a3ebf8db90c9cebf90adf927c6ffb69 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Sync State Message (RFC 2748 pag. 26 and pag. 29\r
- *\r
- *   The format of the Synchronize State Query message is as follows:\r
- *\r
- *              <Synchronize State> ::= <Common Header>\r
- *                                      [<Client Handle>]\r
- *                                      [<Integrity>]\r
- *\r
- *   This message indicates that the remote PDP wishes the client (which\r
- *   appears in the common header) to re-send its state. If the optional\r
- *   Client Handle is present, only the state associated with this handle\r
- *   is synchronized. If the PEP does not recognize the requested handle,\r
- *   it MUST immediately send a DRQ message to the PDP for the handle that\r
- *   was specified in the SSQ message. If no handle is specified in the\r
- *    SSQ message, all the active client state MUST be synchronized with\r
- *   the PDP.\r
- *\r
- *   The client performs state synchronization by re-issuing request\r
- *   queries of the specified client-type for the existing state in the\r
- *   PEP. When synchronization is complete, the PEP MUST issue a\r
- *   synchronize state complete message to the PDP.\r
- *\r
- *         <Synchronize State Complete>  ::= <Common Header>\r
- *                                           [<Client Handle>]\r
- *                                           [<Integrity>]\r
- *\r
- *   The Client Handle object only needs to be included if the corresponding\r
- *   Synchronize State Message originally referenced a specific handle.\r
- *\r
- * @version COPSSyncStateMsg.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSSyncStateMsg extends COPSMsg {\r
-\r
-    /* COPSHeader coming from base class */\r
-    private COPSHandle  _clientHandle;\r
-    private COPSIntegrity  _integrity;\r
-\r
-    public COPSSyncStateMsg() {\r
-        _clientHandle = null;\r
-        _integrity = null;\r
-    }\r
-\r
-    /**\r
-          Parse data and create COPSSyncStateMsg object\r
-     */\r
-    protected COPSSyncStateMsg(byte[] data) throws COPSException  {\r
-        _clientHandle = null;\r
-        _integrity = null;\r
-        parse(data);\r
-    }\r
-\r
-    /**\r
-     * Checks the sanity of COPS message and throw an\r
-     * COPSException when data is bad.\r
-     */\r
-    public void checkSanity() throws COPSException {\r
-        if (_hdr == null) {\r
-            throw new COPSException("Bad message format");\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Add message header\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHeader hdr) throws COPSException {\r
-        if (hdr == null)\r
-            throw new COPSException ("Null Header");\r
-        if ((hdr.getOpCode() != COPSHeader.COPS_OP_SSC) &&\r
-                (hdr.getOpCode() != COPSHeader.COPS_OP_SSQ))\r
-            throw new COPSException ("Error Header (no COPS_OP_SSX)");\r
-        _hdr = hdr;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add client handle to the message\r
-     *\r
-     * @param    handle              a  COPSHandle\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSHandle handle) throws COPSException {\r
-        if (handle == null)\r
-            throw new COPSException ("Null Handle");\r
-\r
-        //Message integrity object should be the very last one\r
-        //If it is already added\r
-        if (_integrity != null)\r
-            throw new COPSException ("No null Handle");\r
-\r
-        _clientHandle = handle;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Add integrity object\r
-     *\r
-     * @param    integrity           a  COPSIntegrity\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    public void add (COPSIntegrity integrity) throws COPSException {\r
-        if (integrity == null)\r
-            throw new COPSException ("Null Integrity");\r
-        if (!integrity.isMessageIntegrity())\r
-            throw new COPSException ("Error Integrity");\r
-        _integrity = integrity;\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * If the optional Client Handle is present, only the state associated\r
-      * with this handle is synchronized. If no handle is specified in the\r
-      * SSQ message, all the active client state MUST be synchronized with\r
-      * the PDP.\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasClientHandle() {\r
-        return (_clientHandle != null);\r
-    }\r
-\r
-    /**\r
-     * Get client Handle\r
-     *\r
-     * @return   a COPSHandle\r
-     *\r
-     */\r
-    public COPSHandle getClientHandle() {\r
-        return _clientHandle;\r
-    }\r
-\r
-    /**\r
-     * Returns true if it has integrity object\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean hasIntegrity() {\r
-        return (_integrity != null);\r
-    }\r
-\r
-    /**\r
-     * Get Integrity. Should check hasIntegrity() before calling\r
-     *\r
-     * @return   a COPSIntegrity\r
-     *\r
-     */\r
-    public COPSIntegrity getIntegrity() {\r
-        return (_integrity);\r
-    }\r
-\r
-    /**\r
-     * Writes data to given socket\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        // checkSanity();\r
-        if (_hdr != null) _hdr.writeData(id);\r
-        if (_clientHandle != null) _clientHandle.writeData(id);\r
-        if (_integrity != null) _integrity.writeData(id);\r
-\r
-    }\r
-\r
-    /**\r
-     * Parse data\r
-     *\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(byte[] data) throws COPSException {\r
-        super.parseHeader(data);\r
-\r
-        while (_dataStart < _dataLength) {\r
-            byte[] buf = new byte[data.length - _dataStart];\r
-            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
-\r
-            COPSObjHeader objHdr = COPSObjHeader.parse(buf);\r
-            switch (objHdr.getCNum()) {\r
-                case HANDLE:\r
-                    _clientHandle = new COPSHandle(buf);\r
-                    _dataStart += _clientHandle.getDataLength();\r
-                    break;\r
-                case MSG_INTEGRITY:\r
-                    _integrity = new COPSIntegrity(buf);\r
-                    _dataStart += _integrity.getDataLength();\r
-                    break;\r
-                default:\r
-                    throw new COPSException("Bad Message format, unknown object type");\r
-            }\r
-        }\r
-        checkSanity();\r
-    }\r
-\r
-    /**\r
-     * Parse data\r
-     *\r
-     * @param    hdr                 a  COPSHeader\r
-     * @param    data                a  byte[]\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
-\r
-        if ((hdr.getOpCode() != COPSHeader.COPS_OP_SSC) &&\r
-                (hdr.getOpCode() != COPSHeader.COPS_OP_SSQ))\r
-            throw new COPSException ("Error Header (no COPS_OP_SSX)");\r
-\r
-        _hdr = hdr;\r
-        parse(data);\r
-        setMsgLength();\r
-    }\r
-\r
-    /**\r
-     * Set the message length, base on the set of objects it contains\r
-     *\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    protected void setMsgLength() throws COPSException {\r
-        short len = 0;\r
-        if (_clientHandle != null) len += _clientHandle.getDataLength();\r
-        if (_integrity != null) len += _integrity.getDataLength();\r
-        _hdr.setMsgLength(len);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _hdr.dump(os);\r
-\r
-        if (_clientHandle != null)\r
-            _clientHandle.dump(os);\r
-\r
-        if (_integrity != null) {\r
-            _integrity.dump(os);\r
-        }\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * COPS Sync State Message (RFC 2748 pg. 26 and pg. 29
+ *
+ *   The format of the Synchronize State Query message is as follows:
+ *
+ *              <Synchronize State> ::= <Common Header>
+ *                                      [<Client Handle>]
+ *                                      [<Integrity>]
+ *
+ *   This message indicates that the remote PDP wishes the client (which
+ *   appears in the common header) to re-send its state. If the optional
+ *   Client Handle is present, only the state associated with this handle
+ *   is synchronized. If the PEP does not recognize the requested handle,
+ *   it MUST immediately send a DRQ message to the PDP for the handle that
+ *   was specified in the SSQ message. If no handle is specified in the
+ *    SSQ message, all the active client state MUST be synchronized with
+ *   the PDP.
+ *
+ *   The client performs state synchronization by re-issuing request
+ *   queries of the specified client-type for the existing state in the
+ *   PEP. When synchronization is complete, the PEP MUST issue a
+ *   synchronize state complete message to the PDP.
+ *
+ *         <Synchronize State Complete>  ::= <Common Header>
+ *                                           [<Client Handle>]
+ *                                           [<Integrity>]
+ *
+ *   The Client Handle object only needs to be included if the corresponding
+ *   Synchronize State Message originally referenced a specific handle.
+ *
+ * @version COPSSyncStateMsg.java, v 1.00 2003
+ *
+ */
+public class COPSSyncStateMsg extends COPSMsg {
+
+    // Optional
+    private final COPSHandle  _clientHandle;
+    private final COPSIntegrity  _integrity;
+
+    /**
+     * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
+     * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
+     * @param clientType - the type of client that created the message (required)
+     * @param handle - the handle (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    @Deprecated
+    public COPSSyncStateMsg(final short clientType, final COPSHandle handle, final COPSIntegrity integrity) {
+        this(new COPSHeader(OPCode.SSQ, clientType), handle, integrity);
+    }
+
+    /**
+     * Constructor (generally used for sending messages).
+     * @param version - the supported PCMM Version
+     * @param flag - the flag...
+     * @param clientType - the type of client that created the message (required)
+     * @param handle - the handle (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSSyncStateMsg(final int version, final Flag flag, final short clientType, final COPSHandle handle,
+                            final COPSIntegrity integrity) {
+        this(new COPSHeader(version, flag, OPCode.SSQ, clientType), handle, integrity);
+    }
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSHeader information is known.
+     * @param hdr - COPS Header
+     * @param handle - the handle (optional)
+     * @param integrity - the integrity (optional)
+     * @throws java.lang.IllegalArgumentException
+     */
+    protected COPSSyncStateMsg(final COPSHeader hdr, final COPSHandle handle, final COPSIntegrity integrity) {
+        super(hdr);
+        if (!hdr.getOpCode().equals(OPCode.SSQ))
+            throw new IllegalArgumentException("OPCode must be of type - " + OPCode.SSQ);
+        _clientHandle = handle;
+        _integrity = integrity;
+    }
+
+    // Getters
+    public COPSHandle getClientHandle() {
+        return _clientHandle;
+    }
+    public COPSIntegrity getIntegrity() {
+        return (_integrity);
+    }
+
+    @Override
+    protected int getDataLength() {
+        int out = 0;
+        if (_clientHandle != null) out += _clientHandle.getDataLength() + _clientHandle.getHeader().getHdrLength();
+        if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        return out;
+    }
+
+    @Override
+    protected void writeBody(final Socket socket) throws IOException {
+        if (_clientHandle != null) _clientHandle.writeData(socket);
+        if (_integrity != null) _integrity.writeData(socket);
+    }
+
+    @Override
+    protected void dumpBody(final OutputStream os) throws IOException {
+        if (_clientHandle != null) _clientHandle.dump(os);
+        if (_integrity != null) _integrity.dump(os);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof COPSSyncStateMsg)) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final COPSSyncStateMsg that = (COPSSyncStateMsg) o;
+
+        return !(_clientHandle != null ? !_clientHandle.equals(that._clientHandle) : that._clientHandle != null) &&
+                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (_clientHandle != null ? _clientHandle.hashCode() : 0);
+        result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Responsible for parsing a byte array to create a COPSReqMsg object
+     * @param hdrData - the object's header data
+     * @param data - the byte array to parse
+     * @return - the message object
+     * @throws COPSException
+     */
+    public static COPSSyncStateMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
+        // Variables for constructor
+        COPSHandle clientHandle = null;
+        COPSIntegrity integrity = null;
+
+        int dataStart = 0;
+        while (dataStart < data.length) {
+            final byte[] buf = new byte[data.length - dataStart];
+            System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
+
+            final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
+            switch (objHdrData.header.getCNum()) {
+                case HANDLE:
+                    clientHandle = COPSHandle.parse(objHdrData, buf);
+                    break;
+                case MSG_INTEGRITY:
+                    integrity = COPSIntegrity.parse(objHdrData, buf);
+                    break;
+                default:
+                    throw new COPSException("Bad Message format, unknown object type");
+            }
+            dataStart += objHdrData.msgByteCount;
+        }
+
+        return new COPSSyncStateMsg(hdrData.header, clientHandle, integrity);
+    }
+
+}
+
+
+
index e44e93ae83ca8fb057397bcfad4d32a8ed3b9b3a..db144928d03d2d3342466e123046c76b614c6a5a 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Timer Object\r
- *\r
- * @version COPSTimer.java, v 1.00 2003\r
- *\r
- */\r
-public abstract class COPSTimer extends COPSObjBase {\r
-\r
-    protected COPSObjHeader _objHdr;\r
-    private short _reserved;\r
-    private short _timerValue;\r
-\r
-    /**\r
-     * Returns size in number of octects, including header\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getDataLength() {\r
-        //Add the size of the header also\r
-        return (_objHdr.getDataLength());\r
-    }\r
-\r
-    /**\r
-     * Method getTimerVal\r
-     *\r
-     * @return   a short\r
-     *\r
-     */\r
-    public short getTimerVal() {\r
-        return _timerValue;\r
-    };\r
-\r
-    /**\r
-     * Method isTimer\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isTimer() {\r
-        return true;\r
-    };\r
-\r
-    /**\r
-     * Method isKATimer\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isKATimer() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Method isAcctTimer\r
-     *\r
-     * @return   a boolean\r
-     *\r
-     */\r
-    public boolean isAcctTimer() {\r
-        return false;\r
-    };\r
-\r
-    /**\r
-     * Write data to given socket in Network byte order\r
-     *\r
-     * @param    id                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void writeData(Socket id) throws IOException {\r
-        _objHdr.writeData(id);\r
-\r
-        byte[] buf = new byte[4];\r
-\r
-        buf[0] = (byte) (_reserved >> 8);\r
-        buf[1] = (byte) _reserved;\r
-        buf[2] = (byte) (_timerValue >> 8);\r
-        buf[3] = (byte) _timerValue;\r
-        COPSUtil.writeData(id, buf, 4);\r
-    }\r
-\r
-    protected COPSTimer(COPSObjHeader hdr, short timeVal) {\r
-        _objHdr = hdr;\r
-        //Time range is 1 - 65535 seconds\r
-        _timerValue = timeVal;\r
-        // _objHdr.setDataLength(sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-     * Receive data that is in netwrok byte order and fill in the obj.\r
-     */\r
-    protected COPSTimer(byte[] dataPtr) {\r
-        _objHdr = COPSObjHeader.parse(dataPtr);\r
-\r
-        _reserved |= ((short) dataPtr[4]) << 8;\r
-        _reserved |= ((short) dataPtr[5]) & 0xFF;\r
-        _timerValue |= ((short) dataPtr[6]) << 8;\r
-        _timerValue |= ((short) dataPtr[7]) & 0xFF;\r
-\r
-        // _objHdr.setDataLength(sizeof(u_int32_t));\r
-        _objHdr.setDataLength((short) 4);\r
-    }\r
-\r
-    /**\r
-     * Write an object textual description in the output stream\r
-     *\r
-     * @param    os                  an OutputStream\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    public void dump(OutputStream os) throws IOException {\r
-        _objHdr.dump(os);\r
-        os.write(new String("Timer val: " + _timerValue + "\n").getBytes());\r
-    }\r
-\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * For extension by other COPS Timer Objects such as COPSAcctTimer & COPSKATimer
+ */
+public abstract class COPSTimer extends COPSObjBase {
+
+    // TODO - determine what is the function of this member
+    private final short _reserved;
+
+    /**
+     * The timer values
+     */
+    private final short _timerValue;
+
+    /**
+     * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
+     * COPSObjHeader information is known
+     * @param header - the object header
+     * @param reserved - ???
+     * @param timerVal - the timer value
+     */
+    protected COPSTimer(final COPSObjHeader header, final short reserved, final short timerVal) {
+        super(header);
+        _reserved = reserved;
+        _timerValue = timerVal;
+    }
+
+    /**
+     * Method getTimerVal
+     * @return   a short
+     */
+    public short getTimerVal() {
+        return _timerValue;
+    }
+
+    @Override
+    public void writeBody(Socket socket) throws IOException {
+        byte[] buf = new byte[4];
+
+        buf[0] = (byte) (_reserved >> 8);
+        buf[1] = (byte) _reserved;
+        buf[2] = (byte) (_timerValue >> 8);
+        buf[3] = (byte) _timerValue;
+        COPSUtil.writeData(socket, buf, 4);
+    }
+
+    @Override
+    protected int getDataLength() {
+        return 4;
+    }
+
+    @Override
+    public void dumpBody(final OutputStream os) throws IOException {
+        os.write(("Timer val: " + _timerValue + "\n").getBytes());
+    }
+
+}
+
index 56471de758ed8c85c58cbc5c404a8fee4e355a84..eb75cbc9b2095bd4b5dfe21f805711348f5fd9f1 100644 (file)
@@ -1,91 +1,42 @@
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.net.Socket;\r
-\r
-// import org.umu.cops.common.COPSDebug;\r
-\r
-/**\r
- * COPS Transceiver\r
- *\r
- * @version COPSTransceiver.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSTransceiver {\r
-\r
-    /**\r
-     * Method sendMsg\r
-     *\r
-     * @param    msg                 a  COPSMsg\r
-     * @param    fd                  a  Socket\r
-     *\r
-     * @throws   IOException\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    static public void sendMsg(COPSMsg msg, Socket fd) throws IOException, COPSException {\r
-        // COPSDebug.out("COPSTransceiver", "sendMsg ******************************** START" );\r
-\r
-        msg.checkSanity();\r
-        msg.writeData(fd);\r
-\r
-        // COPSDebug.out("COPSTransceiver", "sendMsg ******************************** END" );\r
-    }\r
-\r
-    /**\r
-     * Method receiveMsg\r
-     *\r
-     * @param    fd                  a  Socket\r
-     *\r
-     * @return   a COPSMsg\r
-     *\r
-     * @throws   IOException\r
-     * @throws   COPSException\r
-     *\r
-     */\r
-    static public COPSMsg receiveMsg (Socket fd)  throws IOException, COPSException {\r
-        int nread = 0;\r
-        byte[] hBuf = new byte[8];\r
-\r
-        // COPSDebug.out("COPSTransceiver", "receiveMsg ******************************** START" );\r
-\r
-        nread = COPSUtil.readData(fd, hBuf, 8);\r
-\r
-        if (nread == 0) {\r
-            throw new COPSException("Error reading connection");\r
-        }\r
-\r
-        if (nread != 8) {\r
-            throw new COPSException("Bad COPS message");\r
-        }\r
-\r
-        COPSHeader hdr = new COPSHeader(hBuf);\r
-        int dataLen = hdr.getMsgLength() - hdr.getHdrLength();\r
-        // COPSDebug.out("COPSTransceiver", "COPS Msg length :[" + dataLen + "]\n" );\r
-        byte[] buf = new byte[dataLen + 1];\r
-        nread = 0;\r
-\r
-        nread = COPSUtil.readData(fd, buf, dataLen);\r
-        buf[dataLen] = (byte) '\0';\r
-        // COPSDebug.out("COPSTransceiver", "Data read length:[" + nread + "]\n");\r
-\r
-        if (nread != dataLen) {\r
-            throw new COPSException("Bad COPS message");\r
-        }\r
-\r
-        COPSMsgParser prser = new COPSMsgParser();\r
-        COPSMsg msg = prser.parse(hdr, buf);\r
-\r
-        // COPSDebug.out("COPSTransceiver", "Message received");\r
-\r
-        // COPSDebug.out("COPSTransceiver", "receiveMsg ******************************** END" );\r
-        return msg;\r
-    }\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.net.Socket;
+
+/**
+ * Utilities for sending and receiving COPS messages
+ *
+ * @version COPSTransceiver.java, v 1.00 2003
+ *
+ */
+public class COPSTransceiver {
+
+    /**
+     * Method sendMsg
+     * @param    msg                 a  COPSMsg
+     * @param    fd                  a  Socket
+     * @throws   IOException
+     * @throws   COPSException
+     */
+    static public void sendMsg(final COPSMsg msg, final Socket fd) throws IOException, COPSException {
+        msg.writeData(fd);
+    }
+
+    /**
+     * Parses a COPS message coming in via the socket
+     * @param    socket - the socket from which the message will arrive
+     * @return   a COPSMsg object
+     * @throws   IOException
+     * @throws   COPSException
+     */
+    static public COPSMsg receiveMsg(final Socket socket) throws IOException, COPSException {
+        return COPSMsgParser.parseMessage(socket);
+    }
+}
+
index 072da7b1f860fb1542f3cf768830df0a4e587baa..81acff906ed3c6d31fa6601c31fd3f21b7e1f16c 100644 (file)
-/*\r
- * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-import java.util.Date;\r
-\r
-/**\r
- * COPS Utils\r
- *\r
- * @version COPSUtil.java, v 2.00 2004\r
- *\r
- */\r
-public class COPSUtil {\r
-\r
-    /**\r
-     * Method writeData\r
-     *\r
-     * @param    id                  a  Socket\r
-     * @param    data                a  byte[]\r
-     * @param    len                 an int\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    static void writeData(Socket id, byte[] data, int len) throws IOException {\r
-        OutputStream output;\r
-        output = id.getOutputStream();\r
-\r
-        output.write(data,0,len);\r
-    }\r
-\r
-    /**\r
-     * Reads nchar from a given sockets, blocks on read untill nchar are read of conenction has error\r
-     * bRead returns the bytes read\r
-     *\r
-     * @param    connId              a  Socket\r
-     * @param    dataRead            a  byte[]\r
-     * @param    nchar               an int\r
-     *\r
-     * @return   an int\r
-     *\r
-     * @throws   IOException\r
-     *\r
-     */\r
-    static int readData(Socket connId, byte[] dataRead, int nchar)  throws IOException {\r
-        InputStream input;\r
-        input = connId.getInputStream();\r
-\r
-        int nread = 0;\r
-        int startTime = (int) (new Date().getTime());\r
-        do {\r
-            if (input.available() != 0) {\r
-                nread += input.read(dataRead,nread,nchar-nread);\r
-                startTime = (int) (new Date().getTime());\r
-            } else {\r
-                int nowTime = (int) (new Date().getTime());\r
-                if ((int)(nowTime - startTime) > 2000)\r
-                    break;\r
-            }\r
-        } while (nread != nchar);\r
-\r
-        return nread;\r
-    }\r
-}\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * Class to hold static utilitarian methods for streaming bytes over a Socket.
+ *
+ * @version COPSUtil.java, v 2.00 2004
+ *
+ */
+public class COPSUtil {
+
+    private final static Logger logger = LoggerFactory.getLogger(COPSUtil.class);
+
+    /**
+     * Streams COPS data
+     * @param    socket                  a  Socket
+     * @param    data                a  byte[]
+     * @param    len                 an int
+     * @throws   IOException
+     */
+    public static void writeData(final Socket socket, final byte[] data, final int len) throws IOException {
+        logger.trace("Writing COPS data");
+        socket.getOutputStream().write(data, 0, len);
+    }
+
+    /**
+     * Returns true if the data contained within data1 + padding1 is equivalent to data2 + padding2
+     * @param data1 - the data from the first
+     * @param padding1 - the padding from the first
+     * @param data2 - the data from the second
+     * @param padding2 - the padding from the second
+     * @return - t/f
+     */
+    public static boolean copsDataPaddingEquals(final COPSData data1, final COPSData padding1,
+                                                final COPSData data2, final COPSData padding2) {
+        final byte[] data1Bytes = data1.getData();
+        final byte[] padding1Bytes = padding1.getData();
+
+        final byte[] data2Bytes = data2.getData();
+        final byte[] padding2Bytes = padding2.getData();
+
+        if (data1Bytes.length + padding1Bytes.length != data2Bytes.length + padding2Bytes.length)
+            return false;
+
+        final ByteArrayOutputStream thisStream = new ByteArrayOutputStream();
+        final ByteArrayOutputStream thatStream = new ByteArrayOutputStream();
+        try {
+            thisStream.write(data1Bytes);
+            thisStream.write(padding1Bytes);
+            thatStream.write(data2Bytes);
+            thatStream.write(padding2Bytes);
+            return Arrays.equals(thisStream.toByteArray(), thatStream.toByteArray());
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Reads nchar from a given sockets, blocks on read untill nchar are read of conenction has error
+     * bRead returns the bytes read
+     *
+     * @param    connId              a  Socket
+     * @param    dataRead            a  byte[]
+     * @param    nchar               an int
+     *
+     * @return   an int
+     *
+     * @throws   IOException
+     *
+     */
+    @Deprecated
+    static int readData(Socket connId, byte[] dataRead, int nchar)  throws IOException {
+        InputStream input;
+        input = connId.getInputStream();
+
+        int nread = 0;
+        int startTime = (int) (new Date().getTime());
+        do {
+            if (input.available() != 0) {
+                nread += input.read(dataRead,nread,nchar-nread);
+                startTime = (int) (new Date().getTime());
+            } else {
+                int nowTime = (int) (new Date().getTime());
+                if ((nowTime - startTime) > 2000)
+                    break;
+            }
+        } while (nread != nchar);
+
+        return nread;
+    }
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSAcctTimerTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSAcctTimerTest.java
new file mode 100644 (file)
index 0000000..d7625ca
--- /dev/null
@@ -0,0 +1,84 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSAcctTimer class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSAcctTimerTest {
+
+    private final static COPSObjHeader defaultHeader = new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF);
+
+    @Test
+    public void testValidTimeAndDefaultHeader() {
+        final COPSAcctTimer timer = new COPSAcctTimer((short)10);
+        Assert.assertEquals((short)10, timer.getTimerVal());
+        Assert.assertEquals(defaultHeader, timer.getHeader());
+    }
+
+    @Test
+    public void testValidTimeReservedAndDefaultHeader() {
+        final COPSAcctTimer timer = new COPSAcctTimer((short) 4, (short)10);
+        Assert.assertEquals((short)10, timer.getTimerVal());
+        Assert.assertEquals(defaultHeader, timer.getHeader());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidCNum() {
+        new COPSAcctTimer(new COPSObjHeader(CNum.CONTEXT, CType.DEF), (short) 4, (short)10);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidCType() {
+        new COPSAcctTimer(new COPSObjHeader(CNum.ACCT_TIMER, CType.REPL), (short) 4, (short)10);
+    }
+
+    @Test
+    public void testValidCustomHeader() {
+        final COPSAcctTimer timer = new COPSAcctTimer(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), (short) 4, (short)10);
+        Assert.assertEquals((short)10, timer.getTimerVal());
+        Assert.assertEquals(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), timer.getHeader());
+    }
+
+    @Test
+    public void testDumpDefaultHeader() throws Exception {
+        final COPSAcctTimer timer = new COPSAcctTimer((short) 4, (short)10);
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        timer.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Account-Timer**", lines[0]);
+        Assert.assertEquals("C-num: ACCT_TIMER", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Timer val: 10", lines[3]);
+    }
+
+    @Test
+    public void testDumpCustomHeader() throws Exception {
+        final COPSAcctTimer timer = new COPSAcctTimer(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF),
+                (short) 4, (short)100);
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        timer.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Account-Timer**", lines[0]);
+        Assert.assertEquals("C-num: ACCT_TIMER", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Timer val: 100", lines[3]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientAcceptMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientAcceptMsgTest.java
new file mode 100644 (file)
index 0000000..d3b482e
--- /dev/null
@@ -0,0 +1,163 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSClientAcceptMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSClientAcceptMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSClientAcceptMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSClientAcceptMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSKATimer((short)1), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSClientAcceptMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSKATimer((short)1), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullTimer() {
+        new COPSClientAcceptMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSClientAcceptMsg(hdr, new COPSKATimer((short)1), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CC, IPCMMClient.CLIENT_TYPE);
+        new COPSClientAcceptMsg(hdr, new COPSKATimer((short)1), null, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSClientAcceptMsg msg = new COPSClientAcceptMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSKATimer((short)1), null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSKATimer((short)1), msg.getKATimer());
+        Assert.assertNull(msg.getAcctTimer());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAll() {
+        final COPSClientAcceptMsg msg = new COPSClientAcceptMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSKATimer((short)1), new COPSAcctTimer((short)1), new COPSIntegrity());
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSKATimer((short)1), msg.getKATimer());
+        Assert.assertEquals(new COPSAcctTimer((short)1), msg.getAcctTimer());
+        Assert.assertEquals(new COPSIntegrity(), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientAcceptMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSClientAcceptMsg msg = new COPSClientAcceptMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSKATimer((short)1), new COPSAcctTimer((short)1), new COPSIntegrity());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(19, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: CAT", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientAcceptMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSClientAcceptMsg msg = new COPSClientAcceptMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSKATimer((short)5), null, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientAcceptMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final COPSClientAcceptMsg msg = new COPSClientAcceptMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSKATimer((short)5), new COPSAcctTimer((short)6),
+                new COPSIntegrity(8, 9, new COPSData("12345")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientCloseMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientCloseMsgTest.java
new file mode 100644 (file)
index 0000000..fcaf0c0
--- /dev/null
@@ -0,0 +1,171 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSClientCloseMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSClientCloseMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSClientCloseMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSClientCloseMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSClientCloseMsg(1, null, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullError() {
+        new COPSClientCloseMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSClientCloseMsg(hdr, new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.NA, IPCMMClient.CLIENT_TYPE);
+        new COPSClientCloseMsg(hdr, new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), null, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSClientCloseMsg msg = new COPSClientCloseMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), msg.getError());
+        Assert.assertNull(msg.getRedirAddr());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAll() throws Exception {
+        final COPSClientCloseMsg msg = new COPSClientCloseMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED),
+                new COPSIpv4PdpRedirectAddress("localhost", 7777, (short)0),
+                new COPSIntegrity());
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), msg.getError());
+        Assert.assertEquals(new COPSIpv4PdpRedirectAddress("localhost", 7777, (short) 0), msg.getRedirAddr());
+        Assert.assertEquals(new COPSIntegrity(), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientCloseMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSClientCloseMsg msg = new COPSClientCloseMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED),
+                new COPSIpv4PdpRedirectAddress("localhost", 7777, (short)0),
+                new COPSIntegrity());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(22, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: CC", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientCloseMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSClientCloseMsg msg = new COPSClientCloseMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.AUTH_REQUIRED), null, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientCloseMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final COPSClientCloseMsg msg = new COPSClientCloseMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSError(ErrorTypes.BAD_HANDLE_REF, ErrorTypes.MA),
+                new COPSIpv4PdpRedirectAddress("localhost", 7777, (short)0),
+                new COPSIntegrity(8, 9, new COPSData("12345")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientOpenMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientOpenMsgTest.java
new file mode 100644 (file)
index 0000000..9a51c72
--- /dev/null
@@ -0,0 +1,217 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSClientSI.CSIType;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSClientOpenMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSClientOpenMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSClientOpenMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSClientOpenMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSPepId(new COPSData()),
+                null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSClientOpenMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSPepId(new COPSData()), null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullPepId() {
+        new COPSClientOpenMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSClientOpenMsg(hdr, new COPSPepId(new COPSData()), null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+        new COPSClientOpenMsg(hdr, new COPSPepId(new COPSData()), null, null, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")), null, null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSPepId(new COPSData("12345")), msg.getPepId());
+        Assert.assertNull(msg.getClientSI());
+        Assert.assertNull(msg.getPdpAddress());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAllIpv4() throws Exception {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")),
+                new COPSClientSI(CSIType.NAMED, new COPSData("123456")),
+                new COPSIpv4LastPdpAddr("localhost", 7777, (short)0),
+                new COPSIntegrity(3, 4, new COPSData("1234567")));
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.UNSOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSPepId(new COPSData("12345")), msg.getPepId());
+        Assert.assertEquals(new COPSClientSI(CSIType.NAMED, new COPSData("123456")), msg.getClientSI());
+        Assert.assertEquals(new COPSIpv4LastPdpAddr("localhost", 7777, (short) 0), msg.getPdpAddress());
+        Assert.assertEquals(new COPSIntegrity(3, 4, new COPSData("1234567")), msg.getIntegrity());
+    }
+
+    @Test
+    public void validAllIpv6() throws Exception {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")),
+                new COPSClientSI(CSIType.NAMED, new COPSData("123456")),
+                new COPSIpv6LastPdpAddr("localhost", 7777, (short)0),
+                new COPSIntegrity(3, 4, new COPSData("1234567")));
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.UNSOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSPepId(new COPSData("12345")), msg.getPepId());
+        Assert.assertEquals(new COPSClientSI(CSIType.NAMED, new COPSData("123456")), msg.getClientSI());
+        Assert.assertEquals(new COPSIpv6LastPdpAddr("localhost", 7777, (short)0), msg.getPdpAddress());
+        Assert.assertEquals(new COPSIntegrity(3, 4, new COPSData("1234567")), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientOpenMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")),
+                new COPSClientSI(CSIType.NAMED, new COPSData("123456")),
+                new COPSIpv4LastPdpAddr("localhost", 7777, (short)0),
+                new COPSIntegrity(3, 4, new COPSData("1234567")));
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(26, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: UNSOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: OPN", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientOpenMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")), null, null, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientOpenMsg object without any nulls for IPv4 addresses
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAllIpv4() throws Exception {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")),
+                new COPSClientSI(CSIType.NAMED, new COPSData("123456")),
+                new COPSIpv4LastPdpAddr("localhost", 7777, (short)0),
+                new COPSIntegrity(3, 4, new COPSData("1234567")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSClientOpenMsg object without any nulls for IPv6 addresses
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAllIpv6() throws Exception {
+        final COPSClientOpenMsg msg = new COPSClientOpenMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSPepId(new COPSData("12345")),
+                new COPSClientSI(CSIType.NAMED, new COPSData("123456")),
+                new COPSIpv6LastPdpAddr("localhost", 7777, (short)0),
+                new COPSIntegrity(3, 4, new COPSData("1234567")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientSITest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientSITest.java
new file mode 100644 (file)
index 0000000..6f9e7cb
--- /dev/null
@@ -0,0 +1,113 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSClientSI.CSIType;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSClientSI class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSClientSITest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCSItype() {
+        new COPSClientSI(CSIType.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullData() {
+        new COPSClientSI(CSIType.SIGNALED, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSClientSI(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSClientSI(new COPSObjHeader(CNum.ACCT_TIMER, CType.CSI), new COPSData());
+    }
+
+    @Test
+    public void csiSignaledEmptyData() {
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData());
+        Assert.assertEquals(CSIType.SIGNALED, clientSI.getCsiType());
+        Assert.assertEquals(CNum.CSI, clientSI.getHeader().getCNum());
+        Assert.assertEquals(CSIType.SIGNALED.ordinal(), clientSI.getHeader().getCType().ordinal());
+        Assert.assertEquals(new COPSData(), clientSI.getData());
+        Assert.assertEquals(0, clientSI.getDataLength());
+    }
+
+    @Test
+    public void csiSignaledUnPaddedData() {
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData("1234"));
+        Assert.assertEquals(CSIType.SIGNALED, clientSI.getCsiType());
+        Assert.assertEquals(CNum.CSI, clientSI.getHeader().getCNum());
+        Assert.assertEquals(CSIType.SIGNALED.ordinal(), clientSI.getHeader().getCType().ordinal());
+        Assert.assertEquals(new COPSData("1234"), clientSI.getData());
+        Assert.assertEquals(4, clientSI.getDataLength());
+    }
+
+    @Test
+    public void csiSignaledPaddedData() {
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData("12345"));
+        Assert.assertEquals(CSIType.SIGNALED, clientSI.getCsiType());
+        Assert.assertEquals(CNum.CSI, clientSI.getHeader().getCNum());
+        Assert.assertEquals(CSIType.SIGNALED.ordinal(), clientSI.getHeader().getCType().ordinal());
+        Assert.assertEquals(new COPSData("12345"), clientSI.getData());
+        Assert.assertEquals(8, clientSI.getDataLength());
+    }
+
+    @Test
+    public void csiNamedPaddedData() {
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.NAMED, new COPSData("12345"));
+        Assert.assertEquals(CSIType.NAMED, clientSI.getCsiType());
+        Assert.assertEquals(CNum.CSI, clientSI.getHeader().getCNum());
+        Assert.assertEquals(CSIType.NAMED.ordinal(), clientSI.getHeader().getCType().ordinal());
+        Assert.assertEquals(new COPSData("12345"), clientSI.getData());
+        Assert.assertEquals(8, clientSI.getDataLength());
+    }
+
+    @Test
+    public void csiNamedDumpPadded() throws Exception {
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.NAMED, new COPSData("12345"));
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        clientSI.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Client-SI**", lines[0]);
+        Assert.assertEquals("C-num: CSI", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("CSI-type: NAMED", lines[3]);
+        Assert.assertEquals("client-SI: 12345", lines[4]);
+    }
+
+    @Test
+    public void csiSignaledDumpUnpadded() throws Exception {
+        final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData("1234"));
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        clientSI.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Client-SI**", lines[0]);
+        Assert.assertEquals("C-num: CSI", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("CSI-type: SIGNALED", lines[3]);
+        Assert.assertEquals("client-SI: 1234", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSContextTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSContextTest.java
new file mode 100644 (file)
index 0000000..6f3012f
--- /dev/null
@@ -0,0 +1,106 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSContext class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSContextTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullRType() {
+        new COPSContext(null, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSContext(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), RType.CONFIG, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSContext(new COPSObjHeader(CNum.CONTEXT, CType.NA), RType.CONFIG, (short)0);
+    }
+
+    @Test
+    public void dumpConfig0() throws Exception {
+        final COPSContext context = new COPSContext(RType.CONFIG, (short)0);
+        Assert.assertEquals(4, context.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        context.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Context**", lines[0]);
+        Assert.assertEquals("C-num: CONTEXT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("context: Configuration,0", lines[3]);
+    }
+
+    @Test
+    public void dumpInAdmin99() throws Exception {
+        final COPSContext context = new COPSContext(RType.IN_ADMIN, (short)99);
+        Assert.assertEquals(4, context.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        context.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Context**", lines[0]);
+        Assert.assertEquals("C-num: CONTEXT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("context: Incoming Message/Admission Control,99", lines[3]);
+    }
+
+    @Test
+    public void dumpResAlloc25() throws Exception {
+        final COPSContext context = new COPSContext(RType.RES_ALLOC, (short)25);
+        Assert.assertEquals(4, context.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        context.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Context**", lines[0]);
+        Assert.assertEquals("C-num: CONTEXT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("context: Resource allocation,25", lines[3]);
+    }
+
+    @Test
+    public void dumpOut15() throws Exception {
+        final COPSContext context = new COPSContext(RType.OUT, (short)15);
+        Assert.assertEquals(4, context.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        context.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Context**", lines[0]);
+        Assert.assertEquals("C-num: CONTEXT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("context: Outgoing message,15", lines[3]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
index 252814b564fc6af708e8fcc5dc21916ead8ad1cc..ef8a7b9e3bb40b2ec4e55c0b5c94b16817a71097 100644 (file)
@@ -13,7 +13,7 @@ public class COPSDataFirstConstructorTest {
     @Test
     public void defaultConstructor() {
         final COPSData data = new COPSData();
-        Assert.assertEquals(null, data.getData());
+        Assert.assertArrayEquals(new byte[0], data.getData());
         Assert.assertEquals(0, data.length());
         Assert.assertEquals("", data.str());
         Assert.assertTrue(data.equals(new COPSData()));
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionMsgTest.java
new file mode 100644 (file)
index 0000000..583d2e4
--- /dev/null
@@ -0,0 +1,367 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for the first constructor of the COPSDecisionMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSDecisionMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSDecisionMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    final static Map<COPSContext, Set<COPSDecision>> staticDecisions = new HashMap<>();
+    static {
+        final Set<COPSDecision> decisions1 = new HashSet<>();
+        decisions1.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData("12345")));
+        staticDecisions.put(new COPSContext(RType.CONFIG, (short)1), decisions1);
+    }
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0WithError() {
+        new COPSDecisionMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0WithDecisions() {
+        new COPSDecisionMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlagWithError() {
+        new COPSDecisionMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlagWithDecisions() {
+        new COPSDecisionMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandleDeprecatedWithError() {
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandleDeprecatedWithDecisions() {
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null, staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandleWithError() {
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null,
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandleWithDecisions() {
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null, staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullErrorDeprecated() {
+        final COPSError error = null;
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullError() {
+        final COPSError error = null;
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullDecisionsDeprecated() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = null;
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullDecisions() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = null;
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyDecisionsMapDeprecated() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyDecisionsMap() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullDecisionsSetDeprecated() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        decisions.put(new COPSContext(RType.CONFIG, (short)1), null);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullDecisionsSet() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        decisions.put(new COPSContext(RType.CONFIG, (short)1), null);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyDecisionsSetDeprecated() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        decisions.put(new COPSContext(RType.CONFIG, (short)1), new HashSet<COPSDecision>());
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyDecisionsSet() {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        decisions.put(new COPSContext(RType.CONFIG, (short)1), new HashSet<COPSDecision>());
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeaderErrorOnly() {
+        final COPSHeader hdr = null;
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
+                null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeaderDecisionsOnly() {
+        final COPSHeader hdr = null;
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHdrErrorOnly() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CC, IPCMMClient.CLIENT_TYPE);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
+                null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHdrDecisionsOnly() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CC, IPCMMClient.CLIENT_TYPE);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void withErrorAndDecisions() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
+                staticDecisions, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullErrorAndDecisions() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, null, null);
+    }
+
+    @Test
+    public void validProtectedError() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
+        final COPSDecisionMsg msg = new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()),
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
+        Assert.assertEquals(OPCode.DEC, msg.getHeader().getOpCode());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(hdr, msg.getHeader());
+        Assert.assertEquals(new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), msg.getError());
+        Assert.assertNotNull(msg.getDecisions());
+        Assert.assertTrue(msg.getDecisions().isEmpty());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validProtectedDecisions() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
+        final COPSDecisionMsg msg = new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()),
+                null, staticDecisions, null);
+        Assert.assertEquals(OPCode.DEC, msg.getHeader().getOpCode());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(hdr, msg.getHeader());
+        Assert.assertNull(msg.getError());
+        Assert.assertNotNull(msg.getDecisions());
+        Assert.assertFalse(msg.getDecisions().isEmpty());
+        Assert.assertNotSame(staticDecisions, msg.getDecisions());
+        Assert.assertEquals(staticDecisions, msg.getDecisions());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSDecisionMsg object with error and no decisions
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpErrorAll() throws Exception {
+        final COPSDecisionMsg msg = new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
+                new COPSIntegrity());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(20, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: UNSOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: DEC", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSDecisionMsg object with error and no decisions
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpDecisionsAll() throws Exception {
+        final COPSDecisionMsg msg = new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData()), staticDecisions, new COPSIntegrity());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(24, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: UNSOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: DEC", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSDecisionMsg error object with the minimal necessary attributes.
+     * It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteErrorMin() throws Exception {
+        final COPSDecisionMsg msg = new COPSDecisionMsg(2, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData("12345")), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.COMM_FAILURE),
+                null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSDecisionMsg error object with all valid attributes.
+     * It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteErrorWithIntegrity() throws Exception {
+        final COPSDecisionMsg msg = new COPSDecisionMsg(2, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData("12345")), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.COMM_FAILURE),
+                new COPSIntegrity(2, 3, new COPSData("123456")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSDecisionMsg error object with all valid attributes.
+     * It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteDecisionsWithIntegrity() throws Exception {
+        final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
+        final COPSContext context1 = new COPSContext(RType.CONFIG, (short)1);
+        final Set<COPSDecision> decisions1 = new HashSet<>();
+        decisions1.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData("12345")));
+        decisions1.add(new COPSDecision(CType.NAMED, Command.NULL, DecisionFlag.REQSTATE, new COPSData("123456")));
+        decisions.put(context1, decisions1);
+
+        final COPSContext context2 = new COPSContext(RType.IN_ADMIN, (short)2);
+        final Set<COPSDecision> decisions2 = new HashSet<>();
+        decisions2.add(new COPSDecision(CType.STATELESS, Command.REMOVE, DecisionFlag.REQERROR, new COPSData("1234567")));
+        decisions.put(context2, decisions2);
+
+        final COPSDecisionMsg msg = new COPSDecisionMsg(2, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData("12345")), decisions, new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionTest.java
new file mode 100644 (file)
index 0000000..4a80f87
--- /dev/null
@@ -0,0 +1,361 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSDecision class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSDecisionTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor1NullCommand() {
+        new COPSDecision(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NullCType() {
+        new COPSDecision(null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NaCType() {
+        new COPSDecision(CType.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NullData() {
+        new COPSDecision(CType.DEF, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor3NullCommand() {
+        new COPSDecision(null, DecisionFlag.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor3NullDecisionFlag() {
+        new COPSDecision(Command.INSTALL, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor4NullCType() {
+        new COPSDecision(null, Command.INSTALL, DecisionFlag.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor4NaCType() {
+        new COPSDecision(CType.NA, Command.INSTALL, DecisionFlag.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor4NullCommand() {
+        new COPSDecision(CType.CSI, null, DecisionFlag.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor4NullFlags() {
+        new COPSDecision(CType.CSI, Command.INSTALL, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor5NullCType() {
+        final CType cType = null;
+        new COPSDecision(cType, Command.INSTALL, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor5NaCType() {
+        new COPSDecision(CType.NA, Command.INSTALL, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor5NullCommand() {
+        new COPSDecision(CType.CSI, null, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor5NullFlags() {
+        new COPSDecision(CType.CSI, Command.INSTALL, null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor5NullData() {
+        new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.NA, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor6NullHeader() {
+        final COPSObjHeader hdr = null;
+        new COPSDecision(hdr, Command.INSTALL, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor6InvalidCNum() {
+        new COPSDecision(new COPSObjHeader(CNum.ACCT_TIMER, CType.CSI), Command.INSTALL, DecisionFlag.NA,
+                new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor6NullCommand() {
+        new COPSDecision(new COPSObjHeader(CNum.DEC, CType.CSI), null, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor6NullDecison() {
+        new COPSDecision(new COPSObjHeader(CNum.DEC, CType.CSI), Command.INSTALL, null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor6NullData() {
+        new COPSDecision(new COPSObjHeader(CNum.DEC, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+    }
+
+    @Test
+    public void constructor1CommandInstall() throws Exception {
+        final COPSDecision decision = new COPSDecision(Command.INSTALL);
+        Assert.assertEquals(Command.INSTALL, decision.getCommand());
+        Assert.assertEquals(4, decision.getDataLength());
+        Assert.assertEquals(new COPSData(), decision.getData());
+        Assert.assertEquals(DecisionFlag.NA, decision.getFlag());
+        Assert.assertEquals("Default", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Decision (Default)", lines[3]);
+        Assert.assertEquals("Command code: INSTALL", lines[4]);
+        Assert.assertEquals("Command flags: NA", lines[5]);
+    }
+
+    @Test
+    public void constructor1CommandRemove() throws Exception {
+        final COPSDecision decision = new COPSDecision(Command.REMOVE);
+        Assert.assertEquals(Command.REMOVE, decision.getCommand());
+        Assert.assertEquals(4, decision.getDataLength());
+        Assert.assertEquals(new COPSData(), decision.getData());
+        Assert.assertEquals(DecisionFlag.NA, decision.getFlag());
+        Assert.assertEquals("Default", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Decision (Default)", lines[3]);
+        Assert.assertEquals("Command code: REMOVE", lines[4]);
+        Assert.assertEquals("Command flags: NA", lines[5]);
+    }
+
+    @Test
+    public void constructor2ValidCTypeEmptyData() throws Exception {
+        final COPSDecision decision = new COPSDecision(CType.DEF, new COPSData());
+        Assert.assertEquals(Command.NULL, decision.getCommand());
+        Assert.assertEquals(4, decision.getDataLength());
+        Assert.assertEquals(new COPSData(), decision.getData());
+        Assert.assertEquals(DecisionFlag.NA, decision.getFlag());
+        Assert.assertEquals("Default", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Decision (Default)", lines[3]);
+        Assert.assertEquals("Command code: NULL", lines[4]);
+        Assert.assertEquals("Command flags: NA", lines[5]);
+    }
+
+    @Test
+    public void constructor2ValidCTypeDefUnpaddedData() throws Exception {
+        final COPSDecision decision = new COPSDecision(CType.DEF, new COPSData("1234"));
+        Assert.assertEquals(Command.NULL, decision.getCommand());
+        Assert.assertEquals(8, decision.getDataLength());
+        Assert.assertEquals(new COPSData("1234"), decision.getData());
+        Assert.assertEquals(DecisionFlag.NA, decision.getFlag());
+        Assert.assertEquals("Default", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Decision (Default)", lines[3]);
+        Assert.assertEquals("Command code: NULL", lines[4]);
+        Assert.assertEquals("Command flags: NA", lines[5]);
+    }
+
+    @Test
+    public void constructor2ValidCTypeDefPaddedData() throws Exception {
+        final COPSDecision decision = new COPSDecision(CType.DEF, new COPSData("12345"));
+        Assert.assertEquals(Command.NULL, decision.getCommand());
+        Assert.assertEquals(12, decision.getDataLength());
+        Assert.assertEquals(new COPSData("12345"), decision.getData());
+        Assert.assertEquals(DecisionFlag.NA, decision.getFlag());
+        Assert.assertEquals("Default", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Decision (Default)", lines[3]);
+        Assert.assertEquals("Command code: NULL", lines[4]);
+        Assert.assertEquals("Command flags: NA", lines[5]);
+    }
+
+    @Test
+    public void constructor2ValidCTypeNamedPaddedData() throws Exception {
+        final COPSDecision decision = new COPSDecision(CType.NAMED, new COPSData("12345"));
+        Assert.assertEquals(Command.NULL, decision.getCommand());
+        Assert.assertEquals(12, decision.getDataLength());
+        Assert.assertEquals(new COPSData("12345"), decision.getData());
+        Assert.assertEquals(DecisionFlag.NA, decision.getFlag());
+        Assert.assertEquals("Named decision data", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: NAMED", lines[2]);
+        Assert.assertEquals("Decision (Named decision data)", lines[3]);
+        Assert.assertEquals("Data: 12345", lines[4]);
+    }
+
+    @Test
+    public void constructor3Valid() throws Exception {
+        final COPSDecision decision = new COPSDecision(Command.INSTALL, DecisionFlag.REQERROR);
+        Assert.assertEquals(Command.INSTALL, decision.getCommand());
+        Assert.assertEquals(4, decision.getDataLength());
+        Assert.assertEquals(new COPSData(), decision.getData());
+        Assert.assertEquals(DecisionFlag.REQERROR, decision.getFlag());
+        Assert.assertEquals("Default", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Decision (Default)", lines[3]);
+        Assert.assertEquals("Command code: INSTALL", lines[4]);
+        Assert.assertEquals("Command flags: REQERROR", lines[5]);
+    }
+
+    @Test
+    public void constructor4Valid() throws Exception {
+        final COPSDecision decision = new COPSDecision(CType.NAMED, Command.REMOVE, DecisionFlag.REQSTATE);
+        Assert.assertEquals(Command.REMOVE, decision.getCommand());
+        Assert.assertEquals(4, decision.getDataLength());
+        Assert.assertEquals(new COPSData(), decision.getData());
+        Assert.assertEquals(DecisionFlag.REQSTATE, decision.getFlag());
+        Assert.assertEquals("Named decision data", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: NAMED", lines[2]);
+        Assert.assertEquals("Decision (Named decision data)", lines[3]);
+        Assert.assertEquals("Data: ", lines[4]);
+    }
+
+    @Test
+    public void constructor5Valid() throws Exception {
+        final COPSDecision decision = new COPSDecision(CType.CSI, Command.REMOVE, DecisionFlag.REQSTATE,
+                new COPSData("1234"));
+        Assert.assertEquals(Command.REMOVE, decision.getCommand());
+        Assert.assertEquals(8, decision.getDataLength());
+        Assert.assertEquals(new COPSData("1234"), decision.getData());
+        Assert.assertEquals(DecisionFlag.REQSTATE, decision.getFlag());
+        Assert.assertEquals("Client specific decision data", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: CSI", lines[2]);
+        Assert.assertEquals("Decision (Client specific decision data)", lines[3]);
+        Assert.assertEquals("Data: 1234", lines[4]);
+    }
+
+    @Test
+    public void constructor6Valid() throws Exception {
+        final COPSDecision decision = new COPSDecision(new COPSObjHeader(CNum.DEC, CType.STATELESS), Command.INSTALL,
+                DecisionFlag.REQERROR, new COPSData("1234"));
+        Assert.assertEquals(Command.INSTALL, decision.getCommand());
+        Assert.assertEquals(8, decision.getDataLength());
+        Assert.assertEquals(new COPSData("1234"), decision.getData());
+        Assert.assertEquals(DecisionFlag.REQERROR, decision.getFlag());
+        Assert.assertEquals("Stateless data", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Decision**", lines[0]);
+        Assert.assertEquals("C-num: DEC", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Decision (Stateless data)", lines[3]);
+        Assert.assertEquals("Data: 1234", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSDeleteMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSDeleteMsgTest.java
new file mode 100644 (file)
index 0000000..73f23fd
--- /dev/null
@@ -0,0 +1,176 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSReason.ReasonCode;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSDeleteMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSDeleteMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSDeleteMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSDeleteMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSDeleteMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandle() {
+        new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null,
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullReasonType() {
+        new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSDeleteMsg(hdr, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+        new COPSDeleteMsg(hdr, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSDeleteMsg msg = new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), msg.getReason());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAll() {
+        final COPSDeleteMsg msg = new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA),
+                new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), msg.getReason());
+        Assert.assertEquals(new COPSIntegrity(4, 5, new COPSData("123456")), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSDeleteMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSDeleteMsg msg = new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA),
+                new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(20, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: DRQ", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSDeleteMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSDeleteMsg msg = new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA), null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSDeleteMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final COPSDeleteMsg msg = new COPSDeleteMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.NA),
+                new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSErrorTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSErrorTest.java
new file mode 100644 (file)
index 0000000..f7aafce
--- /dev/null
@@ -0,0 +1,88 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSError class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSErrorTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullErrorCode() {
+        new COPSError(null, ErrorTypes.AUTH_FAILURE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidErrorCode() {
+        new COPSError(ErrorTypes.NA, ErrorTypes.AUTH_FAILURE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullErrorSubCode() {
+        new COPSError(ErrorTypes.AUTH_FAILURE, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSError(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), ErrorTypes.AUTH_FAILURE, ErrorTypes.BAD_HANDLE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSError(new COPSObjHeader(CNum.ERROR, CType.CSI), ErrorTypes.NA, ErrorTypes.BAD_HANDLE);
+    }
+
+    @Test
+    public void valid1() throws Exception {
+        final COPSError error = new COPSError(ErrorTypes.BAD_HANDLE, ErrorTypes.NA);
+        Assert.assertEquals(ErrorTypes.BAD_HANDLE, error.getErrCode());
+        Assert.assertEquals(ErrorTypes.NA, error.getErrSubCode());
+        Assert.assertEquals(4, error.getDataLength());
+        Assert.assertEquals("Bad handle.:", error.getDescription());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        error.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Error**", lines[0]);
+        Assert.assertEquals("C-num: ERROR", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Error Code: BAD_HANDLE", lines[3]);
+        Assert.assertEquals("Error Sub Code: NA", lines[4]);
+    }
+
+    @Test
+    public void valid2() throws Exception {
+        final COPSError error = new COPSError(ErrorTypes.AUTH_REQUIRED, ErrorTypes.FAIL_PROCESS);
+        Assert.assertEquals(ErrorTypes.AUTH_REQUIRED, error.getErrCode());
+        Assert.assertEquals(ErrorTypes.FAIL_PROCESS, error.getErrSubCode());
+        Assert.assertEquals(4, error.getDataLength());
+        Assert.assertEquals("Authentication required.:", error.getDescription());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        error.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Error**", lines[0]);
+        Assert.assertEquals("C-num: ERROR", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Error Code: AUTH_REQUIRED", lines[3]);
+        Assert.assertEquals("Error Sub Code: FAIL_PROCESS", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
index c583081d4a7b9785b111898dccf17a0cef34639d..e04b442c0c0c5d5ab2cea117b2ed6b3f8f62b84b 100644 (file)
@@ -20,9 +20,8 @@ public class COPSHandleFirstConstructorTest {
     public void constructWithDefaultId() {
         final COPSData id = new COPSData();
         final COPSHandle handle = new COPSHandle(id);
-        Assert.assertEquals(4, handle.getDataLength());
+        Assert.assertEquals(0, handle.getDataLength());
         Assert.assertTrue(id.equals(handle.getId()));
-        validateSuperMethods(handle);
 
         final COPSHandle eqHash = new COPSHandle(id);
         Assert.assertTrue(handle.equals(eqHash));
@@ -31,33 +30,16 @@ public class COPSHandleFirstConstructorTest {
 
     @Test
     public void constructWithData() {
-        final COPSData id = new COPSData("12345678");
+        final COPSData id = new COPSData("12345");
         final COPSHandle handle = new COPSHandle(id);
 
         // TODO - need to determine if 12 is indeed correct given the value "123456778"
-        Assert.assertEquals(12, handle.getDataLength());
+        Assert.assertEquals(8, handle.getDataLength());
         Assert.assertTrue(id.equals(handle.getId()));
-        validateSuperMethods(handle);
 
         final COPSHandle eqHash = new COPSHandle(id);
         Assert.assertTrue(handle.equals(eqHash));
         Assert.assertEquals(handle.hashCode(), eqHash.hashCode());
     }
 
-    private void validateSuperMethods(final COPSHandle handle) {
-        Assert.assertTrue(handle.isClientHandle());
-        Assert.assertFalse(handle.isMessageIntegrity());
-        Assert.assertFalse(handle.isClientSI());
-        Assert.assertFalse(handle.isContext());
-        Assert.assertFalse(handle.isCOPSHeader());
-        Assert.assertFalse(handle.isDecision());
-        Assert.assertFalse(handle.isError());
-        Assert.assertFalse(handle.isInterface());
-        Assert.assertFalse(handle.isLocalDecision());
-        Assert.assertFalse(handle.isPdpAddress());
-        Assert.assertFalse(handle.isPepId());
-        Assert.assertFalse(handle.isReason());
-        Assert.assertFalse(handle.isReport());
-        Assert.assertFalse(handle.isTimer());
-    }
 }
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleSecondConstructorTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleSecondConstructorTest.java
deleted file mode 100644 (file)
index c863f15..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.umu.cops.stack;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Tests for the second constructor of the COPSHandle class.
- * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSHandle had been
- * released and my assumptions may be incorrect.
- */
-public class COPSHandleSecondConstructorTest {
-
-    @Test(expected = IllegalArgumentException.class)
-    public void nullBytes() {
-        final byte[] bytes = null;
-        new COPSHandle(bytes);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyBytes() {
-        new COPSHandle(new byte[]{});
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void oneByte() {
-        new COPSHandle(new byte[]{(byte)1});
-    }
-
-//    @Test
-    // TODO - Determine what values this byte array should contain??? As written, an exception is thrown in COPSData
-    // TODO - when attempting to set the _len attribute.
-    public void fourBytes() {
-        final byte[] bytes = new byte[]{(byte)1, (byte)2, (byte)3, (byte)4, (byte)5};
-        final COPSHandle handle = new COPSHandle(bytes);
-        Assert.assertEquals(4, handle.getDataLength());
-        Assert.fail("Implement me");
-    }
-
-    // TODO - implement more tests once we can determine how exactly to properly instantiate a COPSHandle object
-
-}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSHandleTest.java
new file mode 100644 (file)
index 0000000..6c2a5f3
--- /dev/null
@@ -0,0 +1,141 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSHandle class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSHandle had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSHandleTest {
+
+    private final static COPSObjHeader defaultHeader = new COPSObjHeader(CNum.HANDLE, CType.DEF);
+
+    @Test (expected = IllegalArgumentException.class)
+    public void constructWithNullId() {
+        final COPSData id = null;
+        new COPSHandle(id);
+    }
+
+    @Test
+    public void constructWithDefaultId() {
+        final COPSData id = new COPSData();
+        final COPSHandle handle = new COPSHandle(id);
+
+        Assert.assertEquals(defaultHeader, handle.getHeader());
+        Assert.assertEquals(0, handle.getDataLength());
+        Assert.assertTrue(id.equals(handle.getId()));
+
+        final COPSHandle eqHash = new COPSHandle(id);
+        Assert.assertTrue(handle.equals(eqHash));
+        Assert.assertEquals(handle.hashCode(), eqHash.hashCode());
+    }
+
+    @Test
+    public void constructWithDataNoPadding() {
+        final COPSData id = new COPSData("12345678");
+        final COPSHandle handle = new COPSHandle(id);
+
+        Assert.assertEquals(defaultHeader, handle.getHeader());
+        Assert.assertEquals(8, handle.getDataLength());
+        Assert.assertTrue(id.equals(handle.getId()));
+
+        final COPSHandle eqHash = new COPSHandle(id);
+        Assert.assertTrue(handle.equals(eqHash));
+        Assert.assertEquals(handle.hashCode(), eqHash.hashCode());
+    }
+
+    @Test
+    public void constructWithDataWithPadding() {
+        final COPSData id = new COPSData("123456789");
+        final COPSHandle handle = new COPSHandle(id);
+
+        Assert.assertEquals(defaultHeader, handle.getHeader());
+        Assert.assertEquals(12, handle.getDataLength());
+        Assert.assertTrue(id.equals(handle.getId()));
+
+        final COPSHandle eqHash = new COPSHandle(id);
+        Assert.assertTrue(handle.equals(eqHash));
+        Assert.assertEquals(handle.hashCode(), eqHash.hashCode());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructWithNullHeader() {
+        new COPSHandle(null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructWithHeaderInvalidCNum() {
+        new COPSHandle(new COPSObjHeader(CNum.KA, CType.DEF), new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructWithHeaderInvalidCType() {
+        new COPSHandle(new COPSObjHeader(CNum.HANDLE, CType.REPL), new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructWithNullData() {
+        new COPSHandle(new COPSObjHeader(CNum.HANDLE, CType.DEF), null);
+    }
+
+    @Test
+    public void constructWithHeaderValidCTypeAndDump() throws Exception {
+        final COPSHandle handle = new COPSHandle(new COPSObjHeader(CNum.HANDLE, CType.DEF), new COPSData());
+        Assert.assertEquals(new COPSObjHeader(CNum.HANDLE, CType.DEF), handle.getHeader());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        handle.dump(os);
+        final String out = new String(os.toByteArray());
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Client-handle**", lines[0]);
+        Assert.assertEquals("C-num: HANDLE", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("client-handle: ", lines[3]);
+        System.out.println(out);
+        os.close();
+    }
+
+    @Test
+    public void dumpNoPadding() throws Exception {
+        final COPSHandle handle = new COPSHandle(new COPSData("12345678"));
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        handle.dump(os);
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Client-handle**", lines[0]);
+        Assert.assertEquals("C-num: HANDLE", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("client-handle: 12345678", lines[3]);
+        os.close();
+    }
+
+    @Test
+    public void dumpWithPadding() throws Exception {
+        final COPSData id = new COPSData("123456789");
+        final COPSHandle handle = new COPSHandle(id);
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        handle.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Client-handle**", lines[0]);
+        Assert.assertEquals("C-num: HANDLE", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("client-handle: 123456789", lines[3]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSHeaderTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSHeaderTest.java
new file mode 100644 (file)
index 0000000..df63bd5
--- /dev/null
@@ -0,0 +1,53 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+/**
+ * Tests the construction of the COPSHeader class
+ */
+public class COPSHeaderTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullOPCode1() {
+        new COPSHeader(null, IPCMMClient.CLIENT_TYPE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void zeroVersion() {
+        new COPSHeader(0, Flag.UNSOLICITED, OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlags() {
+        new COPSHeader(1, null, OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullOPCode2() {
+        new COPSHeader(1, Flag.UNSOLICITED, null, IPCMMClient.CLIENT_TYPE);
+    }
+
+    @Test
+    public void validConstructor1() {
+        final COPSHeader header = new COPSHeader(OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+        Assert.assertEquals(1, header.getPcmmVersion());
+        Assert.assertEquals(Flag.UNSOLICITED, header.getFlag());
+        Assert.assertEquals(OPCode.CAT, header.getOpCode());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, header.getClientType());
+    }
+
+    @Test
+    public void validConstructor2() {
+        final COPSHeader header = new COPSHeader(2, Flag.SOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
+        Assert.assertEquals(2, header.getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, header.getFlag());
+        Assert.assertEquals(OPCode.DEC, header.getOpCode());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, header.getClientType());
+    }
+
+    // writeData() will be tested implicitly via the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIntegrityTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIntegrityTest.java
new file mode 100644 (file)
index 0000000..b24c433
--- /dev/null
@@ -0,0 +1,107 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSError class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIntegrityTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSIntegrity(new COPSObjHeader(CNum.NA, CType.DEF), 0, 0, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSIntegrity(new COPSObjHeader(CNum.MSG_INTEGRITY, CType.NA), 0, 0, new COPSData());
+    }
+
+    @Test
+    public void defaultConstructor() throws Exception {
+        final COPSIntegrity integrity = new COPSIntegrity();
+        Assert.assertEquals(0, integrity.getKeyId());
+        Assert.assertEquals(0, integrity.getSeqNum());
+        Assert.assertEquals(new COPSData(), integrity.getKeyDigest());
+        Assert.assertEquals(8, integrity.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        integrity.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Message-Integrity**", lines[0]);
+        Assert.assertEquals("C-num: MSG_INTEGRITY", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Key Id: 0", lines[3]);
+        Assert.assertEquals("Sequence: 0", lines[4]);
+        Assert.assertEquals("Key digest: ", lines[5]);
+    }
+
+    @Test
+    public void nullData() {
+        final COPSIntegrity integrity = new COPSIntegrity(new COPSObjHeader(CNum.MSG_INTEGRITY, CType.DEF), 1, 2, null);
+        Assert.assertEquals(1, integrity.getKeyId());
+        Assert.assertEquals(2, integrity.getSeqNum());
+        Assert.assertEquals(new COPSData(), integrity.getKeyDigest());
+    }
+
+    @Test
+    public void protectedConstructorNoPadding() throws Exception {
+        final COPSIntegrity integrity = new COPSIntegrity(new COPSObjHeader(CNum.MSG_INTEGRITY, CType.DEF), 5, 6,
+                new COPSData("1234"));
+        Assert.assertEquals(5, integrity.getKeyId());
+        Assert.assertEquals(6, integrity.getSeqNum());
+        Assert.assertEquals(new COPSData("1234"), integrity.getKeyDigest());
+        Assert.assertEquals(12, integrity.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        integrity.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Message-Integrity**", lines[0]);
+        Assert.assertEquals("C-num: MSG_INTEGRITY", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Key Id: 5", lines[3]);
+        Assert.assertEquals("Sequence: 6", lines[4]);
+        Assert.assertEquals("Key digest: 1234", lines[5]);
+    }
+
+    @Test
+    public void protectedConstructorWithPadding() throws Exception {
+        final COPSIntegrity integrity = new COPSIntegrity(new COPSObjHeader(CNum.MSG_INTEGRITY, CType.DEF), 5, 6,
+                new COPSData("12345"));
+        Assert.assertEquals(5, integrity.getKeyId());
+        Assert.assertEquals(6, integrity.getSeqNum());
+        Assert.assertEquals(new COPSData("12345"), integrity.getKeyDigest());
+        Assert.assertEquals(16, integrity.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        integrity.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Message-Integrity**", lines[0]);
+        Assert.assertEquals("C-num: MSG_INTEGRITY", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Key Id: 5", lines[3]);
+        Assert.assertEquals("Sequence: 6", lines[4]);
+        Assert.assertEquals("Key digest: 12345", lines[5]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4AddressTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4AddressTest.java
new file mode 100644 (file)
index 0000000..75f8333
--- /dev/null
@@ -0,0 +1,36 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Tests for the COPSIpv4Address class.
+ */
+public class COPSIpv4AddressTest {
+
+    @Test(expected = UnknownHostException.class)
+    public void badHost() throws Exception {
+        new COPSIpv4Address("foo");
+    }
+
+    @Test
+    public void localhost() throws Exception {
+        final COPSIpv4Address address = new COPSIpv4Address("localhost");
+        Assert.assertEquals(4, address.getDataLength());
+        Assert.assertArrayEquals(InetAddress.getByName("localhost").getAddress(), address.getAddressBytes());
+        Assert.assertEquals("localhost", address.getIpName());
+    }
+
+    @Test
+    public void addrBytes() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        final COPSIpv4Address address = new COPSIpv4Address(addr);
+        Assert.assertEquals(4, address.getDataLength());
+        Assert.assertArrayEquals(addr, address.getAddressBytes());
+        Assert.assertEquals("localhost", address.getIpName());
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4InInterfaceTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4InInterfaceTest.java
new file mode 100644 (file)
index 0000000..19c86f5
--- /dev/null
@@ -0,0 +1,66 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSIpv4InInterface class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv4InInterfaceTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddress() {
+        new COPSIpv4InInterface(null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() throws Exception {
+        new COPSIpv4InInterface(null, new COPSIpv4Address("localhost"), 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddressWithHeader() {
+        new COPSIpv4InInterface(new COPSObjHeader(CNum.ININTF, CType.DEF), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSIpv4InInterface(new COPSObjHeader(CNum.HANDLE, CType.DEF), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSIpv4InInterface(new COPSObjHeader(CNum.ININTF, CType.STATELESS), null, 0);
+    }
+
+    @Test
+    public void valid() throws Exception {
+        final COPSIpv4Address address = new COPSIpv4Address("localhost");
+        final COPSIpv4InInterface intf = new COPSIpv4InInterface(address, 5);
+        Assert.assertEquals(new COPSObjHeader(CNum.ININTF, CType.DEF), intf.getHeader());
+        Assert.assertEquals(8, intf.getDataLength());
+        Assert.assertEquals(address, intf._addr);
+        Assert.assertEquals(5, intf._ifindex);
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        intf.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**In-Interface**", lines[0]);
+        Assert.assertEquals("C-num: ININTF", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Address: localhost", lines[3]);
+        Assert.assertEquals("ifindex: 5", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4LastPdpAddrTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4LastPdpAddrTest.java
new file mode 100644 (file)
index 0000000..c45ab10
--- /dev/null
@@ -0,0 +1,112 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Tests for the first constructor of the COPSIpv4LastPdpAddr class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv4LastPdpAddrTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHost() throws Exception {
+        new COPSIpv4LastPdpAddr(null, 1234, (short)0);
+    }
+
+    @Test(expected = UnknownHostException.class)
+    public void invalidHost() throws Exception {
+        new COPSIpv4LastPdpAddr("foo", 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidPort() throws Exception {
+        new COPSIpv4LastPdpAddr("localhost", 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor1() throws Exception {
+        final COPSIpv4LastPdpAddr lastAddr = new COPSIpv4LastPdpAddr("localhost", 1234, (short)0);
+        Assert.assertEquals(8, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Last PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: LAST_PDP_ADDR", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Ipv4LastPdpAddress", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullObjHeader() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4LastPdpAddr(null, addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4LastPdpAddr(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddr() throws Exception {
+        new COPSIpv4LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF), null, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void zeroPort() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF), addr, 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor2() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        final COPSIpv4LastPdpAddr lastAddr = new COPSIpv4LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF),
+                addr, 1234, (short)0);
+        Assert.assertEquals(8, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Last PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: LAST_PDP_ADDR", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Ipv4LastPdpAddress", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4OutInterfaceTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4OutInterfaceTest.java
new file mode 100644 (file)
index 0000000..dd56ecc
--- /dev/null
@@ -0,0 +1,66 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSIpv4OutInterfaceTest class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv4OutInterfaceTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddress() {
+        new COPSIpv4OutInterface(null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() throws Exception {
+        new COPSIpv4OutInterface(null, new COPSIpv4Address("localhost"), 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddressWithHeader() {
+        new COPSIpv4OutInterface(new COPSObjHeader(CNum.OUTINTF, CType.DEF), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSIpv4OutInterface(new COPSObjHeader(CNum.HANDLE, CType.DEF), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSIpv4OutInterface(new COPSObjHeader(CNum.OUTINTF, CType.STATELESS), null, 0);
+    }
+
+    @Test
+    public void valid() throws Exception {
+        final COPSIpv4Address address = new COPSIpv4Address("localhost");
+        final COPSIpv4OutInterface intf = new COPSIpv4OutInterface(address, 5);
+        Assert.assertEquals(new COPSObjHeader(CNum.OUTINTF, CType.DEF), intf.getHeader());
+        Assert.assertEquals(8, intf.getDataLength());
+        Assert.assertEquals(address, intf._addr);
+        Assert.assertEquals(5, intf._ifindex);
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        intf.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Out-Interface**", lines[0]);
+        Assert.assertEquals("C-num: OUTINTF", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Address: localhost", lines[3]);
+        Assert.assertEquals("ifindex: 5", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4PdpRedirectAddressTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv4PdpRedirectAddressTest.java
new file mode 100644 (file)
index 0000000..30f6e11
--- /dev/null
@@ -0,0 +1,112 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Tests for the first constructor of the COPSIpv4PdpRedirectAddress class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv4PdpRedirectAddressTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHost() throws Exception {
+        new COPSIpv4PdpRedirectAddress(null, 1234, (short)0);
+    }
+
+    @Test(expected = UnknownHostException.class)
+    public void invalidHost() throws Exception {
+        new COPSIpv4PdpRedirectAddress("foo", 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidPort() throws Exception {
+        new COPSIpv4PdpRedirectAddress("localhost", 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor1() throws Exception {
+        final COPSIpv4PdpRedirectAddress lastAddr = new COPSIpv4PdpRedirectAddress("localhost", 1234, (short)0);
+        Assert.assertEquals(8, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Redirect PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: PDP_REDIR", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Ipv4PdpRedirectAddress", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullObjHeader() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4PdpRedirectAddress(null, addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4PdpRedirectAddress(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddr() throws Exception {
+        new COPSIpv4PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF), null, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void zeroPort() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        new COPSIpv4PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF), addr, 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor2() throws Exception {
+        final byte[] addr = InetAddress.getByName("localhost").getAddress();
+        final COPSIpv4PdpRedirectAddress lastAddr = new COPSIpv4PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF),
+                addr, 1234, (short)0);
+        Assert.assertEquals(8, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Redirect PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: PDP_REDIR", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Ipv4PdpRedirectAddress", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6AddressTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6AddressTest.java
new file mode 100644 (file)
index 0000000..7c8fefa
--- /dev/null
@@ -0,0 +1,47 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Tests for the COPSIpv6Address class.
+ */
+public class COPSIpv6AddressTest {
+
+    @Test(expected = UnknownHostException.class)
+    public void badHost() throws Exception {
+        new COPSIpv6Address("foo");
+    }
+
+    @Test
+    public void localhost() throws Exception {
+        final COPSIpv6Address address = new COPSIpv6Address("localhost");
+        Assert.assertEquals(16, address.getDataLength());
+        Assert.assertArrayEquals(getLocalhostIpv6Address(), address.getAddressBytes());
+        Assert.assertEquals("localhost", address.getIpName());
+    }
+
+    @Test
+    public void addrBytes() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        final COPSIpv6Address address = new COPSIpv6Address(addr);
+        Assert.assertEquals(16, address.getDataLength());
+        Assert.assertArrayEquals(addr, address.getAddressBytes());
+        Assert.assertEquals("localhost", address.getIpName());
+    }
+
+    private byte[] getLocalhostIpv6Address() throws UnknownHostException {
+        final InetAddress[] addrs = Inet4Address.getAllByName("localhost");
+        for (final InetAddress addr : addrs) {
+            if (addr instanceof Inet6Address) {
+                return addr.getAddress();
+            }
+        }
+        throw new UnknownHostException("InetAddress could not be found");
+    }
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6InInterfaceTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6InInterfaceTest.java
new file mode 100644 (file)
index 0000000..afa9c85
--- /dev/null
@@ -0,0 +1,66 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSIpv6InInterface class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv6InInterfaceTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddress() {
+        new COPSIpv6InInterface(null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() throws Exception {
+        new COPSIpv6InInterface(null, new COPSIpv6Address("localhost"), 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddressWithHeader() {
+        new COPSIpv6InInterface(new COPSObjHeader(CNum.ININTF, CType.STATELESS), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSIpv6InInterface(new COPSObjHeader(CNum.HANDLE, CType.STATELESS), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSIpv6InInterface(new COPSObjHeader(CNum.ININTF, CType.DEF), null, 0);
+    }
+
+    @Test
+    public void valid() throws Exception {
+        final COPSIpv6Address address = new COPSIpv6Address("localhost");
+        final COPSIpv6InInterface intf = new COPSIpv6InInterface(address, 5);
+        Assert.assertEquals(new COPSObjHeader(CNum.ININTF, CType.STATELESS), intf.getHeader());
+        Assert.assertEquals(20, intf.getDataLength());
+        Assert.assertEquals(address, intf._addr);
+        Assert.assertEquals(5, intf._ifindex);
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        intf.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**In-Interface**", lines[0]);
+        Assert.assertEquals("C-num: ININTF", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Address: localhost", lines[3]);
+        Assert.assertEquals("ifindex: 5", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6LastPdpAddrTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6LastPdpAddrTest.java
new file mode 100644 (file)
index 0000000..494635e
--- /dev/null
@@ -0,0 +1,130 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Tests for the first constructor of the COPSIpv6PdpRedirectAddress class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv6LastPdpAddrTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHost() throws Exception {
+        new COPSIpv6LastPdpAddr(null, 1234, (short)0);
+    }
+
+    @Test(expected = UnknownHostException.class)
+    public void invalidHost() throws Exception {
+        new COPSIpv6LastPdpAddr("foo", 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidPort() throws Exception {
+        new COPSIpv6LastPdpAddr("localhost", 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor1() throws Exception {
+        final COPSIpv6LastPdpAddr lastAddr = new COPSIpv6LastPdpAddr("localhost", 1234, (short)0);
+        Assert.assertEquals(20, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Last PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: LAST_PDP_ADDR", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Ipv6LastPdpAddr", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullObjHeader() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6LastPdpAddr(null, addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6LastPdpAddr(new COPSObjHeader(CNum.ACCT_TIMER, CType.STATELESS), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.DEF), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddr() throws Exception {
+        new COPSIpv6LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), null, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void ipv4Addr() throws Exception {
+        final byte[] addr = new byte[] { 127, 0, 0, 1};
+        new COPSIpv6LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void zeroPort() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), addr, 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor2() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        final COPSIpv6LastPdpAddr lastAddr = new COPSIpv6LastPdpAddr(new COPSObjHeader(CNum.LAST_PDP_ADDR,
+                CType.STATELESS), addr, 1234, (short)0);
+        Assert.assertEquals(20, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.LAST_PDP_ADDR, CType.STATELESS), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Last PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: LAST_PDP_ADDR", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Ipv6LastPdpAddr", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+
+    private byte[] getLocalhostIpv6Address() throws UnknownHostException {
+        final InetAddress[] addrs = Inet4Address.getAllByName("localhost");
+        for (final InetAddress addr : addrs) {
+            if (addr instanceof Inet6Address) {
+                return addr.getAddress();
+            }
+        }
+        throw new UnknownHostException("InetAddress could not be found");
+    }
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6OutInterfaceTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6OutInterfaceTest.java
new file mode 100644 (file)
index 0000000..e6181cf
--- /dev/null
@@ -0,0 +1,66 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSIpv6OutInterfaceTest class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv6OutInterfaceTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddress() {
+        new COPSIpv6OutInterface(null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() throws Exception {
+        new COPSIpv6OutInterface(null, new COPSIpv6Address("localhost"), 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddressWithHeader() {
+        new COPSIpv6OutInterface(new COPSObjHeader(CNum.OUTINTF, CType.STATELESS), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSIpv6OutInterface(new COPSObjHeader(CNum.HANDLE, CType.STATELESS), null, 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSIpv6OutInterface(new COPSObjHeader(CNum.OUTINTF, CType.DEF), null, 0);
+    }
+
+    @Test
+    public void valid() throws Exception {
+        final COPSIpv6Address address = new COPSIpv6Address("localhost");
+        final COPSIpv6OutInterface intf = new COPSIpv6OutInterface(address, 5);
+        Assert.assertEquals(new COPSObjHeader(CNum.OUTINTF, CType.STATELESS), intf.getHeader());
+        Assert.assertEquals(20, intf.getDataLength());
+        Assert.assertEquals(address, intf._addr);
+        Assert.assertEquals(5, intf._ifindex);
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        intf.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Out-Interface**", lines[0]);
+        Assert.assertEquals("C-num: OUTINTF", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Address: localhost", lines[3]);
+        Assert.assertEquals("ifindex: 5", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6PdpRedirectAddressTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSIpv6PdpRedirectAddressTest.java
new file mode 100644 (file)
index 0000000..e6c8a42
--- /dev/null
@@ -0,0 +1,130 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Tests for the first constructor of the COPSIpv6PdpRedirectAddress class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSIpv6PdpRedirectAddressTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHost() throws Exception {
+        new COPSIpv6PdpRedirectAddress(null, 1234, (short)0);
+    }
+
+    @Test(expected = UnknownHostException.class)
+    public void invalidHost() throws Exception {
+        new COPSIpv6PdpRedirectAddress("foo", 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidPort() throws Exception {
+        new COPSIpv6PdpRedirectAddress("localhost", 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor1() throws Exception {
+        final COPSIpv6PdpRedirectAddress lastAddr = new COPSIpv6PdpRedirectAddress("localhost", 1234, (short)0);
+        Assert.assertEquals(20, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Redirect PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: PDP_REDIR", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Ipv6PdpRedirectAddress", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullObjHeader() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6PdpRedirectAddress(null, addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6PdpRedirectAddress(new COPSObjHeader(CNum.ACCT_TIMER, CType.STATELESS), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.DEF), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullAddr() throws Exception {
+        new COPSIpv6PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), null, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void ipv4Addr() throws Exception {
+        final byte[] addr = new byte[] { 127, 0, 0, 1};
+        new COPSIpv6PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), addr, 1234, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void zeroPort() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        new COPSIpv6PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), addr, 0, (short)0);
+    }
+
+    @Test
+    public void validConstructor2() throws Exception {
+        final byte[] addr = getLocalhostIpv6Address();
+        final COPSIpv6PdpRedirectAddress lastAddr = new COPSIpv6PdpRedirectAddress(new COPSObjHeader(CNum.PDP_REDIR,
+                CType.STATELESS), addr, 1234, (short)0);
+        Assert.assertEquals(20, lastAddr.getDataLength());
+        Assert.assertEquals(new COPSObjHeader(CNum.PDP_REDIR, CType.STATELESS), lastAddr.getHeader());
+        Assert.assertEquals(1234, lastAddr.getTcpPort());
+        Assert.assertEquals(0, lastAddr.getReserved());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        lastAddr.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(6, lines.length);
+        Assert.assertEquals("**Redirect PDP addr**", lines[0]);
+        Assert.assertEquals("C-num: PDP_REDIR", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Ipv6PdpRedirectAddress", lines[3]);
+        Assert.assertEquals("Address: localhost", lines[4]);
+        Assert.assertEquals("Port: 1234", lines[5]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+
+    private byte[] getLocalhostIpv6Address() throws UnknownHostException {
+        final InetAddress[] addrs = Inet4Address.getAllByName("localhost");
+        for (final InetAddress addr : addrs) {
+            if (addr instanceof Inet6Address) {
+                return addr.getAddress();
+            }
+        }
+        throw new UnknownHostException("InetAddress could not be found");
+    }
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSKAMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSKAMsgTest.java
new file mode 100644 (file)
index 0000000..2e13bfa
--- /dev/null
@@ -0,0 +1,148 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSKAMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSKAMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSKAMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSKAMsg(0, Flag.SOLICITED, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSKAMsg(1, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSKAMsg(hdr, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.NA, IPCMMClient.CLIENT_TYPE);
+        new COPSKAMsg(hdr, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSKAMsg msg = new COPSKAMsg(1, Flag.SOLICITED, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals((short)0, msg.getHeader().getClientType());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAll() throws Exception {
+        final COPSKAMsg msg = new COPSKAMsg(1, Flag.SOLICITED, new COPSIntegrity());
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals((short)0, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSIntegrity(), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSKAMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSKAMsg msg = new COPSKAMsg(1, Flag.SOLICITED, new COPSIntegrity());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(11, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: KA", lines[3]);
+        Assert.assertEquals("Client-type: 0", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSKAMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSKAMsg msg = new COPSKAMsg(1, Flag.SOLICITED, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSKAMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final COPSKAMsg msg = new COPSKAMsg(1, Flag.SOLICITED, new COPSIntegrity(8, 9, new COPSData("12345")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSKATimerTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSKATimerTest.java
new file mode 100644 (file)
index 0000000..9d896ab
--- /dev/null
@@ -0,0 +1,84 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSKATimer class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSKATimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSKATimerTest {
+
+    private final static COPSObjHeader defaultHeader = new COPSObjHeader(CNum.KA, CType.DEF);
+
+    @Test
+    public void testValidTimeAndDefaultHeader() {
+        final COPSKATimer timer = new COPSKATimer((short)10);
+        Assert.assertEquals((short)10, timer.getTimerVal());
+        Assert.assertEquals(defaultHeader, timer.getHeader());
+    }
+
+    @Test
+    public void testValidTimeReservedAndDefaultHeader() {
+        final COPSKATimer timer = new COPSKATimer((short) 4, (short)10);
+        Assert.assertEquals((short)10, timer.getTimerVal());
+        Assert.assertEquals(defaultHeader, timer.getHeader());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidCNum() {
+        new COPSKATimer(new COPSObjHeader(CNum.CONTEXT, CType.DEF), (short) 4, (short)10);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidCType() {
+        new COPSKATimer(new COPSObjHeader(CNum.KA, CType.REPL), (short) 4, (short)10);
+    }
+
+    @Test
+    public void testValidCustomHeader() {
+        final COPSKATimer timer = new COPSKATimer(new COPSObjHeader(CNum.KA, CType.DEF), (short) 4, (short)10);
+        Assert.assertEquals((short)10, timer.getTimerVal());
+        Assert.assertEquals(new COPSObjHeader(CNum.KA, CType.DEF), timer.getHeader());
+    }
+
+    @Test
+    public void testDumpDefaultHeader() throws Exception {
+        final COPSKATimer timer = new COPSKATimer((short) 4, (short)10);
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        timer.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**KA-timer**", lines[0]);
+        Assert.assertEquals("C-num: KA", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Timer val: 10", lines[3]);
+    }
+
+    @Test
+    public void testDumpCustomHeader() throws Exception {
+        final COPSKATimer timer = new COPSKATimer(new COPSObjHeader(CNum.KA, CType.DEF),
+                (short) 4, (short)100);
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        timer.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**KA-timer**", lines[0]);
+        Assert.assertEquals("C-num: KA", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Timer val: 100", lines[3]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSLPDPDecisionTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSLPDPDecisionTest.java
new file mode 100644 (file)
index 0000000..3590702
--- /dev/null
@@ -0,0 +1,121 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSLPDPDecision class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSLPDPDecisionTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor1NullCType() {
+        final CType cType = null;
+        new COPSLPDPDecision(cType, Command.INSTALL, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor1NaCType() {
+        new COPSLPDPDecision(CType.NA, Command.INSTALL, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor1NullCommand() {
+        new COPSLPDPDecision(CType.CSI, null, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor1NullFlags() {
+        new COPSLPDPDecision(CType.CSI, Command.INSTALL, null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor1NullData() {
+        new COPSLPDPDecision(CType.CSI, Command.INSTALL, DecisionFlag.NA, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NullHeader() {
+        final COPSObjHeader hdr = null;
+        new COPSLPDPDecision(hdr, Command.INSTALL, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2InvalidCNum() {
+        new COPSLPDPDecision(new COPSObjHeader(CNum.ACCT_TIMER, CType.CSI), Command.INSTALL, DecisionFlag.NA,
+                new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NullCommand() {
+        new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI), null, DecisionFlag.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NullDecison() {
+        new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI), Command.INSTALL, null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void constructor2NullData() {
+        new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+    }
+
+    @Test
+    public void constructor1Valid() throws Exception {
+        final COPSLPDPDecision decision = new COPSLPDPDecision(CType.CSI, Command.REMOVE, DecisionFlag.REQSTATE,
+                new COPSData("1234"));
+        Assert.assertEquals(Command.REMOVE, decision.getCommand());
+        Assert.assertEquals(8, decision.getDataLength());
+        Assert.assertEquals(new COPSData("1234"), decision.getData());
+        Assert.assertEquals(DecisionFlag.REQSTATE, decision.getFlag());
+        Assert.assertEquals("Client specific decision data", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Local-Decision**", lines[0]);
+        Assert.assertEquals("C-num: LPDP_DEC", lines[1]);
+        Assert.assertEquals("C-type: CSI", lines[2]);
+        Assert.assertEquals("Decision (Client specific decision data)", lines[3]);
+        Assert.assertEquals("Data: 1234", lines[4]);
+    }
+
+    @Test
+    public void constructor2Valid() throws Exception {
+        final COPSLPDPDecision decision = new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.STATELESS), Command.INSTALL,
+                DecisionFlag.REQERROR, new COPSData("1234"));
+        Assert.assertEquals(Command.INSTALL, decision.getCommand());
+        Assert.assertEquals(8, decision.getDataLength());
+        Assert.assertEquals(new COPSData("1234"), decision.getData());
+        Assert.assertEquals(DecisionFlag.REQERROR, decision.getFlag());
+        Assert.assertEquals("Stateless data", decision.getTypeStr());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        decision.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Local-Decision**", lines[0]);
+        Assert.assertEquals("C-num: LPDP_DEC", lines[1]);
+        Assert.assertEquals("C-type: STATELESS", lines[2]);
+        Assert.assertEquals("Decision (Stateless data)", lines[3]);
+        Assert.assertEquals("Data: 1234", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSMsgParserTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSMsgParserTest.java
new file mode 100644 (file)
index 0000000..847d185
--- /dev/null
@@ -0,0 +1,89 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+
+/**
+ * Tests the public static COPSMsgParser methods
+ */
+public class COPSMsgParserTest {
+
+    @Test
+    public void testCombineTwoBytesToOne() {
+
+        byte byte1 = (byte)2;
+        byte byte2 = (byte)15;
+        byte combined = (byte)((byte1) * 16 + (byte2));
+
+        System.out.println("Combined value =" + combined + " Hex value = " + Integer.toHexString(combined) );
+
+    }
+
+    @Test
+    public void testCombineAndSplitForAllValidCombinations() {
+        for (byte byte1 = 0; byte1 < 16; byte1++ ) {
+            for (byte byte2 = 0; byte2 < 16; byte2++ ) {
+                int combined = COPSMsgParser.combineNibbles(byte1, byte2);
+                System.out.println("byte1 = " + byte1 + " byte2 = " + byte2 + " Combined value =" + combined + " Hex value = " + Integer.toHexString(combined) );
+
+                Assert.assertTrue(combined >= 0 && combined < 256);
+                byte[] nibbles = COPSMsgParser.splitByteToNibbles((byte) combined);
+
+                Assert.assertEquals("Nibble 1 value = " + nibbles[0], byte1, nibbles[0]);
+                Assert.assertEquals("Nibble 2 value = " + nibbles[1], byte2, nibbles[1]);
+            }
+        }
+    }
+
+    @Test
+    public void testBytesToShortMin() {
+        final byte byte1 = (byte)0;
+        final byte byte2 = (byte)0;
+        final short val = COPSMsgParser.bytesToShort(byte1, byte2);
+        final byte[] outBytes = COPSMsgParser.shortToBytes(val);
+        Assert.assertEquals(byte1, outBytes[0]);
+        Assert.assertEquals(byte2, outBytes[1]);
+        Assert.assertEquals(0, val);
+    }
+
+    @Test
+    public void testBytesToShortMax() {
+        final byte byte1 = (byte)255;
+        final byte byte2 = (byte)255;
+        final short val = COPSMsgParser.bytesToShort(byte1, byte2);
+        final byte[] outBytes = COPSMsgParser.shortToBytes(val);
+        Assert.assertEquals(byte1, outBytes[0]);
+        Assert.assertEquals(byte2, outBytes[1]);
+    }
+
+    @Test
+    public void testBytesToShortPCMMClientType() {
+        final byte[] outBytes = COPSMsgParser.shortToBytes(IPCMMClient.CLIENT_TYPE);
+        final short val = COPSMsgParser.bytesToShort(outBytes[0], outBytes[1]);
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, val);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCombineByte1TooBig() {
+        COPSMsgParser.combineNibbles((byte)16, (byte)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCombineByte2TooBig() {
+        COPSMsgParser.combineNibbles((byte)0, (byte)16);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCombineByte1TooSmall() {
+        COPSMsgParser.combineNibbles((byte)-1, (byte)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCombineByte2TooSmall() {
+        COPSMsgParser.combineNibbles((byte)0, (byte)-1);
+    }
+
+    // TODO - determine if tests for marshalling & un should be done with this class or implicitly via the COPSMsg objects
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSPepIdTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSPepIdTest.java
new file mode 100644 (file)
index 0000000..b3aa875
--- /dev/null
@@ -0,0 +1,94 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSPepId class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSPepIdTest {
+
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullData() {
+        new COPSPepId(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSPepId(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSPepId(new COPSObjHeader(CNum.PEPID, CType.CSI), new COPSData());
+    }
+
+    @Test
+    public void emptyData() throws Exception {
+        final COPSPepId pepId = new COPSPepId(new COPSData());
+        Assert.assertEquals(CNum.PEPID, pepId.getHeader().getCNum());
+        Assert.assertEquals(new COPSData(), pepId.getData());
+        Assert.assertEquals(0, pepId.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        pepId.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**PEP-id**", lines[0]);
+        Assert.assertEquals("C-num: PEPID", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("PEPID: ", lines[3]);
+    }
+
+    @Test
+    public void unpaddedData() throws Exception {
+        final COPSPepId pepId = new COPSPepId(new COPSData("1234"));
+        Assert.assertEquals(CNum.PEPID, pepId.getHeader().getCNum());
+        Assert.assertEquals(new COPSData("1234"), pepId.getData());
+        Assert.assertEquals(4, pepId.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        pepId.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**PEP-id**", lines[0]);
+        Assert.assertEquals("C-num: PEPID", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("PEPID: 1234", lines[3]);
+    }
+
+    @Test
+    public void paddedData() throws Exception {
+        final COPSPepId pepId = new COPSPepId(new COPSData("12345"));
+        Assert.assertEquals(CNum.PEPID, pepId.getHeader().getCNum());
+        Assert.assertEquals(new COPSData("12345"), pepId.getData());
+        Assert.assertEquals(8, pepId.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        pepId.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**PEP-id**", lines[0]);
+        Assert.assertEquals("C-num: PEPID", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("PEPID: 12345", lines[3]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReasonTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReasonTest.java
new file mode 100644 (file)
index 0000000..dd90344
--- /dev/null
@@ -0,0 +1,88 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSReason.ReasonCode;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSReason class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSReasonTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullReasonCode() {
+        new COPSReason(null, ReasonCode.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidReasonCode() {
+        new COPSReason(ReasonCode.NA, ReasonCode.MALFORMED_DEC);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullSubCode() {
+        new COPSReason(ReasonCode.MANAGEMENT, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSReason(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), ReasonCode.ROUTE_CHANGE, ReasonCode.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSReason(new COPSObjHeader(CNum.REASON_CODE, CType.CSI), ReasonCode.PREEMPTED, ReasonCode.SYNC_HANDLE);
+    }
+
+    @Test
+    public void valid1() throws Exception {
+        final COPSReason reason = new COPSReason(ReasonCode.TRANS_HANDLE, ReasonCode.NA);
+        Assert.assertEquals(ReasonCode.TRANS_HANDLE, reason.getReasonCode());
+        Assert.assertEquals(ReasonCode.NA, reason.getReasonSubCode());
+        Assert.assertEquals(4, reason.getDataLength());
+        Assert.assertEquals("Transient handle.:", reason.getDescription());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        reason.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Reason**", lines[0]);
+        Assert.assertEquals("C-num: REASON_CODE", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Reason Code: TRANS_HANDLE", lines[3]);
+        Assert.assertEquals("Reason Sub Code: NA", lines[4]);
+    }
+
+    @Test
+    public void valid2() throws Exception {
+        final COPSReason reason = new COPSReason(ReasonCode.INSUFF_RESOURCES, ReasonCode.TEAR);
+        Assert.assertEquals(ReasonCode.INSUFF_RESOURCES, reason.getReasonCode());
+        Assert.assertEquals(ReasonCode.TEAR, reason.getReasonSubCode());
+        Assert.assertEquals(4, reason.getDataLength());
+        Assert.assertEquals("Insufficient Resources.:", reason.getDescription());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        reason.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("**Reason**", lines[0]);
+        Assert.assertEquals("C-num: REASON_CODE", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Reason Code: INSUFF_RESOURCES", lines[3]);
+        Assert.assertEquals("Reason Sub Code: TEAR", lines[4]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReportMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReportMsgTest.java
new file mode 100644 (file)
index 0000000..ec90fed
--- /dev/null
@@ -0,0 +1,178 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSClientSI.CSIType;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSReportType.ReportType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSReportMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSReportMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSReportMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSReportMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSReportMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandle() {
+        new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null,
+                new COPSReportType(ReportType.ACCOUNTING), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullReportType() {
+        new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSReportMsg(hdr, new COPSHandle(new COPSData()), new COPSReportType(ReportType.ACCOUNTING), null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+        new COPSReportMsg(hdr, new COPSHandle(new COPSData()), new COPSReportType(ReportType.ACCOUNTING), null, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSReportMsg msg = new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSReportType(ReportType.ACCOUNTING), msg.getReport());
+        Assert.assertNull(msg.getClientSI());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAll() {
+        final COPSReportMsg msg = new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), new COPSClientSI(CSIType.NAMED, new COPSData("1")),
+                new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSReportType(ReportType.ACCOUNTING), msg.getReport());
+        Assert.assertEquals(new COPSClientSI(CSIType.NAMED, new COPSData("1")), msg.getClientSI());
+        Assert.assertEquals(new COPSIntegrity(4, 5, new COPSData("123456")), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSReportMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSReportMsg msg = new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), new COPSClientSI(CSIType.NAMED, new COPSData("1")),
+                new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(24, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: RPT", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSReportMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSReportMsg msg = new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), null, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSReportMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final COPSReportMsg msg = new COPSReportMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSReportType(ReportType.ACCOUNTING), new COPSClientSI(CSIType.NAMED, new COPSData("1")),
+                new COPSIntegrity(4, 5, new COPSData("123456")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReportTypeTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReportTypeTest.java
new file mode 100644 (file)
index 0000000..ab89ce0
--- /dev/null
@@ -0,0 +1,96 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+import org.umu.cops.stack.COPSReportType.ReportType;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for the first constructor of the COPSReportType class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSAcctTimer had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSReportTypeTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullReportType() {
+        new COPSReportType(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidReportType() {
+        new COPSReportType(ReportType.NA);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNum() {
+        new COPSReportType(new COPSObjHeader(CNum.ACCT_TIMER, CType.DEF), ReportType.ACCOUNTING, (short)0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCType() {
+        new COPSReportType(new COPSObjHeader(CNum.RPT, CType.CSI), ReportType.FAILURE, (short)0);
+    }
+
+    @Test
+    public void validSuccessRpt() throws Exception {
+        final COPSReportType reason = new COPSReportType(ReportType.SUCCESS);
+        Assert.assertEquals(ReportType.SUCCESS, reason.getReportType());
+        Assert.assertEquals(4, reason.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        reason.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Report**", lines[0]);
+        Assert.assertEquals("C-num: RPT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Report: Success.", lines[3]);
+    }
+
+    @Test
+    public void validFailureRpt() throws Exception {
+        final COPSReportType reason = new COPSReportType(ReportType.FAILURE);
+        Assert.assertEquals(ReportType.FAILURE, reason.getReportType());
+        Assert.assertEquals(4, reason.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        reason.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Report**", lines[0]);
+        Assert.assertEquals("C-num: RPT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Report: Failure.", lines[3]);
+    }
+
+    @Test
+    public void validAccountingRpt() throws Exception {
+        final COPSReportType reason = new COPSReportType(ReportType.ACCOUNTING);
+        Assert.assertEquals(ReportType.ACCOUNTING, reason.getReportType());
+        Assert.assertEquals(4, reason.getDataLength());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        reason.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("**Report**", lines[0]);
+        Assert.assertEquals("C-num: RPT", lines[1]);
+        Assert.assertEquals("C-type: DEF", lines[2]);
+        Assert.assertEquals("Report: Accounting.", lines[3]);
+    }
+
+    // The writeData() method will be tested implicitly via any of the COPSMsg tests
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReqMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSReqMsgTest.java
new file mode 100644 (file)
index 0000000..8639280
--- /dev/null
@@ -0,0 +1,267 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSClientSI.CSIType;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for the first constructor of the COPSReqMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSReqMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSReqMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSReqMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSContext(RType.CONFIG, (short)0), null, null, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSReqMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSContext(RType.CONFIG, (short)0), null, null, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHandle() {
+        new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null,
+                new COPSContext(RType.CONFIG, (short)0), null, null, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullContext() {
+        new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                null, null, null, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSReqMsg(hdr, new COPSHandle(new COPSData()), new COPSContext(RType.CONFIG, (short)0),
+                null, null, null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CAT, IPCMMClient.CLIENT_TYPE);
+        new COPSReqMsg(hdr, new COPSHandle(new COPSData()), new COPSContext(RType.CONFIG, (short)0),
+                null, null, null, null, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSReqMsg msg = new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSContext(RType.CONFIG, (short)0), null, null, null, null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSContext(RType.CONFIG, (short) 0), msg.getContext());
+        Assert.assertNull(msg.getIntegrity());
+        Assert.assertNull(msg.getInInterface());
+        Assert.assertNull(msg.getOutInterface());
+        Assert.assertTrue(msg.getClientSI().isEmpty());
+        Assert.assertTrue(msg.getDecisions().isEmpty());
+    }
+
+    @Test
+    public void validAllNonCollections() throws Exception {
+        final COPSReqMsg msg = new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSContext(RType.CONFIG, (short)0), new COPSIntegrity(),
+                new COPSIpv4InInterface(new COPSIpv4Address("localhost"), 0),
+                new COPSIpv4OutInterface(new COPSIpv4Address("localhost"), 0),
+                null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSContext(RType.CONFIG, (short)0), msg.getContext());
+        Assert.assertEquals(new COPSIntegrity(), msg.getIntegrity());
+        Assert.assertEquals(new COPSIpv4InInterface(new COPSIpv4Address("localhost"), 0), msg.getInInterface());
+        Assert.assertEquals(new COPSIpv4OutInterface(new COPSIpv4Address("localhost"), 0), msg.getOutInterface());
+        Assert.assertTrue(msg.getClientSI().isEmpty());
+        Assert.assertTrue(msg.getDecisions().isEmpty());
+    }
+
+    @Test
+    public void validNonEmptyCollections() {
+        final Set<COPSClientSI> clientSIs = new HashSet<>();
+        clientSIs.add(new COPSClientSI(CSIType.NAMED, new COPSData("1")));
+        clientSIs.add(new COPSClientSI(CSIType.SIGNALED, new COPSData("2")));
+
+        final Map<COPSContext, Set<COPSLPDPDecision>> decisions = new HashMap<>();
+        final COPSContext context1 = new COPSContext(RType.CONFIG, (short)1);
+        final Set<COPSLPDPDecision> decisions1 = new HashSet<>();
+        decisions1.add(new COPSLPDPDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData("12345")));
+        decisions1.add(new COPSLPDPDecision(CType.NAMED, Command.NULL, DecisionFlag.REQSTATE, new COPSData("123456")));
+        decisions.put(context1, decisions1);
+
+        final COPSContext context2 = new COPSContext(RType.IN_ADMIN, (short)2);
+        final Set<COPSLPDPDecision> decisions2 = new HashSet<>();
+        decisions2.add(new COPSLPDPDecision(CType.STATELESS, Command.REMOVE, DecisionFlag.REQERROR, new COPSData("1234567")));
+        decisions.put(context2, decisions2);
+
+        final COPSReqMsg msg = new COPSReqMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("123")),
+                new COPSContext(RType.IN_ADMIN, (short)2), null, null, null, clientSIs, decisions);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.UNSOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData("123")), msg.getClientHandle());
+        Assert.assertEquals(new COPSContext(RType.IN_ADMIN, (short) 2), msg.getContext());
+        Assert.assertNull(msg.getIntegrity());
+        Assert.assertNull(msg.getInInterface());
+        Assert.assertNull(msg.getOutInterface());
+        Assert.assertEquals(clientSIs, msg.getClientSI());
+        Assert.assertNotSame(clientSIs, msg.getClientSI());
+        Assert.assertEquals(decisions, msg.getDecisions());
+        Assert.assertNotSame(decisions, msg.getDecisions());
+    }
+
+    /**
+     * This test is responsible for creating a COPSReqMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final Set<COPSClientSI> clientSIs = new HashSet<>();
+        clientSIs.add(new COPSClientSI(CSIType.NAMED, new COPSData("1")));
+        clientSIs.add(new COPSClientSI(CSIType.SIGNALED, new COPSData("2")));
+
+        final Map<COPSContext, Set<COPSLPDPDecision>> decisions = new HashMap<>();
+        final COPSContext context1 = new COPSContext(RType.CONFIG, (short)1);
+        final Set<COPSLPDPDecision> decisions1 = new HashSet<>();
+        decisions1.add(new COPSLPDPDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData("12345")));
+        decisions1.add(new COPSLPDPDecision(CType.NAMED, Command.NULL, DecisionFlag.REQSTATE, new COPSData("123456")));
+        decisions.put(context1, decisions1);
+
+        final COPSContext context2 = new COPSContext(RType.IN_ADMIN, (short)2);
+        final Set<COPSLPDPDecision> decisions2 = new HashSet<>();
+        decisions2.add(new COPSLPDPDecision(CType.STATELESS, Command.REMOVE, DecisionFlag.REQERROR, new COPSData("1234567")));
+        decisions.put(context2, decisions2);
+
+        final COPSReqMsg msg = new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
+                new COPSContext(RType.CONFIG, (short)0), new COPSIntegrity(),
+                new COPSIpv4InInterface(new COPSIpv4Address("localhost"), 0),
+                new COPSIpv4OutInterface(new COPSIpv4Address("localhost"), 0),
+                clientSIs, decisions);
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(52, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: REQ", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSReqMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSReqMsg msg = new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("12345")),
+                new COPSContext(RType.CONFIG, (short)5), null,
+                null, null, null, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSReqMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final Set<COPSClientSI> clientSIs = new HashSet<>();
+        clientSIs.add(new COPSClientSI(CSIType.NAMED, new COPSData("12345")));
+        clientSIs.add(new COPSClientSI(CSIType.SIGNALED, new COPSData("123456")));
+
+        final Map<COPSContext, Set<COPSLPDPDecision>> decisions = new HashMap<>();
+        final COPSContext context1 = new COPSContext(RType.CONFIG, (short)1);
+        final Set<COPSLPDPDecision> decisions1 = new HashSet<>();
+        decisions1.add(new COPSLPDPDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData("12345")));
+        decisions1.add(new COPSLPDPDecision(CType.NAMED, Command.NULL, DecisionFlag.REQSTATE, new COPSData("123456")));
+        decisions.put(context1, decisions1);
+
+        final COPSContext context2 = new COPSContext(RType.IN_ADMIN, (short)2);
+        final Set<COPSLPDPDecision> decisions2 = new HashSet<>();
+        decisions2.add(new COPSLPDPDecision(CType.STATELESS, Command.REMOVE, DecisionFlag.REQERROR, new COPSData("1234567")));
+        decisions.put(context2, decisions2);
+
+        final COPSReqMsg msg = new COPSReqMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("12345")),
+                new COPSContext(RType.CONFIG, (short)5), new COPSIntegrity(3, 4, new COPSData("12345")),
+                new COPSIpv4InInterface(new COPSIpv4Address("localhost"), 5),
+                new COPSIpv4OutInterface(new COPSIpv4Address("localhost"), 6),
+                clientSIs, decisions);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/COPSSyncStateMsgTest.java b/packetcable-driver/src/test/java/org/umu/cops/stack/COPSSyncStateMsgTest.java
new file mode 100644 (file)
index 0000000..4f3313d
--- /dev/null
@@ -0,0 +1,156 @@
+package org.umu.cops.stack;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSHeader.Flag;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * Tests for the first constructor of the COPSSyncStateMsg class.
+ * Should any of these tests be inaccurate it is due to the fact that they have been written after COPSSyncStateMsg had been
+ * released and my assumptions may be incorrect.
+ */
+public class COPSSyncStateMsgTest {
+
+    private final static int testPort = 7777;
+    TestCOPSServer server;
+    Socket outSocket;
+
+    @Before
+    public void setup() throws Exception {
+        server = new TestCOPSServer(testPort);
+        server.start();
+        outSocket = new Socket(InetAddress.getLocalHost(), testPort);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        outSocket.close();
+        server.close();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void version0() {
+        new COPSSyncStateMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullFlag() {
+        new COPSSyncStateMsg(1, null, IPCMMClient.CLIENT_TYPE, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullHeader() {
+        final COPSHeader hdr = null;
+        new COPSSyncStateMsg(hdr, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidHeader() {
+        final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.NA, IPCMMClient.CLIENT_TYPE);
+        new COPSSyncStateMsg(hdr, null, null);
+    }
+
+    @Test
+    public void validMinimal() {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null, null);
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertNull(msg.getClientHandle());
+        Assert.assertNull(msg.getIntegrity());
+    }
+
+    @Test
+    public void validAll() throws Exception {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData()),
+                new COPSIntegrity());
+
+        Assert.assertEquals(1, msg.getHeader().getPcmmVersion());
+        Assert.assertEquals(Flag.SOLICITED, msg.getHeader().getFlag());
+        Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
+        Assert.assertEquals(new COPSHandle(new COPSData()), msg.getClientHandle());
+        Assert.assertEquals(new COPSIntegrity(), msg.getIntegrity());
+    }
+
+    /**
+     * This test is responsible for creating a COPSSyncStateMsg object without any nulls or empty collections
+     * and then is dumped to an OutputStream.
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testDumpAll() throws Exception {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData()),
+                new COPSIntegrity());
+
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        msg.dump(os);
+
+        final String out = new String(os.toByteArray());
+        System.out.println(out);
+        final String[] lines = out.split("\n");
+        Assert.assertEquals(15, lines.length);
+
+        // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
+        Assert.assertEquals("**MSG HEADER**", lines[0]);
+        Assert.assertEquals("Version: 1", lines[1]);
+        Assert.assertEquals("Flags: SOLICITED", lines[2]);
+        Assert.assertEquals("OpCode: SSQ", lines[3]);
+        Assert.assertEquals("Client-type: -32758", lines[4]);
+    }
+
+    /**
+     * This test is responsible for creating a COPSSyncStateMsg object with the minimal necessary attributes to make
+     * it valid. It is then streamed over a socket (unmarshalled) then reassembled (marshalled).
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteMinimal() throws Exception {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, null, null);
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+    /**
+     * This test is responsible for creating a COPSSyncStateMsg object without any nulls or empty collections
+     * and then is streamed over a socket (unmarshalled) then reassembled (marshalled)
+     * @throws Exception - Test should fail if any exception is thrown
+     */
+    @Test
+    public void testWriteAll() throws Exception {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(1, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
+                new COPSHandle(new COPSData()),
+                new COPSIntegrity(8, 9, new COPSData("12345")));
+
+        msg.writeData(outSocket);
+
+        final long start = System.currentTimeMillis();
+        while (server.copsMsgs.size() < 1) {
+            Thread.sleep(5);
+            if (System.currentTimeMillis() - start > 2000) break;
+        }
+
+        Assert.assertEquals(1, server.copsMsgs.size());
+        Assert.assertEquals(msg, server.copsMsgs.get(0));
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/umu/cops/stack/TestCOPSServer.java b/packetcable-driver/src/test/java/org/umu/cops/stack/TestCOPSServer.java
new file mode 100644 (file)
index 0000000..8a40a8a
--- /dev/null
@@ -0,0 +1,44 @@
+package org.umu.cops.stack;
+
+import org.junit.Assert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Server used to test client/server socket communications.
+ */
+public class TestCOPSServer extends Thread {
+
+    private final static Logger logger = LoggerFactory.getLogger(TestCOPSServer.class);
+    private final ServerSocket serverSocket;
+    final List<COPSMsg> copsMsgs = new ArrayList<>();
+
+    public TestCOPSServer(final int port) throws IOException {
+        serverSocket = new ServerSocket(port);
+        Assert.assertTrue(serverSocket.isBound());
+    }
+
+    public void close() throws IOException {
+        this.interrupt();
+        serverSocket.close();
+    }
+
+    public void run() {
+        try {
+            final Socket socket = serverSocket.accept();
+            final COPSMsg copsMsg = COPSTransceiver.receiveMsg(socket);
+            logger.info("Read value = " + copsMsg);
+            copsMsgs.add(copsMsg);
+            socket.close();
+        } catch (Exception e) {
+            logger.error("Error processing message", e);
+        }
+
+    }
+}