Merge changes If0630105,I9d2d5e61,I1cea2a32,Icc05b6a7,Ic57eb4f8, ...
authorThomas Kee <xsited@yahoo.com>
Fri, 8 May 2015 23:22:45 +0000 (23:22 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 8 May 2015 23:22:45 +0000 (23:22 +0000)
* changes:
  Moved up some of the methods from the PEP and PDP OSMsgSender to their respective supers.
  Created abstract super class for all COPS Message Senders as each contained duplicate members. This refactoring should help with the further refactoring slated for the state managers and data process class hierarchies.
  Ensure all *DataProcess classes have been changed from abstract classes to interfaces as each does not contain any methods. Also moving common methods up the class hierarchy to allow for easier refactoring of the COPS connection and state managers.
  Created abstract super class for all COPS state managers called COPSStateMan as each contained a lot of identical code and began making the state managers more immutable.
  Generalize the COPSPdpException class to a COPSException to make upstream exception handling easier.
  Generalize the COPSPepException class to a COPSException to make upstream exception handling easier.
  Expanded CMTS emulator to accept at least one type of gate request. Future work will allow for the ability to configure gates for validation. With an emulator that can accept gate requests, I have expanded the PCMMService tests to include setting and removal of a gate request to a single mock CMTS. Additionally, as I had encountered issues unmarshalling COPSDecisionMsg objects containing a gate request, another test has been included here (which may be better suited to be located in COPSDecisionMsgTest but the gate set mock object being used can only be used in this module) that creates and parses a COPSDecisionMsg object used for setting gates.
  Added comment to the reasoning behind the hashCode() logic implemented in the COPSHandle class per David M. Karr's review on change #19455.
  Removed commented line and replaced with a TODO per David M. Karr's review to change #19457.
  Generalize the COPSPepException class to a COPSException to make upstream exception handling easier.
  Fixed block responsible for parsing the PCMM gate request's traffic profile from a byte[]. Only commented the BestEffortService line as we will most likely need to support the parsing of other types of ITrafficProfile objects.
  Fixed the routine responsible for parsing a gate request decision message.
  Fixed hashCode() so it returns the same value after the data in the _data + _padding is taken into account.
  Removed the requirement that the COPSData member (aka. _data) cannot be null. Found this issue while building tests for the packetcable-policy-server PCMMService class for connecting to and setting gates for a CCAP.
  Improved exception handling, increased immutability, and general houskeeping.
  Generalizing COPSPdpException to a COPSException.
  Fix to NPE during instantiation after moving the instantiation of the gateIidMap member after the call to the private method getGates().
  With previous change to AbstractPCMMServer, instantiation of the CMTS class now requires one to specify the port number that will be opened else the ServerSocket class will assign one automatically.
  Now Karaf module capable of starting the new bundles contained in the new feature odl-packetcable-policy-server-all.
  New feature bundle for the new feature odl-packetcable-policy-server-all.
  New configuration bundle for the new feature odl-packetcable-policy-server-all.
  The provider module for the Arris designed APIs.
  New model module for use in the new feature to be called odl-packetcable-policy-server-all.
  Miscellaneous driver fixes found while migrating and testing the new Arris API submission that will live in a new feature called odl-packetcable-policy-server-all.
  Added an optional COPSClientSI object as a member to the COPSDecisionMsg as per specs.
  Added new constructor. May need to tighten down interfaces in the future.

72 files changed:
features-packetcable-policy/pom.xml [new file with mode: 0644]
features-packetcable-policy/src/main/resources/features.xml [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMGlobalConfig.java
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/gates/IClassifier.java
packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java
packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java
packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java
packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java
packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java
packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java
packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java
packetcable-driver/src/main/java/org/pcmm/messages/impl/MessageFactory.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/COPSDataProcess.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/COPSMsgSender.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/COPSStateMan.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpException.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/COPSPepException.java
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSConnection.java
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSDataProcess.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/COPSPdpException.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/COPSPepException.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/COPSClientSI.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/COPSHandle.java
packetcable-driver/src/test/java/org/pcmm/test/Main.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSClientSITest.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionMsgTest.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSDecisionTest.java
packetcable-driver/src/test/java/org/umu/cops/stack/COPSLPDPDecisionTest.java
packetcable-policy-config/pom.xml [new file with mode: 0644]
packetcable-policy-config/src/main/resources/80-packetcable.xml [new file with mode: 0644]
packetcable-policy-karaf/pom.xml [new file with mode: 0644]
packetcable-policy-model/pom.xml [new file with mode: 0644]
packetcable-policy-model/src/main/yang/packetcable.yang [new file with mode: 0644]
packetcable-policy-server/pom.xml [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMService.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Response.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/ValidateInstanceData.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/packetcable/packetcable/policy/server/impl/rev140131/PacketcableProviderModule.java [new file with mode: 0644]
packetcable-policy-server/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/packetcable/packetcable/policy/server/impl/rev140131/PacketcableProviderModuleFactory.java [new file with mode: 0644]
packetcable-policy-server/src/main/yang/packetcable-policy-server.yang [new file with mode: 0644]
packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java [new file with mode: 0644]
packetcable-provider/src/main/java/org/opendaylight/controller/packetcable/provider/processors/PCMMDataProcessor.java
pom.xml

diff --git a/features-packetcable-policy/pom.xml b/features-packetcable-policy/pom.xml
new file mode 100644 (file)
index 0000000..92d56cb
--- /dev/null
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+   <parent>
+    <artifactId>packetcable</artifactId>
+    <groupId>org.opendaylight.packetcable</groupId>
+    <version>1.2.0-SNAPSHOT</version>
+  </parent>
+   <!--
+    Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+    maven repos etc.  If you run this archetype in a subdirectory of your project, it
+    will pick the pom.xml from the parent directory as the parent pom, which may or may
+    not be correct.
+  -->
+   <artifactId>features-packetcable-policy</artifactId>
+   <groupId>org.opendaylight.packetcable</groupId>
+   <!-- Optional Uncomment version if you are not using a parent pom.xml
+   <version>1.2.0-SNAPSHOT</version>
+   -->
+   <packaging>jar</packaging>
+   <properties>
+      <features.file>features.xml</features.file>
+      <!-- Optional: Move these properties to your parent pom and possibly
+            DependencyManagement section of your parent pom -->
+      <branding.version>1.1.0-SNAPSHOT</branding.version>
+      <karaf.resources.version>1.5.0-SNAPSHOT</karaf.resources.version>
+      <karaf.empty.version>1.5.0-SNAPSHOT</karaf.empty.version>
+      <surefire.version>2.16</surefire.version>
+   </properties>
+   <dependencies>
+    <!--
+      Necessary: Put dependencies on any feature repos
+      you use in your features.xml file.
+
+      Note: they will need to be <type>xml</xml>
+      and <classifier>features</classifier>.
+      One other thing to watch for is to make sure they are
+      <scope>compile</compile>, which they should be by default,
+      but be cautious lest they be at a different scope in a parent pom.
+
+      Examples:
+    -->
+        <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>features-yangtools</artifactId>
+          <version>0.7.0-SNAPSHOT</version>
+          <classifier>features</classifier>
+          <type>xml</type>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>features-mdsal</artifactId>
+          <version>1.2.0-SNAPSHOT</version>
+          <classifier>features</classifier>
+          <type>xml</type>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.packetcable</groupId>
+          <artifactId>packetcable-policy-config</artifactId>
+          <version>${project.version}</version>
+          <classifier>config</classifier>
+          <type>xml</type>
+        </dependency>
+
+
+
+
+    <!--
+      Necessary TODO: Put dependencies for bundles directly referenced
+      in your features.xml file.  For every <bundle> reference in your
+      features.xml file, you need a corresponding dependency here.
+
+      Examples:
+    -->
+      <dependency>
+        <groupId>org.opendaylight.packetcable</groupId>
+        <artifactId>packetcable-policy-server</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.packetcable</groupId>
+        <artifactId>packetcable-policy-model</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.packetcable</groupId>
+        <artifactId>packetcable-driver</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+    <!-- test to validate features.xml -->
+    <dependency>
+      <groupId>org.opendaylight.odlparent</groupId>
+      <artifactId>features-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-empty</artifactId>
+      <version>${karaf.empty.version}</version>
+      <type>zip</type>
+    </dependency>
+    <!-- Uncomment this if you get an error : java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.format(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>1.7.2</version>
+    </dependency>
+    -->
+
+   </dependencies>
+   <build>
+      <resources>
+         <resource>
+            <directory>src/main/resources</directory>
+            <filtering>true</filtering>
+         </resource>
+      </resources>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-resources-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>filter</id>
+                  <phase>generate-resources</phase>
+                  <goals>
+                     <goal>resources</goal>
+                  </goals>
+               </execution>
+            </executions>
+         </plugin>
+         <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>build-helper-maven-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>attach-artifacts</id>
+                  <phase>package</phase>
+                  <goals>
+                     <goal>attach-artifact</goal>
+                  </goals>
+                  <configuration>
+                     <artifacts>
+                        <artifact>
+                           <file>${project.build.directory}/classes/${features.file}</file>
+                           <type>xml</type>
+                           <classifier>features</classifier>
+                        </artifact>
+                     </artifacts>
+                  </configuration>
+               </execution>
+            </executions>
+         </plugin>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <version>${surefire.version}</version>
+            <configuration>
+              <systemPropertyVariables>
+                <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+                <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+                <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
+              </systemPropertyVariables>
+              <dependenciesToScan>
+               <dependency>org.opendaylight.odlparent:features-test</dependency>
+              </dependenciesToScan>
+            </configuration>
+          </plugin>
+      </plugins>
+   </build>
+   <scm>
+      <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</developerConnection>
+      <tag>HEAD</tag>
+      <url>https://git.opendaylight.org/gerrit/gitweb?p=packetcable.git;a=summary</url>
+   </scm>
+</project>
diff --git a/features-packetcable-policy/src/main/resources/features.xml b/features-packetcable-policy/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..a684b60
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<features name="odl-packetcable-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+    <!--
+        Please read the features guidelines:
+        https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Feature_Best_Practices
+    -->
+    <!--
+    Add repo entries for the repositories of features you refer to in this feature file but do not define here.
+    <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/0.1.0-SNAPSHOT/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-adsal/${feature.adsal.version}/xml/features</repository>      
+    <repository>mvn:org.opendaylight.controller/features-adsal-compatibility/1.5.0-SNAPSHOT/xml/features</repository>
+    -->
+    <repository>mvn:org.opendaylight.yangtools/features-yangtools/0.7.0-SNAPSHOT/xml/features</repository>
+    <repository>mvn:org.opendaylight.controller/features-mdsal/1.2.0-SNAPSHOT/xml/features</repository>
+    <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
+
+    <feature name='odl-packetcable-policy-server-all' version='${project.version}' description='OpenDaylight :: packetcable :: policy :: All'>
+            <feature version='${project.version}'>odl-packetcable-policy-server</feature>
+            <feature version='${project.version}'>odl-packetcable-policy-model</feature>
+            <feature version='${project.version}'>odl-packetcable-driver</feature>
+    </feature>
+
+    <!--
+        Define your features.  It is useful to list then in order of dependency.  So if A depends on B, list A first.
+        It's also nice to list inside a feature, first the features it needs, then the bundles it needs, then the configfiles.
+            <feature version='0.1.0-SNAPSHOT'>odl-openflowplugin-flow-services</feature>
+           <bundle>mvn:com.google.common.collect/collect/14.0</bundle>
+
+    -->
+        <!--- * Basic MD-SAL Consumer -->
+        <!--- * Basic MD-SAL Model feature -->
+        <feature name='odl-packetcable-policy-model' version='${project.version}' description='OpenDaylight :: packetcable :: policy :: Model'>
+            <feature version='0.7.0-SNAPSHOT'>odl-yangtools-binding</feature>
+            <feature version='0.7.0-SNAPSHOT'>odl-yangtools-models</feature>
+            <bundle>mvn:org.opendaylight.packetcable/packetcable-policy-model/${project.version}</bundle>
+        </feature>
+
+        <!--- * Basic MD-SAL Provider -->
+        <feature name='odl-packetcable-policy-server' version='${project.version}' description='OpenDaylight :: packetcable :: policy :: Provider'>
+            <feature version='1.2.0-SNAPSHOT'>odl-mdsal-broker</feature>
+            <bundle>mvn:org.opendaylight.packetcable/packetcable-policy-server/${project.version}</bundle>
+            <bundle>mvn:org.opendaylight.packetcable/packetcable-driver/${project.version}</bundle>
+            <feature version='${project.version}'>odl-packetcable-policy-model</feature>
+            <feature version='${project.version}'>odl-packetcable-driver</feature>
+            <configfile finalname="etc/opendaylight/karaf/80-packetcable.xml">mvn:org.opendaylight.packetcable/packetcable-policy-config/${project.version}/xml/config</configfile>
+        </feature>
+
+        <!--- * * -->
+        <feature name='odl-packetcable-driver' version='${project.version}' description='OpenDaylight :: packetcable :: Driver'>
+            <feature version='1.2.0-SNAPSHOT'>odl-mdsal-broker</feature>
+       </feature>
+
+</features>
index 3d141d69b042a9815aefd6ad9569dc2f28c3086e..0c6ade508335ee475c6ab96c9cf51bc4c798026d 100644 (file)
@@ -4,6 +4,14 @@
 
 package org.pcmm;
 
+import org.pcmm.gates.IPCMMGate;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * TODO - Remove all uses of this class which is evil as it contains environmental settings
+ */
 public class PCMMGlobalConfig {
     // System
     public static int Debug = 0;
@@ -93,6 +101,13 @@ public class PCMMGlobalConfig {
     public static int getGateID2() {
         return GateID2;
     }
+
+    /**
+     * Global TransactionId to Gate Request map allows recovery of CCAP GateIds
+     * TODO - need to find a better means to store shared state.
+     */
+
+    public static Map<Short, IPCMMGate> transactionGateMap = new ConcurrentHashMap<>();
 }
 
 /*
index 28eae315d5b20a003d9618b6a0e6e2f7edb24625..77a3fe6e7360816a19ebd7e1140615927958bf53 100644 (file)
@@ -16,75 +16,53 @@ 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
  */
 public class PCMMPdpAgent extends COPSPdpAgent {
 
-    public final static Logger logger = LoggerFactory.getLogger(PCMMPdpAgent.class);
+    private static final Logger logger = LoggerFactory.getLogger(PCMMPdpAgent.class);
 
     /** Well-known port for PCMM */
     public static final int WELL_KNOWN_PDP_PORT = 3918;
 
-    private COPSPepId _pepId;
-    private String _pepIdString;
     /**
      * PEP host name
      */
-    private String psHost;
+    private final String psHost;
 
     /**
      * PEP port
      */
-    private int psPort;
-
-    private Socket socket;
+    private final int psPort;
 
     /**
      * Policy data processing object
      */
-    private PCMMPdpDataProcess _process;
-    private COPSHandle _handle;
-//    private short _transactionID;
+    private final PCMMPdpDataProcess _process;
 
+    // Next two attributes are initialized when connected
     /**
-     * Temporary until can refactor PdpAgent classes
-     */
-    @Deprecated
-    private final Map<String, PCMMPdpConnection> _connectionMap;
-
-    /**
-     * Creates a PDP Agent
-     *
-     * @param clientType
-     *            COPS Client-type
-     * @param process
-     *            Object to perform policy data processing
+     * The Socket connection to the PEP
      */
-    public PCMMPdpAgent(short clientType, PCMMPdpDataProcess process) {
-        this(clientType, null, WELL_KNOWN_PDP_PORT, process);
-    }
+    private transient Socket socket;
+    private transient COPSHandle _handle;
 
     /**
      * Creates a PDP Agent
      *
-     * @param clientType
-     *            COPS Client-type
-     * @param psHost
-     *            Host to connect to
-     * @param psPort
-     *            Port to connect to
-     * @param process
-     *            Object to perform policy data processing
+     * @param clientType - COPS Client-type
+     * @param psHost - Host to connect to
+     * @param psPort - Port to connect to
+     * @param process - Object to perform policy data processing
      */
-    public PCMMPdpAgent(short clientType, String psHost, int psPort, PCMMPdpDataProcess process) {
+    public PCMMPdpAgent(final short clientType, final String psHost, final int psPort,
+                        final PCMMPdpDataProcess process) {
         super(psPort, clientType, null);
         this._process = process;
         this.psHost = psHost;
-        this._connectionMap = new ConcurrentHashMap<>();
+        this.psPort = psPort;
     }
 
     /**
@@ -97,117 +75,108 @@ public class PCMMPdpAgent extends COPSPdpAgent {
     /**
      * Connects to a PDP
      *
-     * @param psHost
-     *            CMTS host name
-     * @param psPort
-     *            CMTS port
      * @return <tt>true</tt> if PDP accepts the connection; <tt>false</tt>
      *         otherwise
      * @throws java.net.UnknownHostException
      * @throws java.io.IOException
      * @throws COPSException
-     * @throws COPSPdpException
      */
-    public boolean connect(String psHost, int psPort) throws IOException, COPSException, COPSPdpException {
-
-        this.psHost = psHost;
-        this.psPort = psPort;
+    public boolean connect() throws IOException, COPSException {
         // Create Socket and send OPN
-        InetAddress addr = InetAddress.getByName(psHost);
-        try {
-            socket = new Socket(addr, psPort);
-        } catch (IOException e) {
-            logger.error("Error creating socket connection", e);
-            return (false);
-        }
-        logger.info("PDP Socket Opened");
-        // Loop through for Incoming messages
+        final InetAddress addr = InetAddress.getByName(psHost);
+        socket = new Socket(addr, psPort);
+        logger.debug("{} {}", getClass().getName(), "PDP Socket Opened");
 
-        // server infinite loop
-        // while(true)
-        {
-
-            // We're waiting for an message
-            try {
-                logger.info("PDP  COPSTransceiver.receiveMsg");
-                COPSMsg msg = COPSTransceiver.receiveMsg(socket);
-                if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
-                    logger.info("PDP msg.getHeader().isAClientOpen");
-                    handleClientOpenMsg(socket, msg);
-                } else {
-                    try {
-                        socket.close();
-                    } catch (Exception ex) {
-                        logger.error("Unexpected exception closing socket", ex);
-                    }
-                }
-            } catch (Exception e) { // COPSException, IOException
+        // We're waiting for an message
+        try {
+            logger.debug("Waiting to receiveMsg");
+            final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+            logger.debug("Message received of type - " + msg.getHeader().getOpCode());
+            if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
+                handleClientOpenMsg(socket, msg);
+            } else {
                 try {
                     socket.close();
                 } catch (Exception ex) {
-                    logger.error("Unexpected exception closing socket", ex);
+                    logger.error("Unexpected error closing socket", ex);
                 }
-                return true;
             }
+        } catch (Exception e) {
+            logger.error("Unexpected error handing client open message", e);
+            try {
+                socket.close();
+            } catch (Exception ex) {
+                logger.error("Unexpected error closing socket", ex);
+            }
+            return true;
         }
+
         return false;
     }
 
-    /**
-     * 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 {
+    // TODO - remove and let super handle after DataProcess & PdpConnection classes are properly refactored
+    @Override
+    public void disconnect (final String pepID, final COPSError error) throws COPSException, IOException {
+        final PCMMPdpConnection pdpConn = (PCMMPdpConnection) _connectionMap.get(pepID);
+        if (pdpConn != null) {
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(), error, null, null);
+            closeMsg.writeData(pdpConn.getSocket());
+            pdpConn.close();
+        }
+
+        final Thread thread = threadMap.remove(pepID);
+        if (thread != null) thread.interrupt();
+    }
+
+    // TODO - this method should be broken apart into smaller pieces.
+    @Override
+    protected void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+        logger.info("Processing client open message");
         final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
-        final COPSPepId pepId = cMsg.getPepId();
+        _pepId = cMsg.getPepId();
 
         // Validate Client Type
         if (msg.getHeader().getClientType() != getClientType()) {
             // Unsupported client type
-            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
                     new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
             try {
                 closeMsg.writeData(conn);
             } catch (IOException unae) {
-                logger.error("Unexpected error writing COPS data", unae);
+                logger.error("Unexpected error writing data", unae);
             }
 
             throw new COPSException("Unsupported client type");
         }
 
         // PEPId is mandatory
-        if (pepId == null) {
+        if (_pepId == null) {
             // Mandatory COPS object missing
-            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
                     new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
             try {
                 closeMsg.writeData(conn);
             } catch (IOException unae) {
-                logger.error("Unexpected error writing COPS data", unae);
+                logger.error("Unexpected error closing socket", unae);
             }
 
             throw new COPSException("Mandatory COPS object missing (PEPId)");
         }
-        setPepId(pepId);
+
         // Support
         if ((cMsg.getClientSI() != null) ) {
             final MMVersionInfo _mminfo = new MMVersionInfo(cMsg.getClientSI().getData().getData());
-            logger.info("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + "  minor:" +
+            logger.debug("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + "  minor:" +
                     _mminfo.getMinorVersionNB());
 
         } else {
-            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+            // Unsupported objects
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
                     new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
             try {
                 closeMsg.writeData(conn);
             } catch (IOException unae) {
-                logger.error("Unexpected error writing COPS data", unae);
+                logger.error("Unexpected error writing data", unae);
             }
 
             throw new COPSException("Unsupported objects (PdpAddress, Integrity)");
@@ -216,29 +185,29 @@ public class PCMMPdpAgent extends COPSPdpAgent {
         */
 
         // Connection accepted
-        final COPSKATimer katimer = new COPSKATimer(getKaTimer());
-        final COPSAcctTimer acctTimer = new COPSAcctTimer(getAcctTimer());
         final COPSClientAcceptMsg acceptMsg;
         if (getAcctTimer() != 0)
-            acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, acctTimer, null);
+            acceptMsg = new COPSClientAcceptMsg(getClientType(), new COPSKATimer(getKaTimer()),
+                    new COPSAcctTimer(getAcctTimer()), null);
         else
-            acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
-
+            acceptMsg = new COPSClientAcceptMsg(getClientType(), new COPSKATimer(getKaTimer()), null, null);
         acceptMsg.writeData(conn);
         // XXX - handleRequestMsg
         try {
-            logger.info("PDP COPSTransceiver.receiveMsg");
-            COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
+            logger.debug("handleClientOpenMsg() - Waiting to receive message");
+            final COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
+            logger.debug("Received message of type - " + rmsg.getHeader().getOpCode());
             // Client-Close
             if (rmsg.getHeader().getOpCode().equals(OPCode.CC)) {
-                logger.info("Client close description - " + ((COPSClientCloseMsg) rmsg).getError().getDescription());
+                System.out.println(((COPSClientCloseMsg) rmsg)
+                        .getError().getDescription());
                 // close the socket
-                final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+                final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
                         new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
                 try {
                     closeMsg.writeData(conn);
                 } catch (IOException unae) {
-                    logger.error("Unexpected exception writing COPS data", unae);
+                    logger.error("Unexpected error writing data", unae);
                 }
                 throw new COPSException("CMTS requetsed Client-Close");
             } else {
@@ -248,139 +217,45 @@ public class PCMMPdpAgent extends COPSPdpAgent {
                     _handle = rMsg.getClientHandle();
                 } else
                     throw new COPSException("Can't understand request");
-
             }
         } catch (Exception e) { // COPSException, IOException
-            throw new COPSException("Error COPSTransceiver.receiveMsg");
+            throw new COPSException("Error COPSTransceiver.receiveMsg", e);
         }
 
-        logger.info("PDPCOPSConnection");
-        PCMMPdpConnection pdpConn = new PCMMPdpConnection(pepId, conn, _process);
-        pdpConn.setKaTimer(getKaTimer());
-        if (getAcctTimer() != 0)
-            pdpConn.setAccTimer(getAcctTimer());
+        logger.debug("PDPCOPSConnection");
+        final PCMMPdpConnection pdpConn = new PCMMPdpConnection(_pepId, conn, _process, getKaTimer(), getAcctTimer());
 
         // XXX - handleRequestMsg
         // XXX - check handle is valid
-        PCMMPdpReqStateMan man = new PCMMPdpReqStateMan(getClientType(), _handle.getId().str());
-        pdpConn.getReqStateMans().put(_handle.getId().str(),man);
-        man.setDataProcess(_process);
+        final PCMMPdpReqStateMan man = new PCMMPdpReqStateMan(getClientType(), _handle, _process);
+        pdpConn.addStateMan(_handle.getId().str(), man);
         try {
             man.initRequestState(conn);
         } catch (COPSPdpException unae) {
-            logger.error("Error initializing the state manager's request state");
+            logger.error("Unexpected error initializing state", unae);
         }
         // XXX - End handleRequestMsg
 
-        logger.info("PDP Thread(pdpConn).start");
-        new Thread(pdpConn).start();
-        _connectionMap.put(pepId.getData().str(), pdpConn);
-    }
-
-    /**
-     * @return the _psHost
-     */
-    public String getPsHost() {
-        return psHost;
-    }
-
-    /**
-     * TODO - make the host immutable
-     * @param _psHost
-     *            the _psHost to set
-     */
-    @Deprecated
-    public void setPsHost(String _psHost) {
-        this.psHost = _psHost;
-    }
+        logger.info("Starting PDP connection thread to - " + psHost);
 
-    /**
-     * @return the _psPort
-     */
-    public int getPsPort() {
-        return psPort;
+        // TODO - store the thread reference so it is possible to manage.
+        final Thread thread = new Thread(pdpConn, "Agent for - " + psHost);
+        thread.start();
+        threadMap.put(_pepId.getData().str(), thread);
+        _connectionMap.put(_pepId.getData().str(), pdpConn);
     }
 
-    /**
-     * TODO - make the port immutable
-     * @param _psPort
-     *            the _psPort to set
-     */
-    @Deprecated
-    public void setPsPort(int _psPort) {
-        this.psPort = _psPort;
-    }
-
-    /**
-     * @return the socket
-     */
     public Socket getSocket() {
         return socket;
     }
 
-    /**
-     * TODO - Ensure socket is not overly transient
-     * @param socket
-     *            the socket to set
-     */
-    @Deprecated
-    public void setSocket(Socket socket) {
-        this.socket = socket;
-    }
-
-    /**
-     * @return the _process
-     */
-    public PCMMPdpDataProcess getProcess() {
-        return _process;
-    }
-
-    /**
-     * @param _process
-     *            the _process to set
-     */
-    public void setProcess(PCMMPdpDataProcess _process) {
-        this._process = _process;
-    }
-
-    /**
-      * Gets the client handle
-      * @return   Client's <tt>COPSHandle</tt>
-      */
     public COPSHandle getClientHandle() {
         return _handle;
     }
 
-    /**
-      * Gets the PepId
-      * @return   <tt>COPSPepId</tt>
-      */
-    public COPSPepId getPepId() {
-        return _pepId;
-    }
-
     public String getPepIdString() {
-        return _pepIdString;
+        return _pepId.getData().str();
     }
 
-    /**
-     * Sets the PepId
-     * TODO - make PEP ID and the associate string immutable or remove altogether
-     * @param   pepId - COPSPepId
-     */
-    @Deprecated
-    public void setPepId(COPSPepId pepId) {
-        _pepId = pepId;
-        _pepIdString = pepId.getData().str();
-     }
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.pcmm.rcd.IPCMMClient#isConnected()
-     */
-    public boolean isConnected() {
-        return socket != null && socket.isConnected();
-    }
-
-
 }
+
index 2967f811eff51b1379dd4c95cd990a371f68f531..15fbb4990050f8bca116222f074b8ee4ef3ccf23 100644 (file)
@@ -8,62 +8,62 @@ 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 javax.annotation.concurrent.ThreadSafe;
 import java.io.IOException;
 import java.net.Socket;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Class for managing an provisioning connection at the PDP side.
+ * Class for managing an provisioning connection at the PDP side for receiving and brokering out COPS messages.
  */
+@ThreadSafe
 public class PCMMPdpConnection implements Runnable {
 
-
-    public final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
+    private final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
 
     /**
     Socket connected to PEP
      */
-    private Socket _sock;
+    private final Socket _sock;
 
     /**
-    PEP identifier
-    */
-    private COPSPepId _pepId;
+     * PEP identifier
+     * TODO - Determine why the original author put this object into this class
+     */
+    private final COPSPepId _pepId;
 
     /**
-     *  Time of the latest keep-alive received
+     * Time of the latest keep-alive received
      */
     protected Date _lastRecKa;
 
     /**
-   Maps a Client Handle to a Handler
+     * Maps a Client Handle to a Handler
      */
-    protected Map<String, PCMMPdpReqStateMan> _managerMap;
+    protected final Map<String, PCMMPdpReqStateMan> _managerMap;
 
     /**
      *  PDP policy data processor class
      */
-    protected PCMMPdpDataProcess _process;
+    protected final PCMMPdpDataProcess _process;
 
     /**
-   Accounting timer value (secs)
+     * Accounting timer value (secs)
      */
-    protected short _acctTimer;
+    protected final short _acctTimer;
 
     /**
-   Keep-alive timer value (secs)
+     * Keep-alive timer value (secs)
      */
-    protected short _kaTimer;
+    protected final short _kaTimer;
 
     /**
-   COPS error returned by PEP
+     * COPS error returned by PEP on close
      */
-    protected COPSError _error;
+    protected transient COPSError _error;
 
     /**
      * Creates a new PDP connection
@@ -72,45 +72,18 @@ public class PCMMPdpConnection implements Runnable {
      * @param sock Socket connected to PEP
      * @param process Object for processing policy data
      */
-    public PCMMPdpConnection(COPSPepId pepId, Socket sock, PCMMPdpDataProcess process) {
-        _sock = sock;
+    public PCMMPdpConnection(final COPSPepId pepId, final Socket sock, final PCMMPdpDataProcess process,
+                             final short kaTimer, final short acctTimer) {
         _pepId = pepId;
-        _managerMap = new ConcurrentHashMap<>();
-        _kaTimer = 120;
+        _sock = sock;
         _process = process;
-    }
-
-    /**
-     * Sets the keep-alive timer value
-     * @param kaTimer Keep-alive timer value (secs)
-     */
-    public void setKaTimer(final short kaTimer) {
         _kaTimer = kaTimer;
-    }
-
-    /**
-     * Sets the accounting timer value
-     * @param acctTimer Accounting timer value (secs)
-     */
-    public void setAccTimer(final short acctTimer) {
         _acctTimer = acctTimer;
+        _managerMap = new ConcurrentHashMap<>();
     }
 
-    /**
-     * Gets the accounting timer value
-     * @return Accounting timer value (secs)
-     */
-    public short getAcctTimer() {
-        return _acctTimer;
-    }
-
-    /**
-     * Gets the handle map
-     * @return   A <tt>Hashtable</tt> holding the handle map
-     */
-    public Map<String, PCMMPdpReqStateMan> getReqStateMans() {
-        // Defensive copy
-        return new HashMap<>(_managerMap);
+    public void addStateMan(final String key, final PCMMPdpReqStateMan man) {
+        _managerMap.put(key, man);
     }
 
     /**
@@ -125,9 +98,8 @@ public class PCMMPdpConnection implements Runnable {
      * Closes the socket to the PEP
      * @throws IOException
      */
-    protected void close()
-    throws IOException {
-        _sock.close();
+    protected void close() throws IOException {
+        if (!_sock.isClosed()) _sock.close();
     }
 
     /**
@@ -142,12 +114,17 @@ public class PCMMPdpConnection implements Runnable {
      * Main loop
      */
     public void run () {
+        logger.info("Starting socket listener.");
         Date _lastSendKa = new Date();
         _lastRecKa = new Date();
-        try {
-            while (!_sock.isClosed()) {
+
+        // Loop while socket is open
+        while (!_sock.isClosed()) {
+            try {
                 if (_sock.getInputStream().available() != 0) {
+                    logger.info("Waiting to process socket messages");
                     processMessage(_sock);
+                    logger.info("Message processed");
                     _lastRecKa = new Date();
                 }
 
@@ -168,28 +145,31 @@ public class PCMMPdpConnection implements Runnable {
                     cTime = (int) (new Date().getTime());
 
                     if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
-                        // TODO - determine what is the client type to be used here?
                         final COPSKAMsg msg = new COPSKAMsg(null);
+                        logger.info("Sending KA message to CCAP");
                         COPSTransceiver.sendMsg(msg, _sock);
+                        logger.info("Sent KA message gto CCAP");
                         _lastSendKa = new Date();
                     }
                 }
 
                 try {
                     Thread.sleep(500);
-                } catch (Exception e) {
-                    logger.error("Unexpected exception while sleeping", e);
+                } catch (InterruptedException e) {
+                    logger.info("Shutting down socket connection to CCAP");
+                    break;
                 }
-
+            } catch (IOException e) {
+                logger.error("Exception reading from socket - exiting", e);
+                break;
+            } catch (COPSException e) {
+                logger.error("Exception processing message - continue processing", e);
             }
-        } catch (Exception e) {
-            logger.error("Error reading messages from socket", e);
         }
 
-        // connection closed by server
-        // COPSDebug.out(getClass().getName(),"Connection closed by client");
         try {
-            _sock.close();
+            if (! _sock.isClosed())
+                _sock.close();
         } catch (IOException e) {
             logger.error("Error closing socket", e);
         }
@@ -206,43 +186,43 @@ public class PCMMPdpConnection implements Runnable {
      * 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 {
+    private void processMessage(final Socket conn) throws COPSException, IOException {
         final 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.SSQ)) {
-            handleSyncComplete(conn, msg);
-        } else {
-            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+        logger.info("Processing message received of type - " + msg.getHeader().getOpCode());
+
+        switch (msg.getHeader().getOpCode()) {
+            case CC:
+                handleClientCloseMsg(conn, (COPSClientCloseMsg)msg);
+                break;
+            case KA:
+                handleKeepAliveMsg(conn, (COPSKAMsg)msg);
+                break;
+            case REQ:
+                handleRequestMsg(conn, (COPSReqMsg)msg);
+                break;
+            case RPT:
+                handleReportMsg(conn, (COPSReportMsg)msg);
+                break;
+            case DRQ:
+                handleDeleteRequestMsg(conn, (COPSDeleteMsg)msg);
+                break;
+            case SSQ:
+                handleSyncComplete(conn, (COPSSyncStateMsg)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>]
-     *
+     * @param    cMsg                a  COPSClientCloseMsg
      */
-    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
-        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+    private void handleClientCloseMsg(final Socket conn, final COPSClientCloseMsg cMsg) {
         _error = cMsg.getError();
+        logger.info("Closing client with error - " + _error.getDescription());
         try {
             // Support
             if (cMsg.getIntegrity() != null) {
@@ -255,36 +235,17 @@ public class PCMMPdpConnection implements Runnable {
         }
     }
 
-    /**
-     * 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
-     *
+     * @param    kaMsg               a  COPSKAMsg
      */
-    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
-        COPSKAMsg cMsg = (COPSKAMsg) msg;
-
-        COPSKAMsg kaMsg = (COPSKAMsg) msg;
+    private void handleKeepAliveMsg(final Socket conn, final COPSKAMsg kaMsg) {
         try {
             // Support
-            if (cMsg.getIntegrity() != null) {
+            if (kaMsg.getIntegrity() != null) {
                 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
             }
-
             kaMsg.writeData(conn);
         } catch (Exception unae) {
             logger.error("Unexpected exception while writing keep-alive message", unae);
@@ -293,66 +254,31 @@ public class PCMMPdpConnection implements Runnable {
 
     /**
      * Handle Delete Request Message
-     *
-     * <Delete Request> ::= <Common Header>
-     *                      <Client Handle>
-     *                      <Reason>
-     *                      [<Integrity>]
-     *
-     * Not support [<Integrity>]
-     *
      * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    cMsg                a  COPSDeleteMsg
      */
-    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() + "]");
-
+    private void handleDeleteRequestMsg(final Socket conn, final COPSDeleteMsg cMsg) throws COPSPdpException {
         // Support
         if (cMsg.getIntegrity() != null) {
             logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
         }
 
         // 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());
-        }
-
-        final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
+        final PCMMPdpReqStateMan man = _managerMap.remove(cMsg.getClientHandle().getId().str());
         if (man == null) {
-            logger.warn("State manager not found");
+            logger.warn("Cannot delete request state, no state manger found");
         } 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
-     *
+     * @param    reqMsg              a  COPSReqMsg
      */
-    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
-
-        final COPSReqMsg reqMsg = (COPSReqMsg) msg;
-//        COPSContext cntxt = reqMsg.getContext();
+    private void handleRequestMsg(final Socket conn, final COPSReqMsg reqMsg) throws COPSException {
         final COPSHeader header = reqMsg.getHeader();
-        //short reqType = cntxt.getRequestType();
         final short cType = header.getClientType();
 
         // Support
@@ -360,18 +286,15 @@ public class PCMMPdpConnection implements Runnable {
             logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
         }
 
-        PCMMPdpReqStateMan man;
-        man = _managerMap.get(reqMsg.getClientHandle().getId().str());
-        if (man == null) {
+        final PCMMPdpReqStateMan man;
+        if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
 
-            man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
+            man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle(), _process);
             _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());
+            logger.info("Created state manager for ID - " + reqMsg.getClientHandle().getId().str());
+        } else {
+            man = _managerMap.get(reqMsg.getClientHandle().getId().str());
         }
 
         man.processRequest(reqMsg);
@@ -379,25 +302,10 @@ public class PCMMPdpConnection implements Runnable {
 
     /**
      * 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
-     *
+     * @param    repMsg              a  COPSReportMsg
      */
-    private void handleReportMsg(Socket conn, COPSMsg msg)
-    throws COPSPdpException {
-        COPSReportMsg repMsg = (COPSReportMsg) msg;
-        // COPSHandle handle = repMsg.getClientHandle();
-        // COPSHeader header = repMsg.getHeader();
-
+    private void handleReportMsg(final Socket conn, final COPSReportMsg repMsg) throws COPSPdpException {
         // Support
         if (repMsg.getIntegrity() != null) {
             logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
@@ -413,17 +321,10 @@ public class PCMMPdpConnection implements Runnable {
 
     /**
      * Method handleSyncComplete
-     *
      * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    cMsg                a  COPSSyncStateMsg
      */
-    private void handleSyncComplete(Socket conn, COPSMsg msg)
-    throws COPSPdpException {
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
-        // COPSHandle handle = cMsg.getClientHandle();
-        // COPSHeader header = cMsg.getHeader();
-
+    private void handleSyncComplete(final Socket conn, final COPSSyncStateMsg cMsg) throws COPSException {
         // Support
         if (cMsg.getIntegrity() != null) {
             logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
@@ -442,7 +343,7 @@ public class PCMMPdpConnection implements Runnable {
      * @throws COPSException
      * @throws COPSPdpException
      */
-    protected void syncAllRequestState() throws COPSException, COPSPdpException {
+    protected void syncAllRequestState() throws COPSException {
         for (final PCMMPdpReqStateMan man : _managerMap.values()) {
             man.syncRequestState();
         }
index 770a578fadd5b80989dfcde8329524cb981e1234..6ed55206509efd316a63d8dae7ed4db66f48da46 100644 (file)
@@ -10,12 +10,15 @@ import org.pcmm.gates.IGateSpec.Direction;
 import org.pcmm.gates.impl.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSMsgSender;
 import org.umu.cops.prpdp.COPSPdpException;
 import org.umu.cops.stack.*;
+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.OPCode;
+import org.umu.cops.stack.COPSObjHeader.CNum;
 import org.umu.cops.stack.COPSObjHeader.CType;
 
 import java.io.IOException;
@@ -27,8 +30,6 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-//temp
-//pcmm
 /*
  * Example of an UNSOLICITED decision
  *
@@ -44,33 +45,15 @@ import java.util.Set;
 /**
  * COPS message transceiver class for provisioning connections at the PDP side.
  */
-public class PCMMPdpMsgSender {
+public class PCMMPdpMsgSender extends COPSMsgSender {
 
     public final static Logger logger = LoggerFactory.getLogger(PCMMPdpMsgSender.class);
 
-    /**
-     * Socket connected to PEP
-     */
-    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;
-
-    /**
-     *
-     */
     protected short _transactionID;
-    protected short _classifierID;
+    protected final short _classifierID;
+
     // XXX - this does not need to be here
-    protected int _gateID;
+    protected IGateID _gateID;
 
     /**
      * Creates a PCMMPdpMsgSender
@@ -82,42 +65,16 @@ public class PCMMPdpMsgSender {
      * @param sock
      *            Socket to the PEP
      */
-    public PCMMPdpMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
-        // COPS Handle
-        _handle = clientHandle;
-        _clientType = clientType;
-
-        _transactionID = 0;
-        _classifierID = 0;
-        _sock = sock;
+    public PCMMPdpMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock)
+            throws COPSPdpException {
+        this(clientType, (short)0, clientHandle, sock);
     }
 
     public PCMMPdpMsgSender(final short clientType, final short tID, final COPSHandle clientHandle,
-                            final Socket sock) {
-        // COPS Handle
-        _handle = clientHandle;
-        _clientType = clientType;
+                            final Socket sock) throws COPSPdpException {
+        super(clientType, clientHandle, sock);
         _transactionID = tID;
         _classifierID = 0;
-        _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;
     }
 
     /**
@@ -129,6 +86,14 @@ public class PCMMPdpMsgSender {
         return _transactionID;
     }
 
+    /**
+     * Gets the gate-id
+     *
+     * @return the gate-id value
+     */
+    public IGateID getGateID() {
+        return _gateID;
+    }
 
     /**
      * Sends a PCMM GateSet COPS Decision message
@@ -144,7 +109,11 @@ public class PCMMPdpMsgSender {
         trID.setTransactionIdentifier(_transactionID);
 
         gate.setTransactionID(trID);
-
+        // retain the transactionId to gate request mapping for gateID recovery after response
+        // see PCMMPdpReqStateMan.processReport()
+        final Short trIDnum = trID.getTransactionIdentifier();
+        logger.info("Adding gate to cache - " + gate + " with key - " + trIDnum);
+        PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
 
         // new pcmm specific clientsi
         final byte[] data = gate.getData();
@@ -152,17 +121,14 @@ public class PCMMPdpMsgSender {
         // 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)));
+        decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
         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));
+        final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, clientSD);
+
         // ** Send the GateSet Decision
-        // **
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
@@ -256,7 +222,7 @@ public class PCMMPdpMsgSender {
         // TODO - Use some variable here or remove...
         if (true) {
             //eclassifier.setProtocol(IClassifier.Protocol.NONE);
-            eclassifier.setProtocol(IClassifier.Protocol.TCP);
+//            eclassifier.setProtocol(IClassifier.Protocol.TCP);
             try {
                 InetAddress subIP = InetAddress
                                     .getByName(PCMMGlobalConfig.SubscriberID);
@@ -293,7 +259,7 @@ public class PCMMPdpMsgSender {
             eclassifier.setPriority((byte) 65);
 
         } else {
-            classifier.setProtocol(IClassifier.Protocol.TCP);
+//            classifier.setProtocol(IClassifier.Protocol.TCP);
             try {
                 InetAddress subIP = InetAddress
                                     .getByName(PCMMGlobalConfig.SubscriberID);
@@ -321,17 +287,14 @@ public class PCMMPdpMsgSender {
         final byte[] data = gate.getData();
 
         final Set<COPSDecision> decisionSet = new HashSet<>();
-        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
-                new COPSData(data, 0, data.length)));
+        decisionSet.add(new COPSDecision(CType.NA, Command.INSTALL, DecisionFlag.REQERROR));
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+        final COPSClientSI clientSD = new COPSClientSI(CSIType.NAMED, new COPSData(data, 0, data.length));
 
         // 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???
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
 
         // ** Send the GateSet Decision
         // **
@@ -418,7 +381,7 @@ public class PCMMPdpMsgSender {
         // XXX - if the version major is less than 4 we need to use Classifier
         if (true) {
             //eclassifier.setProtocol(IClassifier.Protocol.NONE);
-            eclassifier.setProtocol(IClassifier.Protocol.TCP);
+//            eclassifier.setProtocol(IClassifier.Protocol.TCP);
             try {
                 InetAddress subIP = InetAddress
                                     .getByName(PCMMGlobalConfig.SubscriberID);
@@ -455,7 +418,7 @@ public class PCMMPdpMsgSender {
             eclassifier.setPriority((byte) 65);
 
         } else {
-            classifier.setProtocol(IClassifier.Protocol.TCP);
+//            classifier.setProtocol(IClassifier.Protocol.TCP);
             try {
                 InetAddress subIP = InetAddress
                                     .getByName(PCMMGlobalConfig.SubscriberID);
@@ -483,16 +446,14 @@ public class PCMMPdpMsgSender {
         byte[] data = gate.getData();
 
         final Set<COPSDecision> decisionSet = new HashSet<>();
-        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData(data, 0, data.length)));
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR));
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+        final COPSClientSI clientSD = new COPSClientSI(CSIType.NAMED, new COPSData(data, 0, data.length));
 
         // 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???
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, clientSD);
 
         // ** Send the GateSet Decision
         // **
@@ -521,7 +482,7 @@ public class PCMMPdpMsgSender {
                     logger.info("the CMTS has sent a Gate-Set-Ack response");
                     // here CMTS responded that he acknowledged the Gate-Set
                     // TODO do further check of Gate-Set-Ack GateID etc...
-                    _gateID = responseGate.getGateID().getGateID();
+                    _gateID = responseGate.getGateID();
                     return true;
                 } else {
                     return false;
@@ -529,7 +490,7 @@ public class PCMMPdpMsgSender {
             }
             return false;
         } catch (Exception e) { // COPSException, IOException
-            throw new COPSPdpException("Error COPSTransceiver.receiveMsg");
+            throw new COPSPdpException("Error COPSTransceiver.receiveMsg", e);
         }
     }
 
@@ -561,10 +522,6 @@ public class PCMMPdpMsgSender {
         .setRequestTransmissionPolicy(
             PCMMGlobalConfig.BETransmissionPolicy);
 
-        // byte[] content = "1234".getBytes();
-
-        // handle.setId(new COPSData(content, 0, content.length));
-
         // set transaction ID to gate set
         trID.setGateCommandType(ITransactionID.GateSet);
         _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID);
@@ -584,7 +541,7 @@ public class PCMMPdpMsgSender {
          * .setServiceClassName("S_up");
          */
 
-        classifier.setProtocol(IClassifier.Protocol.TCP);
+//        classifier.setProtocol(IClassifier.Protocol.TCP);
         try {
             InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
             InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
@@ -608,16 +565,14 @@ public class PCMMPdpMsgSender {
         final byte[] data = gate.getData();
 
         final Set<COPSDecision> decisionSet = new HashSet<>();
-        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL,
-                DecisionFlag.REQERROR, new COPSData(data, 0, data.length)));
+        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR));
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
+        final COPSClientSI clientSD = new COPSClientSI(CSIType.NAMED, new COPSData(data, 0, data.length));
+
         // 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));
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
 
         // ** Send the GateSet Decision
         // **
@@ -626,7 +581,6 @@ public class PCMMPdpMsgSender {
         } catch (IOException e) {
             logger.error("Failed to send the decision", e);
         }
-
     }
 
     /**
@@ -634,57 +588,34 @@ public class PCMMPdpMsgSender {
      *
      * @throws COPSPdpException
      */
-    public void sendGateDelete(int gID) throws COPSPdpException {
-        /*
-         * Example of an UNSOLICITED decision <Gate Control Command> = <COPS
-         * Common Header> <Client Handle> <Context> <Decision Flags> <ClientSI
-         * Data> <ClientSI Data> = <Gate-Set> | <Gate-Info> | <Gate-Delete> |
-         * <PDP-Config> | <Synch-Request> | <Msg-Receipt> <Gate-Delete> =
-         * <Decision Header> <TransactionID> <AMID> <SubscriberID> <GateID>
-         */
-        // Common Header with the same ClientType as the request
-        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 IGateID gateID = new GateID();
-
+    public void sendGateDelete(final IPCMMGate gate) throws COPSPdpException {
         // set transaction ID to gate set
+        final ITransactionID trID = new TransactionID();
         trID.setGateCommandType(ITransactionID.GateDelete);
         _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID);
         trID.setTransactionIdentifier(_transactionID);
+        gate.setTransactionID(trID);
 
-        amid.setApplicationType((short) 1);
-        amid.setApplicationMgrTag((short) 1);
-        gateID.setGateID(gID);
+        Short trIDnum = trID.getTransactionIdentifier();
+        PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
 
-        try {
-            InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
-            subscriberID.setSourceIPAddress(subIP);
-        } catch (UnknownHostException unae) {
-            logger.error("Error getByName", unae);
-        }
-
-        gate.setTransactionID(trID);
-        gate.setAMID(amid);
-        gate.setSubscriberID(subscriberID);
-        gate.setGateID(gateID);
+        // gateDelete only requires AMID, subscriberID, and gateID
+        // remove the gateSpec, traffic profile, and classifiers from original gate request
+        gate.setGateSpec(null);
+        gate.setTrafficProfile(null);
+        gate.setClassifier(null);
+        // clear the error object
+        gate.setError(null);
 
         // XXX - GateID
         final byte[] data = gate.getData();
-
         final Set<COPSDecision> decisionSet = new HashSet<>();
-        decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
-                new COPSData(data, 0, data.length)));
+        decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
-        decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
+        decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
+        final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
 
-        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));
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
 
         // ** Send the GateDelete Decision
         // **
@@ -713,15 +644,12 @@ public class PCMMPdpMsgSender {
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
-        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
-                decisionMap, null);
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, null);
 
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
-            throw new COPSPdpException(
-                "Failed to send the open new request state, reason: "
-                + e.getMessage());
+            throw new COPSPdpException("Failed to send the open new request state", e);
         }
     }
 
@@ -734,13 +662,11 @@ public class PCMMPdpMsgSender {
         /*
          * <Gate-Info> ::= <Common Header> [<Client Handle>] [<Integrity>]
          */
-        final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), new COPSHandle(_handle.getId()), null);
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), _handle, null);
         try {
             msg.writeData(_sock);
         } catch (IOException e) {
-            throw new COPSPdpException(
-                "Failed to send the GateInfo request, reason: "
-                + e.getMessage());
+            throw new COPSPdpException("Failed to send the GateInfo request", e);
         }
     }
 
@@ -756,13 +682,11 @@ public class PCMMPdpMsgSender {
          */
 
         // Client Handle with the same clientHandle as the request
-        final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), new COPSHandle(_handle.getId()), null);
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), _handle, null);
         try {
             msg.writeData(_sock);
         } catch (IOException e) {
-            throw new COPSPdpException(
-                "Failed to send the sync state request, reason: "
-                + e.getMessage());
+            throw new COPSPdpException("Failed to send the sync state request", e);
         }
     }
     // XXX - Temp
index a8ab70568e546bb171af269586329c3e3e9b4443..5f5e3c81302d56b1c0039100062018a49c3106cf 100644 (file)
@@ -4,10 +4,13 @@
 
 package org.pcmm;
 
+import org.pcmm.gates.IGateID;
+import org.pcmm.gates.IPCMMGate;
 import org.pcmm.gates.ITransactionID;
 import org.pcmm.gates.impl.PCMMGateReq;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
 import org.umu.cops.prpdp.COPSPdpException;
 import org.umu.cops.stack.*;
 import org.umu.cops.stack.COPSReportType.ReportType;
@@ -20,159 +23,36 @@ import java.util.Map;
 /**
  * State manager class for provisioning requests, at the PDP side.
  */
-public class PCMMPdpReqStateMan {
+public class PCMMPdpReqStateMan extends COPSStateMan {
 
-    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;
+    private final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
 
     /**
      * Object for performing policy data processing
      */
-    protected PCMMPdpDataProcess _process;
-
-    /**
-     *  Current state of the request being managed
-     */
-    protected short _status;
+    protected final PCMMPdpDataProcess _process;
 
     /** COPS message transceiver used to send COPS messages */
-    protected PCMMPdpMsgSender _sender;
+    protected transient 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;
+    // TODO - consider sending in the COPSHandle object instead
+    public PCMMPdpReqStateMan(final short clientType, final COPSHandle clientHandle, final PCMMPdpDataProcess process) {
+        super(clientType, clientHandle);
+        this._process = process;
     }
 
-    /**
-     * 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 {
+    @Override
+    protected void initRequestState(final Socket sock) throws COPSException {
         // Inits an object for sending COPS messages to the PEP
         _sender = new PCMMPdpMsgSender(_clientType, _handle, sock);
 
         // Initial state
-        _status = ST_INIT;
+        _status = Status.ST_INIT;
     }
 
 
@@ -182,12 +62,12 @@ public class PCMMPdpReqStateMan {
      * @param msg   COPS request received from the PEP
      * @throws COPSPdpException
      */
-    protected void processRequest(COPSReqMsg msg)
-    throws COPSPdpException {
+    public void processRequest(final COPSReqMsg msg) throws COPSPdpException {
 
-        COPSHeader hdrmsg = msg.getHeader();
-        COPSHandle handlemsg = msg.getClientHandle();
-        COPSContext contextmsg = msg.getContext();
+        // TODO - Implement me
+//        COPSHeader hdrmsg = msg.getHeader();
+//        COPSHandle handlemsg = msg.getClientHandle();
+//        COPSContext contextmsg = msg.getContext();
 
         //** Analyze the request
         //**
@@ -250,8 +130,9 @@ public class PCMMPdpReqStateMan {
      * Processes a report
      * @param msg   Report message from the PEP
      * @throws COPSPdpException
+     * TODO - break apart this method
      */
-    protected void processReport(COPSReportMsg msg) throws COPSPdpException {
+    protected void processReport(final COPSReportMsg msg) throws COPSPdpException {
         // Report Type
         final COPSReportType rtypemsg = msg.getReport();
 
@@ -262,8 +143,9 @@ public class PCMMPdpReqStateMan {
 
             // PCMMUtils.WriteBinaryDump("COPSReportClientSI", data);
             logger.info("PCMMGateReq Parse Gate Message");
-            PCMMGateReq gateMsg = new PCMMGateReq(data);
+            final PCMMGateReq gateMsg = new PCMMGateReq(data);
 
+            // TODO FIXME - Why is this Map being filled but never used???
             final Map<String, String> repSIs = new HashMap<>();
             String strobjprid = "";
             final COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());
@@ -275,8 +157,8 @@ public class PCMMPdpReqStateMan {
                 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());
+                    logger.info("PRID: " + strobjprid);
+                    logger.info("EPD: " + obj.getData().str());
                     break;
                 default:
                     logger.error("Object s-num: " + obj.getSNum() + "stype " + obj.getSType());
@@ -288,42 +170,68 @@ public class PCMMPdpReqStateMan {
             logger.info("rtypemsg process");
             //** Here we must act in accordance with
             //** the report received
+
+            // retrieve and remove the transactionId to gate request map entry
+            // see PCMMPdpMsgSender.sendGateSet(IPCMMGate gate)
+            final ITransactionID trID = gateMsg.getTransactionID();
+            final Short trIDnum = trID.getTransactionIdentifier();
+
+            logger.info("Removing gate from cache with key - " + trIDnum);
+            final IPCMMGate gate = PCMMGlobalConfig.transactionGateMap.remove(trIDnum);
+            if (gate != null) {
+                // capture the "error" message if any
+                gate.setError(gateMsg.getError());
+                logger.info("Setting error on gate - " + gateMsg.getError());
+            }else {
+                logger.error("processReport(): gateReq not found for transactionID {}", trIDnum);
+                return;
+            }
+
             if (rtypemsg.getReportType().equals(ReportType.SUCCESS)) {
                 logger.info("rtypemsg success");
-                _status = ST_REPORT;
+                _status = Status.ST_REPORT;
+                final IGateID gateID = gateMsg.getGateID();
+                logger.info("Setting gate ID on gate object - " + gateID);
+                gate.setGateID(gateID);
                 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());
-                }
+                final String cmdType;
+                if ( trID.getGateCommandType() == ITransactionID.GateDeleteAck ) {
+                    cmdType = "GateDeleteAck";
+                } else if ( trID.getGateCommandType() == ITransactionID.GateSetAck ) {
+                    cmdType = "GateSetAck";
+                } else cmdType = null;
+                // capture the gateId from the response message
+                final IGateID gateID = gateMsg.getGateID();
+                logger.info("Setting gate ID on gate object - " + gateID);
+                gate.setGateID(gateID);
+                int gateIdInt = gateID.getGateID();
+                String gateIdHex = String.format("%08x", gateIdInt);
+                logger.info(getClass().getName() + ": " + cmdType + ": GateID = " + gateIdHex);
             }
             if (rtypemsg.getReportType().equals(ReportType.FAILURE)) {
                 logger.info("rtypemsg failure");
-                _status = ST_REPORT;
+                _status = 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)) {
+            } else if (rtypemsg.getReportType().equals(ReportType.ACCOUNTING)) {
                     logger.info("rtypemsg account");
-                    _status = ST_ACCT;
+                    _status = Status.ST_ACCT;
                     if (_process != null)
                         _process.acctReport(this, gateMsg);
-                }
+            }
+
+            // let the waiting gateSet/gateDelete sender proceed
+            // TODO - see PCMMService#processReport() gate.notify(). Should determine a better means to
+            // TODO - handle this synchronization.
+            logger.info("Notify gate request has been updated with ID - " + gate.getGateID());
+            synchronized(gate) {
+                gate.notify();
+            }
+            logger.info("Out processReport");
         }
     }
 
@@ -332,54 +240,49 @@ public class PCMMPdpReqStateMan {
     * @param error  Reason
     * @throws COPSPdpException
     */
-    protected void processClosedConnection(COPSError error)
-    throws COPSPdpException {
+    protected void processClosedConnection(final COPSError error) throws COPSPdpException {
         if (_process != null)
             _process.notifyClosedConnection(this, error);
 
-        _status = ST_CCONN;
+        _status = Status.ST_CCONN;
     }
 
     /**
      * Called when no keep-alive is received
      * @throws COPSPdpException
      */
-    protected void processNoKAConnection()
-    throws COPSPdpException {
+    protected void processNoKAConnection() throws COPSPdpException {
         if (_process != null)
             _process.notifyNoKAliveReceived(this);
 
-        _status = ST_NOKA;
+        _status = Status.ST_NOKA;
     }
 
     /**
     * Deletes the request state
     * @throws COPSPdpException
     */
-    protected void finalizeRequestState()
-    throws COPSPdpException {
+    protected void finalizeRequestState() throws COPSPdpException {
         _sender.sendDeleteRequestState();
-        _status = ST_FINAL;
+        _status = Status.ST_FINAL;
     }
 
     /**
     * Asks for a COPS sync
     * @throws COPSPdpException
     */
-    protected void syncRequestState()
-    throws COPSPdpException {
+    protected void syncRequestState() throws COPSPdpException {
         _sender.sendSyncRequestState();
-        _status = ST_SYNC;
+        _status = Status.ST_SYNC;
     }
 
     /**
      * Opens a new request state
      * @throws COPSPdpException
      */
-    protected void openNewRequestState()
-    throws COPSPdpException {
+    protected void openNewRequestState() throws COPSPdpException {
         _sender.sendOpenNewRequestState();
-        _status = ST_NEW;
+        _status = Status.ST_NEW;
     }
 
     /**
@@ -387,12 +290,11 @@ public class PCMMPdpReqStateMan {
      * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP
      * @throws COPSPdpException
      */
-    protected void processDeleteRequestState(COPSDeleteMsg dMsg)
-    throws COPSPdpException {
+    protected void processDeleteRequestState(COPSDeleteMsg dMsg) throws COPSPdpException {
         if (_process != null)
             _process.closeRequestState(this);
 
-        _status = ST_DEL;
+        _status = Status.ST_DEL;
     }
 
 }
index 6aea0ae67e2a627d79fe62d6a7d566717b9dfd00..3226f50fe7538afebc321cebda0d0c6def2c4600 100644 (file)
@@ -5,10 +5,10 @@
 
 package org.pcmm.gates;
 
-import java.net.InetAddress;
-
 import org.pcmm.base.IPCMMBaseObject;
 
+import java.net.InetAddress;
+
 /**
  *
  *
@@ -16,11 +16,11 @@ import org.pcmm.base.IPCMMBaseObject;
  */
 public interface IClassifier extends IPCMMBaseObject {
 
-    static final short LENGTH = 24;
-    static final byte SNUM = 6;
-    static final byte STYPE = 1;
+    short LENGTH = 24;
+    byte SNUM = 6;
+    byte STYPE = 1;
 
-    static enum Protocol {
+    enum Protocol {
         /*ICMP((short) 1), IGMP((short) 2), */
         NONE((short)0), TCP((short) 6), UDP((short) 17);
 
@@ -87,14 +87,14 @@ public interface IClassifier extends IPCMMBaseObject {
      *
      * @return the protocol.
      */
-    Protocol getProtocol();
+    short getProtocol();
 
     /**
      * @see <a
      *      href="http://www.iana.org/assignments/protocol-numbers/protocol-numbers.txt">protocols</a>
-     * @param p
+     * @param p - the protocol value
      */
-    void setProtocol(Protocol p);
+    void setProtocol(short p);
 
     /**
      * Priority may be used to distinguish between multiple classifiers that
index 10f4500318fde856d441a1fe4c1ce37f2473f998..e81d1dc98cca2b6b8417378aebb23020c79c6f26 100644 (file)
@@ -13,16 +13,12 @@ import org.pcmm.base.IPCMMBaseObject;
  * information regarding the treatment of other objects specified in the Gate
  * message.
  * </p>
- *
- *
- *
- *
  */
 public interface IGateSpec extends IPCMMBaseObject {
 
-    static final byte SNUM = 5;
-    static final byte STYPE = 1;
-    static final short LENGTH = 16;
+    byte SNUM = 5;
+    byte STYPE = 1;
+    short LENGTH = 16;
 
     /**
      * <p>
@@ -34,11 +30,11 @@ public interface IGateSpec extends IPCMMBaseObject {
      *
      *
      */
-    public enum Direction {
+    enum Direction {
 
         UPSTREAM((byte) 1), DOWNSTREAM((byte) 0);
 
-        private Direction(byte value) {
+        Direction(byte value) {
             this.value = value;
         }
 
@@ -69,16 +65,16 @@ public interface IGateSpec extends IPCMMBaseObject {
             }
         }
 
-    };
+    }
 
     /**
      *
      */
-    public enum DSCPTOS {
+    enum DSCPTOS {
 
-        ENABLE((byte) 1), OVERRIDE((byte) 0);
+        ENABLE((byte) 2), OVERRIDE((byte) 0);
 
-        private DSCPTOS(byte value) {
+        DSCPTOS(byte value) {
             this.value = value;
         }
 
@@ -109,7 +105,7 @@ public interface IGateSpec extends IPCMMBaseObject {
 
         private byte value;
 
-    };
+    }
 
     /**
      * <p>
@@ -221,10 +217,13 @@ public interface IGateSpec extends IPCMMBaseObject {
 
     /**
      *
-     * @param dscpTos
+     * @param dscpTos - the object used to overwrite
      */
     void setDSCP_TOSOverwrite(DSCPTOS dscpTos);
 
+    // set the DSCP_TOS value
+    void setDSCP_TOSOverwrite(byte dscpTos);
+
     /**
      *
      * @return DSCP/TOS
@@ -233,7 +232,7 @@ public interface IGateSpec extends IPCMMBaseObject {
 
     /**
      *
-     * @return
+     * @return - the mask
      */
     byte getDSCP_TOSMask();
 
index a9d689f158a2d501986761957edfc5800c732304..1a026dab958f608977eecf1293c76397d14536e1 100644 (file)
@@ -5,27 +5,82 @@
 
 package org.pcmm.gates;
 
+import java.net.InetAddress;
+
 public interface IIPv6Classifier extends IExtendedClassifier {
-    static final short LENGTH = 64;
-    static final byte SNUM = 6;
-    static final byte STYPE = 3;
+    short LENGTH = 64;
+    byte SNUM = 6;
+    byte STYPE = 3;
+
+    // flags: Flow Label match enable flag
+    void setFlowLabelEnableFlag(byte flag);
+    byte getFlowLabelEnableFlag();
 
     // Tc-low
+    void setTcLow(byte tcLow);
+    byte getTcLow();
+
     // Tc-high
+    void setTcHigh(byte tcHigh);
+    byte getTcHigh();
+
     // Tc-mask
+    void setTcMask(byte tcHigh);
+    byte getTcMask();
+
     // Flow Label
+    void setFlowLabel(Long flowLabel);
+    int getFlowLabel();
+
     // Next Header Type
+    void setNextHdr(short nxtHdr);
+    short getNextHdr();
+
     // Source Prefix Length
+    void setSourcePrefixLen(byte srcPrefixLen);
+    byte getSourcePrefixLen();
+
     // Destination Prefix Length
+    void setDestinationPrefixLen(byte dstPrefixLen);
+    byte getDestinationPrefixLen();
+
     // IPv6 Source Address
+    void setSourceIPAddress(InetAddress a);
+    InetAddress getSourceIPAddress();
+
     // IPv6 Destination Address
+    void setDestinationIPAddress(InetAddress a);
+    InetAddress getDestinationIPAddress();
+
     // Source Port Start
+    short getSourcePortStart();
+    void setSourcePortStart(short p);
+
     // Source Port End
+    short getSourcePortEnd();
+    void setSourcePortEnd(short p);
+
     // Destination Port Start
+    short getDestinationPortStart();
+    void setDestinationPortStart(short p);
+
     // Destination Port End
+    short getDestinationPortEnd();
+    void setDestinationPortEnd(short p);
+
     // ClassifierID
+    short getClassifierID();
+    void setClassifierID(short p);
+
     // Priority
+    void setPriority(byte p);
+    byte getPriority();
+
     // Activation State
-    // Action
+    void setActivationState(byte s);
+    byte getActivationState();
 
+    // Action
+    void setAction(byte a);
+    byte getAction();
 }
index 838472200d32d2b61fac0f43b9804d93c1a01763..6fa5d79a8bbdba0f9523ba243a247e8a61f1b536 100644 (file)
@@ -3,15 +3,15 @@
  */
 package org.pcmm.gates.impl;
 
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IClassifier;
+
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 
-import org.pcmm.base.impl.PCMMBaseObject;
-import org.pcmm.gates.IClassifier;
-
 /**
- *
+ * TODO - Cleanup this interface
  */
 public class Classifier extends PCMMBaseObject implements IClassifier {
 
@@ -23,16 +23,16 @@ public class Classifier extends PCMMBaseObject implements IClassifier {
     }
 
     /**
-     * @param data
+     * @param data - the data to add
      */
     public Classifier(byte[] data) {
         super(data);
     }
 
     /**
-     * @param len
-     * @param sType
-     * @param sNum
+     * @param len - the classifier's length
+     * @param sType - the sType value
+     * @param sNum - the sNum value
      */
     public Classifier(short len, byte sType, byte sNum) {
         super(len, sType, sNum);
@@ -134,8 +134,8 @@ public class Classifier extends PCMMBaseObject implements IClassifier {
      * @see org.pcmm.gates.IClassifier#getProtocol()
      */
     @Override
-    public Protocol getProtocol() {
-        return Protocol.valueOf(getShort((short) 0));
+    public short getProtocol() {
+        return getShort((short) 0);
     }
 
     /*
@@ -144,8 +144,8 @@ public class Classifier extends PCMMBaseObject implements IClassifier {
      * @see org.pcmm.gates.IClassifier#setProtocol(short)
      */
     @Override
-    public void setProtocol(Protocol p) {
-        setShort(p.getValue(), (short) 0);
+    public void setProtocol(short p) {
+        setShort(p, (short) 0);
     }
 
     /*
index 854d54327db642fbe525f79da045ee3fde815723..382b08a3df81e764673cb06e8ec25a87028ad6cc 100644 (file)
@@ -13,7 +13,7 @@ public class DOCSISServiceClassNameTrafficProfile extends PCMMBaseObject
             implements ITrafficProfile {
 
     public static final byte STYPE = 2;
-    public static final short LENGTH = 12;
+    public static final short LENGTH = 24;
 
     /**
      *
@@ -23,16 +23,16 @@ public class DOCSISServiceClassNameTrafficProfile extends PCMMBaseObject
     }
 
     /**
-     * @param data
+     * @param data - the data bytes to parse
      */
     public DOCSISServiceClassNameTrafficProfile(byte[] data) {
         super(data);
     }
 
     /**
-     * @param len
-     * @param sType
-     * @param sNum
+     * @param len - the classifier's length
+     * @param sType - the sType value
+     * @param sNum - the sNum value
      */
     public DOCSISServiceClassNameTrafficProfile(short len, byte sType, byte sNum) {
         super(len, sType, sNum);
index 0e68f50934961159f413748aa03b8d1ee33e3085..2ebc2bcdb45b656b46fc2ae516129f4aedd01f23 100644 (file)
@@ -3,12 +3,12 @@
  */
 package org.pcmm.gates.impl;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
 import org.pcmm.base.impl.PCMMBaseObject;
 import org.pcmm.gates.IExtendedClassifier;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
 /**
  *
  */
@@ -20,16 +20,16 @@ public class ExtendedClassifier extends PCMMBaseObject implements
     }
 
     /**
-     * @param data
+     * @param data - the data bytes to parse
      */
     public ExtendedClassifier(byte[] data) {
         super(data);
     }
 
     /**
-     * @param len
-     * @param sType
-     * @param sNum
+     * @param len - the classifier's length
+     * @param sType - the sType value
+     * @param sNum - the sNum value
      */
     public ExtendedClassifier(short len, byte sType, byte sNum) {
         super(len, sType, sNum);
@@ -132,8 +132,8 @@ public class ExtendedClassifier extends PCMMBaseObject implements
      * @see org.pcmm.gates.IClassifier#getProtocol()
      */
     @Override
-    public Protocol getProtocol() {
-        return Protocol.valueOf(getShort((short) 0));
+    public short getProtocol() {
+        return getShort((short) 0);
     }
 
     /*
@@ -142,8 +142,8 @@ public class ExtendedClassifier extends PCMMBaseObject implements
      * @see org.pcmm.gates.IClassifier#setProtocol(short)
      */
     @Override
-    public void setProtocol(Protocol p) {
-        setShort(p.getValue(), (short) 0);
+    public void setProtocol(short p) {
+        setShort(p, (short) 0);
     }
 
     /*
index dce286e99b4d4252bd0d42edf8c9254f1b093bfc..914855852403819e6b32cf194e6f62d2eeb5c97c 100644 (file)
@@ -12,6 +12,9 @@ import org.pcmm.gates.ISessionClassID;
  */
 public class GateSpec extends PCMMBaseObject implements IGateSpec {
 
+    // GateSpec flags are Direction (bit 0) and DSCPTOS overwrite enable (bit 1)
+    private byte flags = 0;
+
     public GateSpec() {
         super(LENGTH, STYPE, SNUM);
     }
@@ -37,7 +40,9 @@ public class GateSpec extends PCMMBaseObject implements IGateSpec {
 
     @Override
     public void setDirection(Direction direction) {
-        setByte(direction.getValue(), (short) 0);
+        // OR in the Direction flag with the DSCPTOS enable flag
+        flags |= direction.getValue();
+        setByte(flags, (short) 0);
     }
 
     @Override
@@ -84,9 +89,17 @@ public class GateSpec extends PCMMBaseObject implements IGateSpec {
 
     @Override
     public void setDSCP_TOSOverwrite(DSCPTOS dscpTos) {
-        setByte(dscpTos.getValue(), (short) 1);
+        // OR in the DSCPTOS enable flag with the Direction flag
+        flags |= dscpTos.getValue();
+        setByte(flags, (short) 0);
     }
 
+    @Override
+    public void setDSCP_TOSOverwrite(byte dscpTos) {
+        setByte(dscpTos, (short) 1);
+    }
+
+
     @Override
     public DSCPTOS getDSCP_TOSOverwrite() {
         return DSCPTOS.valueOf(getByte((short) 1));
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java
new file mode 100644 (file)
index 0000000..1280865
--- /dev/null
@@ -0,0 +1,347 @@
+/**
+
+ * Copyright (c) 2014 CableLabs.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IIPv6Classifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ *
+ */
+public class IPv6Classifier extends PCMMBaseObject implements
+        IIPv6Classifier {
+
+    private Logger logger = LoggerFactory.getLogger(IPv6Classifier.class);
+
+    public IPv6Classifier() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data - the data bytes to parse
+     */
+    public IPv6Classifier(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len - the classifier's length
+     * @param sType - the sType value
+     * @param sNum - the sNum value
+     */
+    public IPv6Classifier(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    // offset:length Field Name: Description
+    // 00:01 Flags: 0000.0001 Flow Label enable match
+    // 01:01 Tc-low
+    // 02:01 Tc-high
+    // 03:01 Tc-mask
+    // 04:04 Flow Label: low order 20 bits; high order 12 bits ignored
+    // 08:02 Next Header Type
+    // 10:01 Source Prefix Length
+    // 11:01 Destination Prefix Length
+    // 12:16 IPv6 Source Address
+    // 28:16 IPv6 Destination Address
+    // 44:02 Source Port Start
+    // 46:02 Source Port End
+    // 48:02 Destination Port Start
+    // 50:02 Destination Port End
+    // 52:02 ClassifierID
+    // 54:01 Priority
+    // 55:01 Activation State
+    // 56:01 Action
+    // 57:03 Reserved
+
+    // 00:01 Flags: 0000.0001 Flow Label enable match
+    @Override
+    public void setFlowLabelEnableFlag(byte flag) {
+        setByte(flag, (short) 0);
+    }
+    @Override
+    public byte getFlowLabelEnableFlag() {
+        return getByte((short) 0);
+    }
+
+    // 01:01 Tc-low
+    @Override
+    public void setTcLow(byte tcLow) {
+        setByte(tcLow, (short) 1);
+    }
+    @Override
+    public byte getTcLow() {
+        return getByte((short) 1);
+    }
+
+    // 02:01 Tc-high
+    @Override
+    public void setTcHigh(byte tcHigh) {
+        setByte(tcHigh, (short) 2);
+    }
+    @Override
+    public byte getTcHigh() {
+        return getByte((short) 2);
+    }
+
+    // 03:01 Tc-mask
+    @Override
+    public void setTcMask(byte tcMask) {
+        setByte(tcMask, (short) 3);
+    }
+    @Override
+    public byte getTcMask() {
+        return getByte((short) 3);
+    }
+
+    // 04:04 Flow Label: low order 20 bits; high order 12 bits ignored
+    @Override
+    public void setFlowLabel(Long flowLabel) {
+        setInt(flowLabel.intValue(), (short) 4);
+    }
+    @Override
+    public int getFlowLabel() {
+        return getInt((short) 4);
+    }
+
+    // 08:02 Next Header Type
+    @Override
+    public void setNextHdr(short nxtHdr) {
+        setShort(nxtHdr, (short) 8);
+    }
+    @Override
+    public short getNextHdr() {
+        return getShort((short) 8);
+    }
+
+    // 10:01 Source Prefix Length
+    @Override
+    public void setSourcePrefixLen(byte srcPrefixLen) {
+        setByte(srcPrefixLen, (short) 10);
+    }
+    @Override
+    public byte getSourcePrefixLen() {
+        return getByte((short) 10);
+    }
+
+    // 11:01 Destination Prefix Length
+    @Override
+    public void setDestinationPrefixLen(byte dstPrefixLen) {
+        setByte(dstPrefixLen, (short) 11);
+    }
+    @Override
+    public byte getDestinationPrefixLen() {
+        return getByte((short) 11);
+    }
+
+    // 12:16 IPv6 Source Address
+    @Override
+    public void setSourceIPAddress(InetAddress a) {
+        setBytes(a.getAddress(), (short) 12);
+    }
+    @Override
+    public InetAddress getSourceIPAddress() {
+        try {
+            return InetAddress.getByAddress(getBytes((short) 12, (short) 16));
+        } catch (UnknownHostException e) {
+            logger.error("getSourceIPAddress(): Malformed IPv6 address: {}", e.getMessage());
+        }
+        return null;
+    }
+
+    // 28:16 IPv6 Destination Address
+    @Override
+    public void setDestinationIPAddress(InetAddress a) {
+        setBytes(a.getAddress(), (short) 28);
+    }
+    @Override
+    public InetAddress getDestinationIPAddress() {
+        try {
+            return InetAddress.getByAddress(getBytes((short) 28, (short) 16));
+        } catch (UnknownHostException e) {
+            logger.error("getDestinationIPAddress(): Malformed IPv6 address: {}", e.getMessage());
+        }
+        return null;
+    }
+    // 44:02 Source Port Start
+    @Override
+    public short getSourcePortStart() {
+        return getShort((short) 44);
+    }
+    @Override
+    public void setSourcePortStart(short p) {
+        setShort(p, (short) 44);
+    }
+
+    // 46:02 Source Port End
+    @Override
+    public short getSourcePortEnd() {
+        return getShort((short) 46);
+    }
+    @Override
+    public void setSourcePortEnd(short p) {
+        setShort(p, (short) 46);
+    }
+
+    // 48:02 Destination Port Start
+    @Override
+    public short getDestinationPortStart() {
+        return getShort((short) 48);
+    }
+    @Override
+    public void setDestinationPortStart(short p) {
+        setShort(p, (short) 48);
+    }
+
+    // 50:02 Destination Port End
+    @Override
+    public short getDestinationPortEnd() {
+        return getShort((short) 50);
+    }
+    @Override
+    public void setDestinationPortEnd(short p) {
+        setShort(p, (short) 50);
+    }
+
+    // 52:02 ClassifierID
+    @Override
+    public short getClassifierID() {
+        return getShort((short) 52);
+    }
+
+    @Override
+    public void setClassifierID(short p) {
+        setShort(p, (short) 52);
+    }
+
+    // 54:01 Priority
+    @Override
+    public void setPriority(byte p) {
+        setByte(p, (short) 54);
+    }
+    @Override
+    public byte getPriority() {
+        return getByte((short) 54);
+    }
+
+    // 55:01 Activation State
+    @Override
+    public void setActivationState(byte s) {
+        setByte(s, (short) 55);
+    }
+    @Override
+    public byte getActivationState() {
+        return getByte((short) 55);
+    }
+
+    // 56:01 Action
+    @Override
+    public void setAction(byte a) {
+        setByte(a, (short) 56);
+    }
+    @Override
+    public byte getAction() {
+        return getByte((short) 56);
+    }
+
+
+
+    // baggage from IExtendedClassifier
+    // not used in IPv6 classifiers
+    @Override
+    public void setIPSourceMask(InetAddress a) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setIPDestinationMask(InetAddress m) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public InetAddress getIPSourceMask() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public InetAddress getIPDestinationMask() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public short getDestinationPort() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setDestinationPort(short p) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public short getSourcePort() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setSourcePort(short p) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public short getProtocol() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setProtocol(short p) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public byte getDSCPTOS() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setDSCPTOS(byte v) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public byte getDSCPTOSMask() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setDSCPTOSMask(byte v) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
index 90dd6c6eb9cee2183971b35b08a3daf7b6c72b86..57121b055dbffae638a544368307bd7e661254da 100644 (file)
@@ -62,7 +62,8 @@ public class PCMMGateReq implements IPCMMGate {
                 setGateSpec(new GateSpec(dataBuffer));
                 break;
             case ITrafficProfile.SNUM:
-                setTrafficProfile(new BestEffortService(dataBuffer));
+                // TODO - Will need to support other traffic profiles
+                setTrafficProfile(new DOCSISServiceClassNameTrafficProfile(dataBuffer));
                 break;
             case IClassifier.SNUM:
                 setClassifier(new Classifier(dataBuffer));
index ce2d60597a591438cc7d9b910b8023f39d2d8cc5..47ca9dcda00e9adc82aa4647c3d157d2a5fad925 100644 (file)
@@ -132,7 +132,7 @@ public class MessageFactory implements IMessageFactory {
         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);
+        final COPSDecisionMsg msg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, handle, decisionMap, null, null);
 
         // TODO - determine why this block has been commented out
         // try {
index f8d519e4ed43d78e82131826096c80a067de57e2..5bd01d491f2e196ae484d7c1b884086f571abaae 100644 (file)
@@ -44,10 +44,18 @@ public abstract class AbstractPCMMServer implements IPCMMServer {
 
        IWorkerPool pool;
 
+       /**
+        * Constructor to use the port number contained within the PCMMProperties static object
+        */
        protected AbstractPCMMServer() {
                this(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
        }
 
+       /**
+        * Constructor for starting the server to a pre-defined port number. When 0 is used, the server socket will
+        * assign one for you. To determine which port is being used, call getPort() after startServer() is called.
+        * @param port - the port number on which to start the server
+        */
        protected AbstractPCMMServer(int port) {
                // XXX - Assert.assertTrue(port >= 0 && port <= 65535);
                this.port = port;
@@ -67,6 +75,7 @@ public abstract class AbstractPCMMServer implements IPCMMServer {
                        return;
                try {
                        serverSocket = new ServerSocket(port);
+                       port = serverSocket.getLocalPort();
                        logger.info("Server started and listening on port :" + port);
                } catch (IOException e) {
                        logger.error(e.getMessage());
@@ -151,21 +160,6 @@ public abstract class AbstractPCMMServer implements IPCMMServer {
                return null;
        }
 
-       /**
-        * @return the serverSocket
-        */
-       public ServerSocket getServerSocket() {
-               return serverSocket;
-       }
-
-       /**
-        * @param serverSocket
-        *            the serverSocket to set
-        */
-       public void setServerSocket(ServerSocket serverSocket) {
-               this.serverSocket = serverSocket;
-       }
-
        /**
         * @return the port
         */
index 927063100a6eb485fcf6058f9c8bcc1bd0ba439c..09ae644047cf0700e7439d4ad25d0fba468998d7 100644 (file)
@@ -8,6 +8,7 @@ import org.pcmm.gates.ITransactionID;
 import org.pcmm.gates.impl.PCMMGateReq;
 import org.pcmm.messages.impl.MessageFactory;
 import org.pcmm.rcd.ICMTS;
+import org.umu.cops.COPSStateMan;
 import org.umu.cops.prpep.COPSPepConnection;
 import org.umu.cops.prpep.COPSPepDataProcess;
 import org.umu.cops.prpep.COPSPepException;
@@ -20,12 +21,24 @@ import java.util.*;
 import java.util.concurrent.Callable;
 
 /**
- *
+ * This class starts a mock CMTS that can be used for testing.
  */
 public class CMTS extends AbstractPCMMServer implements ICMTS {
 
+       /**
+        * Constructor for having the server port automatically assigned
+        * Call getPort() after startServer() is called to determine the port number of the server
+        */
        public CMTS() {
-               super();
+               this(0);
+       }
+
+       /**
+        * Constructor for starting the server to a pre-defined port number
+        * @param port - the port number on which to start the server.
+        */
+       public CMTS(final int port) {
+               super(port);
        }
 
        @Override
@@ -33,7 +46,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
 
                return new AbstractPCMMClientHandler(socket) {
 
-                       private String handle;
+                       private COPSHandle handle;
 
                        public void run() {
                                try {
@@ -76,11 +89,11 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                                {
                                                        Properties prop = new Properties();
                                                        COPSMsg reqMsg = MessageFactory.getInstance().create(OPCode.REQ, prop);
-                                                       handle = ((COPSReqMsg) reqMsg).getClientHandle().getId().str();
+                                                       handle = ((COPSReqMsg) reqMsg).getClientHandle();
                                                        sendRequest(reqMsg);
                                                }
                                                // Create the connection manager
-                                               PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
+                                               final PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
                                                // pcmm specific handler
                                                // conn.addReqStateMgr(handle, new
                                                // PCMMPSReqStateMan(CLIENT_TYPE, handle));
@@ -119,42 +132,29 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                };
        }
 
-       /* public */class PCMMCmtsConnection extends COPSPepConnection {
+       class PCMMCmtsConnection extends COPSPepConnection {
 
                public PCMMCmtsConnection(final short clientType, final Socket sock) {
                        super(clientType, sock);
                }
 
-               public COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process)
-                               throws COPSException, COPSPepException {
+               public COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
+                               throws COPSException {
                        return super.addRequestState(clientHandle, process);
                }
-
-               // public void addReqStateMgr(String hanlde, COPSPepReqStateMan r) {
-               // // map < String(COPSHandle), COPSPepReqStateMan>;
-               // getReqStateMans().put(hanlde, r);
-               // }
        }
 
-       @SuppressWarnings("rawtypes")
        class PCMMPSReqStateMan extends COPSPepReqStateMan {
 
-               public PCMMPSReqStateMan(final short clientType, final String clientHandle) {
-                       super(clientType, clientHandle);
-                       _process = new CmtsDataProcessor();
-
+               public PCMMPSReqStateMan(final short clientType, final COPSHandle clientHandle) {
+                       super(clientType, clientHandle, new CmtsDataProcessor());
                }
 
                @Override
-               protected void processDecision(COPSDecisionMsg dMsg)
-                               throws COPSPepException {
-
-                       // COPSHandle handle = dMsg.getClientHandle();
-                       Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
-
-            Map<String, String> removeDecs = new HashMap<>();
-            Map<String, String> installDecs = new HashMap<>();
-            Map<String, String> errorDecs = new HashMap<>();
+               protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
+            final Map<String, String> removeDecs = new HashMap<>();
+                       final Map<String, String> installDecs = new HashMap<>();
+                       final Map<String, String> errorDecs = new HashMap<>();
 
                        for (final Set<COPSDecision> copsDecisions : dMsg.getDecisions().values()) {
                                final COPSDecision cmddecision = copsDecisions.iterator().next();
@@ -164,7 +164,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                 switch (cmddecision.getCommand()) {
                     case INSTALL:
                         for (final COPSDecision decision : copsDecisions) {
-                            COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                                                       final 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
@@ -182,7 +182,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                         }
                     case REMOVE:
                         for (final COPSDecision decision : copsDecisions) {
-                            COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                                                       final 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
@@ -204,7 +204,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                        if (_process != null) {
                                // ** Apply decisions to the configuration
                                _process.setDecisions(this, removeDecs, installDecs, errorDecs);
-                               _status = ST_DECS;
+                               _status = Status.ST_DECS;
                                if (_process.isFailReport(this)) {
                                        // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
                                        _sender.sendFailReport(_process.getReportData(this));
@@ -212,13 +212,12 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                        // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
                                        _sender.sendSuccessReport(_process.getReportData(this));
                                }
-                               _status = ST_REPORT;
+                               _status = Status.ST_REPORT;
                        }
                }
        }
 
-       @SuppressWarnings("rawtypes")
-       class CmtsDataProcessor extends COPSPepDataProcess {
+       class CmtsDataProcessor implements COPSPepDataProcess {
 
                private Map<String, String> removeDecs;
                private Map<String, String> installDecs;
@@ -231,7 +230,6 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                        setErrorDecs(new HashMap<String, String>());
                }
 
-               @SuppressWarnings("unchecked")
                @Override
                public void setDecisions(final COPSPepReqStateMan man, final Map<String, String> removeDecs,
                                  final Map<String, String> installDecs, final Map<String, String> errorDecs) {
@@ -242,16 +240,16 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                }
 
                @Override
-               public boolean isFailReport(COPSPepReqStateMan man) {
+               public boolean isFailReport(final COPSPepReqStateMan man) {
                        return (errorDecs != null && errorDecs.size() > 0);
                }
 
                @Override
-               public Map<String, String> getReportData(COPSPepReqStateMan man) {
+               public Map<String, String> getReportData(final COPSPepReqStateMan man) {
                        if (isFailReport(man)) {
                                return errorDecs;
                        } else {
-                               Map<String, String> siDataHashTable = new HashMap<>();
+                               final Map<String, String> siDataHashTable = new HashMap<>();
                                if (installDecs.size() > 0) {
                                        String data = "";
                                        for (String k : installDecs.keySet()) {
@@ -259,7 +257,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                                break;
                                        }
                                        final ITransactionID transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
-                                       IPCMMGate responseGate = new PCMMGateReq();
+                                       final IPCMMGate responseGate = new PCMMGateReq();
                                        responseGate.setTransactionID(transactionID);
 
                     // TODO FIXME - Why is the key always null??? What value should be used here???
@@ -271,38 +269,35 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                }
 
                @Override
-               public Hashtable getClientData(COPSPepReqStateMan man) {
+               public Map<String, String> getClientData(COPSPepReqStateMan man) {
                        // TODO Auto-generated method stub
-                       return new Hashtable<String, String>();
+                       return new HashMap<>();
                }
 
                @Override
-               public Hashtable getAcctData(COPSPepReqStateMan man) {
+               public Map<String, String> getAcctData(COPSPepReqStateMan man) {
                        // TODO Auto-generated method stub
-                       return new Hashtable<String, String>();
+                       return new HashMap<>();
                }
 
                @Override
-               public void notifyClosedConnection(COPSPepReqStateMan man, COPSError error) {
-
+               public void notifyClosedConnection(final COPSStateMan man, final COPSError error) {
+                       // TODO Auto-generated method stub
                }
 
                @Override
-               public void notifyNoKAliveReceived(COPSPepReqStateMan man) {
+               public void notifyNoKAliveReceived(final COPSStateMan man) {
                        // TODO Auto-generated method stub
-
                }
 
                @Override
-               public void closeRequestState(COPSPepReqStateMan man) {
+               public void closeRequestState(final COPSStateMan man) {
                        // TODO Auto-generated method stub
-
                }
 
                @Override
-               public void newRequestState(COPSPepReqStateMan man) {
+               public void newRequestState(final COPSPepReqStateMan man) {
                        // TODO Auto-generated method stub
-
                }
 
                public Map<String, String> getRemoveDecs() {
@@ -336,5 +331,6 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                public void setStateManager(COPSPepReqStateMan stateManager) {
                        this.stateManager = stateManager;
                }
+
        }
 }
index 1b2ee2aaece391803ba7d5d8cbf0fde4aa23f5ba..8c3127097570c4f870a35706543e05e3c3a8a756 100644 (file)
@@ -534,7 +534,7 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
             if (getVersionInfo().getMajorVersionNB() >= 4) {
                 classifier = new ExtendedClassifier();
                 // eclassifier.setProtocol(IClassifier.Protocol.NONE);
-                classifier.setProtocol(IClassifier.Protocol.TCP);
+//                classifier.setProtocol(IClassifier.Protocol.TCP);
                 try {
                     InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
                     InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
@@ -569,7 +569,7 @@ public class PCMMPolicyServer extends AbstractPCMMServer implements IPCMMPolicyS
 
             } else {
                 classifier = new Classifier();
-                classifier.setProtocol(IClassifier.Protocol.TCP);
+//                classifier.setProtocol(IClassifier.Protocol.TCP);
                 try {
                     InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
                     InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
diff --git a/packetcable-driver/src/main/java/org/umu/cops/COPSDataProcess.java b/packetcable-driver/src/main/java/org/umu/cops/COPSDataProcess.java
new file mode 100644 (file)
index 0000000..3d950b6
--- /dev/null
@@ -0,0 +1,29 @@
+package org.umu.cops;
+
+import org.umu.cops.stack.COPSError;
+
+/**
+ * Defines the standard methods for implementors for processing COPS data.
+ */
+public interface COPSDataProcess {
+
+    /**
+     * Notifies a keep-alive timeout
+     * @param man   The associated request state manager
+     */
+    void notifyNoKAliveReceived(COPSStateMan man);
+
+    /**
+     * Notifies that the connection has been closed
+     * @param man  The associated request state manager
+     * @param error Reason
+     */
+    void notifyClosedConnection(COPSStateMan man, COPSError error);
+
+    /**
+     * Notifies that a request state has been closed
+     * @param man   The associated request state manager
+     */
+    void closeRequestState(COPSStateMan man);
+
+}
diff --git a/packetcable-driver/src/main/java/org/umu/cops/COPSMsgSender.java b/packetcable-driver/src/main/java/org/umu/cops/COPSMsgSender.java
new file mode 100644 (file)
index 0000000..e26db97
--- /dev/null
@@ -0,0 +1,52 @@
+package org.umu.cops;
+
+import org.umu.cops.stack.COPSHandle;
+
+import java.net.Socket;
+
+/**
+ * Abstract COPS Message sender
+ */
+public abstract class COPSMsgSender {
+
+    /**
+     * 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;
+
+    /**
+     * Socket connected to PEP
+     */
+    protected final Socket _sock;
+
+    public COPSMsgSender(final short clientType, final COPSHandle handle, final Socket sock) {
+        if (handle == null) throw new IllegalArgumentException("Client handle must not be null");
+        if (sock == null) throw new IllegalArgumentException("Socket must not be null");
+        this._clientType = clientType;
+        this._handle = handle;
+        this._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;
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/umu/cops/COPSStateMan.java b/packetcable-driver/src/main/java/org/umu/cops/COPSStateMan.java
new file mode 100644 (file)
index 0000000..2b742f6
--- /dev/null
@@ -0,0 +1,103 @@
+package org.umu.cops;
+
+import org.umu.cops.prpdp.COPSPdpException;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSSyncStateMsg;
+
+import java.net.Socket;
+
+/**
+ * Abstract COPS state manager.
+ */
+public abstract class COPSStateMan {
+
+    // TODO - place these values into an enumeration
+    /**
+     * 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;
+
+    /**
+     *  Current state of the request being managed
+     */
+    protected transient Status _status;
+
+    /**
+     * Constructor
+     * @param clientType - the client type
+     * @param clientHandle - the unique handle to the client
+     */
+    public COPSStateMan(final short clientType, final COPSHandle clientHandle) {
+        this._clientType = clientType;
+        this._handle = clientHandle;
+        this._status = 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 short getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Gets the status of the request
+     * @return      Request state value
+     */
+    public Status getStatus() {
+        return _status;
+    }
+
+    /**
+     * Called when COPS sync is completed
+     * @param    repMsg              COPS sync message
+     * @throws COPSPdpException
+     */
+    public void processSyncComplete(final COPSSyncStateMsg repMsg) throws COPSException {
+        _status = Status.ST_SYNCALL;
+        // TODO - maybe we should notifySyncComplete ...
+    }
+
+    /**
+     * Initializes a new request state over a socket
+     * @param sock  Socket to the PEP
+     * @throws COPSPdpException
+     */
+    protected abstract void initRequestState(final Socket sock) throws COPSException;
+
+    /**
+     * The different state manager statuses
+     */
+    public enum Status {
+        NA,
+        ST_CREATE, // Request State created
+        ST_INIT, // Request received
+        ST_DECS, // Decisions sent
+        ST_REPORT, // Report received
+        ST_FINAL, // Request state finalized
+        ST_NEW, // New request state solicited
+        ST_DEL, // Delete request state solicited
+        ST_SYNC, // SYNC request sent
+        ST_SYNCALL, // SYNC completed
+        ST_CCONN, // Close connection received
+        ST_NOKA, // Keep-alive timeout
+        ST_ACCT, // Accounting timeout
+    }
+
+}
index 9375888f445ffa34450d1b37c42c4f3e1d1cae98..3aad574e6de64b335234e2956fd9f01340ffdd44 100644 (file)
@@ -6,42 +6,40 @@
 \r
 package org.umu.cops.ospdp;\r
 \r
+import org.umu.cops.stack.COPSException;\r
+\r
 /**\r
  * COPS PEP Exception\r
  *\r
  * @version COPSPepException.java, v 2.00 2004\r
  *\r
  */\r
-public class COPSPdpException extends Exception {\r
-\r
-    private int rc;\r
-    final static int GENERAL_ERROR = 0x00000001;\r
+public class COPSPdpException extends COPSException {\r
 \r
     /**\r
      * Creates a <tt>COPSPdpException</tt> with the given message.\r
-     * @param msg     Exception message\r
+     * @param msg    Exception message\r
      */\r
     public COPSPdpException(String msg) {\r
         super(msg);\r
-        rc=0;\r
     }\r
 \r
     /**\r
      * Creates a <tt>COPSPdpException</tt> with the given message and return code.\r
-     * @param msg     Exception message\r
-     * @param retCode     Return code\r
+     * @param msg       Exception message\r
+     * @param retCode   Return code\r
      */\r
     public COPSPdpException(String msg, int retCode) {\r
-        super(msg);\r
-        rc = retCode;\r
+        super(msg, retCode);\r
     }\r
 \r
     /**\r
-     * Gets the return code of the exception\r
-     * @return   Exception's return code\r
+     * Creates a <tt>COPSPdpException</tt> with the given message and throwable.\r
+     * @param msg       Exception message\r
+     * @param t         the Throwable\r
      */\r
-    public int returnCode() {\r
-        return rc;\r
+    public COPSPdpException(String msg, Throwable t) {\r
+        super(msg, t);\r
     }\r
 \r
 }\r
index 3619572fd39043f005306ce8447056c7f2012f2e..7022289cd75495db4ba0ce020b7290acdd25636d 100644 (file)
@@ -223,8 +223,8 @@ public class COPSPdpOSConnection implements Runnable {
      * 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);
+    private void processMessage(final Socket conn) throws COPSException, IOException {
+        final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
 
         if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
             handleClientCloseMsg(conn, msg);
@@ -339,8 +339,7 @@ public class COPSPdpOSConnection implements Runnable {
 
         // Delete clientHandler
         if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
-            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
-            //  cMsg.getClientHandle().getId().getData());
+            logger.warn("Missing state manager for for ClientHandle" + cMsg.getClientHandle().getId().str());
         }
 
         final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
@@ -368,7 +367,7 @@ public class COPSPdpOSConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
+    private void handleRequestMsg(final Socket conn, final COPSMsg msg) throws COPSException {
         final COPSReqMsg reqMsg = (COPSReqMsg) msg;
         final COPSHeader header = reqMsg.getHeader();
         final short cType = header.getClientType();
@@ -380,9 +379,8 @@ public class COPSPdpOSConnection implements Runnable {
 
         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 = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle(), _process);
+            _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
             man.initRequestState(_sock);
         } else {
             man = _managerMap.get(reqMsg.getClientHandle().getId().str());
@@ -430,7 +428,7 @@ public class COPSPdpOSConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleSyncComplete(Socket conn, COPSMsg msg) throws COPSPdpException {
+    private void handleSyncComplete(final Socket conn, final COPSMsg msg) throws COPSException {
         final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
 
         // Support
@@ -448,10 +446,9 @@ public class COPSPdpOSConnection implements Runnable {
 
     /**
      * Requests a COPS sync from the PEP
-     * @throws COPSException
      * @throws COPSPdpException
      */
-    protected void syncAllRequestState() throws COPSException, COPSPdpException {
+    protected void syncAllRequestState() throws COPSException {
         for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
             man.syncRequestState();
         }
index c45c7cbf75cb7decd04d6a556f59fa461e6df724..3db300e80dcca59d7252b1fdb9991fe730ffdb64 100644 (file)
@@ -1,79 +1,67 @@
 package org.umu.cops.ospdp;
 
+import org.umu.cops.COPSDataProcess;
 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 {
+public interface COPSPdpOSDataProcess extends COPSDataProcess {
+
     /**
      * 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);
+    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);
+    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);
+    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);
+    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);
+    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);
+    void acctReport(COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
 
     /**
-     * Notifies a keep-alive timeout
+     * Notifies that no accounting report has been received
      * @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);
+    void notifyNoAcctReport(COPSPdpOSReqStateMan man);
 
     /**
      * 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);
+    void notifyDeleteRequestState(COPSPdpOSReqStateMan man);
 
 }
index e469e4fa06ece6e5d81b65cc4de10810ea3a7d49..e91fcb93a78cfd00b7df2558a56cd97930c5e7a7 100644 (file)
@@ -1,9 +1,9 @@
 package org.umu.cops.ospdp;
 
+import org.umu.cops.prpdp.COPSPdpMsgSender;
 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;
@@ -15,22 +15,7 @@ import java.util.*;
  *
  * 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;
+public class COPSPdpOSMsgSender extends COPSPdpMsgSender {
 
     /**
      * Creates a COPSPepMsgSender
@@ -39,28 +24,8 @@ public class COPSPdpOSMsgSender {
      * @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;
+    public COPSPdpOSMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
+        super(clientType, clientHandle, sock);
     }
 
     /**
@@ -121,8 +86,8 @@ public class COPSPdpOSMsgSender {
         }
 
         // Client Handle with the same clientHandle as the request
-        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(1, flag, getClientType(),
-                new COPSHandle(getClientHandle().getId()), decisions, null);
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(1, flag, getClientType(), _handle, decisions,
+                null, null);
 
         //** Send decision
         //**
@@ -133,81 +98,4 @@ public class COPSPdpOSMsgSender {
         }
     }
 
-    /**
-     * 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 dce9b2b47f062ee57b77100a01263da2721e72c7..cc598b104a365c3bc1422e2ae3772ff08f200331 100644 (file)
@@ -1,5 +1,6 @@
 package org.umu.cops.ospdp;
 
+import org.umu.cops.COPSStateMan;
 import org.umu.cops.stack.*;
 
 import java.net.Socket;
@@ -8,164 +9,42 @@ 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;
+public class COPSPdpOSReqStateMan extends COPSStateMan {
 
     /**
      * Object for performing policy data processing
      */
-    protected COPSPdpOSDataProcess _process;
-
-    /**
-     *  Current state of the request being managed
-     */
-    protected short _status;
+    private final COPSPdpOSDataProcess _process;
 
     /** COPS message transceiver used to send COPS messages */
-    protected COPSPdpOSMsgSender _sender;
+    private transient 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;
+    // TODO - consider sending in the COPSHandle object instead
+    public COPSPdpOSReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPdpOSDataProcess process) {
+        super(clientType, clientHandle);
+        this._process = process;
     }
 
-    /**
-     * 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 {
+    @Override
+    protected void initRequestState(final Socket sock) throws COPSException {
         // Inits an object for sending COPS messages to the PDP
         _sender = new COPSPdpOSMsgSender(_clientType, _handle, sock);
 
         // Initial state
-        _status = ST_INIT;
+        _status = Status.ST_INIT;
     }
 
     /**
      * Processes a COPS request
      * @param msg   COPS request received from the PEP
-     * @throws COPSPdpException
+     * @throws COPSException
      */
-    protected void processRequest(COPSReqMsg msg) throws COPSPdpException {
+    protected void processRequest(COPSReqMsg msg) throws COPSException {
         //** Here we must retrieve a decision depending on the
         //** supplied ClientSIs
         /*Vector removeDecs = new Vector();
@@ -179,7 +58,7 @@ public class COPSPdpOSReqStateMan {
         //** We create a SOLICITED decision
         //**
         _sender.sendSolicitedDecision(removeDecs, installDecs);
-        _status = ST_DECS;
+        _status = Status.ST_DECS;
     }
 
     /**
@@ -215,15 +94,15 @@ public class COPSPdpOSReqStateMan {
             //** the report received
             switch (rtypemsg.getReportType()) {
                 case SUCCESS:
-                    _status = ST_REPORT;
+                    _status = Status.ST_REPORT;
                     _process.successReport(this, msg.getClientSI());
                     break;
                 case FAILURE:
-                    _status = ST_REPORT;
+                    _status = Status.ST_REPORT;
                     _process.failReport(this, msg.getClientSI());
                     break;
                 case ACCOUNTING:
-                    _status = ST_ACCT;
+                    _status = Status.ST_ACCT;
                     _process.acctReport(this, msg.getClientSI());
                     break;
             }
@@ -236,54 +115,49 @@ public class COPSPdpOSReqStateMan {
      * @param error Reason
      * @throws COPSPdpException
      */
-    protected void processClosedConnection(COPSError error)
-    throws COPSPdpException {
+    protected void processClosedConnection(final COPSError error) throws COPSPdpException {
         if (_process != null)
             _process.notifyClosedConnection(this, error);
 
-        _status = ST_CCONN;
+        _status = Status.ST_CCONN;
     }
 
     /**
      * Called when no keep-alive is received
      * @throws COPSPdpException
      */
-    protected void processNoKAConnection()
-    throws COPSPdpException {
+    protected void processNoKAConnection() throws COPSPdpException {
         if (_process != null)
             _process.notifyNoKAliveReceived(this);
 
-        _status = ST_NOKA;
+        _status = Status.ST_NOKA;
     }
 
     /**
      * Deletes the request state
      * @throws COPSPdpException
      */
-    protected void finalizeRequestState()
-    throws COPSPdpException {
+    protected void finalizeRequestState() throws COPSException {
         _sender.sendDeleteRequestState();
-        _status = ST_FINAL;
+        _status = Status.ST_FINAL;
     }
 
     /**
      * Asks for a COPS sync
      * @throws COPSPdpException
      */
-    protected void syncRequestState()
-    throws COPSPdpException {
+    protected void syncRequestState() throws COPSException {
         _sender.sendSyncRequestState();
-        _status = ST_SYNC;
+        _status = Status.ST_SYNC;
     }
 
     /**
      * Opens a new request state
      * @throws COPSPdpException
      */
-    protected void openNewRequestState()//FIXME: unused?
-    throws COPSPdpException {
+    protected void openNewRequestState() throws COPSException {
         _sender.sendOpenNewRequestState();
-        _status = ST_NEW;
+        _status = Status.ST_NEW;
     }
 
     /**
@@ -291,12 +165,11 @@ public class COPSPdpOSReqStateMan {
      * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP
      * @throws COPSPdpException
      */
-    protected void processDeleteRequestState(COPSDeleteMsg dMsg)
-    throws COPSPdpException {
+    protected void processDeleteRequestState(final COPSDeleteMsg dMsg) throws COPSPdpException {
         if (_process != null)
             _process.closeRequestState(this);
 
-        _status = ST_DEL;
+        _status = Status.ST_DEL;
     }
 
 }
index 6f3fde731ef8822dbd2156ef9158377af519b24c..74e51a878d902a05d50aeaeee391f36d1f266155 100644 (file)
@@ -6,45 +6,26 @@
 \r
 package org.umu.cops.ospep;\r
 \r
+import org.umu.cops.stack.COPSException;\r
+\r
 /**\r
  * COPS PEP Exception\r
  *\r
  * @version COPSPepException.java, v 2.00 2004\r
  *\r
  */\r
-public class COPSPepException extends Exception {\r
-\r
-    private int rc;\r
-    final static int GENERAL_ERROR = 0x00000001;\r
-\r
-    /**\r
-     * Creates a <tt>COPSPdpException</tt> with the given message.\r
-     * @param msg    Exception message\r
-     */\r
+public class COPSPepException extends COPSException {\r
 \r
-    public COPSPepException(String msg) {\r
-        super(msg);\r
-        rc=0;\r
+    public COPSPepException(String s) {\r
+        super(s);\r
     }\r
 \r
-    /**\r
-      * Creates a <tt>COPSPdpException</tt> with the given message and return code.\r
-      * @param msg      Exception message\r
-      * @param retCode     Return code\r
-      */\r
     public COPSPepException(String msg, int retCode) {\r
-        super(msg);\r
-        rc = retCode;\r
+        super(msg, retCode);\r
     }\r
 \r
-    /**\r
-     * Returns the return code of the exception\r
-     *\r
-     * @return   Exception's return code\r
-     *\r
-     */\r
-    public int returnCode() {\r
-        return rc;\r
+    public COPSPepException(String msg, Throwable t) {\r
+        super(msg, t);\r
     }\r
 \r
 }\r
index 0154c09c5eab6fe1f13b463322f3a3038fdb8797..116aeefe32ecb19155770703ae58d10605616ac4 100644 (file)
@@ -228,7 +228,7 @@ public class COPSPepOSConnection implements Runnable {
      * @throws COPSException
      * @throws IOException
      */
-    protected void processMessage(Socket conn) throws COPSPepException, COPSException, IOException {
+    protected void processMessage(Socket conn) throws COPSException, IOException {
         COPSMsg msg = COPSTransceiver.receiveMsg(conn);
 
         if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
@@ -327,10 +327,10 @@ public class COPSPepOSConnection implements Runnable {
      * @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());
+    private void handleDecisionMsg(final COPSMsg msg) throws COPSException {
+        final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+        final COPSHandle handle = dMsg.getClientHandle();
+        final COPSPepOSReqStateMan manager = _managerMap.get(handle.getId().str());
         manager.processDecision(dMsg);
     }
 
@@ -345,8 +345,8 @@ public class COPSPepOSConnection implements Runnable {
      * @param    msg                 a  COPSMsg
      *
      */
-    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
+    private void handleSyncStateReqMsg(final Socket conn, final COPSMsg msg) throws COPSException {
+        final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
         // COPSHandle handle = cMsg.getClientHandle();
         // COPSHeader header = cMsg.getHeader();
 
@@ -354,7 +354,7 @@ public class COPSPepOSConnection implements Runnable {
         if (cMsg.getIntegrity() != null)
             logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
 
-        COPSPepOSReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
+        final COPSPepOSReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
 
         if (manager == null)
             logger.warn("Unable to find state manager with ID - " + cMsg.getClientHandle().getId().str());
@@ -369,17 +369,13 @@ public class COPSPepOSConnection implements Runnable {
      * @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);
+                                                   final List<COPSClientSI> clientSIs) throws COPSException {
+        final COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType,
+                new COPSHandle(new COPSData(clientHandle)), process, clientSIs);
         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;
@@ -388,10 +384,9 @@ public class COPSPepOSConnection implements Runnable {
     /**
      * Deletes a request state
      * @param manager   Request state manager
-     * @throws COPSException
      * @throws COPSPepException
      */
-    protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {
+    protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException {
         manager.finalizeRequestState();
     }
 
index 1ee476bfec82af7073f4873da708e5e7516524ce..840c6bce3b768c701afb46c85032eb2a8664c39a 100644 (file)
@@ -1,59 +1,41 @@
-package org.umu.cops.ospep;\r
-\r
-import java.util.Vector;\r
-\r
-import org.umu.cops.stack.COPSDecisionMsg;\r
-import org.umu.cops.stack.COPSError;\r
-\r
-/**\r
- * Abstract class for implementing policy data processing classes for outsourcing PEPs.\r
- */\r
-public abstract class COPSPepOSDataProcess {\r
-    /**\r
-     * Applies the decisions from the PDP\r
-     * @param man   The request state manager\r
-     * @param dMsg  The decisions message\r
-     * @return <tt>true</tt> if failed (reports indicate failure), <tt>false</tt> otherwise\r
-     */\r
-    public abstract boolean setDecisions(COPSPepOSReqStateMan man, COPSDecisionMsg dMsg);\r
-\r
-    /**\r
-     * Gets the report data\r
-     * @param man   The request state manager\r
-     * @return A <tt>Vector</tt> holding the report data\r
-     */\r
-    public abstract Vector getReportData(COPSPepOSReqStateMan man);\r
-\r
-    /**\r
-     * Gets the supplied client data\r
-     * @param man   The request state manager\r
-     * @return A <tt>Vector</tt> holding the client data\r
-     */\r
-    public abstract Vector getClientData(COPSPepOSReqStateMan man);\r
-\r
-    /**\r
-     * Gets the account data\r
-     * @param man   The request state manager\r
-     * @return A <tt>Vector</tt> holding the account data\r
-     */\r
-    public abstract Vector getAcctData(COPSPepOSReqStateMan man);\r
-\r
-    /**\r
-     * Called when the connection is closed\r
-     * @param man   The request state manager\r
-     * @param error Reason\r
-     */\r
-    public abstract void notifyClosedConnection (COPSPepOSReqStateMan man, COPSError error);\r
-\r
-    /**\r
-     * Called when the keep-alive message is not received\r
-     * @param man   The request state manager\r
-     */\r
-    public abstract void notifyNoKAliveReceived (COPSPepOSReqStateMan man);\r
-\r
-    /**\r
-     * Process a PDP request to close a Request State\r
-     * @param man   The request state manager\r
-     */\r
-    public abstract void closeRequestState(COPSPepOSReqStateMan man);\r
-}\r
+package org.umu.cops.ospep;
+
+import org.umu.cops.COPSDataProcess;
+import org.umu.cops.stack.COPSDecisionMsg;
+
+import java.util.Vector;
+
+/**
+ * Abstract class for implementing policy data processing classes for outsourcing PEPs.
+ */
+public interface COPSPepOSDataProcess extends COPSDataProcess {
+    /**
+     * Applies the decisions from the PDP
+     * @param man   The request state manager
+     * @param dMsg  The decisions message
+     * @return <tt>true</tt> if failed (reports indicate failure), <tt>false</tt> otherwise
+     */
+    boolean setDecisions(COPSPepOSReqStateMan man, COPSDecisionMsg dMsg);
+
+    /**
+     * Gets the report data
+     * @param man   The request state manager
+     * @return A <tt>Vector</tt> holding the report data
+     */
+    Vector getReportData(COPSPepOSReqStateMan man);
+
+    /**
+     * Gets the supplied client data
+     * @param man   The request state manager
+     * @return A <tt>Vector</tt> holding the client data
+     */
+    Vector getClientData(COPSPepOSReqStateMan man);
+
+    /**
+     * Gets the account data
+     * @param man   The request state manager
+     * @return A <tt>Vector</tt> holding the account data
+     */
+    Vector getAcctData(COPSPepOSReqStateMan man);
+
+}
index 5ddeed14987f29902db68e061b2354d25dba57e8..92bd9aa31a8aa3fed887bfa3f761ff74187773cc 100644 (file)
@@ -1,8 +1,8 @@
 package org.umu.cops.ospep;
 
+import org.umu.cops.prpep.COPSPepMsgSender;
 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;
@@ -13,22 +13,7 @@ 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;
+public class COPSPepOSMsgSender extends COPSPepMsgSender {
 
     /**
      * Creates a COPSPepMsgSender
@@ -37,28 +22,8 @@ public class COPSPepOSMsgSender {
      * @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;
+    public COPSPepOSMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
+        super(clientType, clientHandle, sock);
     }
 
     /**
@@ -122,39 +87,4 @@ public class COPSPepOSMsgSender {
         }
     }
 
-    /**
-     * 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 3a19c5059b11f7362afef55657000394b52092a2..ffcd54cf4e314bc24841a4a27eab4048f7642cbc 100644 (file)
@@ -1,80 +1,19 @@
 package org.umu.cops.ospep;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
 import org.umu.cops.stack.*;
 
 import java.net.Socket;
-import java.util.List;
-import java.util.Set;
-import java.util.Vector;
+import java.util.*;
 
 /**
  * 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;
+public class COPSPepOSReqStateMan extends COPSStateMan {
 
-    /**
-     * 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;
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepOSReqStateMan.class);
 
     /**
      * ClientSI data from signaling.
@@ -82,92 +21,35 @@ public class COPSPepOSReqStateMan {
     protected final Set<COPSClientSI> _clientSIs;
 
     /**
-     *  Current state of the request being managed
+        Object for performing policy data processing
      */
-    protected short _status;
+    protected final COPSPepOSDataProcess _process;
 
     /**
         COPS message transceiver used to send COPS messages
      */
-    protected COPSPepOSMsgSender _sender;
+    protected transient COPSPepOSMsgSender _sender;
 
     /**
      * Sync state
      */
-    protected boolean _syncState;
+    protected transient 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;
+    public COPSPepOSReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepOSDataProcess process,
+                                final Collection<COPSClientSI> clientSIs) {
+        super(clientType, clientHandle);
+        this._process = process;
+        this._clientSIs = new HashSet<>(clientSIs);
         _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 {
+    @Override
+    protected void initRequestState(final Socket sock) throws COPSException {
         // Inits an object for sending COPS messages to the PDP
         _sender = new COPSPepOSMsgSender(_clientType, _handle, sock);
 
@@ -183,16 +65,16 @@ public class COPSPepOSReqStateMan {
         _sender.sendRequest(_clientSIs);
 
         // Initial state
-        _status = ST_INIT;
+        _status = Status.ST_INIT;
     }
 
     /**
      * Deletes the request state
      * @throws COPSPepException
      */
-    protected void finalizeRequestState() throws COPSPepException {
+    protected void finalizeRequestState() throws COPSException {
         _sender.sendDeleteRequest();
-        _status = ST_FINAL;
+        _status = Status.ST_FINAL;
     }
 
     /**
@@ -200,31 +82,27 @@ public class COPSPepOSReqStateMan {
      * @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();
-
+    protected void processDecision(final COPSDecisionMsg dMsg) throws COPSException {
         //** 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;
+        final boolean isFailReport = _process.setDecisions(this, dMsg);
+        _status = Status.ST_DECS;
 
         if (isFailReport) {
-            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
+            logger.info("Sending FAIL Report");
             _sender.sendFailReport(_process.getReportData(this));
         } else {
-            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
+            logger.info("Sending SUCCESS Report");
             _sender.sendSuccessReport(_process.getReportData(this));
         }
-        _status = ST_REPORT;
+        _status = Status.ST_REPORT;
 
         if (!_syncState) {
             _sender.sendSyncComplete();
             _syncState = true;
-            _status = ST_SYNCALL;
+            _status = Status.ST_SYNCALL;
         }
     }
 
@@ -234,11 +112,11 @@ public class COPSPepOSReqStateMan {
      * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PDP
      * @throws COPSPepException
      */
-    protected void processDeleteRequestState(COPSDecisionMsg dMsg) throws COPSPepException {
+    protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
         if (_process != null)
             _process.closeRequestState(this);
 
-        _status = ST_DEL;
+        _status = Status.ST_DEL;
     }
 
     /**
@@ -252,7 +130,7 @@ public class COPSPepOSReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg) throws COPSPepException {
+    protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSException {
         _syncState = false;
         // If an object exists for retrieving the PEP features,
         // use it for retrieving them.
@@ -260,7 +138,7 @@ public class COPSPepOSReqStateMan {
         // Send the request
         _sender.sendRequest(_clientSIs);
 
-        _status = ST_SYNC;
+        _status = Status.ST_SYNC;
     }
 
     /**
@@ -268,11 +146,11 @@ public class COPSPepOSReqStateMan {
      * @param error Reason
      * @throws COPSPepException
      */
-    protected void processClosedConnection(COPSError error) throws COPSPepException {
+    protected void processClosedConnection(final COPSError error) throws COPSPepException {
         if (_process != null)
             _process.notifyClosedConnection(this, error);
 
-        _status = ST_CCONN;
+        _status = Status.ST_CCONN;
     }
 
     /**
@@ -283,7 +161,7 @@ public class COPSPepOSReqStateMan {
         if (_process != null)
             _process.notifyNoKAliveReceived(this);
 
-        _status = ST_NOKA;
+        _status = Status.ST_NOKA;
     }
 
     /**
@@ -291,13 +169,12 @@ public class COPSPepOSReqStateMan {
      * @throws COPSPepException
      */
     protected void processAcctReport() throws COPSPepException {
-        Vector report = new Vector();
-
-        if (_process != null)
-            report = _process.getAcctData(this);
+        final List<COPSClientSI> report;
+        if (_process != null) report = new ArrayList<>(_process.getAcctData(this));
+        else report = new ArrayList<>();
 
         _sender.sendAcctReport(report);
 
-        _status = ST_ACCT;
+        _status = Status.ST_ACCT;
     }
 }
index a5c9dd6ef029d4af43ca701ca16dd010cce8dbba..d71b8ec4d4b9702e51a73eae352dc85a0c532ace 100644 (file)
@@ -23,39 +23,45 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class COPSPdpAgent extends Thread {
 
-    public final static Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
+    private static final Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
 
     /** Well-known port for COPS */
-    public static final int WELL_KNOWN_PDP_PORT = 3288;
+    //    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
+     * PDP host port
      */
     private int _serverPort;
 
     /**
-        Client-type of connecting PEP
+     * Client-type of connecting PEP
      */
     private short _clientType;
 
     /**
-        Accounting timer (secs)
+     * Accounting timer (secs)
      */
     private short _acctTimer;
 
     /**
-        Keep-alive timer (secs)
+     * Keep-alive timer (secs)
      */
     private short _kaTimer;
 
     /**
-        Maps a PEP-ID to a connection
+     * The PEP ID
      */
-    private final Map<String, COPSPdpConnection> _connectionMap;
+    protected transient COPSPepId _pepId;
+
+    /**
+     *   Maps a PEP-ID to a connection
+     *   TODO - Refactor COPSPdpConnection to extend PCMMPdpConnection. Until then, the value must remain an Object
+     */
+    protected Map<String, Object> _connectionMap;
     // map < String(PEPID), COPSPdpConnection > ConnectionMap;
 
     /**
@@ -64,20 +70,9 @@ public class COPSPdpAgent extends Thread {
     private COPSPdpDataProcess _process;
 
     /**
-     * Creates a PDP Agent
-     *
-     * @param clientType    COPS Client-type
-     * @param process       Object to perform policy data processing
+     * Holds all of the threads to manage by PEP ID
      */
-    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;
-    }
+    protected final Map<String, Thread> threadMap;
 
     /**
      * Creates a PDP Agent
@@ -95,22 +90,7 @@ public class COPSPdpAgent extends Thread {
         _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;
+        this.threadMap = new ConcurrentHashMap<>();
     }
 
     /**
@@ -145,7 +125,7 @@ public class COPSPdpAgent extends Thread {
      * @throws IOException
      */
     public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
-        final COPSPdpConnection pdpConn = _connectionMap.get(pepID);
+        final COPSPdpConnection pdpConn = (COPSPdpConnection)_connectionMap.get(pepID);
         final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
         closeMsg.writeData(pdpConn.getSocket());
         pdpConn.close();
@@ -157,10 +137,8 @@ public class COPSPdpAgent extends Thread {
      * @throws COPSException
      * @throws COPSPdpException
      */
-    public void sync (String pepID)
-    throws COPSException, COPSPdpException {
-
-        COPSPdpConnection pdpConn = _connectionMap.get(pepID);
+    public void sync(final String pepID) throws COPSException, COPSPdpException {
+        COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);
         pdpConn.syncAllRequestState();
     }
 
@@ -168,7 +146,7 @@ public class COPSPdpAgent extends Thread {
      * Removes a PEP from the connection map
      * @param pepID PEP-ID of the PEP to be removed
      */
-    public void delete (String pepID) {
+    public void delete(final String pepID) {
         _connectionMap.remove(pepID);
     }
 
@@ -181,12 +159,10 @@ public class COPSPdpAgent extends Thread {
             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();
+                final Socket socket = serverSocket.accept();
 
                 // COPSDebug.out(getClass().getName(),"New connection accepted " +
                 //           socket.getInetAddress() +
@@ -195,14 +171,15 @@ public class COPSPdpAgent extends Thread {
                 // We're waiting for an OPN message
                 try {
                     final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+                    logger.info("Message received - " + msg);
                     if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
                         handleClientOpenMsg(socket, msg);
                     } else {
-                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+                        logger.error("Not an open message, closing socket");
                         try {
                             socket.close();
                         } catch (Exception ex) {
-                            logger.error("Error closing socket", ex);
+                            logger.error("Unexpected exception closing socket", ex);
                         }
                     }
                 } catch (Exception e) { // COPSException, IOException
@@ -211,7 +188,7 @@ public class COPSPdpAgent extends Thread {
                     try {
                         socket.close();
                     } catch (Exception ex) {
-                        logger.error("Error closing socket", ex);
+                        logger.error("Unexpected exception closing socket", ex);
                     }
                 }
             }
@@ -221,74 +198,73 @@ public class COPSPdpAgent extends Thread {
     }
 
     /**
-      * 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 {
+     * 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
+     * TODO - Refactor PCMMPdpAgent#handleClientOpenMsg() as it contains much of this same logic
+     */
+    protected void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
         final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
-        final COPSPepId pepId = cMsg.getPepId();
+        _pepId = cMsg.getPepId();
 
         // Validate Client Type
-        if (msg.getHeader().getClientType() == _clientType) {
+        if (msg.getHeader().getClientType() != _clientType) {
             // Unsupported client type
-            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+            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 COPS data", unae);
+                logger.error("Unexpected exception writing data", unae);
             }
 
             throw new COPSException("Unsupported client type");
         }
 
         // PEPId is mandatory
-        if (pepId == null) {
+        if (_pepId == null) {
             // Mandatory COPS object missing
-            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+            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 close message", unae);
+                logger.error("Unexpected exception writing data", unae);
             }
 
             throw new COPSException("Mandatory COPS object missing (PEPId)");
         }
 
         // Support
-        if ( (cMsg.getClientSI() != null) ||
-                (cMsg.getPdpAddress() != null) ||
-                (cMsg.getIntegrity() != null)) {
-
+        if ( (cMsg.getClientSI() != null) || (cMsg.getPdpAddress() != null) || (cMsg.getIntegrity() != null)) {
             // Unsupported objects
-            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+            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 close message", unae);
+                logger.error("Exception 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, null, null);
-        else acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer,
+        if (_acctTimer != 0)
+            acceptMsg = new COPSClientAcceptMsg(_clientType, new COPSKATimer(_kaTimer),
                 new COPSAcctTimer(_acctTimer), null);
+        else
+            acceptMsg = new COPSClientAcceptMsg(_clientType, new COPSKATimer(_kaTimer),null, null);
         acceptMsg.writeData(conn);
 
-        final COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);
+        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);
+        _connectionMap.put(_pepId.getData().str(), pdpConn);
     }
 
 }
index 31a9379e143b0575c0c0bbb3e0f3943d5dda51d6..be632633499c954fe69dda93167ccb7f76e645de 100644 (file)
@@ -226,7 +226,7 @@ public class COPSPdpConnection implements Runnable {
      * 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 {
+    private void processMessage(final Socket conn) throws COPSException, IOException {
         final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
         switch (msg.getHeader().getOpCode()) {
             case CC:
@@ -384,9 +384,8 @@ public class COPSPdpConnection implements Runnable {
         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 = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle(), _process);
+            _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
             man.initRequestState(_sock);
 
             // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
@@ -438,18 +437,15 @@ public class COPSPdpConnection implements Runnable {
      * @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();
+    private void handleSyncComplete(final Socket conn, final COPSMsg msg) throws COPSException {
+        final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
 
         // Support
         if (cMsg.getIntegrity() != null) {
             logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
         }
 
-        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+        final COPSPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
         if (man == null) {
             logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
         } else {
@@ -462,7 +458,7 @@ public class COPSPdpConnection implements Runnable {
      * @throws COPSException
      * @throws COPSPdpException
      */
-    protected void syncAllRequestState() throws COPSException, COPSPdpException {
+    protected void syncAllRequestState() throws COPSException {
         for (final COPSPdpReqStateMan man : _managerMap.values()) {
             man.syncRequestState();
         }
index 14f31426ecf7a1447167a5c2429cf06aa1c2d9f2..20eb2f854b124cbc5ea4ba9ea713ae20f5c8885c 100644 (file)
@@ -6,7 +6,7 @@
 
 package org.umu.cops.prpdp;
 
-import org.umu.cops.stack.COPSError;
+import org.umu.cops.COPSDataProcess;
 
 import java.util.Hashtable;
 import java.util.Map;
@@ -14,71 +14,60 @@ import java.util.Map;
 /**
  * Abstract class for implementing policy data processing classes for provisioning PDPs.
  */
-public interface COPSPdpDataProcess {
+public interface COPSPdpDataProcess extends COPSDataProcess {
+
     /**
      * 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);
+    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);
+    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);
+    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);
+    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);
+    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);
+    void acctReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
 
     /**
-     * Notifies a keep-alive timeout
+     * Notifies that no accounting report has been received
      * @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);
+    void notifyNoAcctReport(COPSPdpReqStateMan man);
 
     /**
      * Notifies that a request state has been deleted
      * @param man   The associated request state manager
      */
-    public void notifyDeleteRequestState (COPSPdpReqStateMan man);
+    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 fc4c74d45c1a60a17faae24da95b034d4c6a7302..257032ce45f3c19acdb2d5b8e4d7b2a02956a911 100644 (file)
@@ -1,48 +1,46 @@
-/*\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
-/**\r
- * Exception class for PDP errors\r
- *\r
- * @version COPSPdpException.java, v 2.00 2004\r
- *\r
- */\r
-\r
-public class COPSPdpException extends Exception {\r
-\r
-    private int rc;\r
-    final static int GENERAL_ERROR = 0x00000001;\r
-\r
-    /**\r
-    * Creates a <tt>COPSPdpException</tt> with the given message.\r
-    * @param msg    Exception message\r
-    */\r
-    public COPSPdpException(String msg) {\r
-        super(msg);\r
-        rc=0;\r
-    }\r
-\r
-    /**\r
-     * Creates a <tt>COPSPdpException</tt> with the given message and return code.\r
-     * @param msg       Exception message\r
-     * @param retCode   Return code\r
-     */\r
-    public COPSPdpException(String msg, int retCode) {\r
-        super(msg);\r
-        rc = retCode;\r
-    }\r
-\r
-    /**\r
-     * Gets the return code of the exception\r
-     * @return    Exception's return code\r
-     */\r
-    public int returnCode() {\r
-        return rc;\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.COPSException;
+
+/**
+ * Exception class for PDP errors
+ *
+ * @version COPSPdpException.java, v 2.00 2004
+ *
+ */
+
+public class COPSPdpException extends COPSException {
+
+    /**
+    * Creates a <tt>COPSPdpException</tt> with the given message.
+    * @param msg    Exception message
+    */
+    public COPSPdpException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Creates a <tt>COPSPdpException</tt> with the given message and return code.
+     * @param msg       Exception message
+     * @param retCode   Return code
+     */
+    public COPSPdpException(String msg, int retCode) {
+        super(msg, retCode);
+    }
+
+    /**
+     * Creates a <tt>COPSPdpException</tt> with the given message and throwable.
+     * @param msg       Exception message
+     * @param t         the Throwable
+     */
+    public COPSPdpException(String msg, Throwable t) {
+        super(msg, t);
+    }
+
+}
index 87c24ac6b487333c4862e823ff55b9cc226d00d0..787411540b7161598ab84b92ce005786e0781d6d 100644 (file)
@@ -6,6 +6,7 @@
 
 package org.umu.cops.prpdp;
 
+import org.umu.cops.COPSMsgSender;
 import org.umu.cops.stack.*;
 import org.umu.cops.stack.COPSContext.RType;
 import org.umu.cops.stack.COPSDecision.Command;
@@ -24,23 +25,7 @@ import java.util.Set;
  *
  * 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;
+public class COPSPdpMsgSender extends COPSMsgSender {
 
     /**
      * Creates a COPSPepMsgSender
@@ -50,27 +35,7 @@ public class COPSPdpMsgSender {
      * @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;
+        super(clientType, clientHandle, sock);
     }
 
     /**
@@ -81,24 +46,6 @@ public class COPSPdpMsgSender {
      */
     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<>();
 
@@ -147,11 +94,9 @@ public class COPSPdpMsgSender {
 
         // 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);
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, null);
 
         //** Send the decision
-        //**
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
@@ -167,28 +112,6 @@ public class COPSPdpMsgSender {
      */
     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<>();
@@ -241,11 +164,9 @@ public class COPSPdpMsgSender {
         decisionMsg.add(intr);
         /**/
 
-        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
-                decisionMap, null);
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, null);
 
         //** Send the decision
-        //**
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
@@ -255,30 +176,15 @@ public class COPSPdpMsgSender {
 
     /**
      * Sends a message asking that the request state be deleted
-     * @throws   COPSPdpException
+     * @throws COPSException
      */
-    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);
+    public void sendDeleteRequestState() throws COPSException {
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
         final Set<COPSDecision> decisionSet = new HashSet<>();
-        decisionSet.add(dec);
+        decisionSet.add(new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE));
         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
-        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
-                decisionMap, null);
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, null);
         try {
             decisionMsg.writeData(_sock);
         } catch (IOException e) {
@@ -288,29 +194,15 @@ public class COPSPdpMsgSender {
 
     /**
      * Sends a request asking that a new request state be created
-     * @throws   COPSPdpException
+     * @throws COPSException
      */
-    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);
+    public void sendOpenNewRequestState() throws COPSException {
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
         final Set<COPSDecision> decisionSet = new HashSet<>();
-        decisionSet.add(dec);
+        decisionSet.add(new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE));
         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
 
-        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(_handle.getId()),
-                decisionMap, null);
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, null);
 
         try {
             decisionMsg.writeData(_sock);
@@ -321,16 +213,10 @@ public class COPSPdpMsgSender {
 
     /**
      * Sends a message asking for a COPS sync operation
-     * @throws COPSPdpException
+     * @throws COPSException
      */
-    public void sendSyncRequestState()
-    throws COPSPdpException {
-        /* <Synchronize State Request>  ::= <Common Header>
-         *                                  [<Client Handle>]
-         *                                  [<Integrity>]
-         */
-
-        final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, new COPSHandle(_handle.getId()), null);
+    public void sendSyncRequestState() throws COPSException {
+        final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
         try {
             msg.writeData(_sock);
         } catch (IOException e) {
index 2c60428f0a273e586bf9368541f113e3cce89762..74c16f627198baa9767746f02a94373486bf0ae6 100644 (file)
@@ -6,6 +6,9 @@
 
 package org.umu.cops.prpdp;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
 import org.umu.cops.stack.*;
 
 import java.net.Socket;
@@ -15,157 +18,35 @@ import java.util.Map;
 /**
  * State manager class for provisioning requests, at the PDP side.
  */
-public class COPSPdpReqStateMan {
+public class COPSPdpReqStateMan extends COPSStateMan {
 
-    /**
-     * Request State created
-     */
-    public final static short ST_CREATE = 1;
-    /**
-     * Request received
-     */
-    public final static short ST_INIT = 2;
-    /**
-     * Decisions sent
-     */
-    public final static short ST_DECS = 3;
-    /**
-     * Report received
-     */
-    public final static short ST_REPORT = 4;
-    /**
-     * Request State finalized
-     */
-    public final static short ST_FINAL = 5;
-    /**
-     * New Request State solicited
-     */
-    public final static short ST_NEW = 6;
-    /**
-     * Delete Request State solicited
-     */
-    public final static short ST_DEL = 7;
-    /**
-     * SYNC request sent
-     */
-    public final static short ST_SYNC = 8;
-    /**
-     * SYNC completed
-     */
-    public final static short ST_SYNCALL = 9;
-    /**
-     * Close connection received
-     */
-    public final static short ST_CCONN = 10;
-    /**
-     * Keep-alive timeout
-     */
-    public final static short ST_NOKA = 11;
-    /**
-     * Accounting timeout
-     */
-    public final static short ST_ACCT = 12;
-
-    /**
-     * COPS client-type that identifies the policy client
-     */
-    protected short _clientType;
-
-    /**
-     *  COPS client handle used to uniquely identify a particular
-     *  PEP's request for a client-type
-     */
-    protected COPSHandle _handle;
+    private final static Logger logger = LoggerFactory.getLogger(COPSPdpReqStateMan.class);
 
     /**
      * Object for performing policy data processing
      */
-    protected COPSPdpDataProcess _process;
-
-    /**
-     *  Current state of the request being managed
-     */
-    protected short _status;
+    protected final COPSPdpDataProcess _process;
 
     /** COPS message transceiver used to send COPS messages */
-    protected COPSPdpMsgSender _sender;
+    protected transient 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;
+    public COPSPdpReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPdpDataProcess process) {
+        super(clientType, clientHandle);
+        this._process = process;
     }
 
-    /**
-     * 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 {
+    @Override
+    protected void initRequestState(final 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;
+        _status = Status.ST_INIT;
     }
 
     /**
@@ -173,12 +54,12 @@ public class COPSPdpReqStateMan {
      * @param msg   COPS request received from the PEP
      * @throws COPSPdpException
      */
-    protected void processRequest(COPSReqMsg msg)
-    throws COPSPdpException {
+    protected void processRequest(final COPSReqMsg msg) throws COPSPdpException {
 
-        COPSHeader hdrmsg = msg.getHeader();
-        COPSHandle handlemsg = msg.getClientHandle();
-        COPSContext contextmsg = msg.getContext();
+        // TODO - Implement me
+//        COPSHeader hdrmsg = msg.getHeader();
+//        COPSHandle handlemsg = msg.getClientHandle();
+//        COPSContext contextmsg = msg.getContext();
 
         //** Analyze the request
         //**
@@ -265,12 +146,8 @@ public class COPSPdpReqStateMan {
         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:
@@ -278,27 +155,26 @@ public class COPSPdpReqStateMan {
                     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());
+                    logger.info("PRID: " + strobjprid);
+                    logger.info("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;
+                    _status = Status.ST_REPORT;
                     _process.successReport(this, repSIs);
                     break;
                 case FAILURE:
-                    _status = ST_REPORT;
+                    _status = Status.ST_REPORT;
                     _process.failReport(this, repSIs);
                     break;
                 case ACCOUNTING:
-                    _status = ST_ACCT;
+                    _status = Status.ST_ACCT;
                     _process.acctReport(this, repSIs);
                     break;
             }
@@ -312,54 +188,49 @@ public class COPSPdpReqStateMan {
      * @param error Reason
      * @throws COPSPdpException
      */
-    protected void processClosedConnection(COPSError error)
-    throws COPSPdpException {
+    protected void processClosedConnection(final COPSError error) throws COPSPdpException {
         if (_process != null)
             _process.notifyClosedConnection(this, error);
 
-        _status = ST_CCONN;
+        _status = Status.ST_CCONN;
     }
 
     /**
      * Called when no keep-alive is received
      * @throws COPSPdpException
      */
-    protected void processNoKAConnection()
-    throws COPSPdpException {
+    protected void processNoKAConnection() throws COPSPdpException {
         if (_process != null)
             _process.notifyNoKAliveReceived(this);
 
-        _status = ST_NOKA;
+        _status = Status.ST_NOKA;
     }
 
     /**
      * Deletes the request state
      * @throws COPSPdpException
      */
-    protected void finalizeRequestState()
-    throws COPSPdpException {
+    protected void finalizeRequestState() throws COPSException {
         _sender.sendDeleteRequestState();
-        _status = ST_FINAL;
+        _status = Status.ST_FINAL;
     }
 
     /**
      * Asks for a COPS sync
      * @throws COPSPdpException
      */
-    protected void syncRequestState()
-    throws COPSPdpException {
+    protected void syncRequestState() throws COPSException {
         _sender.sendSyncRequestState();
-        _status = ST_SYNC;
+        _status = Status.ST_SYNC;
     }
 
     /**
      * Opens a new request state
      * @throws COPSPdpException
      */
-    protected void openNewRequestState()
-    throws COPSPdpException {
+    protected void openNewRequestState() throws COPSException {
         _sender.sendOpenNewRequestState();
-        _status = ST_NEW;
+        _status = Status.ST_NEW;
     }
 
     /**
@@ -367,12 +238,11 @@ public class COPSPdpReqStateMan {
      * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP
      * @throws COPSPdpException
      */
-    protected void processDeleteRequestState(COPSDeleteMsg dMsg)
-    throws COPSPdpException {
+    protected void processDeleteRequestState(final COPSDeleteMsg dMsg) throws COPSPdpException {
         if (_process != null)
             _process.closeRequestState(this);
 
-        _status = ST_DEL;
+        _status = Status.ST_DEL;
     }
 
 }
index e57823ece6afe3fe02b8bc0ac93711b1cff4d3ad..e7ab809d9260249aec2701409b8f13f2eb7d9117 100644 (file)
@@ -6,6 +6,8 @@
 
 package org.umu.cops.prpep;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.*;
 import org.umu.cops.stack.COPSHeader.OPCode;
 
@@ -20,6 +22,8 @@ import java.net.UnknownHostException;
  */
 public class COPSPepAgent {
 
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepAgent.class);
+
     /**
         PEP's Identifier
      */
@@ -117,9 +121,8 @@ public class COPSPepAgent {
      * @throws   COPSException
      * @throws   COPSPepException
      */
-    public boolean connect(String psHost, int psPort) throws IOException, COPSException, COPSPepException {
-
-        // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");
+    public boolean connect(String psHost, int psPort) throws IOException, COPSException {
+        logger.info("Thread ( " + _pepID + ") - Connecting to PDP");
         _psHost = psHost;
         _psPort = psPort;
 
@@ -173,8 +176,8 @@ public class COPSPepAgent {
      * @throws COPSPepException
      * @throws COPSException
      */
-    public COPSPepReqStateMan addRequestState(final String handle, final COPSPepDataProcess process)
-            throws COPSPepException, COPSException {
+    public COPSPepReqStateMan addRequestState(final COPSHandle handle, final COPSPepDataProcess process)
+            throws COPSException {
         if (_conn != null) {
             return _conn.addRequestState(handle, process);
         }
@@ -188,8 +191,7 @@ public class COPSPepAgent {
      * @throws COPSPepException
      * @throws COPSException
      */
-    public void deleteRequestState(final COPSPepReqStateMan man)
-    throws COPSPepException, COPSException {
+    public void deleteRequestState(final COPSPepReqStateMan man) throws COPSException {
         if (_conn != null)
             _conn.deleteRequestState(man);
     }
@@ -225,8 +227,8 @@ public class COPSPepAgent {
      * @throws   COPSPepException
      *
      */
-    private COPSPepConnection processConnection(String psHost, int psPort)
-            throws IOException, COPSException, COPSPepException {
+    private COPSPepConnection processConnection(final String psHost, final int psPort)
+            throws IOException, COPSException {
         // Build OPN
         final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, new COPSPepId(new COPSData(_pepID)),
                 null, null, null);
index f51109fdd398cf406acb7d122bf476406a66cc03..c6173cadd6c6e5612059e698e690a0c02116f695 100644 (file)
@@ -26,7 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class COPSPepConnection implements Runnable {
 
-    public final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
 
     /** Socket connected to PDP */
     protected Socket _sock;
@@ -55,7 +55,7 @@ public class COPSPepConnection implements Runnable {
     /**
         Maps a COPS Client Handle to a Request State Manager
      */
-    protected final Map<String, COPSPepReqStateMan> _managerMap;
+    protected final Map<COPSHandle, COPSPepReqStateMan> _managerMap;
 
     /**
         COPS error returned by PDP
@@ -68,7 +68,6 @@ public class COPSPepConnection implements Runnable {
      * @param sock          Socket connected to PDP
      */
     public COPSPepConnection(final short clientType, final Socket sock) {
-
         _clientType = clientType;
         _sock = sock;
 
@@ -236,21 +235,21 @@ public class COPSPepConnection implements Runnable {
      * @throws COPSException
      * @throws IOException
      */
-    protected byte processMessage(final Socket conn) throws COPSPepException, COPSException, IOException {
+    protected byte processMessage(final Socket conn) throws COPSException, IOException {
         final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
 
         switch (msg.getHeader().getOpCode()) {
             case CC:
-                handleClientCloseMsg(conn, msg);
+                handleClientCloseMsg(conn, (COPSClientCloseMsg)msg);
                 return (byte)OPCode.CC.ordinal();
             case DEC:
-                handleDecisionMsg(conn, msg);
+                handleDecisionMsg((COPSDecisionMsg)msg);
                 return (byte)OPCode.DEC.ordinal();
             case SSQ:
-                handleSyncStateReqMsg(conn, msg);
+                handleSyncStateReqMsg((COPSSyncStateMsg)msg);
                 return (byte)OPCode.SSQ.ordinal();
             case KA:
-                handleKeepAliveMsg(conn, msg);
+                handleKeepAliveMsg((COPSKAMsg)msg);
                 return (byte)OPCode.KA.ordinal();
             default:
                 throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
@@ -259,31 +258,18 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * 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>]
-     *
+     * @param    cMsg                a  COPSClientCloseMsg
      */
-    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
-        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+    private void handleClientCloseMsg(final Socket conn, final COPSClientCloseMsg cMsg) {
         _error = cMsg.getError();
-
-        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
-
+        logger.info("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);
@@ -292,9 +278,7 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Method getError
-     *
      * @return   a COPSError
-     *
      */
     protected COPSError getError()  {
         return _error;
@@ -302,25 +286,14 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Handle Keep Alive Message
-     *
-     * <Keep-Alive> ::= <Common Header>
-     *                  [<Integrity>]
-     *
-     * Not support [<Integrity>]
-     *
-     * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    cMsg                a  COPSKAMsg
      */
-    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
-        COPSKAMsg cMsg = (COPSKAMsg) msg;
-
-        // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
-
+    private void handleKeepAliveMsg(final COPSKAMsg cMsg) {
+        logger.info("Get KAlive Msg");
         try {
             // Support
             if (cMsg.getIntegrity() != null) {
-                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+                logger.warn("Unsupported objects (Integrity)");
             }
 
             // should we do anything else?? ....
@@ -332,39 +305,20 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Method handleDecisionMsg
-     *
-     * <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>
-     *
-     * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    dMsg                 a  COPSDecisionMsg
      */
-    private void handleDecisionMsg(final Socket conn, final COPSMsg msg) throws COPSPepException {
-        final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+    private void handleDecisionMsg(final COPSDecisionMsg dMsg) throws COPSException {
         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
-                final COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
-                if (manager == null)
-                    logger.warn("Unable to find state manager with key - " + handle.getId().str());
+                final COPSPepReqStateMan manager = _managerMap.get(handle);
+                if (manager == null) {
+                    logger.warn("Unable to find state manager with key - " + handle);
+                    return;
+                }
 
                 // Check message type
                 // TODO FIXME - Use of manager object could result in a NPE
@@ -374,10 +328,10 @@ public class COPSPepConnection implements Runnable {
                         manager.processDeleteRequestState(dMsg);
                     else
                         // Open new Request State
-                        handleOpenNewRequestStateMsg(conn, handle);
+                        handleOpenNewRequestStateMsg(handle);
                 } else
                     // Decision
-                    manager.processDecision(dMsg);
+                    manager.processDecision(dMsg, _sock);
             }
         }
     }
@@ -385,82 +339,59 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Method handleOpenNewRequestStateMsg
-     *
-     * @param    conn                a  Socket
      * @param    handle              a  COPSHandle
-     *
      */
-    private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle) throws COPSPepException {
-
-        COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
+    private void handleOpenNewRequestStateMsg(final COPSHandle handle) throws COPSPepException {
+        final COPSPepReqStateMan manager = _managerMap.get(handle);
         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();
+        else
+            manager.processOpenNewRequestState();
     }
 
     /**
      * Method handleSyncStateReqMsg
-     *
-     *              <Synchronize State> ::= <Common Header>
-     *                                      [<Client Handle>]
-     *                                      [<Integrity>]
-     *
-     * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    cMsg                a  COPSSyncStateMsg
      */
-    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
-
-        // Support
+    private void handleSyncStateReqMsg(final COPSSyncStateMsg cMsg) throws COPSPepException {
         if (cMsg.getIntegrity() != null) {
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            logger.warn("Unsupported objects (Integrity)");
         }
 
-        COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
-        if (manager == null) {
+        final COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle());
+        if (manager == null)
             logger.warn("Unable to find state manager with key - " + cMsg.getClientHandle().getId().str());
-        } else {
+        else
             manager.processSyncStateRequest(cMsg);
-        }
     }
 
     /**
      * Method createRequestState
-     *
      * @param    clientHandle             a  String
      * @param    process                  a  COPSPepDataProcess
-     *
      * @return   a COPSPepmanager
-     *
      * @throws   COPSException
      * @throws   COPSPepException
-     *
      */
-    protected COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process) throws COPSException,
-            COPSPepException {
-        COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
+    protected COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
+            throws COPSException {
+        final COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle, process);
         if (_managerMap.get(clientHandle) != null)
             throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
 
-        manager.setDataProcess(process);
-        _managerMap.put(clientHandle,manager);
+        _managerMap.put(clientHandle, manager);
+        logger.info("Added state manager with key - " + clientHandle);
         manager.initRequestState(_sock);
         return manager;
     }
 
     /**
      * Method deleteRequestState
-     *
      * @param    manager             a  COPSPepReqStateMan
-     *
      * @throws   COPSException
      * @throws   COPSPepException
-     *
      */
-    protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException, COPSPepException {
+    protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException {
         manager.finalizeRequestState();
     }
 
index 9bda235f9347336ff6f9cbdc65d73c1c70c81ebe..0e7dcfe82a61ebe22e10a8fe14aa77f541ee926b 100644 (file)
@@ -6,7 +6,7 @@
 
 package org.umu.cops.prpep;
 
-import org.umu.cops.stack.COPSError;
+import org.umu.cops.COPSDataProcess;
 
 import java.util.Map;
 
@@ -16,7 +16,7 @@ import java.util.Map;
  * @version COPSPepDataProcess.java, v 2.00 2004
  *
  */
-public abstract class COPSPepDataProcess {
+public interface COPSPepDataProcess extends COPSDataProcess {
 
     /**
      * Establish PDP decisions
@@ -27,59 +27,38 @@ public abstract class COPSPepDataProcess {
      * @param errorDecs - the error decisions
      */
 
-       public abstract void setDecisions(COPSPepReqStateMan man, Map<String, String> removeDecs,
+       void setDecisions(COPSPepReqStateMan man, Map<String, String> removeDecs,
                                       Map<String, String> installDecs, Map<String, String> errorDecs);
 
     /**
      *  If the report is fail, return true
-     *
      * @return - t/f
      */
-    public abstract boolean isFailReport(COPSPepReqStateMan man);
+    boolean isFailReport(COPSPepReqStateMan man);
 
     /**
      * Return Report Data
-     *
      * @return - the report data
      */
-    public abstract Map<String, String> getReportData(COPSPepReqStateMan man);
+    Map<String, String> getReportData(COPSPepReqStateMan man);
 
     /**
      * Return Client Data
-     *
      * @return - the client data
      */
-    public abstract Map<String, String> getClientData(COPSPepReqStateMan man);
+    Map<String, String> getClientData(COPSPepReqStateMan man);
 
     /**
      * Return Accounting Data
-     *
      * @return - the accounting data
      */
-    public abstract Map<String, String> getAcctData(COPSPepReqStateMan man);
-
-    /**
-     * Notify the connection closed
-     */
-    public abstract void notifyClosedConnection(COPSPepReqStateMan man, COPSError error);
-
-    /**
-     * Notify the KAlive timeout
-     */
-    public abstract void notifyNoKAliveReceived(COPSPepReqStateMan man);
-
-    /**
-     * Process a PDP request to close a Request State
-     *
-     * @param man       Request State Manager
-     */
-    public abstract void closeRequestState(COPSPepReqStateMan man);
+    Map<String, String> getAcctData(COPSPepReqStateMan man);
 
     /**
      * Process a PDP request to open a new Request State
      *
      * @param man       Request State Manager
      */
-    public abstract void newRequestState(COPSPepReqStateMan man);
+    void newRequestState(COPSPepReqStateMan man);
 }
 
index ccac8ee9898ba8380cc506403edb6c12fe294260..3b68a2456419cdac6aea36823fb4dbab0788cbe9 100644 (file)
@@ -6,35 +6,26 @@
 \r
 package org.umu.cops.prpep;\r
 \r
+import org.umu.cops.stack.COPSException;\r
+\r
 /**\r
  * COPS PEP Exception\r
  *\r
  * @version COPSPepException.java, v 2.00 2004\r
  *\r
  */\r
-public class COPSPepException extends Exception {\r
-\r
-    private int rc;\r
-    final static int GENERAL_ERROR = 0x00000001;\r
+public class COPSPepException extends COPSException {\r
 \r
     public COPSPepException(String s) {\r
         super(s);\r
-        rc=0;\r
     }\r
 \r
     public COPSPepException(String msg, int retCode) {\r
-        super(msg);\r
-        rc = retCode;\r
+        super(msg, retCode);\r
     }\r
 \r
-    /**\r
-     * Return error code\r
-     *\r
-     * @return    error code\r
-     *\r
-     */\r
-    public int returnCode() {\r
-        return rc;\r
+    public COPSPepException(String msg, Throwable t) {\r
+        super(msg, t);\r
     }\r
 \r
 }\r
index 17a03b1c1a7e2d0f5593fbdcc5dfbe0c9422e5e4..7bb35ce28b898989aa8d0338758a8652eb747b76 100644 (file)
@@ -6,6 +6,7 @@
 
 package org.umu.cops.prpep;
 
+import org.umu.cops.COPSMsgSender;
 import org.umu.cops.stack.*;
 import org.umu.cops.stack.COPSClientSI.CSIType;
 import org.umu.cops.stack.COPSContext.RType;
@@ -24,23 +25,7 @@ import java.util.Set;
  * @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;
+public class COPSPepMsgSender extends COPSMsgSender {
 
     /**
      * Create a COPSPepMsgSender
@@ -49,32 +34,8 @@ public class COPSPepMsgSender {
      * @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;
+    public COPSPepMsgSender(short clientType, COPSHandle clientHandle, Socket sock) {
+        super(clientType, clientHandle, sock);
     }
 
     /**
@@ -176,11 +137,9 @@ public class COPSPepMsgSender {
      *   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 {
+    public void sendSyncComplete() throws COPSException {
         final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
         try {
             msg.writeData(_sock);
@@ -194,11 +153,9 @@ public class COPSPepMsgSender {
      * 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 {
+    public void sendDeleteRequest() throws COPSException {
         // *** TODO: send a real reason
         final COPSReason reason = new COPSReason(ReasonCode.UNSPECIFIED, ReasonCode.NA);
         final COPSDeleteMsg msg = new COPSDeleteMsg(_clientType, _handle, reason, null);
index dc0e1d834f46743b3a15b822e5b9694674185109..ff07ce672e9ce6bef936fd31f967a24bf8e3135b 100644 (file)
@@ -6,12 +6,20 @@
 
 package org.umu.cops.prpep;
 
+import org.pcmm.gates.impl.GateID;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+import org.umu.cops.stack.COPSReportType.ReportType;
 
+import java.io.IOException;
 import java.net.Socket;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
@@ -35,87 +43,24 @@ import java.util.Set;
  * @version COPSPepReqStateMan.java, v 2.00 2004
  *
  */
-public class COPSPepReqStateMan {
+public class COPSPepReqStateMan extends COPSStateMan {
 
-    /**
-     * 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;
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
 
     /**
         The PolicyDataProcess is used to process policy data in the PEP
      */
-    protected COPSPepDataProcess _process;
-
-    /**
-     *  State Request State
-     */
-    protected short _status;
+    protected final COPSPepDataProcess _process;
 
     /**
         The Msg Sender is used to send COPS messages
      */
-    protected COPSPepMsgSender _sender;
+    protected transient COPSPepMsgSender _sender;
 
     /**
      * Sync State
      */
-    protected boolean _syncState;
+    protected transient boolean _syncState;
 
     /**
      * Create a State Request Manager
@@ -123,60 +68,10 @@ public class COPSPepReqStateMan {
      * @param    clientHandle                a Client Handle
      *
      */
-    public COPSPepReqStateMan(final short clientType, final String clientHandle) {
-        _handle = new COPSHandle(new COPSData(clientHandle));
-        _clientType = clientType;
+    public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepDataProcess process) {
+        super(clientType, clientHandle);
+        this._process = process;
         _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;
     }
 
     /**
@@ -185,8 +80,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void initRequestState(Socket sock)
-    throws COPSPepException {
+    protected void initRequestState(final Socket sock) throws COPSException {
         // Inits an object for sending COPS messages to the PDP
         _sender = new COPSPepMsgSender(_clientType, _handle, sock);
 
@@ -203,7 +97,7 @@ public class COPSPepReqStateMan {
         _sender.sendRequest(clientSIs);
 
         // Initial state
-        _status = ST_INIT;
+        _status = Status.ST_INIT;
     }
 
     /**
@@ -212,10 +106,9 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void finalizeRequestState()
-    throws COPSPepException {
+    protected void finalizeRequestState() throws COPSException {
         _sender.sendDeleteRequest();
-        _status = ST_FINAL;
+        _status = Status.ST_FINAL;
     }
 
     /**
@@ -226,32 +119,80 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processDecision(COPSDecisionMsg dMsg)
-    throws COPSPepException {
-        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
-
-        // COPSHandle handle = dMsg.getClientHandle();
+    protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSException {
+        logger.info("Processing decision message - " + dMsg);
         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()) {
+        for (final Set<COPSDecision> copsDecisions: decisions.values()) {
             final COPSDecision cmddecision = copsDecisions.iterator().next();
             String prid = "";
             switch (cmddecision.getCommand()) {
                 case INSTALL:
+                    // TODO - break up this block
                     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;
+                        if (decision.getData().getData().length != 0) {
+                            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;
+                            }
+                        }
+                        if (decision.getFlag().equals(DecisionFlag.REQERROR)) {
+                            // This is assuming a gate set right or wrong
+                            if (dMsg.getDecisions().size() == 1 && dMsg.getDecSI() != null) {
+                                final PCMMGateReq gateReq = new PCMMGateReq(dMsg.getDecSI().getData().getData());
+                                // TODO - Check and/or Set state here
+                                // Gate ADD gateReq.getTrafficProfile() != null
+                                // Gate REMOVE gateReq.getTrafficProfile() == null
+//                                    final String gateName = trafficProfile.getData().str();
+//                                    final Direction gateDir = gateReq.getGateSpec().getDirection();
+                                final boolean success = true;
+
+                                // Set response
+                                final List<Byte> data = new ArrayList<>();
+                                for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
+                                    data.add(val);
+                                for (final byte val : gateReq.getAMID().getAsBinaryArray())
+                                    data.add(val);
+                                for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
+                                    data.add(val);
+
+                                // Assign a gate ID
+                                final GateID gateID = new GateID();
+                                gateID.setGateID(UUID.randomUUID().hashCode());
+                                for (final byte val : gateID.getAsBinaryArray())
+                                    data.add(val);
+
+
+                                final byte[] csiArr = new byte[data.size()];
+                                for (int i = 0; i < data.size(); i++) {
+                                    csiArr[i] = data.get(i);
+                                }
+                                final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
+
+                                final COPSReportMsg reportMsg;
+                                // TODO FIXME - success is always true
+                                if (success) {
+                                    reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
+                                            new COPSReportType(ReportType.SUCCESS), si, null);
+                                } else {
+                                    reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
+                                            new COPSReportType(ReportType.FAILURE), si, null);
+                                }
+
+                                try {
+                                    reportMsg.writeData(socket);
+                                } catch (IOException e) {
+                                    throw new COPSPepException("Error writing gate set SUCCESS Report", e);
+                                }
+                            }
                         }
                     }
                     break;
@@ -278,7 +219,7 @@ public class COPSPepReqStateMan {
         // TODO - why is this collection never getting populated???
         final Map<String, String> errorDecs = new HashMap<>();
         _process.setDecisions(this, removeDecs, installDecs, errorDecs);
-        _status = ST_DECS;
+        _status = Status.ST_DECS;
 
 
         if (_process.isFailReport(this)) {
@@ -288,12 +229,12 @@ public class COPSPepReqStateMan {
             // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
             _sender.sendSuccessReport(_process.getReportData(this));
         }
-        _status = ST_REPORT;
+        _status = Status.ST_REPORT;
 
         if (!_syncState) {
             _sender.sendSyncComplete();
             _syncState = true;
-            _status = ST_SYNCALL;
+            _status = Status.ST_SYNCALL;
         }
     }
 
@@ -303,13 +244,12 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processOpenNewRequestState()
-    throws COPSPepException {
+    protected void processOpenNewRequestState() throws COPSPepException {
 
         if (_process != null)
             _process.newRequestState(this);
 
-        _status = ST_NEW;
+        _status = Status.ST_NEW;
     }
 
     /**
@@ -320,12 +260,11 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processDeleteRequestState(COPSDecisionMsg dMsg)
-    throws COPSPepException {
+    protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
         if (_process != null)
             _process.closeRequestState(this);
 
-        _status = ST_DEL;
+        _status = Status.ST_DEL;
     }
 
     /**
@@ -339,8 +278,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)
-    throws COPSPepException {
+    protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSPepException {
         _syncState = false;
         // If an object for retrieving PEP features exists,
         // use it for retrieving them
@@ -354,28 +292,24 @@ public class COPSPepReqStateMan {
         // TODO - do we really want to send the request when the map is empty???
         _sender.sendRequest(clientSIs);
 
-        _status = ST_SYNC;
+        _status = Status.ST_SYNC;
     }
 
-    protected void processClosedConnection(COPSError error)
-    throws COPSPepException {
+    protected void processClosedConnection(final COPSError error) throws COPSPepException {
         if (_process != null)
             _process.notifyClosedConnection(this, error);
 
-        _status = ST_CCONN;
+        _status = Status.ST_CCONN;
     }
 
-    protected void processNoKAConnection()
-    throws COPSPepException {
+    protected void processNoKAConnection() throws COPSPepException {
         if (_process != null)
             _process.notifyNoKAliveReceived(this);
 
-        _status = ST_NOKA;
+        _status = Status.ST_NOKA;
     }
 
-    protected void processAcctReport()
-    throws COPSPepException {
-
+    protected void processAcctReport() throws COPSPepException {
         final Map<String, String> report;
         if (_process != null) report = _process.getAcctData(this);
         else report = new HashMap<>();
@@ -383,7 +317,7 @@ public class COPSPepReqStateMan {
         // TODO - do we really want to send when the map is empty???
         _sender.sendAcctReport(report);
 
-        _status = ST_ACCT;
+        _status = Status.ST_ACCT;
     }
 
 }
index e25fb91624924f15aee678956a9f439163b2ffc4..293332951c22c2356d9dcd09bcd7beeba6a003b7 100644 (file)
@@ -7,6 +7,7 @@
 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;
@@ -62,6 +63,19 @@ public class COPSClientSI extends COPSObjBase {
      */
     private final COPSData _padding;
 
+    /**
+     * Constructor generally used for sending messages
+     * @param ctype - the CSIType
+     * @param data - the data
+     * @throws java.lang.IllegalArgumentException
+     */
+    public COPSClientSI(final CNum cnum, final CType ctype, 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, ctype), data);
+    }
+
     /**
      * Constructor generally used for sending messages
      * @param csitype - the CSIType
@@ -84,14 +98,17 @@ public class COPSClientSI extends COPSObjBase {
      */
     protected COPSClientSI(final COPSObjHeader hdr, final COPSData data) {
         super(hdr);
-        _csiType = VAL_TO_CSI.get(hdr.getCType().ordinal());
+        if (VAL_TO_CSI.get(hdr.getCType().ordinal()) == null) {
+            // TODO - determine if this is a good default value???
+            _csiType = CSIType.NAMED;
+        } else {
+            _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 (!hdr.getCNum().equals(CNum.CSI) && !hdr.getCNum().equals(CNum.DEC))
+            throw new IllegalArgumentException("CNum must be equal to " + CNum.CSI + " or " + CNum.DEC);
         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;
@@ -125,7 +142,7 @@ public class COPSClientSI extends COPSObjBase {
     @Override
     public void writeBody(final Socket socket) throws IOException {
         COPSUtil.writeData(socket, _data.getData(), _data.length());
-        COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+        if (_padding.length() > 0) COPSUtil.writeData(socket, _padding.getData(), _padding.length());
     }
 
     @Override
index 4e152bc890995425c84ab9ad913b075841de1b21..a3847c247a0592739739a3e0f5a79ba987cf4baf 100644 (file)
@@ -112,7 +112,7 @@ public class COPSDecision extends COPSObjBase {
      * @throws java.lang.IllegalArgumentException
      */
     public COPSDecision(final Command cmdCode) {
-        this(CType.DEF, cmdCode, DecisionFlag.NA, new COPSData());
+        this(CType.DEF, cmdCode, DecisionFlag.NA, null);
     }
 
     /**
@@ -132,7 +132,7 @@ public class COPSDecision extends COPSObjBase {
      * @throws java.lang.IllegalArgumentException
      */
     public COPSDecision(final Command cmdCode, final DecisionFlag flags) {
-        this(CType.DEF, cmdCode, flags, new COPSData());
+        this(CType.DEF, cmdCode, flags, null);
     }
 
     /**
@@ -143,7 +143,7 @@ public class COPSDecision extends COPSObjBase {
      * @throws java.lang.IllegalArgumentException
      */
     public COPSDecision(final CType cType, final Command cmdCode, final DecisionFlag flags) {
-        this(cType, cmdCode, flags, new COPSData());
+        this(cType, cmdCode, flags, null);
     }
 
     /**
@@ -178,11 +178,12 @@ public class COPSDecision extends COPSObjBase {
         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 == null) _data = new COPSData();
+        else _data = data;
 
         if ((_data.length() % 4) != 0) {
             final int padLen = 4 - (_data.length() % 4);
index 3bb81fbf997b763bbe8700ec9cf4ba0f5d860b70..8e87363e3ae6d4447606e813e376009248a8268d 100644 (file)
@@ -8,6 +8,7 @@ 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;
@@ -73,6 +74,7 @@ public class COPSDecisionMsg extends COPSMsg {
     private final COPSError _error;
     private final Map<COPSContext, Set<COPSDecision>> _decisions;
     private final COPSIntegrity _integrity;
+    private final COPSClientSI _decSI;
 
     /**
      * Constructor for Decision messages containing a COPS Error.
@@ -81,11 +83,12 @@ public class COPSDecisionMsg extends COPSMsg {
      * @param clientHandle - the handle (required)
      * @param error - the error (required)
      * @param integrity - the integrity (optional)
+     * @param decSI - the client SI for the description(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);
+    public COPSDecisionMsg(final short clientType, final COPSHandle clientHandle, final COPSError error,
+                           final COPSIntegrity integrity, final COPSClientSI decSI) {
+        this(new COPSHeader(OPCode.DEC, clientType), clientHandle, error, null, integrity, decSI);
     }
 
     /**
@@ -94,10 +97,11 @@ public class COPSDecisionMsg extends COPSMsg {
      * @param clientHandle - the handle (required)
      * @param error - the error (required)
      * @param integrity - the integrity (optional)
+     * @param decSI - the client SI for the description(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);
+                           final COPSError error, final COPSIntegrity integrity, final COPSClientSI decSI) {
+        this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, error, null, integrity, decSI);
     }
 
     /**
@@ -107,11 +111,13 @@ public class COPSDecisionMsg extends COPSMsg {
      * @param clientHandle - the handle (required)
      * @param decisions - the decisions (required)
      * @param integrity - the integrity (optional)
+     * @param decSI - the client SI for the description(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);
+                           final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity,
+                           final COPSClientSI decSI) {
+        this(new COPSHeader(OPCode.DEC, clientType), clientHandle, null, decisions, integrity, decSI);
     }
 
     /**
@@ -120,10 +126,12 @@ public class COPSDecisionMsg extends COPSMsg {
      * @param clientHandle - the handle (required)
      * @param decisions - the decisions (required)
      * @param integrity - the integrity (optional)
+     * @param decSI - the client SI for the description(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);
+                           final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity,
+                           final COPSClientSI decSI) {
+        this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, null, decisions, integrity, decSI);
     }
 
     /**
@@ -133,10 +141,11 @@ public class COPSDecisionMsg extends COPSMsg {
      * @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)
+     * @param decSI - the client SI for the description(optional)
      */
     protected COPSDecisionMsg(final COPSHeader hdr, final COPSHandle clientHandle,
                            final COPSError error, final Map<COPSContext, Set<COPSDecision>> decisions,
-                           final COPSIntegrity integrity) {
+                           final COPSIntegrity integrity, final COPSClientSI decSI) {
         super(hdr);
         if (!hdr.getOpCode().equals(OPCode.DEC))
             throw new IllegalArgumentException("OPCode must be of type - " + OPCode.DEC);
@@ -157,7 +166,7 @@ public class COPSDecisionMsg extends COPSMsg {
         _clientHandle = clientHandle;
         _error = error;
         _integrity = integrity;
-
+        _decSI = decSI;
     }
 
     // Getters
@@ -173,6 +182,9 @@ public class COPSDecisionMsg extends COPSMsg {
     public COPSIntegrity getIntegrity() {
         return _integrity;
     }
+    public COPSClientSI getDecSI() {
+        return _decSI;
+    }
 
     @Override
     protected int getDataLength() {
@@ -188,6 +200,7 @@ public class COPSDecisionMsg extends COPSMsg {
         }
 
         if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+        if (_decSI != null) out += _decSI.getDataLength() + _decSI.getHeader().getHdrLength();
 
         return out;
     }
@@ -207,6 +220,7 @@ public class COPSDecisionMsg extends COPSMsg {
         }
 
         if (_integrity != null) _integrity.writeData(socket);
+        if (_decSI != null) _decSI.writeData(socket);
     }
 
     @Override
@@ -226,6 +240,9 @@ public class COPSDecisionMsg extends COPSMsg {
         if (_integrity != null) {
             _integrity.dump(os);
         }
+        if (_decSI != null) {
+            _decSI.dump(os);
+        }
     }
 
     @Override
@@ -260,7 +277,8 @@ public class COPSDecisionMsg extends COPSMsg {
 
         return _clientHandle.equals(that._clientHandle) &&
                 !(_error != null ? !_error.equals(that._error) : that._error != null) &&
-                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null);
+                !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null) &&
+                !(_decSI != null ? !_decSI.equals(that._decSI) : that._decSI != null);
 
     }
 
@@ -271,6 +289,7 @@ public class COPSDecisionMsg extends COPSMsg {
         result = 31 * result + (_error != null ? _error.hashCode() : 0);
         result = 31 * result + _decisions.hashCode();
         result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+        result = 31 * result + (_decSI != null ? _decSI.hashCode() : 0);
         return result;
     }
 
@@ -287,6 +306,7 @@ public class COPSDecisionMsg extends COPSMsg {
         COPSContext context = null;
         COPSError error = null;
         COPSIntegrity integrity = null;
+        COPSClientSI descSi = null;
         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
 
         int dataStart = 0;
@@ -308,24 +328,42 @@ public class COPSDecisionMsg extends COPSMsg {
                     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);
+                    COPSDecision dec;
+                    if (objHdrData.header.getCType().equals(CType.CSI)) {
+                        // TODO - Revisit, this is pretty darn clunky
+                        try {
+                            dec = COPSDecision.parse(objHdrData, buf);
+                        } catch (IllegalArgumentException e) {
+                            descSi = COPSClientSI.parse(objHdrData, buf);
+                            dec = null;
+                        }
+                    } else {
+                        dec = COPSDecision.parse(objHdrData, buf);
+                    }
+                    if (dec != null) {
+                        if (decisionMap.get(context) != null)
+                            decisionMap.get(context).add(dec);
+                        else {
+                            final Set<COPSDecision> decisions = new HashSet<>();
+                            decisions.add(dec);
+                            decisionMap.put(context, decisions);
+                        }
                     }
                     break;
+                case CSI:
+                    descSi = COPSClientSI.parse(objHdrData, buf);
+                    break;
                 case MSG_INTEGRITY:
                     integrity = COPSIntegrity.parse(objHdrData, buf);
                     break;
                 default:
-                    throw new COPSException("Bad Message format, unknown object type");
+                    throw new COPSException("Bad Message format, unknown object type with CNum - "
+                            + objHdrData.header.getCNum());
             }
             dataStart += objHdrData.msgByteCount;
         }
 
-        return new COPSDecisionMsg(hdrData.header, clientHandle, error, decisionMap, integrity);
+        return new COPSDecisionMsg(hdrData.header, clientHandle, error, decisionMap, integrity, descSi);
     }
 
 }
\ No newline at end of file
index c141fc507286a669490957f37f288294661bf48f..06c03582ee481ce47666448a0a3e7cd885b6f891 100644 (file)
@@ -12,6 +12,8 @@ import org.umu.cops.stack.COPSObjHeader.CType;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * COPS Handle Object (RFC 2748 pag. 9)
@@ -130,8 +132,22 @@ public class COPSHandle extends COPSObjBase {
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + _data.hashCode();
-        result = 31 * result + _padding.hashCode();
+
+        /*
+         Retrieve hash for the bytes contained in both COPSData members as equivalent objects may contain 0 value bytes
+         either trailing in the _data member or contained in the _padding. This generally will occur between an object
+         constructed via a public constructor vs. parsed from a byte[].
+
+         This is important as this object is known to be used as a key to Maps.
+          */
+        final List<Byte> allBytes = new ArrayList<>();
+        for (final byte val : _data.getData()) {
+            allBytes.add(val);
+        }
+        for (final byte val : _padding.getData()) {
+            allBytes.add(val);
+        }
+        result = 31 * allBytes.hashCode();
         return result;
     }
 
index ad1ea5e8ab37e26b501b229664c9250adf497be7..da439ac3e4ea9e4977eb1151a6f95df77e269512 100644 (file)
@@ -3,11 +3,10 @@
  */
 package org.pcmm.test;
 
+import org.pcmm.PCMMConstants;
+import org.pcmm.PCMMProperties;
 import org.pcmm.rcd.ICMTS;
-import org.pcmm.rcd.IPCMMPolicyServer;
-import org.pcmm.rcd.IPCMMPolicyServer.IPSCMTSClient;
 import org.pcmm.rcd.impl.CMTS;
-import org.pcmm.rcd.impl.PCMMPolicyServer;
 
 /**
  *
@@ -18,11 +17,11 @@ public class Main {
         * @param args
         */
        public static void main(String[] args) {
-               ICMTS icmts = new CMTS();
+               ICMTS icmts = new CMTS(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
                icmts.startServer();
-               IPCMMPolicyServer ps = new PCMMPolicyServer();
-               IPSCMTSClient client = ps.requestCMTSConnection("localhost");
-               client.gateSet();
+//             IPCMMPolicyServer ps = new PCMMPolicyServer();
+//             IPSCMTSClient client = ps.requestCMTSConnection("localhost");
+//             client.gateSet();
                // IWorkerPool pool = new WorkerPool(2);
                // IWorker worker = new Worker(new Callable<String>() {
                // @Override
index 6f9e7cb58ba096788b2ec636905e3c6fcb0f0e00..3b67dd725ee6231b3e5e643f48de907a16c3b545 100644 (file)
@@ -15,6 +15,31 @@ import java.io.ByteArrayOutputStream;
  */
 public class COPSClientSITest {
 
+    @Test(expected = IllegalArgumentException.class)
+    public void nullCNumConstructor1() {
+        new COPSClientSI(null, CType.CSI, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCNumConstructor1() {
+        new COPSClientSI(CNum.ACCT_TIMER, CType.CSI, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullCTypeConstructor1() {
+        new COPSClientSI(CNum.DEC, null, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidCTypeConstructor1() {
+        new COPSClientSI(CNum.DEC, CType.NA, new COPSData());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void nullDataConstructor1() {
+        new COPSClientSI(CNum.DEC, CType.CSI, null);
+    }
+
     @Test(expected = IllegalArgumentException.class)
     public void invalidCSItype() {
         new COPSClientSI(CSIType.NA, new COPSData());
@@ -35,6 +60,15 @@ public class COPSClientSITest {
         new COPSClientSI(new COPSObjHeader(CNum.ACCT_TIMER, CType.CSI), new COPSData());
     }
 
+    @Test
+    public void validConstructor1() {
+        final COPSClientSI clientSI = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData());
+        Assert.assertEquals(CSIType.NAMED, clientSI.getCsiType());
+        Assert.assertEquals(CNum.DEC, clientSI.getHeader().getCNum());
+        Assert.assertEquals(CType.CSI, clientSI.getHeader().getCType());
+        Assert.assertEquals(new COPSData(), clientSI.getData());
+    }
+
     @Test
     public void csiSignaledEmptyData() {
         final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData());
index a13969c648e43ff0d30e1a841071a9de12f91eaa..c97380d0db3f429d54a83fe5cd79ef5c1df78e18 100644 (file)
@@ -5,6 +5,7 @@ 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;
@@ -54,157 +55,162 @@ public class COPSDecisionMsgTest {
     @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);
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void version0WithDecisions() {
         new COPSDecisionMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
-                staticDecisions, null);
+                staticDecisions, null, 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);
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void nullFlagWithDecisions() {
         new COPSDecisionMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
-                staticDecisions, null);
+                staticDecisions, null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void nullHandleDeprecatedWithError() {
         new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null,
-                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void nullHandleDeprecatedWithDecisions() {
-        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null, staticDecisions, null);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null, staticDecisions, null, 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);
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void nullHandleWithDecisions() {
-        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null, staticDecisions, null);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null, staticDecisions, null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void nullErrorDeprecated() {
         final COPSError error = null;
-        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null, 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);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error,
+                null, 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);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, 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);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+                null, 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);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, 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);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+                null, 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);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, 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);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+                null, 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);
+        new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, 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);
+        new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+                null, 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);
+                null, null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void nullHeaderDecisionsOnly() {
         final COPSHeader hdr = null;
-        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null, 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);
+                null, 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);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null, 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);
+                staticDecisions, null, 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);
+        new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, 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);
+                new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null, null);
         Assert.assertEquals(OPCode.DEC, msg.getHeader().getOpCode());
         Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
         Assert.assertEquals(hdr, msg.getHeader());
@@ -218,7 +224,7 @@ public class COPSDecisionMsgTest {
     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);
+                null, staticDecisions, null, null);
         Assert.assertEquals(OPCode.DEC, msg.getHeader().getOpCode());
         Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
         Assert.assertEquals(hdr, msg.getHeader());
@@ -239,7 +245,7 @@ public class COPSDecisionMsgTest {
     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());
+                new COPSIntegrity(), new COPSClientSI(CSIType.NAMED, new COPSData()));
 
         final ByteArrayOutputStream os = new ByteArrayOutputStream();
         msg.dump(os);
@@ -247,7 +253,7 @@ public class COPSDecisionMsgTest {
         final String out = new String(os.toByteArray());
         System.out.println(out);
         final String[] lines = out.split("\n");
-        Assert.assertEquals(20, lines.length);
+        Assert.assertEquals(25, lines.length);
 
         // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
         Assert.assertEquals("**MSG HEADER**", lines[0]);
@@ -265,7 +271,8 @@ public class COPSDecisionMsgTest {
     @Test
     public void testDumpDecisionsAll() throws Exception {
         final COPSDecisionMsg msg = new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
-                new COPSHandle(new COPSData()), staticDecisions, new COPSIntegrity());
+                new COPSHandle(new COPSData()), staticDecisions, new COPSIntegrity(),
+                new COPSClientSI(CSIType.NAMED, new COPSData()));
 
         final ByteArrayOutputStream os = new ByteArrayOutputStream();
         msg.dump(os);
@@ -273,7 +280,7 @@ public class COPSDecisionMsgTest {
         final String out = new String(os.toByteArray());
         System.out.println(out);
         final String[] lines = out.split("\n");
-        Assert.assertEquals(24, lines.length);
+        Assert.assertEquals(29, lines.length);
 
         // Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
         Assert.assertEquals("**MSG HEADER**", lines[0]);
@@ -292,7 +299,7 @@ public class COPSDecisionMsgTest {
     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);
+                null, null);
 
         msg.writeData(outSocket);
 
@@ -315,7 +322,7 @@ public class COPSDecisionMsgTest {
     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")));
+                new COPSIntegrity(2, 3, new COPSData("123456")), new COPSClientSI(CSIType.NAMED, new COPSData("123")));
 
         msg.writeData(outSocket);
 
@@ -349,7 +356,8 @@ public class COPSDecisionMsgTest {
         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")));
+                new COPSHandle(new COPSData("12345")), decisions, new COPSIntegrity(4, 5, new COPSData("123456")),
+                new COPSClientSI(CSIType.NAMED, new COPSData("123")));
 
         msg.writeData(outSocket);
 
index 4a80f87e36c8d43ab3139e8a0146938efe89d98b..79582127fd688a70e2b18bd463cc5c7bb64734cc 100644 (file)
@@ -31,11 +31,6 @@ public class COPSDecisionTest {
         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);
@@ -87,11 +82,6 @@ public class COPSDecisionTest {
         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;
@@ -116,7 +106,14 @@ public class COPSDecisionTest {
 
     @Test(expected = IllegalArgumentException.class)
     public void constructor6NullData() {
-        new COPSDecision(new COPSObjHeader(CNum.DEC, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+        new COPSDecision(new COPSObjHeader(CNum.CSI, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+    }
+
+    @Test
+    public void cNumDECAndNullData() {
+        final COPSDecision decision = new COPSDecision(CType.DEF, null);
+        Assert.assertNotNull(decision.getData());
+        Assert.assertEquals(0, decision.getData().getData().length);
     }
 
     @Test
index 3590702ca4ff95cfd99ad542e4ce490580923364..97b2673cbd6392fc2fa7dcb3b674e4058651dcf8 100644 (file)
@@ -37,11 +37,6 @@ public class COPSLPDPDecisionTest {
         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;
@@ -64,9 +59,10 @@ public class COPSLPDPDecisionTest {
         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);
+        final COPSLPDPDecision decision = new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI),
+                Command.INSTALL, DecisionFlag.NA, null);
+        Assert.assertEquals(0, decision.getData().getData().length);
     }
 
     @Test
diff --git a/packetcable-policy-config/pom.xml b/packetcable-policy-config/pom.xml
new file mode 100644 (file)
index 0000000..38ee663
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <artifactId>packetcable</artifactId>
+    <groupId>org.opendaylight.packetcable</groupId>
+    <version>1.2.0-SNAPSHOT</version>
+  </parent>
+  <!--
+    Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+    maven repos etc.  If you run this archetype in a subdirectory of your project, it
+    will pick the pom.xml from the parent directory as the parent pom, which may or may
+    not be correct.
+  -->
+  <!-- 
+    Necessary TODO: Replace the contents of src/main/resources/80-packetcable.xml with
+    the proper config subsystem contents for your module
+  -->
+  <artifactId>packetcable-policy-config</artifactId>
+  <groupId>org.opendaylight.packetcable</groupId>
+  <description>Configuration files for md-sal</description>
+  <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+   <version>1.1.0-SNAPSHOT</version>
+   -->
+  <packaging>jar</packaging>
+  <properties>
+      <!-- Optional TODO: Rename your configfile to taste -->
+      <configfile>80-packetcable.xml</configfile>
+  </properties>
+  <build>
+    <plugins>
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${configfile}</file>
+                  <type>xml</type>
+                  <classifier>config</classifier>
+                </artifact>
+                <!--
+                  Optional TODO: Add additional config files
+                    You may need to add more than one config file
+                    if so, you just need to add additional <artifact> entries
+                    here WITH DIFFERENT CLASSIFIERS
+                    Example:
+                    <artifact>
+                      <file>${project.build.directory}/classes/<another-configfile></file>
+                      <type>xml</type>
+                      <classifier>config-<meaningful suffix to describe your other configfile></classifier>
+                    </artifact>
+                -->
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+      <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</developerConnection>
+      <tag>HEAD</tag>
+      <url>https://git.opendaylight.org/gerrit/gitweb?p=packetcable.git;a=summary</url>
+   </scm>
+</project>
diff --git a/packetcable-policy-config/src/main/resources/80-packetcable.xml b/packetcable-policy-config/src/main/resources/80-packetcable.xml
new file mode 100644 (file)
index 0000000..2057f96
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+    <required-capabilities>
+        <capability>urn:opendaylight:params:xml:ns:yang:packetcable:packetcable-policy-server:impl?module=packetcable-policy-server-impl&amp;revision=2014-01-31</capability>
+    </required-capabilities>
+    <configuration>
+
+        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:packetcable:packetcable-policy-server:impl">
+                        prefix:packetcable-policy-server-impl
+                    </type>
+                    <name>packetcable-policy-server-default-impl</name>
+                    <data-broker>
+                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+                       <name>binding-data-broker</name>
+                    </data-broker>
+                    <rpc-registry>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+                        <name>binding-rpc-broker</name>
+                    </rpc-registry> 
+                </module>
+            </modules>
+        </data>
+    </configuration>
+</snapshot>
diff --git a/packetcable-policy-karaf/pom.xml b/packetcable-policy-karaf/pom.xml
new file mode 100644 (file)
index 0000000..0cccab2
--- /dev/null
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>packetcable</artifactId>
+    <groupId>org.opendaylight.packetcable</groupId>
+    <version>1.2.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>packetcable-policy-karaf</artifactId>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <properties>
+    <!-- Optional TODO: Move these properties to your parent pom and possibly
+            DependencyManagement section of your parent pom -->
+    <branding.version>1.1.0-SNAPSHOT</branding.version>
+    <karaf.resources.version>1.5.0-SNAPSHOT</karaf.resources.version>
+  </properties>
+
+  <dependencies>
+    <!-- Basic Karaf dependencies -->
+    <dependency>
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>framework</artifactId>
+      <version>${karaf.version}</version>
+      <type>kar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>standard</artifactId>
+      <version>${karaf.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- ODL Branding -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>karaf.branding</artifactId>
+      <version>${branding.version}</version>
+      <scope>compile</scope>
+    </dependency>
+
+    <!-- ODL Resources needed for karaf -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-resources</artifactId>
+      <version>${karaf.resources.version}</version>
+    </dependency>
+
+    <!-- Project local feautures -->
+    <!--
+      Necessary TODO put your features here.
+
+      Note: they will need to be <type>xml</xml>
+      and <classifier>features</classifier>.
+
+      Note: they must be <scope>runtime</scope>
+
+      Note: usually you would only need to depend
+      on your own feature file here for your local distro,
+      and possible the features-mdsal for odl-restconf
+      (although, strange situations do exist :) )
+
+      Example:
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>features-mdsal</artifactId>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.openflowplugin</groupId>
+        <artifactId>features-openflowplugin</artifactId>
+        <version>0.1.0-SNAPSHOT</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+    -->
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>features-mdsal</artifactId>
+          <classifier>features</classifier>
+          <version>${project.version}</version>
+          <type>xml</type>
+          <scope>runtime</scope>
+      </dependency>
+<!--
+      <dependency>
+        <groupId>org.opendaylight.l2switch</groupId>
+        <artifactId>features-l2switch</artifactId>
+        <classifier>features</classifier>
+        <version>0.2.0-SNAPSHOT</version>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+-->
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>features-restconf</artifactId>
+          <classifier>features</classifier>
+          <version>1.2.0-SNAPSHOT</version>
+          <type>xml</type>
+          <scope>runtime</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.dlux</groupId>
+          <artifactId>features-dlux</artifactId>
+          <classifier>features</classifier>
+          <version>0.2.0-SNAPSHOT</version>
+          <type>xml</type>
+          <scope>runtime</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.packetcable</groupId>
+        <artifactId>features-packetcable-policy</artifactId>
+        <classifier>features</classifier>
+        <version>${project.version}</version>
+        <type>xml</type>
+        <scope>runtime</scope>
+      </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.eclipse.m2e</groupId>
+          <artifactId>lifecycle-mapping</artifactId>
+          <version>1.0.0</version>
+          <configuration>
+            <lifecycleMappingMetadata>
+              <pluginExecutions>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.felix</groupId>
+                    <artifactId>maven-bundle-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>cleanVersions</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>copy</goal>
+                      <goal>unpack</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.karaf.tooling</groupId>
+                    <artifactId>karaf-maven-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>commands-generate-help</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.fusesource.scalate</groupId>
+                    <artifactId>maven-scalate-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>sitegen</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.servicemix.tooling</groupId>
+                    <artifactId>depends-maven-plugin</artifactId>
+                    <versionRange>[0,)</versionRange>
+                    <goals>
+                      <goal>generate-depends-file</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore></ignore>
+                  </action>
+                </pluginExecution>
+              </pluginExecutions>
+            </lifecycleMappingMetadata>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.karaf.tooling</groupId>
+        <artifactId>karaf-maven-plugin</artifactId>
+        <version>${karaf.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <bootFeatures>
+            <feature>standard</feature>
+            <!-- Uncomment the following lines to ensure restconf & dlux are automatically installed -->
+            <!--<feature>odl-restconf</feature>-->
+            <!--<feature>odl-dlux-core</feature>-->
+            <feature>odl-mdsal-apidocs</feature>
+            <feature>odl-packetcable-policy-server-all</feature>
+            <!--
+              Optional TODO: Add entries here for the features you want in your local distro
+              Note: odl-restconf is a separate feature from odl-mdsal-broker.  If you want
+              restconf, you need to list it here explicitely.
+              Examples:
+              <feature>odl-openflowplugin-flow-services</feature>
+              <feature>odl-restconf</feature>
+            -->
+            <!-- Final TODO: Remove TODO Comments ;) -->
+          </bootFeatures>
+        </configuration>
+        <executions>
+          <execution>
+            <id>process-resources</id>
+            <goals>
+              <goal>install-kars</goal>
+            </goals>
+            <phase>process-resources</phase>
+          </execution>
+          <execution>
+            <id>package</id>
+            <goals>
+              <goal>instance-create-archive</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.6</version>
+        <executions>
+          <execution>
+            <id>copy</id>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <phase>generate-resources</phase>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.opendaylight.controller</groupId>
+                  <artifactId>karaf.branding</artifactId>
+                  <version>${karaf.branding.version}</version>
+                  <outputDirectory>target/assembly/lib</outputDirectory>
+                  <destFileName>karaf.branding-${branding.version}.jar</destFileName>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
+          <execution>
+            <id>unpack-karaf-resources</id>
+            <goals>
+              <goal>unpack-dependencies</goal>
+            </goals>
+            <phase>prepare-package</phase>
+            <configuration>
+             <outputDirectory>${project.build.directory}/assembly</outputDirectory>
+             <groupId>org.opendaylight.controller</groupId>
+             <includeArtifactIds>opendaylight-karaf-resources</includeArtifactIds>
+             <excludes>META-INF\/**</excludes>
+             <excludeTransitive>true</excludeTransitive>
+             <ignorePermissions>false</ignorePermissions>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+            <execution>
+                <phase>prepare-package</phase>
+                <goals>
+                    <goal>run</goal>
+                </goals>
+                <configuration>
+                  <tasks>
+                    <chmod perm="755">
+                        <fileset dir="${project.build.directory}/assembly/bin">
+                          <include name="karaf" />
+                          <include name="instance" />
+                          <include name="start" />
+                          <include name="stop" />
+                          <include name="status" />
+                          <include name="client" />
+                          <include name="shell" />
+                        </fileset>
+                    </chmod>
+                  </tasks>
+                </configuration>
+            </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://git.opendaylight.org/gerrit/gitweb?p=packetcable.git;a=summary</url>
+  </scm>
+</project>
diff --git a/packetcable-policy-model/pom.xml b/packetcable-policy-model/pom.xml
new file mode 100644 (file)
index 0000000..74efaa1
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.packetcable</groupId>
+        <artifactId>packetcable</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>packetcable-policy-model</artifactId>
+    <packaging>bundle</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-yang-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>maven-sal-api-gen-plugin</artifactId>
+                        <version>${yangtools.version}</version>
+                        <type>jar</type>
+                    </dependency>
+                </dependencies>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                    <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <tag>HEAD</tag>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+</project>
diff --git a/packetcable-policy-model/src/main/yang/packetcable.yang b/packetcable-policy-model/src/main/yang/packetcable.yang
new file mode 100644 (file)
index 0000000..c919acd
--- /dev/null
@@ -0,0 +1,309 @@
+module packetcable
+{
+    namespace "urn:packetcable";
+    prefix "pcmm";
+
+    import ietf-yang-types     { prefix yang; }
+    import ietf-inet-types     { prefix inet; }
+
+    description "This module contains the PCMM Converged Cable Access Platform (CCAP) definitions";
+    organization "OpenDaylight Project";
+
+    revision 2015-03-27 {
+        description "Initial revision of PCMM CCAP definitions";
+    }
+
+
+       // Global typedefs
+       typedef service-class-name {
+        type string { length "2..16"; }
+        description "The Service Class Name is MUST be 2-16 bytes.";
+    }
+    typedef service-flow-direction {
+           type enumeration {
+                     enum us {
+                       value "1";
+                       description "Upstream service flow.";
+                     }
+                     enum ds {
+                       value "2";
+                       description "Downstream service flow.";
+                     }
+               }
+       description "This value represents the service flow direction.";
+       }
+       typedef tp-protocol {
+               type uint16 {range "0..257";}
+           description "This value represents the IP transport protocol (or Next Header) where 256 is any protocol and 257 is TCP or UDP";
+        }
+        typedef tos-byte {
+               type uint8;
+               description "TOS/TC byte or mask";
+        }
+
+
+       // CCAP devices
+       container ccap {
+               list ccaps {
+                       description "
+                               CCAP devices are known by their network name which is any string.
+                               Each CCAP device has a network address:port, a list of subscriber IP subnets,
+                               and a list of available Service Class Names.
+                               ";
+                   key "ccapId";
+                       leaf ccapId {
+                           type string;
+                               description "CCAP Identity";
+                           }
+                   uses ccap-attributes;
+           }
+    }
+
+       grouping ccap-attributes {
+               description "
+                       Each CCAP device has a COPS connection address:port,
+                       a list of subscriber IP subnets, and
+                       a list of available Service Class Names.
+                       ";
+               container connection {
+                       leaf ipAddress {
+                       type inet:ip-address;
+                       description "IP Address of CCAP";
+               }
+               leaf port {
+                       type inet:port-number;
+                       description "COPS session TCP port number";
+                       default 3918;
+               }
+        }
+        container amId {
+               leaf am-tag {
+                       type uint16;
+                       description "Application Manager Tag -- unique for this operator";
+               }
+               leaf am-type {
+                       type uint16;
+                       description "Application Manager Type -- unique for this AM tag";
+               }
+        }
+               leaf-list subscriber-subnets {
+                       type inet:ip-prefix;
+               }
+               leaf-list upstream-scns {
+                       type service-class-name;
+               }
+               leaf-list downstream-scns {
+                       type service-class-name;
+               }
+        leaf response {
+            type string;
+            description "HTTP response from the PUT operation provided by the API";
+        }
+       }
+
+       // PCMM QoS Gates
+    container qos {
+       description "
+               PCMM QoS Gates are organized as a tree by Application/Subscriber/Gate:
+                       Each Application is known by its appId which is any string.
+                       Each Subscriber is known by its subId which is a CPE IP address in either IPv4 or IPv6 format.
+                       Each Gate is known by its gateId which is any string.
+
+               The subscriber's CPE IP address is used to locate the CCAP device that is currently hosting the
+               the Cable Modem that is connected to the subscriber's device. Therefore, it is not necessary
+               for the PCMM applications to know the topology of the CCAP devices and CMs in the network path
+               to their subscriber devices.
+
+               Note that each CCAP entry contains a list of connected subscriber IP subnets as well as a list
+               of all Service Class Names (SCNs) available on the CCAP device.
+               ";
+               uses pcmm-qos-gates;
+    }
+
+    grouping pcmm-qos-gates {
+        list apps {
+            key "appId";
+                   leaf appId {
+                       type string;
+                       description "Application Identity";
+                   }
+            list subs {
+                key "subId";
+                           leaf subId {
+                           type string;
+                               description "Subscriber Identity -- must be a CM or CPE IP address";
+                           }
+                   list gates {
+                       key "gateId";
+                                   leaf gateId {
+                                       type string;
+                                       description "Qos Gate Identity";
+                                   }
+                                   uses pcmm-qos-gate-attributes;
+                   }
+            }
+       }
+    }
+
+    grouping pcmm-qos-gate-attributes {
+       uses pcmm-qos-gate-spec;
+       uses pcmm-qos-traffic-profile;
+               uses pcmm-qos-classifier;
+               uses pcmm-qos-ext-classifier;
+               uses pcmm-qos-ipv6-classifier;
+               leaf response {
+            type string;
+            description "HTTP response from the PUT operation provided by the API";
+        }
+    }
+
+    grouping pcmm-qos-gate-spec {
+       container gate-spec {
+                       leaf direction {
+                               type service-flow-direction;
+                               description "Gate Direction (ignored for traffic profile SCN)";
+                       }
+                       leaf dscp-tos-overwrite {
+                               type tos-byte;
+                               description "Optional DSCP/TOS overwrite value";
+                       }
+                       leaf dscp-tos-mask {
+                               type tos-byte;
+                               description "Optional DSCP/TOS overwrite AND mask";
+                       }
+               }
+    }
+
+    grouping pcmm-qos-traffic-profile {
+       container traffic-profile {
+                   leaf service-class-name {
+                       type service-class-name;
+                       description "The Service Class Name (SCN). This SCN must be pre-provisioned on the target CCAP";
+                   }
+               }
+    }
+
+    grouping tp-port-match-ranges {
+        leaf srcPort-start {
+            type inet:port-number;
+            description "TCP/UDP source port range start.";
+        }
+        leaf srcPort-end {
+            type inet:port-number;
+            description "TCP/UDP source port range end.";
+        }
+        leaf dstPort-start {
+            type inet:port-number;
+            description "TCP/UDP destination port range start.";
+        }
+        leaf dstPort-end {
+            type inet:port-number;
+            description "TCP/UDP destination port range end.";
+        }
+    }
+
+    grouping pcmm-qos-classifier {
+       container classifier {
+               leaf srcIp {
+                       type inet:ipv4-address;
+                       description "Source IPv4 address (exact match)";
+                       }
+               leaf dstIp {
+                       type inet:ipv4-address;
+                       description "Destination IPv4 address (exact match)";
+                       }
+                       leaf tos-byte {
+                               type tos-byte;
+                               description "TOS/DSCP match";
+                       }
+                       leaf tos-mask {
+                               type tos-byte;
+                               description "TOS/DSCP mask";
+                       }
+               leaf protocol {
+                       type tp-protocol;
+                       description "IPv4 transport protocol";
+                       }
+                       leaf srcPort {
+                       type inet:port-number;
+                       description "TCP/UDP source port (exact match).";
+                       }
+                       leaf dstPort {
+                       type inet:port-number;
+                       description "TCP/UDP destination port (exact match).";
+                       }
+               }
+    }
+
+    grouping pcmm-qos-ext-classifier {
+       container ext-classifier {
+               leaf srcIp {
+                       type inet:ipv4-address;
+                       description "Source IPv4 address match";
+                       }
+               leaf srcIpMask {
+                       type inet:ipv4-address;
+                       description "Source IPv4 mask";
+                       }
+               leaf dstIp {
+                       type inet:ipv4-address;
+                       description "Destination IPv4 address match";
+                       }
+               leaf dstIpMask {
+                       type inet:ipv4-address;
+                       description "Destination IPv4 mask";
+                       }
+                       leaf tos-byte {
+                               type tos-byte;
+                               description "TOS/DSCP match";
+                       }
+                       leaf tos-mask {
+                               type tos-byte;
+                               description "TOS/DSCP mask";
+                       }
+               leaf protocol {
+                       type tp-protocol;
+                       description "IPv4 transport protocol";
+                       }
+                       uses tp-port-match-ranges;
+               }
+    }
+
+    grouping pcmm-qos-ipv6-classifier {
+       container ipv6-classifier {
+               leaf srcIp6 {
+                       type inet:ipv6-prefix;
+                       description "Source IPv6 prefix match in  <address/len> notation";
+                       }
+               leaf dstIp6 {
+                       type inet:ipv6-prefix;
+                       description "Destination IPv6 prefix match in <address/len> notation";
+                       }
+                       leaf tc-low {
+                               type tos-byte;
+                               description "TC low range match";
+                       }
+                       leaf tc-high {
+                               type tos-byte;
+                               description "TC high range match";
+                       }
+                       leaf tc-mask {
+                               type tos-byte;
+                               description "TC mask";
+                       }
+               leaf next-hdr {
+                       type tp-protocol;
+                       description "IPv6 Next Header";
+                       }
+                       leaf flow-label {
+                               type uint32 {
+                                       range "0 .. 1048575";
+                               }
+                               description "IPv6 Flow Label (20 bits)";
+                       }
+                       uses tp-port-match-ranges;
+               }
+    }
+
+}
+
diff --git a/packetcable-policy-server/pom.xml b/packetcable-policy-server/pom.xml
new file mode 100644 (file)
index 0000000..2af7323
--- /dev/null
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.packetcable</groupId>
+        <artifactId>packetcable</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>packetcable-policy-server</artifactId>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <sal-binding-api.version>1.2.0-SNAPSHOT</sal-binding-api.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>packetcable-driver</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>packetcable-policy-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-yang-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>2.0.2-beta</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>org.opendaylight.controller.config.yang.toaster_provider,</Export-Package>
+                        <Import-Package>*</Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>config</id>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                                    <additionalConfiguration>
+                                        <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                                    </additionalConfiguration>
+                                </generator>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                    <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <tag>HEAD</tag>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+</project>
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java
new file mode 100644 (file)
index 0000000..5257632
--- /dev/null
@@ -0,0 +1,337 @@
+/**
+ * Build PCMM gate requests from API QoS Gate objects
+ */
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.pcmm.gates.*;
+import org.pcmm.gates.IGateSpec.DSCPTOS;
+import org.pcmm.gates.IGateSpec.Direction;
+import org.pcmm.gates.impl.DOCSISServiceClassNameTrafficProfile;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.pcmm.gates.impl.SubscriberID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ *
+ * PacketCable data processor
+ *
+ */
+public class PCMMGateReqBuilder {
+
+       private Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class);
+
+       private PCMMGateReq gateReq = null;
+
+       public PCMMGateReqBuilder() {
+               gateReq = new org.pcmm.gates.impl.PCMMGateReq();
+       }
+
+       public PCMMGateReq getGateReq() {
+               return gateReq;
+       }
+
+       public void build(AmId qosAmId){
+               IAMID amId = new org.pcmm.gates.impl.AMID();
+               amId.setApplicationMgrTag(qosAmId.getAmTag().shortValue());
+               amId.setApplicationType(qosAmId.getAmType().shortValue());
+        gateReq.setAMID(amId);
+       }
+
+       public void build(InetAddress qosSubId){
+               ISubscriberID subId = new SubscriberID();
+               subId.setSourceIPAddress(qosSubId);
+               gateReq.setSubscriberID(subId);
+       }
+
+       public void build(GateSpec qosGateSpec, ServiceFlowDirection scnDirection) {
+               IGateSpec gateSpec = new org.pcmm.gates.impl.GateSpec();
+               // service flow direction
+               ServiceFlowDirection qosDir = null;
+               Direction gateDir = null;
+               if (scnDirection != null) {
+                       qosDir = scnDirection;
+               } else if (qosGateSpec.getDirection() != null) {
+                       qosDir = qosGateSpec.getDirection();
+               }
+               if (qosDir == ServiceFlowDirection.Ds) {
+                       gateDir = Direction.DOWNSTREAM;
+               } else if (qosDir == ServiceFlowDirection.Us) {
+                       gateDir = Direction.UPSTREAM;
+               }
+               gateSpec.setDirection(gateDir);
+               // DSCP/TOS Overwrite
+               TosByte tosOverwrite = qosGateSpec.getDscpTosOverwrite();
+               if (tosOverwrite != null) {
+                       byte gateTos = tosOverwrite.getValue().byteValue();
+                       gateSpec.setDSCP_TOSOverwrite(DSCPTOS.ENABLE);
+                       gateSpec.setDSCP_TOSOverwrite(gateTos);
+                       TosByte tosMask = qosGateSpec.getDscpTosMask();
+                       if (tosMask != null) {
+                               byte gateTosMask = tosMask.getValue().byteValue();
+                               gateSpec.setDSCP_TOSMask(gateTosMask);
+                       } else {
+                               gateSpec.setDSCP_TOSMask((byte)0xff);
+                       }
+               }
+               gateReq.setGateSpec(gateSpec);
+       }
+
+       public void build(TrafficProfile qosTrafficProfile) {
+               if (qosTrafficProfile.getServiceClassName() != null) {
+                       String scn = qosTrafficProfile.getServiceClassName().getValue();
+                       DOCSISServiceClassNameTrafficProfile trafficProfile = new DOCSISServiceClassNameTrafficProfile();
+                       if (scn.length() <= 16) { // NB.16 char SCN is max length per PCMM spec
+                               trafficProfile.setServiceClassName(scn);
+                               gateReq.setTrafficProfile(trafficProfile);
+                       }
+               }
+       }
+
+       private InetAddress getByName(String ipAddressStr){
+               InetAddress ipAddress = null;
+               try {
+                       ipAddress = InetAddress.getByName(ipAddressStr);
+               } catch (UnknownHostException e) {
+                       logger.error(e.getMessage());
+               }
+               return ipAddress;
+       }
+
+       public void build(Classifier qosClassifier) {
+               // Legacy classifier
+               IClassifier classifier = new org.pcmm.gates.impl.Classifier();
+               classifier.setPriority((byte) 64);
+               if (qosClassifier.getProtocol() != null){
+                       classifier.setProtocol(qosClassifier.getProtocol().getValue().shortValue());
+               }
+               if (qosClassifier.getSrcIp() != null) {
+                       InetAddress sip = getByName(qosClassifier.getSrcIp().getValue());
+                       if (sip != null) {
+                               classifier.setSourceIPAddress(sip);
+                       }
+               }
+               if (qosClassifier.getDstIp() != null) {
+                       InetAddress dip = getByName(qosClassifier.getDstIp().getValue());
+                       if (dip != null) {
+                               classifier.setDestinationIPAddress(dip);
+                       }
+               }
+               if (qosClassifier.getSrcPort() != null) {
+                       classifier.setSourcePort(qosClassifier.getSrcPort().getValue().shortValue());
+               }
+               if (qosClassifier.getDstPort() != null) {
+                       classifier.setDestinationPort(qosClassifier.getDstPort().getValue().shortValue());
+               }
+               if (qosClassifier.getTosByte() != null) {
+                       classifier.setDSCPTOS(qosClassifier.getTosByte().getValue().byteValue());
+                       if (qosClassifier.getTosMask() != null) {
+                               classifier.setDSCPTOSMask(qosClassifier.getTosMask().getValue().byteValue());
+                       } else {
+                               // set default TOS mask
+                               classifier.setDSCPTOSMask((byte)0xff);
+                       }
+               }
+               // push the classifier to the gate request
+               gateReq.setClassifier(classifier);
+       }
+
+       public void build(ExtClassifier qosExtClassifier) {
+               // Extended classifier
+               IExtendedClassifier extClassifier = new org.pcmm.gates.impl.ExtendedClassifier();
+               extClassifier.setPriority((byte) 64);
+               extClassifier.setActivationState((byte) 0x01);
+               // Protocol -- zero is match any
+               if (qosExtClassifier.getProtocol() != null){
+                       extClassifier.setProtocol(qosExtClassifier.getProtocol().getValue().shortValue());
+               } else {
+                       extClassifier.setProtocol((short)0);
+               }
+               // Source IP address & mask
+               if (qosExtClassifier.getSrcIp() != null) {
+                       InetAddress sip = getByName(qosExtClassifier.getSrcIp().getValue());
+                       if (sip != null) {
+                               extClassifier.setSourceIPAddress(sip);
+                               if (qosExtClassifier.getSrcIpMask() != null) {
+                                       InetAddress sipMask = getByName(qosExtClassifier.getSrcIpMask().getValue());
+                                       extClassifier.setIPSourceMask(sipMask);
+                               } else {
+                                       // default mask is /32
+                                       extClassifier.setIPSourceMask(getByName("255.255.255.255"));
+                               }
+                       }
+               }
+               // Destination IP address & mask
+               if (qosExtClassifier.getDstIp() != null) {
+                       InetAddress dip = getByName(qosExtClassifier.getDstIp().getValue());
+                       if (dip != null) {
+                               extClassifier.setDestinationIPAddress(dip);
+                               if (qosExtClassifier.getDstIpMask() != null) {
+                                       InetAddress dipMask = getByName(qosExtClassifier.getDstIpMask().getValue());
+                                       extClassifier.setIPDestinationMask(dipMask);
+                               } else {
+                                       // default mask is /32
+                                       extClassifier.setIPDestinationMask(getByName("255.255.255.255"));
+                               }
+                       }
+               }
+               // default source port range must be set to match any even if qosExtClassifier has no range
+               // match any port range is 0-65535, NOT 0-0
+               short startPort = (short)0;
+               short endPort = (short)65535;
+               if (qosExtClassifier.getSrcPortStart() != null) {
+                       startPort = qosExtClassifier.getSrcPortStart().getValue().shortValue();
+                       endPort = startPort;
+                       if (qosExtClassifier.getSrcPortEnd() != null) {
+                               endPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue();
+                       }
+                       if (startPort > endPort) {
+                               logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same", startPort, endPort);
+                               endPort = startPort;
+                       }
+               }
+               extClassifier.setSourcePortStart(startPort);
+               extClassifier.setSourcePortEnd(endPort);
+               // default destination port range must be set to match any even if qosExtClassifier has no range
+               // match any port range is 0-65535, NOT 0-0
+               startPort = (short)0;
+               endPort = (short)65535;
+               if (qosExtClassifier.getDstPortStart() != null) {
+                       startPort = qosExtClassifier.getDstPortStart().getValue().shortValue();
+                       endPort = startPort;
+                       if (qosExtClassifier.getDstPortEnd() != null) {
+                               endPort = qosExtClassifier.getDstPortEnd().getValue().shortValue();
+                       }
+                       if (startPort > endPort) {
+                               logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same", startPort, endPort);
+                               endPort = startPort;
+                       }
+               }
+               extClassifier.setDestinationPortStart(startPort);
+               extClassifier.setDestinationPortEnd(endPort);
+               // DSCP/TOP byte
+               if (qosExtClassifier.getTosByte() != null) {
+                       // OR in the DSCP/TOS enable bit 0x01
+                       extClassifier.setDSCPTOS((byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01));
+                       if (qosExtClassifier.getTosMask() != null) {
+                               extClassifier.setDSCPTOSMask(qosExtClassifier.getTosMask().getValue().byteValue());
+                       } else {
+                               // set default TOS mask
+                               extClassifier.setDSCPTOSMask((byte)0xff);
+                       }
+               }
+               // push the extended classifier to the gate request
+               gateReq.setClassifier(extClassifier);
+       }
+
+       public void build(Ipv6Classifier qosIpv6Classifier) {
+               // IPv6 classifier
+               IIPv6Classifier ipv6Classifier = new org.pcmm.gates.impl.IPv6Classifier();
+               ipv6Classifier.setPriority((byte) 64);
+               ipv6Classifier.setActivationState((byte) 0x01);
+               // Flow Label
+               if (qosIpv6Classifier.getFlowLabel() != null){
+                       ipv6Classifier.setFlowLabel(qosIpv6Classifier.getFlowLabel());
+                       ipv6Classifier.setFlowLabelEnableFlag((byte)0x01);
+               }
+               // Next Header
+               if (qosIpv6Classifier.getNextHdr() != null){
+                       ipv6Classifier.setNextHdr(qosIpv6Classifier.getNextHdr().getValue().shortValue());
+               } else {
+                       // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option
+                       ipv6Classifier.setNextHdr((short)256);
+               }
+               // Source IPv6 address & prefix len
+               byte prefLen;
+               if (qosIpv6Classifier.getSrcIp6() != null) {
+                       String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/");
+                       String Ipv6AddressStr = parts[0];
+                       InetAddress sip6 = getByName(Ipv6AddressStr);
+                       if (sip6 != null) {
+                               ipv6Classifier.setSourceIPAddress(sip6);
+                       }
+                       prefLen = (byte)128;
+                       if (parts.length > 1) {
+                               prefLen = (byte)Integer.parseInt(parts[1]);
+                       }
+                       ipv6Classifier.setSourcePrefixLen(prefLen);
+               }
+               // Destination IPv6 address & prefix len
+               if (qosIpv6Classifier.getDstIp6() != null) {
+                       String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/");
+                       String Ipv6AddressStr = parts[0];
+                       InetAddress dip6 = getByName(Ipv6AddressStr);
+                       if (dip6 != null) {
+                               ipv6Classifier.setDestinationIPAddress(dip6);
+                       }
+                       prefLen = (byte)128;
+                       if (parts.length > 1) {
+                               prefLen = (byte)Integer.parseInt(parts[1]);
+                       }
+                       ipv6Classifier.setDestinationPrefixLen(prefLen);
+               }
+               // default source port range must be set to match any -- even if qosExtClassifier has no range value
+               // match any port range is 0-65535, NOT 0-0
+               short startPort = (short)0;
+               short endPort = (short)65535;
+               if (qosIpv6Classifier.getSrcPortStart() != null) {
+                       startPort = qosIpv6Classifier.getSrcPortStart().getValue().shortValue();
+                       endPort = startPort;
+                       if (qosIpv6Classifier.getSrcPortEnd() != null) {
+                               endPort = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue();
+                       }
+                       if (startPort > endPort) {
+                               logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same", startPort, endPort);
+                               endPort = startPort;
+                       }
+               }
+               ipv6Classifier.setSourcePortStart(startPort);
+               ipv6Classifier.setSourcePortEnd(endPort);
+               // default destination port range must be set to match any -- even if qosExtClassifier has no range value
+               // match any port range is 0-65535, NOT 0-0
+               startPort = (short)0;
+               endPort = (short)65535;
+               if (qosIpv6Classifier.getDstPortStart() != null) {
+                       startPort = qosIpv6Classifier.getDstPortStart().getValue().shortValue();
+                       endPort = startPort;
+                       if (qosIpv6Classifier.getDstPortEnd() != null) {
+                               endPort = qosIpv6Classifier.getDstPortEnd().getValue().shortValue();
+                       }
+                       if (startPort > endPort) {
+                               logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same", startPort, endPort);
+                               endPort = startPort;
+                       }
+               }
+               ipv6Classifier.setDestinationPortStart(startPort);
+               ipv6Classifier.setDestinationPortEnd(endPort);
+               // TC low, high, mask
+               if (qosIpv6Classifier.getTcLow() != null) {
+                       ipv6Classifier.setTcLow(qosIpv6Classifier.getTcLow().getValue().byteValue());
+                       if (qosIpv6Classifier.getTcHigh() != null) {
+                               ipv6Classifier.setTcHigh(qosIpv6Classifier.getTcHigh().getValue().byteValue());
+                       }
+                       if (qosIpv6Classifier.getTcMask() != null) {
+                               ipv6Classifier.setTcMask(qosIpv6Classifier.getTcMask().getValue().byteValue());
+                       } else {
+                               // set default TOS mask
+                               ipv6Classifier.setTcMask((byte)0xff);
+                       }
+               } else {
+                       // mask 0x00 is match any
+                       ipv6Classifier.setTcMask((byte)0x00);
+               }
+               // push the IPv6 classifier to the gate request
+               gateReq.setClassifier(ipv6Classifier);
+       }
+}
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMService.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMService.java
new file mode 100644 (file)
index 0000000..97567d4
--- /dev/null
@@ -0,0 +1,273 @@
+package org.opendaylight.controller.packetcable.provider;
+
+import com.google.common.collect.Maps;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
+import org.pcmm.PCMMPdpAgent;
+import org.pcmm.PCMMPdpDataProcess;
+import org.pcmm.PCMMPdpMsgSender;
+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.COPSError;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSException;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Map;
+
+/**
+ * Class responsible for managing the gates for a single CCAP.
+ */
+@ThreadSafe
+public class PCMMService {
+       private Logger logger = LoggerFactory.getLogger(PCMMService.class);
+
+       private final Ccaps ccap;
+       private final IpAddress ipAddr;
+       private final PortNumber portNum;
+       protected final CcapClient ccapClient;
+       protected Map<String, PCMMGateReq> gateRequests = Maps.newConcurrentMap();
+
+       private final short clientType;
+
+       public PCMMService(final short clientType, final Ccaps ccap) {
+               this.clientType = clientType;
+               this.ccap = ccap;
+               ipAddr = ccap.getConnection().getIpAddress();
+               portNum = ccap.getConnection().getPort();
+               ccapClient = new CcapClient(ipAddr, portNum);
+               logger.info("Attempting to add CCAP with ID {} @ {}:{}", ccap.getCcapId(), ipAddr.getIpv4Address().getValue(), portNum.getValue());
+       }
+
+       public void disconect() {
+               ccapClient.disconnect();
+       }
+
+       // TODO - try and change the return to something other than a String to be parsed to determine success
+       public String addCcap() {
+               ccapClient.connect();
+               if (ccapClient.isConnected) {
+                       logger.info("Connected to CCAP with ID - " + ccap.getCcapId());
+                       return String.format("200 OK - CCAP %s connected @ %s:%d", ccap.getCcapId(),
+                                       ipAddr.getIpv4Address().getValue(), portNum.getValue());
+               } else {
+                       return String.format("404 Not Found - CCAP %s failed to connect @ %s:%d - %s",
+                                       ccap.getCcapId(),
+                                       ipAddr.getIpv4Address().getValue(), portNum.getValue(), ccapClient.errMessage);
+               }
+       }
+
+       // TODO - Consider creating an object to return that contains a success flag, message, and gate ID or gate object
+       // TODO FIXME - the gate appears to be getting set as per restconf but I am not seeing the proper logging occurring
+       public String sendGateSet(final String gatePathStr, final InetAddress subId, final Gates qosGate,
+                                                         final ServiceFlowDirection scnDir) {
+               logger.info("Sending gate to CCAP with ID - " + ccap.getCcapId());
+               // assemble the gate request for this subId
+               final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
+               gateBuilder.build(ccap.getAmId());
+               gateBuilder.build(subId);
+               // force gateSpec.Direction to align with SCN direction
+               final ServiceClassName scn = qosGate.getTrafficProfile().getServiceClassName();
+               if (scn != null) {
+                       gateBuilder.build(qosGate.getGateSpec(), scnDir);
+               } else {
+                       // not an SCN gate
+                       gateBuilder.build(qosGate.getGateSpec(), null);
+               }
+               gateBuilder.build(qosGate.getTrafficProfile());
+
+               // pick a classifier type (only one for now)
+               if (qosGate.getClassifier() != null) {
+                       gateBuilder.build(qosGate.getClassifier());
+               } else if (qosGate.getExtClassifier() != null) {
+                       gateBuilder.build(qosGate.getExtClassifier());
+               } else if (qosGate.getIpv6Classifier() != null) {
+                       gateBuilder.build(qosGate.getIpv6Classifier());
+               }
+               // assemble the final gate request
+               final PCMMGateReq gateReq = gateBuilder.getGateReq();
+
+               // and remember it
+               gateRequests.put(gatePathStr, gateReq);
+               // and send it to the CCAP
+               ccapClient.sendGateSet(gateReq);
+               // and wait for the COPS response to complete processing gate request
+               try {
+                       // TODO - see PCMMPdpReqStateMan#processReport() gate.notify(). Should determine a better means to
+                       // TODO - handle this synchronization.
+                       // TODO - if not changing this, may want to make this timeout configurable
+                       synchronized(gateReq) {
+                               logger.info("Waiting 1000ms for gate request to be updated");
+                               gateReq.wait(1000);
+                               logger.debug("Gate request error - " + gateReq.getError());
+                               logger.debug("Gate request ID - " + gateReq.getGateID());
+                       }
+               } catch (Exception e) {
+                       logger.error("PCMMService: sendGateSet(): gate response timeout exceeded for "
+                                       + gatePathStr + '/' + gateReq, e);
+                       return String.format("408 Request Timeout - gate response timeout exceeded for %s/%s",
+                                       ccap.getCcapId(), gatePathStr);
+               }
+               if (gateReq.getError() != null) {
+                       logger.error("PCMMService: sendGateSet(): returned error: {}",
+                                       gateReq.getError().toString());
+                       return String.format("404 Not Found - sendGateSet for %s/%s returned error - %s",
+                                       ccap.getCcapId(), gatePathStr, gateReq.getError().toString());
+               } else {
+                       if (gateReq.getGateID() != null) {
+                               logger.info(String.format("PCMMService: sendGateSet(): returned GateId %08x: ",
+                                               gateReq.getGateID().getGateID()));
+                               return String.format("200 OK - sendGateSet for %s/%s returned GateId %08x",
+                                               ccap.getCcapId(), gatePathStr, gateReq.getGateID().getGateID());
+                       } else {
+                               logger.info("PCMMService: sendGateSet(): no gateId returned:");
+                               return String.format("404 Not Found - sendGateSet for %s/%s no gateId returned",
+                                               ccap.getCcapId(), gatePathStr);
+                       }
+               }
+       }
+
+       public Boolean sendGateDelete(final String gatePathStr) {
+               logger.info("sendGateDelete() - " + ccap);
+               // recover the original gate request
+               final PCMMGateReq gateReq = gateRequests.remove(gatePathStr);
+               if (gateReq != null) {
+                       ccapClient.sendGateDelete(gateReq);
+                       // and wait for the response to complete
+                       try {
+                               // TODO - see PCMMPdpReqStateMan#processReport() gate.notify(). Should determine a better means to
+                               // TODO - handle this synchronization.
+                               synchronized(gateReq) {
+                                       gateReq.wait(1000);
+                               }
+                       } catch (InterruptedException e) {
+                               logger.error("PCMMService: sendGateDelete(): gate response timeout exceeded for {}/{}",
+                                               gatePathStr, gateReq);
+                       }
+                       if (gateReq.getError() != null) {
+                               logger.warn("PCMMService: sendGateDelete(): returned error: {}", gateReq.getError().toString());
+                               return false;
+                       } else {
+                               if (gateReq.getGateID() != null) {
+                                       logger.info(String.format("PCMMService: sendGateDelete(): deleted GateId %08x: ", gateReq.getGateID().getGateID()));
+                               } else {
+                                       logger.error("PCMMService: sendGateDelete(): deleted but no gateId returned");
+                               }
+                               return true;
+                       }
+               } else {
+                       return false;
+               }
+       }
+
+       private String getIpAddressStr(final IpAddress ipAddress) {
+               final Ipv4Address ipv4 = ipAddress.getIpv4Address();
+               if (ipv4 != null) {
+                       return ipv4.getValue();
+               } else {
+                       return ipAddress.getIpv6Address().getValue();
+               }
+       }
+
+       /**
+        * Used to interface with a CCAP (including CMTSs)
+        */
+       protected class CcapClient {
+               public final PCMMPdpDataProcess pcmmProcess;
+               public final PCMMPdpAgent pcmmPdp;
+
+               private final String ipv4;
+               private final Integer port;
+
+               // Needs to be initialized in connect() method else would be final
+               protected transient PCMMPdpMsgSender pcmmSender;
+
+               private transient Boolean isConnected = false;
+               private transient String errMessage = null;
+
+               /**
+                * Constructor
+                * @param ccapIp - the IP of the CCAP to manage
+                * @param portNum - the port number of the CCAP to manage
+                */
+               public CcapClient(final IpAddress ccapIp, final PortNumber portNum) {
+                       ipv4 = ccapIp.getIpv4Address().getValue();
+                       if (portNum != null)  port = portNum.getValue();
+                       else port = PCMMPdpAgent.WELL_KNOWN_PDP_PORT;
+                       // TODO FIXME - if this object is not null, gate processing will not work correctly
+                       // TODO see - PCMMPdpReqStateMan#processReport() where the report type is success and the process is null
+                       //            pcmmProcess = new PCMMPdpDataProcess();
+                       pcmmProcess = null;
+                       pcmmPdp = new PCMMPdpAgent(clientType, ipv4, port, pcmmProcess);
+               }
+
+               /**
+                * Starts the connection to the CCAP
+                */
+               public void connect( ) {
+                       logger.info("Attempting to connect to host: " + ipv4 + " port: " + port);
+                       try  {
+                               pcmmPdp.connect();
+
+                               // Cannot instantiate until after pcmmPdp.connect() is called as this is where the client handle is created
+                               pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
+
+                               isConnected = true;
+                       } catch (Exception e) {
+                               isConnected = false;
+                               logger.error("Failed to connect to host: " + ipv4 + " port: " + port, e);
+                               errMessage = e.getMessage();
+                       }
+               }
+
+               public void disconnect() {
+                       logger.info("CcapClient: disconnect(): {}:{}", ipv4, port);
+                       try {
+                               pcmmPdp.disconnect(pcmmPdp.getPepIdString(), new COPSError(ErrorTypes.SHUTTING_DOWN, ErrorTypes.NA));
+                               isConnected = false;
+                       } catch (COPSException | IOException e) {
+                               logger.error("CcapClient: disconnect(): {}:{} FAILED: {}", ipv4, port, e.getMessage());
+                       }
+               }
+
+               // TODO - consider returning a new PCMMGateReq object or a future here instead of setting the ID on the old
+               // TODO - request by reference which makes the code more convoluted thus making issues more difficult to track down.
+               public Boolean sendGateSet(final PCMMGateReq gateReq) {
+                       logger.info("CcapClient: sendGateSet(): {}:{} => {}", ipv4, port, gateReq);
+                       try {
+                               pcmmSender.sendGateSet(gateReq);
+
+                               // TODO - determine if this is the correct place to perform this operation as this currently is the
+                               // TODO - place where the gate ID can be set on the gateReq object
+                               //                pcmmSender.handleGateReport(pcmmPdp.getSocket());
+                       } catch (COPSPdpException e) {
+                               logger.error("CcapClient: sendGateSet(): {}:{} => {} FAILED:", ipv4, port, gateReq, e);
+                       }
+                       // and save it back to the gateRequest object for gate delete later
+                       gateReq.setGateID(pcmmSender.getGateID());
+
+                       // TODO - determine why this method is always returning true???
+                       return true;
+               }
+
+               public Boolean sendGateDelete(final PCMMGateReq gateReq) {
+                       logger.info("CcapClient: sendGateDelete(): {}:{} => {}", ipv4, port, gateReq);
+                       try {
+                               pcmmSender.sendGateDelete(gateReq);
+                       } catch (COPSPdpException e) {
+                               logger.error("CcapClient: sendGateDelete(): {}:{} => {} FAILED: {}", ipv4, port, gateReq, e.getMessage());
+                       }
+                       return true;
+               }
+       }
+}
+
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java
new file mode 100644 (file)
index 0000000..2350e75
--- /dev/null
@@ -0,0 +1,495 @@
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.Ccap;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.Qos;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.Apps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.AppsKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.Subs;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.SubsKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.GatesKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.pcmm.rcd.IPCMMClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Called by ODL framework to start this bundle.
+ *
+ * This class is responsible for processing messages received from ODL's restconf interface.
+ * TODO - Remove some of these state maps and move some of this into the PCMMService
+ */
+@ThreadSafe
+public class PacketcableProvider implements DataChangeListener, AutoCloseable {
+
+    private static final Logger logger = LoggerFactory.getLogger(PacketcableProvider.class);
+
+    // keys to the /restconf/config/packetcable:ccap and /restconf/config/packetcable:qos config datastore
+    public static final InstanceIdentifier<Ccap> ccapIID = InstanceIdentifier.builder(Ccap.class).build();
+    public static final InstanceIdentifier<Qos> qosIID = InstanceIdentifier.builder(Qos.class).build();
+
+    /**
+     * The ODL object used to broker messages throughout the framework
+     */
+    private final DataBroker dataBroker;
+
+    /**
+     * The thread pool executor
+     */
+    private final ExecutorService executor;
+
+    // TODO - Revisit these maps and remove the ones no longer necessary
+    private final Map<String, Ccaps> ccapMap = new ConcurrentHashMap<>();
+    private final Map<String, Gates> gateMap = new ConcurrentHashMap<>();
+    private final Map<String, String> gateCcapMap = new ConcurrentHashMap<>();
+    private final Map<Subnet, Ccaps> subscriberSubnetsMap = new ConcurrentHashMap<>();
+    private final Map<ServiceClassName, List<Ccaps>> downstreamScnMap = new ConcurrentHashMap<>();
+    private final Map<ServiceClassName, List<Ccaps>> upstreamScnMap = new ConcurrentHashMap<>();
+
+    /**
+     * Holds a PCMMService object for each CCAP being managed.
+     */
+    private final Map<Ccaps, PCMMService> pcmmServiceMap = new ConcurrentHashMap<>();
+
+    /**
+     * Constructor
+     */
+    public PacketcableProvider(final DataBroker dataBroker) {
+        logger.info("Starting provider");
+        this.dataBroker = dataBroker;
+        executor = Executors.newCachedThreadPool();
+    }
+
+    /**
+     * Implemented from the AutoCloseable interface.
+     */
+    @Override
+    public void close() throws ExecutionException, InterruptedException {
+        executor.shutdown();
+        if (dataBroker != null) {
+            // remove our config datastore instances
+            final AsyncReadWriteTransaction<InstanceIdentifier<?>, ?> tx = dataBroker.newReadWriteTransaction();
+            tx.delete(LogicalDatastoreType.CONFIGURATION, ccapIID);
+            tx.delete(LogicalDatastoreType.CONFIGURATION, qosIID);
+            // TODO - commit() below has been deprecated
+            tx.commit().get();
+        }
+    }
+
+    public InetAddress getInetAddress(final String subId){
+        try {
+            return InetAddress.getByName(subId);
+        } catch (UnknownHostException e) {
+            logger.error("getInetAddress: {} FAILED: {}", subId, e.getMessage());
+            return null;
+        }
+    }
+
+    private String getIpPrefixStr(final IpPrefix ipPrefix) {
+        final Ipv4Prefix ipv4 = ipPrefix.getIpv4Prefix();
+        if (ipv4 != null) {
+            return ipv4.getValue();
+        } else {
+            return ipPrefix.getIpv6Prefix().getValue();
+        }
+    }
+
+    private void updateCcapMaps(final Ccaps ccap) {
+        // add ccap to the subscriberSubnets map
+        for (final IpPrefix ipPrefix : ccap.getSubscriberSubnets()) {
+            try {
+                subscriberSubnetsMap.put(Subnet.createInstance(getIpPrefixStr(ipPrefix)), ccap);
+            } catch (UnknownHostException e) {
+                logger.error("updateSubscriberSubnets: {}:{} FAILED: {}", ipPrefix, ccap, e.getMessage());
+            }
+        }
+        // ccap to upstream SCN map
+        for (final ServiceClassName scn : ccap.getUpstreamScns()) {
+            if (upstreamScnMap.containsKey(scn)) {
+                upstreamScnMap.get(scn).add(ccap);
+            } else {
+                final List<Ccaps> ccapList = new ArrayList<>();
+                ccapList.add(ccap);
+                upstreamScnMap.put(scn, ccapList);
+            }
+        }
+        // ccap to downstream SCN map
+        for (final ServiceClassName scn : ccap.getDownstreamScns()) {
+            if (downstreamScnMap.containsKey(scn)) {
+                downstreamScnMap.get(scn).add(ccap);
+            } else {
+                final List<Ccaps> ccapList = new ArrayList<>();
+                ccapList.add(ccap);
+                downstreamScnMap.put(scn, ccapList);
+            }
+        }
+    }
+
+    private void removeCcapFromAllMaps(final Ccaps ccap) {
+        // remove the ccap from all maps
+        // subscriberSubnets map
+        for (final Map.Entry<Subnet, Ccaps> entry : subscriberSubnetsMap.entrySet()) {
+            if (entry.getValue() == ccap) {
+                subscriberSubnetsMap.remove(entry.getKey());
+            }
+        }
+        // ccap to upstream SCN map
+        for (final Map.Entry<ServiceClassName, List<Ccaps>> entry : upstreamScnMap.entrySet()) {
+            final List<Ccaps> ccapList = entry.getValue();
+            ccapList.remove(ccap);
+            if (ccapList.isEmpty()) {
+                upstreamScnMap.remove(entry.getKey());
+            }
+        }
+        // ccap to downstream SCN map
+        for (final Map.Entry<ServiceClassName, List<Ccaps>> entry : downstreamScnMap.entrySet()) {
+            final List<Ccaps> ccapList = entry.getValue();
+            ccapList.remove(ccap);
+            if (ccapList.isEmpty()) {
+                downstreamScnMap.remove(entry.getKey());
+            }
+        }
+
+        final PCMMService service = pcmmServiceMap.remove(ccap);
+        if (service != null) service.disconect();
+    }
+
+    private Ccaps findCcapForSubscriberId(final InetAddress inetAddr) {
+        Ccaps matchedCcap = null;
+        int longestPrefixLen = -1;
+        for (final Map.Entry<Subnet, Ccaps> entry : subscriberSubnetsMap.entrySet()) {
+            final Subnet subnet = entry.getKey();
+            if (subnet.isInNet(inetAddr)) {
+                int prefixLen = subnet.getPrefixLen();
+                if (prefixLen > longestPrefixLen) {
+                    matchedCcap = entry.getValue();
+                    longestPrefixLen = prefixLen;
+                }
+            }
+        }
+        return matchedCcap;
+    }
+
+    private ServiceFlowDirection findScnOnCcap(final ServiceClassName scn, final Ccaps ccap) {
+        if (upstreamScnMap.containsKey(scn)) {
+            final List<Ccaps> ccapList = upstreamScnMap.get(scn);
+            if (ccapList.contains(ccap)) {
+                return ServiceFlowDirection.Us;
+            }
+        } else if (downstreamScnMap.containsKey(scn)) {
+            final List<Ccaps> ccapList = downstreamScnMap.get(scn);
+            if (ccapList.contains(ccap)) {
+                return ServiceFlowDirection.Ds;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Implemented from the DataChangeListener interface.
+     */
+
+    private class InstanceData {
+        // CCAP Identity
+        public final Map<InstanceIdentifier<Ccaps>, Ccaps> ccapIidMap = new HashMap<>();
+        // Gate Identity
+        public String subId;
+        public final Map<String, String> gatePathMap = new HashMap<>();
+        public String gatePath;
+        public final Map<InstanceIdentifier<Gates>, Gates> gateIidMap = new HashMap<>();
+        // remove path for either CCAP or Gates
+        public final Set<String> removePathList = new HashSet<>();
+
+        public InstanceData(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+            // only used to parse createdData or updatedData
+            getCcaps(thisData);
+            if (ccapIidMap.isEmpty()) {
+                getGates(thisData);
+                if (! gateIidMap.isEmpty()){
+                    gatePath = gatePathMap.get("appId") + "/" + gatePathMap.get("subId");
+                }
+            }
+        }
+
+        public InstanceData(final Set<InstanceIdentifier<?>> thisData) {
+            // only used to parse the removedData paths
+            for (final InstanceIdentifier<?> removeThis : thisData) {
+                getGatePathMap(removeThis);
+                if (gatePathMap.containsKey("ccapId")) {
+                    gatePath = gatePathMap.get("ccapId");
+                    removePathList.add(gatePath);
+                } else if (gatePathMap.containsKey("gateId")) {
+                    gatePath = gatePathMap.get("appId") + "/" + gatePathMap.get("subId") + "/" + gatePathMap.get("gateId");
+                    removePathList.add(gatePath);
+                }
+            }
+        }
+        private void getGatePathMap(final InstanceIdentifier<?> thisInstance) {
+            logger.info("onDataChanged().getGatePathMap(): " + thisInstance);
+            try {
+                final InstanceIdentifier<Ccaps> ccapInstance = thisInstance.firstIdentifierOf(Ccaps.class);
+                if (ccapInstance != null) {
+                    final CcapsKey ccapKey = InstanceIdentifier.keyOf(ccapInstance);
+                    if (ccapKey != null) {
+                        gatePathMap.put("ccapId", ccapKey.getCcapId());
+                    }
+                } else {
+                    // get the gate path keys from the InstanceIdentifier Map key set if they are there
+                    final InstanceIdentifier<Apps> appsInstance = thisInstance.firstIdentifierOf(Apps.class);
+                    if (appsInstance != null) {
+                        final AppsKey appKey = InstanceIdentifier.keyOf(appsInstance);
+                        if (appKey != null) {
+                            gatePathMap.put("appId", appKey.getAppId());
+                        }
+                    }
+                    final InstanceIdentifier<Subs> subsInstance = thisInstance.firstIdentifierOf(Subs.class);
+                    if (subsInstance != null) {
+                        final SubsKey subKey = InstanceIdentifier.keyOf(subsInstance);
+                        if (subKey != null) {
+                            subId = subKey.getSubId();
+                            gatePathMap.put("subId", subId);
+                        }
+                    }
+                    final InstanceIdentifier<Gates> gatesInstance = thisInstance.firstIdentifierOf(Gates.class);
+                    if (gatesInstance != null) {
+                        final GatesKey gateKey = InstanceIdentifier.keyOf(gatesInstance);
+                        if (gateKey != null) {
+                            gatePathMap.put("gateId", gateKey.getGateId());
+                        }
+                    }
+                }
+            } catch (ClassCastException err) {
+                logger.warn("Unexpected exception", err);
+            }
+        }
+
+        private void getCcaps(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+            logger.info("onDataChanged().getCcaps(): " + thisData);
+            for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+                if (entry.getValue() instanceof Ccaps) {
+                    // TODO FIXME - Potential ClassCastException thrown here!!!
+                    ccapIidMap.put((InstanceIdentifier<Ccaps>)entry.getKey(), (Ccaps)entry.getValue());
+                }
+            }
+        }
+
+        private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+            logger.info("onDataChanged().getGates(): " + thisData);
+            for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+                if (entry.getValue() instanceof Gates) {
+                    final Gates gate = (Gates)entry.getValue();
+
+                    // TODO FIXME - Potential ClassCastException thrown here!!!
+                    final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
+                    getGatePathMap(gateIID);
+                    gateIidMap.put(gateIID, gate);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        logger.info("onDataChanged");
+        // Determine what change action took place by looking at the change object's InstanceIdentifier sets
+        // and validate all instance data
+        if (!change.getCreatedData().isEmpty()) {
+            if (!new ValidateInstanceData(dataBroker, change.getCreatedData()).validateYang()) {
+                // leave now -- a bad yang object has been detected and a response object has been inserted
+                return;
+            }
+            onCreate(new InstanceData(change.getCreatedData()));
+        } else if (!change.getRemovedPaths().isEmpty()) {
+            onRemove(new InstanceData(change.getRemovedPaths()));
+        } else if (!change.getUpdatedData().isEmpty()) {
+            if (new ValidateInstanceData(dataBroker, change.getUpdatedData()).isResponseEcho()) {
+                // leave now -- this is an echo of the inserted response object
+                return;
+            }
+            onUpdate(new InstanceData(change.getUpdatedData()));
+        } else {
+            // we should not be here -- complain bitterly and return
+            logger.error("onDataChanged(): Unknown change action: " + change);
+        }
+    }
+
+    private void onCreate(final InstanceData thisData) {
+        logger.info("onCreate(): " + thisData);
+
+        // get the CCAP parameters
+        String message;
+        if (! thisData.ccapIidMap.isEmpty()) {
+            for (Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : thisData.ccapIidMap.entrySet()) {
+                final Ccaps thisCcap = entry.getValue();
+                // get the CCAP node identity from the Instance Data
+                final String ccapId = thisCcap.getCcapId();
+
+                if (pcmmServiceMap.get(thisCcap) == null) {
+                    final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, thisCcap);
+                    // TODO - may want to use the AMID but for the client type but probably not???
+/*
+                            final PCMMService pcmmService = new PCMMService(
+                                    thisCcap.getAmId().getAmType().shortValue(), thisCcap);
+*/
+                    pcmmServiceMap.put(thisCcap, pcmmService);
+                    message = pcmmService.addCcap();
+                    if (message.contains("200 OK")) {
+                        ccapMap.put(ccapId, thisCcap);
+                        updateCcapMaps(thisCcap);
+                        logger.info("onDataChanged(): created CCAP: {}/{} : {}", thisData.gatePath, thisCcap, message);
+                        logger.info("onDataChanged(): created CCAP: {} : {}", thisData.gatePath, message);
+                    } else {
+                        // TODO - when a connection cannot be made, need to remove CCAP from ODL cache.
+                        logger.error("onDataChanged(): create CCAP Failed: {} : {}", thisData.gatePath, message);
+                    }
+                    // set the response string in the config ccap object using a new thread
+                    executor.execute(new Response(dataBroker, entry.getKey(), thisCcap, message));
+                } else {
+                    logger.error("Already monitoring CCAP - " + thisCcap);
+                    break;
+                }
+            }
+        } else {
+            // get the PCMM gate parameters from the ccapId/appId/subId/gateId path in the Maps entry (if new gate)
+            for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : thisData.gateIidMap.entrySet()) {
+                message = null;
+                final Gates gate = entry.getValue();
+                final String gateId = gate.getGateId();
+                final String gatePathStr = thisData.gatePath + "/" + gateId ;
+                final InetAddress subId = getInetAddress(thisData.subId);
+                if (subId != null) {
+                    final Ccaps thisCcap = findCcapForSubscriberId(subId);
+                    if (thisCcap != null) {
+                        final String ccapId = thisCcap.getCcapId();
+                        // verify SCN exists on CCAP and force gateSpec.Direction to align with SCN direction
+                        final ServiceClassName scn = gate.getTrafficProfile().getServiceClassName();
+                        if (scn != null) {
+                            final ServiceFlowDirection scnDir = findScnOnCcap(scn, thisCcap);
+                            if (scnDir != null) {
+                                if (pcmmServiceMap.get(thisCcap) != null) {
+                                    message = pcmmServiceMap.get(thisCcap).sendGateSet(gatePathStr, subId, gate, scnDir);
+                                    if (message.contains("200 OK")) {
+                                        gateMap.put(gatePathStr, gate);
+                                        gateCcapMap.put(gatePathStr, thisCcap.getCcapId());
+                                        logger.info("onDataChanged(): created QoS gate {} for {}/{}/{} - {}",
+                                                gateId, ccapId, gatePathStr, gate, message);
+                                        logger.info("onDataChanged(): created QoS gate {} for {}/{} - {}",
+                                                gateId, ccapId, gatePathStr, message);
+                                    } else {
+                                        logger.info("onDataChanged(): Unable to create QoS gate {} for {}/{}/{} - {}",
+                                                gateId, ccapId, gatePathStr, gate, message);
+                                        logger.error("onDataChanged(): Unable to create QoS gate {} for {}/{} - {}",
+                                                gateId, ccapId, gatePathStr, message);
+                                    }
+                                } else {
+                                    logger.error("Unable to locate PCMM Service for CCAP - " + thisCcap);
+                                    break;
+                                }
+                            } else {
+                                logger.error("PCMMService: sendGateSet(): SCN {} not found on CCAP {} for {}/{}",
+                                        scn.getValue(), thisCcap, gatePathStr, gate);
+                                message = String.format("404 Not Found - SCN %s not found on CCAP %s for %s",
+                                        scn.getValue(), thisCcap.getCcapId(), gatePathStr);
+                            }
+                        }
+                    } else {
+                        final String subIdStr = thisData.subId;
+                        message = String.format("404 Not Found - no CCAP found for subscriber %s in %s",
+                                subIdStr, gatePathStr);
+                        logger.info("onDataChanged(): create QoS gate {} FAILED: no CCAP found for subscriber {}: @ {}/{}",
+                                gateId, subIdStr, gatePathStr, gate);
+                        logger.error("onDataChanged(): create QoS gate {} FAILED: no CCAP found for subscriber {}: @ {}",
+                                gateId, subIdStr, gatePathStr);
+                    }
+                } else {
+                    final String subIdStr = thisData.subId;
+                    message = String.format("400 Bad Request - subId must be a valid IP address for subscriber %s in %s",
+                            subIdStr, gatePathStr);
+                    logger.info("onDataChanged(): create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}/{}",
+                            gateId, subIdStr, gatePathStr, gate);
+                    logger.error("onDataChanged(): create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}",
+                            gateId, subIdStr, gatePathStr);
+                }
+                // set the response message in the config gate object using a new thread
+                executor.execute(new Response(dataBroker, entry.getKey(), gate, message));
+            }
+        }
+    }
+
+    private void onRemove(final InstanceData thisData) {
+        logger.info("onRemove(): " + thisData);
+        for (final String gatePathStr: thisData.removePathList) {
+            if (gateMap.containsKey(gatePathStr)) {
+                final Gates thisGate = gateMap.remove(gatePathStr);
+                final String gateId = thisGate.getGateId();
+                final String ccapId = gateCcapMap.remove(gatePathStr);
+                final Ccaps thisCcap = ccapMap.get(ccapId);
+                final PCMMService service = pcmmServiceMap.get(thisCcap);
+                if (service != null) {
+                    service.sendGateDelete(gatePathStr);
+                    logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr, thisGate);
+                    logger.info("onDataChanged(): removed QoS gate {} for {}/{}: ", gateId, ccapId, gatePathStr);
+                } else
+                    logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
+                            + thisCcap);
+            }
+        }
+        for (final String ccapIdStr: thisData.removePathList) {
+            if (ccapMap.containsKey(ccapIdStr)) {
+                final Ccaps thisCcap = ccapMap.remove(ccapIdStr);
+                removeCcapFromAllMaps(thisCcap);
+            }
+        }
+    }
+
+    private void onUpdate(final InstanceData oldData) {
+        logger.info("onUpdate(): " + oldData);
+        // update operation not allowed -- restore the original config object and complain
+        if (! oldData.ccapIidMap.isEmpty()) {
+            for (final Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : oldData.ccapIidMap.entrySet()) {
+                final Ccaps ccap = entry.getValue();
+                final String ccapId = ccap.getCcapId();
+                String message = String.format("405 Method Not Allowed - %s: CCAP update not permitted (use delete); ",
+                        ccapId);
+                // push new error message onto existing response
+                message += ccap.getResponse();
+                // set the response message in the config object using a new thread -- also restores the original data
+                executor.execute(new Response(dataBroker, entry.getKey(), ccap, message));
+                logger.error("onDataChanged(): CCAP update not permitted {}/{}", ccapId, ccap);
+            }
+        } else {
+            for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : oldData.gateIidMap.entrySet()) {
+                final Gates gate = entry.getValue();
+                final String gatePathStr = oldData.gatePath + "/" + gate.getGateId() ;
+                String message = String.format("405 Method Not Allowed - %s: QoS Gate update not permitted (use delete); ", gatePathStr);
+                // push new error message onto existing response
+                message += gate.getResponse();
+                // set the response message in the config object using a new thread -- also restores the original data
+                executor.execute(new Response(dataBroker, entry.getKey(), gate, message));
+                logger.error("onDataChanged(): QoS Gate update not permitted: {}/{}", gatePathStr, gate);
+            }
+        }
+    }
+
+}
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Response.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Response.java
new file mode 100644 (file)
index 0000000..88132bb
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * The Response object inserts a "response" message object into the given CCAP or Gate object in the
+ * config data store.
+ *
+ * N.B. Updates to the config datastore must be run in a separate thread from the onDataChange() notification.
+ * Therefore, the Response object must always be invoked via executor.execute(resonse) after it is
+ * configured during new Response(dataBroker, ccapIID, ccapbase, message) for example.
+ *
+ * Also note well that when a CCAP or Gate object is updated with this "response" message, it will trigger
+ * another recursive onDataChange() notification seen in the change.getUpdatedData() -- this update must be ignored.
+ */
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.GatesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Response implements Runnable {
+
+       private Logger logger = LoggerFactory.getLogger(Response.class);
+       private DataBroker dataBroker;
+       private String message = null;
+       private InstanceIdentifier<Ccaps> ccapIID = null;
+       private Ccaps ccapBase = null;
+       private InstanceIdentifier<Gates> gateIID = null;
+       private Gates gateBase = null;
+
+       public Response(DataBroker dataBroker, InstanceIdentifier<Ccaps> ccapIID, Ccaps ccapBase, String message) {
+               this.dataBroker = dataBroker;
+               this.ccapIID = ccapIID;
+               this.ccapBase = ccapBase;
+               this.message = message;
+       }
+       public Response(DataBroker dataBroker, InstanceIdentifier<Gates> gateIID, Gates gateBase, String message) {
+               this.dataBroker = dataBroker;
+               this.gateIID = gateIID;
+               this.gateBase = gateBase;
+               this.message = message;
+       }
+
+       public String getMessage() {
+               return message;
+       }
+       public void setMessage(String message) {
+               this.message = message;
+       }
+       public void addMessage(String message) {
+               this.message += message;
+       }
+       public InstanceIdentifier<Ccaps> getCcapIID() {
+               return ccapIID;
+       }
+       public void setCcapIID(InstanceIdentifier<Ccaps> ccapIID) {
+               this.ccapIID = ccapIID;
+       }
+       public Ccaps getCcapBase() {
+               return ccapBase;
+       }
+       public void setCcapBase(Ccaps ccapBase) {
+               this.ccapBase = ccapBase;
+       }
+       public InstanceIdentifier<Gates> getGateIID() {
+               return gateIID;
+       }
+       public void setGateIID(InstanceIdentifier<Gates> gateIID) {
+               this.gateIID = gateIID;
+       }
+       public Gates getGateBase() {
+               return gateBase;
+       }
+       public void setGateBase(Gates gateBase) {
+               this.gateBase = gateBase;
+       }
+
+       @SuppressWarnings("deprecation")
+       public void setResponse(InstanceIdentifier<Ccaps> ccapIID, Ccaps ccapBase, String message) {
+               CcapsBuilder ccapBuilder = new CcapsBuilder(ccapBase);
+               ccapBuilder.setResponse(message);
+               Ccaps ccap = ccapBuilder.build();
+        WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
+        writeTx.merge(LogicalDatastoreType.CONFIGURATION, ccapIID, ccap, true);
+        writeTx.commit();
+        logger.debug("Response.setResponse(ccap) complete {} {} {}", message, ccap, ccapIID);
+       }
+       @SuppressWarnings("deprecation")
+       public void setResponse(InstanceIdentifier<Gates> gateIID, Gates gateBase, String message) {
+               GatesBuilder gateBuilder = new GatesBuilder(gateBase);
+               gateBuilder.setResponse(message);
+               Gates gate = gateBuilder.build();
+        WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
+        writeTx.merge(LogicalDatastoreType.CONFIGURATION, gateIID, gate, true);
+        writeTx.commit();
+        logger.debug("Response.setResponse(gate) complete: {} {} {}", message, gate, gateIID);
+       }
+
+       @Override
+       public void run() {
+               if (ccapIID != null) {
+                       setResponse(ccapIID, ccapBase, message);
+               } else if (gateIID != null) {
+                       setResponse(gateIID, gateBase, message);
+               } else {
+                       logger.error("Unknown Response: must be for a CCAP or Gate instance");
+               }
+       }
+}
+
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/Subnet.java
new file mode 100644 (file)
index 0000000..c0db407
--- /dev/null
@@ -0,0 +1,114 @@
+package org.opendaylight.controller.packetcable.provider;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author c3oe.de, based on snippets from Scott Plante, John Kugelmann
+ */
+public class Subnet
+{
+    final private int bytesSubnetCount;
+    final private BigInteger bigMask;
+    final private BigInteger bigSubnetMasked;
+    final private int prefixLen;
+
+    /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */
+    public Subnet( final InetAddress subnetAddress, final int bits )
+    {
+        this.prefixLen = bits;
+       this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
+        this.bigMask = BigInteger.valueOf( -1 ).shiftLeft( this.bytesSubnetCount*8 - bits ); // mask = -1 << 32 - bits
+        this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
+    }
+
+    /** For use via format "192.168.0.0/255.255.255.0" or single address */
+    public Subnet( final InetAddress subnetAddress, final InetAddress mask )
+    {
+       this.bytesSubnetCount = subnetAddress.getAddress().length;
+        this.bigMask = null == mask ? BigInteger.valueOf( -1 ) : new BigInteger( mask.getAddress() ); // no mask given case is handled here.
+        this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
+        int lowestSetBit = bigMask.getLowestSetBit();
+        this.prefixLen = lowestSetBit == -1 ? 0 : 32 - lowestSetBit;
+    }
+
+    /**
+     * Subnet factory method.
+     * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
+     *      or single address or "2001:db8:85a3:880:0:0:0:0/57"
+     * @return a new instance
+     * @throws UnknownHostException thrown if unsupported subnet mask.
+     */
+    public static Subnet createInstance( final String subnetMask )
+            throws UnknownHostException
+    {
+        final String[] stringArr = subnetMask.split("/");
+        if ( 2 > stringArr.length )
+            return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), null);
+        else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") )
+            return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), InetAddress.getByName( stringArr[ 1 ] ) );
+        else
+            return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), Integer.parseInt( stringArr[ 1 ] ) );
+    }
+
+    public int getPrefixLen() {
+               return prefixLen;
+       }
+
+       public boolean isInNet( final InetAddress address )
+    {
+        final byte[] bytesAddress = address.getAddress();
+        if ( this.bytesSubnetCount != bytesAddress.length )
+            return false;
+        final BigInteger bigAddress = new BigInteger( bytesAddress );
+        return  bigAddress.and( this.bigMask ).equals( this.bigSubnetMasked );
+    }
+
+    @Override
+    final public boolean equals( Object obj )
+    {
+        if ( ! (obj instanceof Subnet) )
+            return false;
+        final Subnet other = (Subnet)obj;
+        return  this.bigSubnetMasked.equals( other.bigSubnetMasked ) &&
+                this.bigMask.equals( other.bigMask ) &&
+                this.bytesSubnetCount == other.bytesSubnetCount;
+    }
+
+    @Override
+    final public int hashCode()
+    {
+        return this.bytesSubnetCount;
+    }
+
+    @Override
+    public String toString()
+    {
+        final StringBuilder buf = new StringBuilder();
+        bigInteger2IpString( buf, this.bigSubnetMasked, this.bytesSubnetCount );
+        buf.append( '/' );
+        bigInteger2IpString( buf, this.bigMask, this.bytesSubnetCount );
+        return buf.toString();
+    }
+
+    static private void bigInteger2IpString( final StringBuilder buf, final BigInteger bigInteger, final int displayBytes )
+    {
+        final boolean isIPv4 = 4 == displayBytes;
+        byte[] bytes = bigInteger.toByteArray();
+        int diffLen = displayBytes - bytes.length;
+        final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00;
+
+        int integer;
+        for ( int i = 0; i < displayBytes; i++ )
+        {
+            if ( 0 < i && ! isIPv4 && i % 2 == 0 )
+                buf.append( ':' );
+            else if ( 0 < i && isIPv4 )
+                buf.append( '.' );
+            integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]);
+            if ( ! isIPv4 && 0x10 > integer )
+                buf.append( '0' );
+            buf.append( isIPv4 ? integer : Integer.toHexString( integer ) );
+        }
+    }
+}
\ No newline at end of file
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/ValidateInstanceData.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/ValidateInstanceData.java
new file mode 100644 (file)
index 0000000..4822881
--- /dev/null
@@ -0,0 +1,971 @@
+/**
+ * Validate all instance data received from the config datastore via the onDataChange() notification.
+ *
+ * N.B. that yang typedefs are not validated when a PUT operation places them into the config datastore.
+ * This means that they can arrive at onDataChange() with invalid values.
+ *
+ * In particular integer range values and string patterns (such as IP prefix/len) are not checked
+ * and accessing these values via any object.getValue() method call will cause an exception (as yang
+ * finally gets around to actually enforcing the typedef).
+ */
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TpProtocol;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.ConnectionBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpecBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.GatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfileBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class ValidateInstanceData {
+
+       private final static Logger logger = LoggerFactory.getLogger(ValidateInstanceData.class);
+
+       // Final members
+       private final DataBroker dataBroker;
+       private final ExecutorService executor;
+
+       // Gate Identities
+       private final Map<InstanceIdentifier<Gates>, Gates> gateIidMap;
+
+       // CCAP Identity
+       private transient Ccaps ccap;
+       private transient InstanceIdentifier<Ccaps> ccapIID;
+
+       public ValidateInstanceData(final DataBroker dataBroker, final Map<InstanceIdentifier<?>, DataObject> thisData) {
+               executor = Executors.newCachedThreadPool();
+               this.dataBroker = dataBroker;
+               getCcap(thisData);
+
+               // Must be instantiated prior to retreiving the gates below
+               gateIidMap = new ConcurrentHashMap<>();
+
+               // TODO FIXME - this value is always null???
+               if (ccap == null) {
+                       getGates(thisData);
+               }
+       }
+       public boolean isResponseEcho() {
+               // see if there is a response object in the updated data
+               // if so this is an echo of the response message insertion so our caller can exit right away
+               if (ccap != null && ccap.getResponse() != null) {
+                       return true;
+               } else if (! gateIidMap.isEmpty() && gateIidMap.values().iterator().next().getResponse() != null) {
+                       return true;
+               }
+               return false;
+       }
+       public boolean validateYang() {
+               final String badText = "400 Bad Request - Invalid Element Values in json object - ";
+               if (isResponseEcho()) {
+                       // don't validiate the echo again
+                       return true;
+               }
+               if (ccap != null) {
+                       Response response = new Response(dataBroker, ccapIID, ccap, badText);
+                       if (! validateCcap(ccap, response)) {
+                               logger.error("Validate CCAP {} failed - {}", ccap.getCcapId(), response.getMessage());
+                               executor.execute(response);
+                               return false;
+                       }
+               } else if (! gateIidMap.isEmpty()) {
+                       for (Map.Entry<InstanceIdentifier<Gates>, Gates> entry : gateIidMap.entrySet()) {
+                               InstanceIdentifier<Gates> gateIID = entry.getKey();
+                               Gates gate = entry.getValue();
+                               Response response = new Response(dataBroker, gateIID, gate, badText);
+                               if (! validateGate(gate, response)) {
+                                       logger.error("Validate Gate {} failed - {}", gate.getGateId(), response.getMessage());
+                                       executor.execute(response);
+                                       return false;
+                               }
+                       }
+               }
+               return true;
+       }
+
+       private void getCcap(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+               for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+                       if (entry.getValue() instanceof Ccaps) {
+                   ccap = (Ccaps)entry.getValue();
+                               // TODO FIXME - ClassCastException waiting to occur here!!!
+                   ccapIID = (InstanceIdentifier<Ccaps>) entry.getKey();
+               }
+           }
+       }
+
+       private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+               for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+                       if (entry.getValue() instanceof Gates) {
+                               final Gates gate = (Gates)entry.getValue();
+                               // TODO FIXME - ClassCastException waiting to occur here!!!
+                               final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
+                               gateIidMap.put(gateIID, gate);
+                       }
+           }
+       }
+       private String validateMethod(final Class<?> thisClass, final Object thisObj, final String methodName) {
+               try {
+                       final Method method = thisClass.getMethod(methodName);
+                       method.invoke(thisObj);
+               } catch (IllegalArgumentException e) {
+                       return e.getMessage();
+               } catch (Exception e) {
+                       return " ";
+//                     error = String.format("%s.%s(): Method failed: %s ", thisClass.getSimpleName(), methodName, e.getMessage());
+               }
+               return null;
+       }
+
+       private boolean validateGateSpec(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+               // gate-spec
+               String message = "";
+               String error;
+               boolean valid = true;
+               GateSpec gateSpec = gate.getGateSpec();
+               if (gateSpec != null) {
+                       final ServiceFlowDirection dir;
+                       error = validateMethod(GateSpec.class, gateSpec, "getDirection");
+                       if (error == null) {
+                               dir = gateSpec.getDirection();
+                               if (dir != null) {
+                                       if (gate.getTrafficProfile().getServiceClassName() != null) {
+                                               message += " gate-spec.direction not allowed for traffic-profile.SCN;";
+                                               valid = false;
+                                       }
+                               }
+                       } else {
+                               message += " gate-spec.direction invalid: must be 'us' or 'ds' -" + error;
+                               dir = null;
+                               valid = false;
+                       }
+                       final TosByte tosByte;
+                       error = validateMethod(GateSpec.class, gateSpec, "getDscpTosOverwrite");
+                       if (error == null) {
+                               tosByte = gateSpec.getDscpTosOverwrite();
+                       } else {
+                               message += " gate-spec.dscp-tos-overwrite invalid: " + error;
+                               tosByte = null;
+                               valid = false;
+                       }
+                       final TosByte tosMask;
+                       error = validateMethod(GateSpec.class, gateSpec, "getDscpTosMask");
+                       if (error == null) {
+                               tosMask = gateSpec.getDscpTosMask();
+                               if (tosByte != null && tosMask == null) {
+                                       message += " gate-spec.dscp-tos-mask missing;";
+                                       valid = false;
+                               }
+                       } else {
+                               message += " gate-spec.dscp-tos-mask invalid: " + error;
+                               tosMask = null;
+                               valid = false;
+                       }
+                       if (! valid) {
+                               // rebuild the gateSpec with nulls replacing bad values
+                               final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
+                               gateSpecBuilder.setDirection(dir);
+                               gateSpecBuilder.setDscpTosOverwrite(tosByte);
+                               gateSpecBuilder.setDscpTosMask(tosMask);
+                               gateSpec = gateSpecBuilder.build();
+                               // update the gate
+                               gateBuilder.setGateSpec(gateSpec);
+                       }
+               }
+               if (! valid) {
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       private boolean validateTrafficProfile(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+               // traffic-profile
+               String message = "";
+               boolean valid = true;
+               TrafficProfile profile = gate.getTrafficProfile();
+               if (profile == null) {
+                       message += " traffic-profile is required;";
+                       valid = false;
+               } else {
+                       final ServiceClassName scn;
+                       final String error = validateMethod(TrafficProfile.class, profile, "getServiceClassName");
+                       if (error == null) {
+                               scn = profile.getServiceClassName();
+                               if (scn == null) {
+                                       message += " traffic-profile.service-class-name missing;";
+                                       valid = false;
+                               }
+                       } else {
+                               message += " traffic-profile.service-class-name invalid: must be 2-16 characters " + error;
+                               scn = null;
+                               valid = false;
+                       }
+                       if (! valid) {
+                               final TrafficProfileBuilder profileBuilder = new TrafficProfileBuilder();
+                               // TODO FIXME - scn is always null???
+                               profileBuilder.setServiceClassName(scn);
+                               profile = profileBuilder.build();
+                               // update the gate
+                               gateBuilder.setTrafficProfile(profile);
+                       }
+               }
+               if (! valid) {
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       // TODO FIXME - Break this method apart
+       private boolean validateClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+               // validate classifier
+               String message = "";
+               boolean valid = true;
+               int count = 0;
+               Classifier classifier = gate.getClassifier();
+               // SIP
+               final Ipv4Address sip;
+               String error = validateMethod(Classifier.class, classifier, "getSrcIp");
+               if (error == null) {
+                       sip = classifier.getSrcIp();
+                       count++;
+               } else {
+                       message += " classifier.srcIp invalid: - " + error;
+                       sip = null;
+                       valid = false;
+               }
+               // DIP
+               final Ipv4Address dip;
+               error = validateMethod(Classifier.class, classifier, "getDstIp");
+               if (error == null) {
+                       dip = classifier.getDstIp();
+                       count++;
+               } else {
+                       message += " classifier.dstIp invalid: - " + error;
+                       dip = null;
+                       valid = false;
+               }
+               // Protocol
+               final TpProtocol proto;
+               error = validateMethod(Classifier.class, classifier, "getProtocol");
+               if (error == null) {
+                       proto = classifier.getProtocol();
+                       count++;
+               } else {
+                       message += " classifier.protocol invalid: - " + error;
+                       proto = null;
+                       valid = false;
+               }
+               // Source Port
+               final PortNumber sport;
+               error = validateMethod(Classifier.class, classifier, "getSrcPort");
+               if (error == null) {
+                       sport = classifier.getSrcPort();
+                       count++;
+               } else {
+                       message += " classifier.srcPort invalid: - " + error;
+                       sport = null;
+                       valid = false;
+               }
+               // Destination Port
+               final PortNumber dport;
+               error = validateMethod(Classifier.class, classifier, "getDstPort");
+               if (error == null) {
+                       dport = classifier.getDstPort();
+                       count++;
+               } else {
+                       message += " classifier.dstPort invalid: - " + error;
+                       dport = null;
+                       valid = false;
+               }
+               // TOS
+               final TosByte tosByte;
+               error = validateMethod(Classifier.class, classifier, "getTosByte");
+               if (error == null) {
+                       tosByte = classifier.getTosByte();
+                       count++;
+               } else {
+                       message += " classifier.tosByte invalid: " + error;
+                       tosByte = null;
+                       valid = false;
+               }
+               final TosByte tosMask;
+               error = validateMethod(Classifier.class, classifier, "getTosMask");
+               if (error == null) {
+                       tosMask = classifier.getTosMask();
+                       if (tosByte != null && tosMask == null) {
+                               message += " classifier.tosMask missing;";
+                               valid = false;
+                       }
+               } else {
+                       message += " classifier.tosMask invalid: " + error;
+                       tosMask = null;
+                       valid = false;
+               }
+               if (count == 0) {
+                       message += " classifer must have at least one match field";
+                       valid = false;
+               }
+               if (! valid) {
+                       final ClassifierBuilder cBuilder = new ClassifierBuilder();
+                       cBuilder.setSrcIp(sip);
+                       cBuilder.setDstIp(dip);
+                       cBuilder.setProtocol(proto);
+                       cBuilder.setSrcPort(sport);
+                       cBuilder.setDstPort(dport);
+                       cBuilder.setTosByte(tosByte);
+                       cBuilder.setTosMask(tosMask);
+                       classifier = cBuilder.build();
+                       gateBuilder.setClassifier(classifier);
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       // TODO FIXME - breakup this method
+       private boolean validateExtClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+               // validate ext-classifier
+               String message = "";
+               String error;
+               boolean valid = true;
+               int count = 0;
+               ExtClassifier extClassifier = gate.getExtClassifier();
+               // SIP & mask
+               final Ipv4Address sip;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIp");
+               if (error == null) {
+                       sip = extClassifier.getSrcIp();
+                       count++;
+               } else {
+                       message += " ext-classifier.srcIp invalid: - " + error;
+                       sip = null;
+                       valid = false;
+               }
+               final Ipv4Address sipMask;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIpMask");
+               if (error == null) {
+                       sipMask = extClassifier.getSrcIpMask();
+                       count++;
+               } else {
+                       message += " ext-classifier.srcIpMask invalid: - " + error;
+                       sipMask = null;
+                       valid = false;
+               }
+               if (sip != null && sipMask == null) {
+                       message += " ext-classifier.srcIpMask missing";
+                       valid = false;
+               }
+               // DIP & mask
+               final Ipv4Address dip;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getDstIp");
+               if (error == null) {
+                       dip = extClassifier.getDstIp();
+                       count++;
+               } else {
+                       message += " ext-classifier.dstIp invalid: - " + error;
+                       dip = null;
+                       valid = false;
+               }
+               final Ipv4Address dipMask;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getDstIpMask");
+               if (error == null) {
+                       dipMask = extClassifier.getDstIpMask();
+                       count++;
+               } else {
+                       message += " ext-classifier.srcIpMask invalid: - " + error;
+                       dipMask = null;
+                       valid = false;
+               }
+               if (dip != null && dipMask == null) {
+                       message += " ext-classifier.dstIpMask missing;";
+                       valid = false;
+               }
+               // Protocol
+               final TpProtocol proto;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getProtocol");
+               if (error == null) {
+                       proto = extClassifier.getProtocol();
+                       count++;
+               } else {
+                       message += " ext-classifier.protocol invalid: - " + error;
+                       proto = null;
+                       valid = false;
+               }
+               // Source port range
+               final PortNumber sportStart;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortStart");
+               if (error == null) {
+                       sportStart = extClassifier.getSrcPortStart();
+                       count++;
+               } else {
+                       message += " ext-classifier.srcPortStart invalid: - " + error;
+                       sportStart = null;
+                       valid = false;
+               }
+               final PortNumber sportEnd;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortEnd");
+               if (error == null) {
+                       sportEnd = extClassifier.getSrcPortEnd();
+                       count++;
+               } else {
+                       message += " ext-classifier.srcPortEnd invalid: - " + error;
+                       sportEnd = null;
+                       valid = false;
+               }
+               if (sportStart != null && sportEnd != null) {
+                       if (sportStart.getValue() > sportEnd.getValue()) {
+                               message += " ext-classifier.srcPortStart greater than srcPortEnd";
+                               valid = false;
+                       }
+               }
+               // Destination port range
+               final PortNumber dportStart;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortStart");
+               if (error == null) {
+                       dportStart = extClassifier.getDstPortStart();
+                       count++;
+               } else {
+                       message += " ext-classifier.dstPortStart invalid: - " + error;
+                       dportStart = null;
+                       valid = false;
+               }
+               final PortNumber dportEnd;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortEnd");
+               if (error == null) {
+                       dportEnd = extClassifier.getDstPortEnd();
+                       count++;
+               } else {
+                       message += " ext-classifier.dstPortEnd invalid: - " + error;
+                       dportEnd = null;
+                       valid = false;
+               }
+               if (dportStart != null && dportEnd != null) {
+                       if (dportStart.getValue() > dportEnd.getValue()) {
+                               message += " ext-classifier.dstPortStart greater than dstPortEnd";
+                               valid = false;
+                       }
+               }
+               // TOS byte
+               final TosByte tosByte;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getTosByte");
+               if (error == null) {
+                       tosByte = extClassifier.getTosByte();
+                       count++;
+               } else {
+                       message += " ext-classifier.tosByte invalid: " + error;
+                       tosByte = null;
+                       valid = false;
+               }
+               final TosByte tosMask;
+               error = validateMethod(ExtClassifier.class, extClassifier, "getTosMask");
+               if (error == null) {
+                       tosMask = extClassifier.getTosMask();
+                       if (tosByte != null && tosMask == null) {
+                               message += " ext-classifier.tosMask missing;";
+                               valid = false;
+                       }
+               } else {
+                       message += " ext-classifier.tosMask invalid: " + error;
+                       tosMask = null;
+                       valid = false;
+               }
+               if (count == 0) {
+                       message += " ext-classifer must have at least one match field";
+                       valid = false;
+               }
+               if (! valid) {
+                       final ExtClassifierBuilder cBuilder = new ExtClassifierBuilder();
+                       cBuilder.setSrcIp(sip);
+                       cBuilder.setSrcIpMask(sipMask);
+                       cBuilder.setDstIp(dip);
+                       cBuilder.setDstIpMask(dipMask);
+                       cBuilder.setProtocol(proto);
+                       cBuilder.setSrcPortStart(sportStart);
+                       cBuilder.setSrcPortEnd(sportEnd);
+                       cBuilder.setDstPortStart(dportStart);
+                       cBuilder.setDstPortEnd(dportEnd);
+                       cBuilder.setTosByte(tosByte);
+                       cBuilder.setTosMask(tosMask);
+                       extClassifier = cBuilder.build();
+                       gateBuilder.setExtClassifier(extClassifier);
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       // TODO FIXME - break apart this method.
+       private boolean validateIpv6Classifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+               // validate ipv6-classifier
+               String message = "";
+               String error;
+               boolean valid = true;
+               int count = 0;
+               Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
+               // Source IPv6 prefix
+               final Ipv6Prefix sip6;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcIp6");
+               if (error == null) {
+                       sip6 = ipv6Classifier.getSrcIp6();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.srcIp invalid: - " + error;
+                       sip6 = null;
+                       valid = false;
+               }
+               // Destination IPv6 prefix
+               final Ipv6Prefix dip6;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstIp6");
+               if (error == null) {
+                       dip6 = ipv6Classifier.getDstIp6();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.dstIp invalid: - " + error;
+                       dip6 = null;
+                       valid = false;
+               }
+               // Flow label
+               Long flowLabel;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getFlowLabel");
+               if (error == null) {
+                       flowLabel = ipv6Classifier.getFlowLabel();
+                       if (flowLabel > 1048575) {
+                               message += " ipv6-classifier.flowLabel invalid: - must be 0..1048575";
+                               flowLabel = null;
+                               valid = false;
+                       } else {
+                               count++;
+                       }
+               } else {
+                       message += " ipv6-classifier.flowLabel invalid: - " + error;
+                       flowLabel = null;
+                       valid = false;
+               }
+               // Next Hdr
+               final TpProtocol nxtHdr;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getNextHdr");
+               if (error == null) {
+                       nxtHdr = ipv6Classifier.getNextHdr();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.nextHdr invalid: - " + error;
+                       nxtHdr = null;
+                       valid = false;
+               }
+               // Source port range
+               final PortNumber sportStart;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortStart");
+               if (error == null) {
+                       sportStart = ipv6Classifier.getSrcPortStart();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.srcPortStart invalid: - " + error;
+                       sportStart = null;
+                       valid = false;
+               }
+               final PortNumber sportEnd;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortEnd");
+               if (error == null) {
+                       sportEnd = ipv6Classifier.getSrcPortEnd();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.srcPortEnd invalid: - " + error;
+                       sportEnd = null;
+                       valid = false;
+               }
+               if (sportStart != null && sportEnd != null) {
+                       if (sportStart.getValue() > sportEnd.getValue()) {
+                               message += " ipv6-classifier.srcPortStart greater than srcPortEnd";
+                               valid = false;
+                       }
+               }
+               // Destination port range
+               final PortNumber dportStart;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortStart");
+               if (error == null) {
+                       dportStart = ipv6Classifier.getDstPortStart();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.dstPortStart invalid: - " + error;
+                       dportStart = null;
+                       valid = false;
+               }
+               final PortNumber dportEnd;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortEnd");
+               if (error == null) {
+                       dportEnd = ipv6Classifier.getDstPortEnd();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.dstPortEnd invalid: - " + error;
+                       dportEnd = null;
+                       valid = false;
+               }
+               if (dportStart != null && dportEnd != null) {
+                       if (dportStart.getValue() > dportEnd.getValue()) {
+                               message += " ipv6-classifier.dstPortStart greater than dstPortEnd";
+                               valid = false;
+                       }
+               }
+               // TC byte
+               final TosByte tcLow;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcLow");
+               if (error == null) {
+                       tcLow = ipv6Classifier.getTcLow();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.tc-low invalid: " + error;
+                       tcLow = null;
+                       valid = false;
+               }
+               final TosByte tcHigh;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcHigh");
+               if (error == null) {
+                       tcHigh = ipv6Classifier.getTcHigh();
+                       count++;
+               } else {
+                       message += " ipv6-classifier.tc-high invalid: " + error;
+                       tcHigh = null;
+                       valid = false;
+               }
+               if (tcLow != null && tcHigh != null) {
+                       if (tcLow.getValue() > tcHigh.getValue()) {
+                               message += " ipv6-classifier.tc-low is greater than tc-high";
+                               valid = false;
+                       }
+               }
+               final TosByte tcMask;
+               error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcMask");
+               if (error == null) {
+                       tcMask = ipv6Classifier.getTcMask();
+               } else {
+                       message += " ipv6-classifier.tc-mask invalid: " + error;
+                       tcMask = null;
+                       valid = false;
+               }
+               if (tcLow != null && tcHigh != null && tcMask == null) {
+                       message += " ipv6-classifier.tc-mask missing;";
+                       valid = false;
+               }
+               if (count == 0) {
+                       message += " ipv6-classifer must have at least one match field";
+                       valid = false;
+               }
+               // rebuild ?
+               if (! valid) {
+                       final Ipv6ClassifierBuilder cBuilder = new Ipv6ClassifierBuilder();
+                       cBuilder.setSrcIp6(sip6);
+                       cBuilder.setDstIp6(dip6);
+                       cBuilder.setFlowLabel(flowLabel);
+                       cBuilder.setNextHdr(nxtHdr);
+                       cBuilder.setSrcPortStart(sportStart);
+                       cBuilder.setSrcPortEnd(sportEnd);
+                       cBuilder.setDstPortStart(dportStart);
+                       cBuilder.setDstPortEnd(dportEnd);
+                       cBuilder.setTcLow(tcLow);
+                       cBuilder.setTcHigh(tcHigh);
+                       cBuilder.setTcMask(tcMask);
+                       ipv6Classifier = cBuilder.build();
+                       gateBuilder.setIpv6Classifier(ipv6Classifier);
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       // TODO FIXME - Do we really want the gate parameter object to be muted by this method?
+       private boolean validateGate(Gates gate, final Response response) {
+               // validate gate elements and null out invalid elements as we go
+               final GatesBuilder gateBuilder = new GatesBuilder();
+               String message = "";
+               boolean rebuild = false;
+               // gate-spec
+               if (! validateGateSpec(gate, gateBuilder, response)) {
+                       rebuild = true;
+               }
+               // traffic-profile
+               if (! validateTrafficProfile(gate, gateBuilder, response)) {
+                       rebuild = true;
+               }
+               // classifiers (one of legacy classifier, ext-classifier, or ipv6 classifier
+               final Classifier classifier = gate.getClassifier();
+               final ExtClassifier extClassifier = gate.getExtClassifier();
+               final Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
+               int count = 0;
+               if (classifier != null) { count++; }
+               if (extClassifier != null) { count++; }
+               if (ipv6Classifier != null) { count++; }
+               if (count < 1){
+                       response.addMessage(" Missing classifer: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
+                       rebuild = true;
+               } else if (count > 1) {
+                       response.addMessage(" Multiple classifiers: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
+                       rebuild = true;
+               } else if (count == 1) {
+                       if (classifier != null) {
+                               // validate classifier
+                               if (! validateClassifier(gate, gateBuilder, response)) {
+                                       rebuild = true;
+                               }
+                       } else if (extClassifier != null) {
+                               //validate ext-classifier
+                               if (! validateExtClassifier(gate, gateBuilder, response)) {
+                                       rebuild = true;
+                               }
+                       } else if (ipv6Classifier != null) {
+                               // TODO FIXME - ipv6Classifier is always null???
+                               // validate ipv6-classifier
+                               if (! validateIpv6Classifier(gate, gateBuilder, response)) {
+                                       rebuild = true;
+                               }
+                       }
+               }
+               // rebuild the gate object with valid data and set the response
+               if (rebuild) {
+                       gateBuilder.setGateId(gate.getGateId());
+                       gateBuilder.setKey(gate.getKey());
+                       // TODO FIXME - the input parameter "gate" is being muted here???
+                       gate = gateBuilder.build();
+                       response.setGateBase(gate);
+                       response.addMessage(message);
+               }
+               return (! rebuild);
+       }
+
+       private boolean validateAmId(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+               // amId
+               String message = "";
+               String error;
+               boolean valid = true;
+               AmId amId = ccap.getAmId();
+               if (amId == null) {
+                       message += " amId is required;";
+                       valid = false;
+               } else {
+                       final Integer amTag;
+                       error = validateMethod(AmId.class, amId, "getAmTag");
+                       if (error == null) {
+                               amTag = amId.getAmTag();
+                               if (amTag == null) {
+                                       message += " amId.amTag missing;";
+                                       valid = false;
+                               }
+                       } else {
+                               message += " amId.amTag invalid: " + error;
+                               amTag = null;
+                               valid = false;
+                       }
+                       final Integer amType;
+                       error = validateMethod(AmId.class, amId, "getAmType");
+                       if (error == null) {
+                               amType = amId.getAmType();
+                               if (amType == null) {
+                                       message += " amId.amType missing;";
+                                       valid = false;
+                               }
+                       } else {
+                               message += " amId.amType invalid: " + error;
+                               amType = null;
+                               valid = false;
+                       }
+                       if (! valid) {
+                               final AmIdBuilder amIdBuilder = new AmIdBuilder();
+                               amIdBuilder.setAmTag(amTag);
+                               amIdBuilder.setAmType(amType);
+                               amId = amIdBuilder.build();
+                               ccapBuilder.setAmId(amId);
+                       }
+               }
+               if (! valid) {
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       private boolean validateConnection(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+               // connection
+               String message = "";
+               String error;
+               boolean valid = true;
+               Connection conn = ccap.getConnection();
+               if (conn == null) {
+                       message += " connection is required;";
+                       valid = false;
+               } else {
+                       // IP address
+                       final IpAddress ipAddress;
+                       error = validateMethod(Connection.class, conn, "getIpAddress");
+                       if (error == null) {
+                               ipAddress = conn.getIpAddress();
+                               if (ipAddress == null) {
+                                       message += " connection.ipAddress missing;";
+                                       valid = false;
+                               }
+                       } else {
+                               message += " connection.ipAddress invalid: " + error;
+                               ipAddress = null;
+                               valid = false;
+                       }
+                       // Port number
+                       final PortNumber portNum;
+                       error = validateMethod(Connection.class, conn, "getPort");
+                       if (error == null) {
+                               portNum = conn.getPort();
+                       } else {
+                               message += " connection.port invalid: " + error;
+                               portNum = null;
+                               valid = false;
+                       }
+                       if (! valid) {
+                               final ConnectionBuilder connBuilder = new ConnectionBuilder();
+                               connBuilder.setIpAddress(ipAddress);
+                               connBuilder.setPort(portNum);
+                               conn = connBuilder.build();
+                               ccapBuilder.setConnection(conn);
+                       }
+               }
+               if (! valid) {
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       private boolean validateSubscriberSubnets(final Ccaps ccap, final CcapsBuilder ccapBuilder,
+                                                                                         final Response response) {
+               // subscriber-subnets
+               String message = "";
+               String error;
+               boolean valid = true;
+               List<IpPrefix> subnets = null;
+               error = validateMethod(Ccaps.class, ccap, "getSubscriberSubnets");
+               if (error == null) {
+                       subnets = ccap.getSubscriberSubnets();
+                       if (subnets == null) {
+                               message += " subscriber-subnets is required;";
+                               valid = false;
+                       }
+               } else {
+                       message += " subscriber-subnets contains invalid IpPrefix - must be <ipaddress>/<prefixlen> format;" + error;
+                       valid = false;
+               }
+               if (! valid) {
+                       // TODO FIXME - subnets is always null???
+                       ccapBuilder.setSubscriberSubnets(subnets);
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       private boolean validateUpstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+               // upstream-scns
+               String message = "";
+               String error;
+               boolean valid = true;
+               List<ServiceClassName> usScns = null;
+               error = validateMethod(Ccaps.class, ccap, "getUpstreamScns");
+               if (error == null) {
+                       usScns = ccap.getUpstreamScns();
+                       if (usScns == null) {
+                               message += " upstream-scns is required;";
+                               valid = false;
+                       }
+               } else {
+                       message += " upstream-scns contains invalid SCN - must be 2-16 characters;" + error;
+                       valid = false;
+               }
+               if (! valid) {
+                       // TODO FIXME - usScns is always null???
+                       ccapBuilder.setUpstreamScns(usScns);
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+       private boolean validateDownstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+               // downstream-scns
+               String message = "";
+               boolean valid = true;
+               List<ServiceClassName> dsScns = null;
+               final String error = validateMethod(Ccaps.class, ccap, "getDownstreamScns");
+               if (error == null) {
+                       dsScns = ccap.getDownstreamScns();
+                       if (dsScns == null) {
+                               message += " downstream-scns is required;";
+                               valid = false;
+                       }
+               } else {
+                       message += " downstream-scns contains invalid SCN - must be 2-16 characters;" + error;
+                       valid = false;
+               }
+               if (! valid) {
+                       // TODO FIXME - dsScns is always null???
+                       ccapBuilder.setDownstreamScns(dsScns);
+                       response.addMessage(message);
+               }
+               return valid;
+       }
+
+
+       // TODO FIXME - Do we really want the ccap parameter object to be muted by this method?
+       private boolean validateCcap(Ccaps ccap, final Response response) {
+               // validate ccap and null out invalid elements as we go
+               final CcapsBuilder ccapBuilder = new CcapsBuilder();
+               String message = "";
+               boolean rebuild = false;
+               // amId
+               if ( ! validateAmId(ccap, ccapBuilder, response))        {
+                       rebuild = true;
+               }
+               // connection
+               if ( ! validateConnection(ccap, ccapBuilder, response))        {
+                       rebuild = true;
+               }
+               // subscriber-subnets
+               if ( ! validateSubscriberSubnets(ccap, ccapBuilder, response))        {
+                       rebuild = true;
+               }
+               // upstream-scns
+               if ( ! validateUpstreamScns(ccap, ccapBuilder, response))        {
+                       rebuild = true;
+               }
+               // downstream-scns
+               if ( ! validateDownstreamScns(ccap, ccapBuilder, response))        {
+                       rebuild = true;
+               }
+               // rebuild the ccap object with valid data and set the response
+               if (rebuild) {
+                       ccapBuilder.setCcapId(ccap.getCcapId());
+                       ccapBuilder.setKey(ccap.getKey());
+                       // TODO FIXME - the input parameter "ccap" is being muted here???
+                       ccap = ccapBuilder.build();
+                       response.setCcapBase(ccap);
+                       response.addMessage(message);
+               }
+               return (! rebuild);
+       }
+}
+
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/packetcable/packetcable/policy/server/impl/rev140131/PacketcableProviderModule.java b/packetcable-policy-server/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/packetcable/packetcable/policy/server/impl/rev140131/PacketcableProviderModule.java
new file mode 100644 (file)
index 0000000..51212ba
--- /dev/null
@@ -0,0 +1,47 @@
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.packetcable.provider.PacketcableProvider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PacketcableProviderModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131.AbstractPacketcableProviderModule {
+    private static final Logger logger = LoggerFactory.getLogger(PacketcableProviderModule.class);
+
+    public PacketcableProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public PacketcableProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131.PacketcableProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        logger.info("Creating PacketcableProvider instance");
+
+        final DataBroker dataBrokerService = getDataBrokerDependency();
+        final PacketcableProvider provider = new PacketcableProvider(dataBrokerService);
+
+        final ListenerRegistration<DataChangeListener> ccapDataChangeListenerRegistration =
+                dataBrokerService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                        PacketcableProvider.ccapIID, provider, DataBroker.DataChangeScope.SUBTREE );
+
+        final ListenerRegistration<DataChangeListener> qosDataChangeListenerRegistration =
+                dataBrokerService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                        PacketcableProvider.qosIID, provider, DataBroker.DataChangeScope.SUBTREE );
+
+
+        logger.info("PacketCableProvider Registered with DataBroker");
+        return provider;
+    }
+
+}
diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/packetcable/packetcable/policy/server/impl/rev140131/PacketcableProviderModuleFactory.java b/packetcable-policy-server/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/packetcable/packetcable/policy/server/impl/rev140131/PacketcableProviderModuleFactory.java
new file mode 100644 (file)
index 0000000..cdd8faa
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: packetcable-policy-server-impl yang module local name: packetcable-policy-server-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Apr 21 12:24:46 MDT 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131;
+public class PacketcableProviderModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131.AbstractPacketcableProviderModuleFactory {
+
+}
diff --git a/packetcable-policy-server/src/main/yang/packetcable-policy-server.yang b/packetcable-policy-server/src/main/yang/packetcable-policy-server.yang
new file mode 100644 (file)
index 0000000..d05911a
--- /dev/null
@@ -0,0 +1,51 @@
+module packetcable-policy-server-impl {
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:packetcable:packetcable-policy-server:impl";
+    prefix "packetcable-policy-server-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+    import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+    import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
+
+    description
+        "This module contains the base YANG definitions for
+        packetcable-policy-server impl implementation.";
+
+    revision "2014-01-31" {
+        description
+            "Initial revision.";
+    }
+
+    // This is the definition of the service implementation as a module identity.
+    identity packetcable-policy-server-impl {
+            base config:module-type;
+            config:java-name-prefix PacketcableProvider;
+    }
+
+    // Augments the 'configuration' choice node under modules/module.
+    augment "/config:modules/config:module/config:configuration" {
+        case packetcable-policy-server-impl {
+            when "/config:modules/config:module/config:type = 'packetcable-policy-server-impl'";
+
+                     //wires in the data-broker and rpc services
+                     container data-broker {
+                       uses config:service-ref {
+                         refine type {
+                             mandatory true;
+                             config:required-identity mdsal:binding-async-data-broker;
+                         }
+                       }
+                     }
+                     container rpc-registry {
+                       uses config:service-ref {
+                         refine type {
+                            mandatory true;
+                            config:required-identity mdsal:binding-rpc-registry;
+                         }
+                       }
+                     }
+        }
+    }
+}
diff --git a/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java b/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java
new file mode 100644 (file)
index 0000000..73de401
--- /dev/null
@@ -0,0 +1,281 @@
+package org.opendaylight.controller.packetcable.provider;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TpProtocol;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.pcmm.gates.IPCMMGate;
+import org.pcmm.rcd.IPCMMClient;
+import org.pcmm.rcd.impl.CMTS;
+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.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+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 the PCMMService's ability to connect to a CMTS. Gate additions will not properly work as there is currently
+ * not any other means to receive acknowledgements. This functionality must be tested by the PCMMService's client
+ * PacketcableProvider.
+ */
+public class PCMMServiceTest {
+
+    /**
+     * The mock CMTS running on localhost with a dynamic port assigned.
+     */
+    private CMTS icmts;
+
+    /**
+     * Represents the IP address of the CM the gate should be set against.
+     */
+    private byte[] cmAddr = new byte[4];
+
+    @Before
+    public void setup() {
+        icmts = new CMTS();
+        icmts.startServer();
+
+        cmAddr[0] = 10;
+        cmAddr[1] = 32;
+        cmAddr[2] = 110;
+        cmAddr[3] = (byte)180;
+    }
+
+    @After
+    public void tearDown() {
+        if (icmts != null) icmts.stopServer();
+    }
+
+    @Test
+    public void testAddCcap() {
+
+        // TODO - comment out for testing
+        //        final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
+//        final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
+
+        // TODO - Use this instead for automated testing
+        final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+        final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
+
+        final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
+        final String message = service.addCcap();
+        Assert.assertNotNull(message);
+        Assert.assertTrue(message, message.startsWith("200"));
+        Assert.assertNotNull(service.ccapClient.pcmmPdp.getClientHandle());
+        service.disconect();
+    }
+
+    @Test
+    public void testAddAndRemoveUpGate() throws Exception {
+
+        // TODO - Use this block to test against a real CMTS
+//        final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
+//        final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
+
+        // TODO - Use this block for automated testing
+        final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+        final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
+
+        final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
+        service.addCcap();
+
+        final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
+        final String gatePath = "testGatePath";
+
+        // Add gate
+        final String msg = service.sendGateSet(gatePath, InetAddress.getByAddress(cmAddr), gate,
+                ServiceFlowDirection.Us);
+        Assert.assertTrue(msg, msg.startsWith("200"));
+
+        // TODO - add validation to the PCMMGateReq contained within the map
+        Assert.assertEquals(1, service.gateRequests.size());
+
+        // Remove gate
+        service.sendGateDelete(gatePath);
+
+        // Wait up to 1 sec for response to be processed
+        final long start = System.currentTimeMillis();
+        while (1000 < System.currentTimeMillis() - start) {
+            if (service.gateRequests.size() == 0) break;
+        }
+        Assert.assertEquals(0, service.gateRequests.size());
+        service.disconect();
+    }
+
+    /**
+     * This tests the instantiation of a COPSDecisionMsg object that is responsible for setting a gate request,
+     * streams it over a mock Socket object and parses the bytes into a new COPSDecisionMsg object which should
+     * be equivalent
+     * @throws Exception - test will fail should any exception be thrown during execution
+     */
+    @Test
+    public void testGateRequestDecisionMsg() throws Exception {
+        final Socket socket = new MockSocket();
+        final Ccaps ccap = makeCcapsObj(icmts.getPort(), "127.0.0.1", "ccap-1");
+        final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+        final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
+        final IPCMMGate gateReq = makeGateRequest(ccap, gate, InetAddress.getByName("localhost"),
+                ServiceFlowDirection.Us);
+        final byte[] data = gateReq.getData();
+
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
+
+        final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("123")),
+                decisionMap, null, clientSD);
+        decisionMsg.writeData(socket);
+
+        final COPSMsg msg = COPSMsgParser.parseMessage(socket);
+        Assert.assertNotNull(msg);
+        Assert.assertEquals(decisionMsg, msg);
+    }
+
+    /**
+     * Creates a mock Ccaps object that can be used for connecting to a CMTS
+     * @param inPort - the CMTS port number
+     * @param ipAddr - the CMTS IPv4 address string
+     * @param ccapId - the ID of the CCAP
+     * @return - the mock Ccaps object
+     */
+    private Ccaps makeCcapsObj(final int inPort, final String ipAddr, final String ccapId) {
+        final Ccaps ccap = Mockito.mock(Ccaps.class);
+        final Connection conn = Mockito.mock(Connection.class);
+        Mockito.when(ccap.getConnection()).thenReturn(conn);
+        final PortNumber port = Mockito.mock(PortNumber.class);
+        Mockito.when(conn.getPort()).thenReturn(port);
+        Mockito.when(port.getValue()).thenReturn(inPort);
+
+        final IpAddress addr = Mockito.mock(IpAddress.class);
+        Mockito.when(conn.getIpAddress()).thenReturn(addr);
+        final Ipv4Address ipv4 = new Ipv4Address(ipAddr);
+        Mockito.when(addr.getIpv4Address()).thenReturn(ipv4);
+
+        Mockito.when(ccap.getCcapId()).thenReturn(ccapId);
+        final AmId amid = Mockito.mock(AmId.class);
+        Mockito.when(ccap.getAmId()).thenReturn(amid);
+        Mockito.when(amid.getAmTag()).thenReturn(0xcada);
+        Mockito.when(amid.getAmType()).thenReturn(1);
+
+        return ccap;
+    }
+
+    /**
+     * Creates a mock Gates object
+     * @param scnValue - the service class name defined on the CMTS
+     * @param dstAddr - the CM address this gate should be set against
+     * @return - the gate request
+     */
+    private Gates makeGateObj(final String scnValue, final Ipv4Address dstAddr, final ServiceFlowDirection direction) {
+        final Gates gate = Mockito.mock(Gates.class);
+        final GateSpec gateSpec = Mockito.mock(GateSpec.class);
+        Mockito.when(gate.getGateSpec()).thenReturn(gateSpec);
+        Mockito.when(gateSpec.getDirection()).thenReturn(direction);
+        // TODO - make sure to write a test when this value is not null
+        Mockito.when(gateSpec.getDscpTosOverwrite()).thenReturn(null);
+        final TrafficProfile trafficProfile = Mockito.mock(TrafficProfile.class);
+        final ServiceClassName scn = Mockito.mock(ServiceClassName.class);
+        Mockito.when(scn.getValue()).thenReturn(scnValue);
+        Mockito.when(trafficProfile.getServiceClassName()).thenReturn(scn);
+        Mockito.when(gate.getTrafficProfile()).thenReturn(trafficProfile);
+
+        // TODO - write tests when this is null and ExtClassifier or Ipv6Classifier objects are not null
+        final Classifier classifier = Mockito.mock(Classifier.class);
+
+        // This is the address of the CM
+        Mockito.when(classifier.getDstIp()).thenReturn(dstAddr);
+
+        final PortNumber dstPort = new PortNumber(4321);
+        Mockito.when(classifier.getDstPort()).thenReturn(dstPort);
+        final TpProtocol protocol = new TpProtocol(0);
+        Mockito.when(classifier.getProtocol()).thenReturn(protocol);
+        final Ipv4Address srcAddr = new Ipv4Address("127.0.0.1");
+        Mockito.when(classifier.getSrcIp()).thenReturn(srcAddr);
+        final PortNumber srcPort = new PortNumber(1234);
+        Mockito.when(classifier.getSrcPort()).thenReturn(srcPort);
+        final TosByte tosByte = new TosByte((short)160);
+        Mockito.when(classifier.getTosByte()).thenReturn(tosByte);
+        final TosByte tosMask = new TosByte((short)224);
+        Mockito.when(classifier.getTosMask()).thenReturn(tosMask);
+
+        // TODO - enhance to test support of the other classifier types
+        Mockito.when(gate.getClassifier()).thenReturn(classifier);
+        Mockito.when(gate.getExtClassifier()).thenReturn(null);
+        Mockito.when(gate.getIpv6Classifier()).thenReturn(null);
+        return gate;
+    }
+
+    private IPCMMGate makeGateRequest(final Ccaps ccap, final Gates gateReq, final InetAddress addrSubId,
+                                     final ServiceFlowDirection direction) {
+        final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
+        gateBuilder.build(ccap.getAmId());
+        gateBuilder.build(addrSubId);
+        // force gateSpec.Direction to align with SCN direction
+        final ServiceClassName scn = gateReq.getTrafficProfile().getServiceClassName();
+        if (scn != null) {
+            gateBuilder.build(gateReq.getGateSpec(), direction);
+        } else {
+            // not an SCN gate
+            gateBuilder.build(gateReq.getGateSpec(), null);
+        }
+        gateBuilder.build(gateReq.getTrafficProfile());
+
+        // pick a classifier type (only one for now)
+        if (gateReq.getClassifier() != null) {
+            gateBuilder.build(gateReq.getClassifier());
+        } else if (gateReq.getExtClassifier() != null) {
+            gateBuilder.build(gateReq.getExtClassifier());
+        } else if (gateReq.getIpv6Classifier() != null) {
+            gateBuilder.build(gateReq.getIpv6Classifier());
+        }
+        // assemble the final gate request
+        return gateBuilder.getGateReq();
+    }
+
+    private class MockSocket extends Socket {
+
+        private ByteArrayOutputStream os = new ByteArrayOutputStream();
+        private ByteArrayInputStream is;
+
+        @Override
+        public OutputStream getOutputStream() {
+            return os;
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            if (is == null) is = new ByteArrayInputStream(os.toByteArray());
+            return is;
+        }
+    }
+
+}
index 92a06bda8264a13613cf5ef00e539069c6508456..924c65088ce7549829b3aaae18538aa1b190a307 100644 (file)
@@ -3,9 +3,6 @@
  */
 package org.opendaylight.controller.packetcable.provider.processors;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
@@ -16,11 +13,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.traffic.profile.best.effort.attributes.BeCommittedEnvelope;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.traffic.profile.best.effort.attributes.BeReservedEnvelope;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.SubscriberIdRpcAddFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.TcpMatchRangesAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.TcpMatchRangesRpcAddFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesRpcAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.tcp.match.ranges.attributes.TcpMatchRanges;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.udp.match.ranges.attributes.UpdMatchRanges;
 import org.pcmm.gates.IClassifier;
@@ -33,6 +26,9 @@ import org.pcmm.gates.impl.ExtendedClassifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
 /**
  * 
  * PacketCable data processor
@@ -64,7 +60,7 @@ public class PCMMDataProcessor {
 
        public IClassifier process(Match match) {
                ExtendedClassifier classifier = new ExtendedClassifier();
-               classifier.setProtocol(IClassifier.Protocol.NONE);
+//             classifier.setProtocol(IClassifier.Protocol.NONE);
                getUdpMatchRangeValues(match.getAugmentation(UdpMatchRangesRpcAddFlow.class), classifier);
                getTcpMatchRangesValues(match.getAugmentation(TcpMatchRangesRpcAddFlow.class), classifier);
                SubscriberIdRpcAddFlow subId = match.getAugmentation(SubscriberIdRpcAddFlow.class);
@@ -145,7 +141,7 @@ public class PCMMDataProcessor {
                short srcPortStart, srcPortEnd, dstPortStart, dstPortEnd;
                srcPortStart = srcPortEnd = dstPortStart = dstPortEnd = 0;
                if (tcpRange != null) {
-                       classifier.setProtocol(IClassifier.Protocol.TCP);
+//                     classifier.setProtocol(IClassifier.Protocol.TCP);
                        TcpMatchRanges tcpMatchRanges = tcpRange.getTcpMatchRanges();
                        PortNumber tcpDestinationPortStart = tcpMatchRanges.getTcpDestinationPortStart();
                        if (tcpDestinationPortStart != null && tcpDestinationPortStart.getValue() != null)
@@ -170,7 +166,7 @@ public class PCMMDataProcessor {
                short srcPortStart, srcPortEnd, dstPortStart, dstPortEnd;
                srcPortStart = srcPortEnd = dstPortStart = dstPortEnd = 0;
                if (updRange != null) {
-                       classifier.setProtocol(IClassifier.Protocol.UDP);
+//                     classifier.setProtocol(IClassifier.Protocol.UDP);
                        UpdMatchRanges updMatchRanges = updRange.getUpdMatchRanges();
                        PortNumber udpDestinationPortStart = updMatchRanges.getUdpDestinationPortStart();
                        if (udpDestinationPortStart != null && udpDestinationPortStart.getValue() != null)
diff --git a/pom.xml b/pom.xml
index 5ea7eefc5ae15dfe1d5c04f2e40d1966d36f5d08..cfeec5b8ad0a68dca3fe3452276b356c6e6a7708 100644 (file)
--- a/pom.xml
+++ b/pom.xml
                <module>features-packetcable</module>
                <module>packetcable-config</module>
                <module>packetcable-karaf</module>
+
+               <!-- New modules for the new Arris API -->
+               <module>packetcable-policy-model</module>
+               <module>packetcable-policy-server</module>
+               <module>features-packetcable-policy</module>
+               <module>packetcable-policy-config</module>
+               <module>packetcable-policy-karaf</module>
        </modules>
        <scm>
                <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>