Add packetcable-driver as a bundle and fix karafe depends. Merge hop-along model... 55/10555/1
authorThomas Kee <xsited@yahoo.com>
Sun, 31 Aug 2014 19:58:29 +0000 (12:58 -0700)
committerThomas Kee <xsited@yahoo.com>
Sun, 31 Aug 2014 19:58:29 +0000 (12:58 -0700)
Change-Id: I83e7fd93fdc7650250a3e05c4903217417b4812d
Signed-off-by: Thomas Kee <xsited@yahoo.com>
172 files changed:
features-packetcable/pom.xml
features-packetcable/src/main/resources/features.xml
packetcable-consumer/pom.xml
packetcable-consumer/src/main/java/org/opendaylight/controller/config/yang/config/pcmm_service/impl/PcmmServiceModule.java [new file with mode: 0644]
packetcable-consumer/src/main/java/org/opendaylight/controller/config/yang/config/pcmm_service/impl/PcmmServiceModuleFactory.java [new file with mode: 0644]
packetcable-consumer/src/main/java/org/opendaylight/controller/org/pcmm/api/PcmmService.java [new file with mode: 0644]
packetcable-consumer/src/main/java/org/opendaylight/controller/org/pcmm/impl/PcmmServiceImpl.java [new file with mode: 0644]
packetcable-consumer/src/main/yang/pcmm-service-impl.yang [new file with mode: 0644]
packetcable-driver/.gitignore [new file with mode: 0644]
packetcable-driver/Makefile [new file with mode: 0644]
packetcable-driver/pom.xml [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMConstants.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMDef.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMGlobalConfig.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMPdpAgent.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMPdpConnection.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMPepAgent.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/PCMMProperties.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/base/IAdapter.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/concurrent/IWorker.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/concurrent/IWorkerPool.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/concurrent/impl/Worker.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/concurrent/impl/WorkerPool.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/gates/impl/package-info.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/messages/IMessage.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/messages/IMessageFactory.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/messages/impl/COPSDecisionMsgEX.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/messages/impl/MessageFactory.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/messages/package-info.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/nio/PCMMChannel.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/objects/PCMMIDHolder.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/objects/PCMMResource.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/objects/PCMMResourceSet.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/objects/PCMMResourcesMapper.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/ICMTS.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMClient.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMPolicyServer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMServer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMClient.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMServer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/impl/CMTS.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/impl/PCMMPolicyServer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/rcd/package-info.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/scd/IApplicationServer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/scd/impl/package-info.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/scd/package-info.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/state/IPCMMRecordKeepingServer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/state/IState.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/state/IStateful.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/state/package-info.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/pcmm/utils/PCMMUtils.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/common/COPSDebug.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/common/COPS_def.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpException.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSAgent.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSConnection.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSDataProcess.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSMsgSender.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSReqStateMan.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepException.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSAgent.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSConnection.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSDataProcess.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSEventListener.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSMsgSender.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSReqStateMan.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpConnection.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpDataProcess.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpException.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpMsgSender.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpReqStateMan.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepAgent.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepConnection.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepDataProcess.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepException.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepMsgSender.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepReqStateMan.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSAcctTimer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientAcceptMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientCloseMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientOpenMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientSI.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSContext.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSData.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecision.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecisionMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSDeleteMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSError.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSException.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSHandle.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeader.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIntegrity.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSInterface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Address.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4InInterface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Interface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4LastPdpAddr.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4OutInterface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpAddress.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Address.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6InInterface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Interface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6LastPdpAddr.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6OutInterface.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpAddress.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSKAMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSKATimer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSLPDPDecision.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsgParser.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjBase.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeader.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPdpAddress.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPepId.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrClassError.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrEPD.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrError.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrErrorPRID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrGlobalError.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrObjBase.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrefixPrID.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReason.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportType.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSReqMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSSyncStateMsg.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSTimer.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSTransceiver.java [new file with mode: 0644]
packetcable-driver/src/main/java/org/umu/cops/stack/COPSUtil.java [new file with mode: 0644]
packetcable-driver/src/main/resources/pcmm.properties [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/BestEffortServiceTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/Main.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/PCErrorTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/PCMMGateReqTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/PCMMResourceSetTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/PCMMWorkflowTest.java [new file with mode: 0644]
packetcable-driver/src/test/java/org/pcmm/test/README.md [new file with mode: 0644]
pom.xml

index 2a3c3ddc71832e82199cddd302119390dbe322ce..0e9e421b7d9dbc0ae5d315d69a43f3a07a7132a0 100644 (file)
           <classifier>features</classifier>
           <type>xml</type>
         </dependency>
-        <dependency>
-          <groupId>org.opendaylight.openflowplugin</groupId>
-          <artifactId>features-openflowplugin</artifactId>
-          <version>0.0.3-SNAPSHOT</version>
-          <classifier>features</classifier>
-          <type>xml</type>
-        </dependency>
       <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>features-flow</artifactId>
         <artifactId>packetcable-model</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.packetcable</groupId>
+        <artifactId>packetcable-driver</artifactId>
+        <version>${project.version}</version>
+      </dependency>
 
     <!--
-      Necessary TODO: Put dependencies for configfiles directly referenced
+      Put dependencies for configfiles directly referenced
       in your features.xml file.  For every <configfile> reference in your
       features.xml file, you need a corresponding dependency here.
 
index cecfeaf67be50fafab86f5af989631170325fbe9..b9b9980e459643c2539b0e5110ea4601136f8087 100644 (file)
@@ -27,6 +27,7 @@
             <feature version='${project.version}'>odl-packetcable-consumer</feature>
             <feature version='${project.version}'>odl-packetcable-provider</feature>
             <feature version='${project.version}'>odl-packetcable-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.
             <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
             <feature version='${project.version}'>odl-packetcable-model</feature>
             <feature version='${project.version}'>odl-packetcable-provider</feature>
-            <bundle>mvn:org.opendaylight.controller.packetcable/packetcable-consumer/${project.version}</bundle>
+            <feature version='${project.version}'>odl-packetcable-driver</feature>
         </feature>
 
         <!--- * Basic MD-SAL Model feature -->
         <feature name='odl-packetcable-model' version='${project.version}' description='OpenDaylight :: packetcable :: Model'>
             <feature version='0.6.2-SNAPSHOT'>odl-yangtools-binding</feature>
             <feature version='0.6.2-SNAPSHOT'>odl-yangtools-models</feature>
-            <!--feature version='0.0.3-SNAPSHOT'>odl-openflowplugin-flow-services</feature-->
-<feature version='${project.version}'>odl-flow-model</feature>
+           <feature version='${project.version}'>odl-flow-model</feature>
             <bundle>mvn:org.opendaylight.controller.packetcable/packetcable-model/${project.version}</bundle>
         </feature>
 
         <feature name='odl-packetcable-provider' version='${project.version}' description='OpenDaylight :: packetcable :: Provider'>
             <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
             <bundle>mvn:org.opendaylight.controller.packetcable/packetcable-provider/${project.version}</bundle>
-            <!--feature version='0.0.3-SNAPSHOT'>odl-openflowplugin-flow-services</feature-->
-<feature version='${project.version}'>odl-flow-model</feature>
+            <bundle>mvn:org.opendaylight.controller.packetcable/packetcable-driver/${project.version}</bundle>
+           <feature version='${project.version}'>odl-flow-model</feature>
             <feature version='${project.version}'>odl-packetcable-model</feature>
+            <feature version='${project.version}'>odl-packetcable-driver</feature>
         </feature>
 
+        <!--- * * -->
+        <feature name='odl-packetcable-driver' version='${project.version}' description='OpenDaylight :: packetcable :: Driver'>
+            <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
+       </feature>
+
 </features>
index c1da112874fd8c1924ce3ca0cb9431694af22994..1f76dc3821781415fe13cc1ae730e25f2d6407ef 100644 (file)
       <version>${project.version}</version>
     </dependency>
     <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>packetcable-driver</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+       <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-api</artifactId>
     </dependency>
diff --git a/packetcable-consumer/src/main/java/org/opendaylight/controller/config/yang/config/pcmm_service/impl/PcmmServiceModule.java b/packetcable-consumer/src/main/java/org/opendaylight/controller/config/yang/config/pcmm_service/impl/PcmmServiceModule.java
new file mode 100644 (file)
index 0000000..7c20cf5
--- /dev/null
@@ -0,0 +1,52 @@
+package org.opendaylight.controller.config.yang.config.pcmm_service.impl;
+
+import org.opendaylight.controller.org.pcmm.api.PcmmService;
+import org.opendaylight.controller.org.pcmm.impl.PcmmServiceImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.service.rev140120.PacketcableServiceService;
+import org.opendaylight.yangtools.concepts.Registration;
+
+public class PcmmServiceModule
+               extends
+               org.opendaylight.controller.config.yang.config.pcmm_service.impl.AbstractPcmmServiceModule {
+       public PcmmServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+               super(identifier, dependencyResolver);
+       }
+
+       public PcmmServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.pcmm_service.impl.PcmmServiceModule 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() {
+               PacketcableServiceService packetcableServiceService = getRpcRegistryDependency().getRpcService(PacketcableServiceService.class);
+               final PcmmService pcmmService = new PcmmServiceImpl(packetcableServiceService);
+               final Registration pcmmListenerReg = getNotificationServiceDependency().registerNotificationListener(pcmmService);
+               final PcmmServiceRuntimeRegistration runtimeReg = getRootRuntimeBeanRegistratorWrapper().register(pcmmService);
+               return new AutoCloseablePcmmService(packetcableServiceService, pcmmListenerReg, runtimeReg);
+       }
+
+       class AutoCloseablePcmmService extends PcmmServiceImpl implements
+                       AutoCloseable {
+               
+               private PcmmServiceRuntimeRegistration runtimeReg;
+               private Registration pcmmListenerReg;
+
+               public AutoCloseablePcmmService(PacketcableServiceService packetcableServiceService, Registration pcmmListenerReg, PcmmServiceRuntimeRegistration runtimeReg) {
+                       super(packetcableServiceService);
+                       this.runtimeReg = runtimeReg;
+                       this.pcmmListenerReg = pcmmListenerReg;
+               }
+
+               @Override
+               public void close() throws Exception {
+                       pcmmListenerReg.close();
+                       runtimeReg.close();
+               }
+
+       }
+}
diff --git a/packetcable-consumer/src/main/java/org/opendaylight/controller/config/yang/config/pcmm_service/impl/PcmmServiceModuleFactory.java b/packetcable-consumer/src/main/java/org/opendaylight/controller/config/yang/config/pcmm_service/impl/PcmmServiceModuleFactory.java
new file mode 100644 (file)
index 0000000..7c6662c
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: pcmm-service-impl yang module local name: pcmm-service-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Aug 11 19:34:09 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.pcmm_service.impl;
+public class PcmmServiceModuleFactory extends org.opendaylight.controller.config.yang.config.pcmm_service.impl.AbstractPcmmServiceModuleFactory {
+
+}
diff --git a/packetcable-consumer/src/main/java/org/opendaylight/controller/org/pcmm/api/PcmmService.java b/packetcable-consumer/src/main/java/org/opendaylight/controller/org/pcmm/api/PcmmService.java
new file mode 100644 (file)
index 0000000..c5d5317
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.org.pcmm.api;
+
+import org.opendaylight.controller.config.yang.config.pcmm_service.impl.PcmmServiceRuntimeMXBean;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.service.rev140120.PacketcableServiceListener;
+
+public interface PcmmService extends PcmmServiceRuntimeMXBean,
+               PacketcableServiceListener {
+
+}
diff --git a/packetcable-consumer/src/main/java/org/opendaylight/controller/org/pcmm/impl/PcmmServiceImpl.java b/packetcable-consumer/src/main/java/org/opendaylight/controller/org/pcmm/impl/PcmmServiceImpl.java
new file mode 100644 (file)
index 0000000..8972271
--- /dev/null
@@ -0,0 +1,99 @@
+package org.opendaylight.controller.org.pcmm.impl;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+
+import org.opendaylight.controller.org.pcmm.api.PcmmService;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.cmts.rev140120.CmtsReference;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.service.rev140120.CmtsAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.service.rev140120.CmtsRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.service.rev140120.CmtsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.service.rev140120.PacketcableServiceService;
+import org.pcmm.rcd.IPCMMPolicyServer;
+import org.pcmm.rcd.IPCMMPolicyServer.IPSCMTSClient;
+import org.pcmm.rcd.impl.PCMMPolicyServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class PcmmServiceImpl implements PcmmService {
+
+       private static final Logger log = LoggerFactory.getLogger(PcmmServiceImpl.class);
+       private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+       private PacketcableServiceService packetcableServiceService;
+       private List<IpAddress> cmtsList;
+       private Map<CmtsReference, IPSCMTSClient> cmtsClients;
+       private IPCMMPolicyServer policyServer;
+
+       public PcmmServiceImpl(PacketcableServiceService packetcableServiceService) {
+               this.packetcableServiceService = packetcableServiceService;
+               policyServer = new PCMMPolicyServer();
+               cmtsClients = Maps.newConcurrentMap();
+               cmtsList = Lists.newArrayList();
+       }
+
+       @Override
+       public void onCmtsAdded(CmtsAdded notification) {
+               String ipv4 = notification.getId().getIpv4Address().getValue();
+               IPSCMTSClient client = policyServer.requestCMTSConnection(ipv4);
+               if (client.isConnected()) {
+                       cmtsClients.put(notification.getCmtsRef(), client);
+                       cmtsList.add(notification.getId());
+               }
+       }
+
+       @Override
+       public void onCmtsRemoved(CmtsRemoved notification) {
+               if (cmtsList.contains(notification.getId()))
+                       cmtsList.remove(notification.getId());
+               if (cmtsClients.containsKey(notification.getCmtsRef())) {
+                       IPSCMTSClient client = cmtsClients.remove(notification.getCmtsRef());
+                       client.disconnect();
+               }
+       }
+
+       @Override
+       public void onCmtsUpdated(CmtsUpdated notification) {
+               // TODO
+       }
+
+       @Override
+       public Boolean sendGateDelete() {
+               // TODO change me
+               boolean ret = true;
+               for (Iterator<IPSCMTSClient> iter = cmtsClients.values().iterator(); iter.hasNext();)
+                       ret &= cmtsClients.get(0).gateDelete();
+               return ret;
+       }
+
+       @Override
+       public Boolean sendGateSynchronize() {
+               boolean ret = true;
+               for (Iterator<IPSCMTSClient> iter = cmtsClients.values().iterator(); iter.hasNext();)
+                       ret &= cmtsClients.get(0).gateSynchronize();
+               return ret;
+       }
+
+       @Override
+       public Boolean sendGateInfo() {
+               boolean ret = true;
+               for (Iterator<IPSCMTSClient> iter = cmtsClients.values().iterator(); iter.hasNext();)
+                       ret &= cmtsClients.get(0).gateInfo();
+               return ret;
+       }
+
+       @Override
+       public Boolean sendGateSet() {
+               boolean ret = true;
+               for (Iterator<IPSCMTSClient> iter = cmtsClients.values().iterator(); iter.hasNext();)
+                       ret &= cmtsClients.get(0).gateSet();
+               return ret;
+       }
+}
diff --git a/packetcable-consumer/src/main/yang/pcmm-service-impl.yang b/packetcable-consumer/src/main/yang/pcmm-service-impl.yang
new file mode 100644 (file)
index 0000000..8b7e78d
--- /dev/null
@@ -0,0 +1,153 @@
+module pcmm-service-impl {
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:pcmm-service:impl";
+    prefix "pcmm-service-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; }
+
+    description
+        "This module contains the base YANG definitions for
+        pcmm-service impl implementation.";
+
+    revision "2014-08-10" {
+        description
+            "Initial revision.";
+    }
+
+    // This is the definition of pcmm service interface identity.
+    identity pcmm-service {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.org.pcmm.api.PcmmService";
+    }
+
+    // This is the definition of pcmm service implementation module identity. 
+    identity pcmm-service-impl {
+            base config:module-type;
+            config:provided-service pcmm-service;
+            config:java-name-prefix PcmmService;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case pcmm-service-impl {
+            when "/config:modules/config:module/config:type = 'pcmm-service-impl'";
+
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-rpc-registry;
+                    }
+                }
+            }
+
+            container notification-service {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-notification-service;
+                    }
+                }
+            }
+        }
+    }
+    
+    augment "/config:modules/config:module/config:state" {
+        case pcmm-service-impl {
+            when "/config:modules/config:module/config:type = 'pcmm-service-impl'";
+            
+            rpcx:rpc-context-instance "send-gate-set-rpc";
+            rpcx:rpc-context-instance "send-gate-delete-rpc";
+            rpcx:rpc-context-instance "send-gate-info-rpc";
+            rpcx:rpc-context-instance "send-gate-synchronize-rpc";
+              
+        }
+    }
+
+    identity send-gate-set-rpc;
+
+    rpc send-gate-set {
+        description
+          "Shortcut JMX call to send a gate-set message for testing.";
+          
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance send-gate-set-rpc;
+                }
+            }
+        }
+        
+        output {
+            leaf result {
+                type boolean;
+            }
+        }
+    }
+    
+      identity send-gate-delete-rpc;
+
+    rpc send-gate-delete {
+        description
+          "Shortcut JMX call to send a gate-delete message for testing.";
+          
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance send-gate-delete-rpc;
+                }
+            }
+        }
+        
+        output {
+            leaf result {
+                type boolean;
+            }
+        }
+    }
+    
+     identity send-gate-synchronize-rpc;
+
+    rpc send-gate-synchronize {
+        description
+          "Shortcut JMX call to send a gate-Synchronize message for testing.";
+          
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance send-gate-synchronize-rpc;
+                }
+            }
+        }
+        
+        output {
+            leaf result {
+                type boolean;
+            }
+        }
+    }
+    
+          identity send-gate-info-rpc;
+
+    rpc send-gate-info {
+        description
+          "Shortcut JMX call to send a gate-info message for testing.";
+          
+        input {
+            uses rpcx:rpc-context-ref {
+                refine context-instance {
+                    rpcx:rpc-context-instance send-gate-info-rpc;
+                }
+            }
+        }
+        
+        output {
+            leaf result {
+                type boolean;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packetcable-driver/.gitignore b/packetcable-driver/.gitignore
new file mode 100644 (file)
index 0000000..ea8c4bf
--- /dev/null
@@ -0,0 +1 @@
+/target
diff --git a/packetcable-driver/Makefile b/packetcable-driver/Makefile
new file mode 100644 (file)
index 0000000..f7a5699
--- /dev/null
@@ -0,0 +1,82 @@
+# define compiler and compiler flag variables
+
+JFLAGS = -g
+JC = javac
+JUNIT=/usr/share/junit/junit.jar
+JCOPS=src/main/java/jcops.jar
+PCMM=src/main/java/pcmm.jar
+CLASSPATH =  -classpath .:$(PCMM):$(JCOPS):$(JUNIT)
+JFLAGS = -encoding UTF-8  $(CLASSPATH) 
+JAR_PKG = Test.jar
+
+
+#
+# Clear any default targets for building .class files from .java files; we 
+# will provide our own target entry to do this in this makefile.
+# make has a set of default targets for different suffixes (like .c.o) 
+# Currently, clearing the default for .java.class is not necessary since 
+# make does not have a definition for this target, but later versions of 
+# make may, so it doesn't hurt to make sure that we clear any default 
+# definitions for these
+#
+
+.SUFFIXES: .java .class
+
+
+#
+# Here is our target entry for creating .class files from .java files 
+# This is a target entry that uses the suffix rule syntax:
+#      DSTS:
+#              rule
+#  'TS' is the suffix of the target file, 'DS' is the suffix of the dependency 
+#  file, and 'rule'  is the rule for building a target 
+# '$*' is a built-in macro that gets the basename of the current target 
+# Remember that there must be a < tab > before the command line ('rule') 
+#
+
+.java.class:
+       $(JC) $(JFLAGS) $*.java
+
+
+#
+# CLASSES is a macro consisting of 4 words (one for each java source file)
+#
+
+SOURCES = \
+        Main.java \
+        Test.java 
+
+
+CLASSES = $(SOURCES:%.java=%.class)
+
+#
+# the default make target entry
+#
+
+default: classes 
+
+
+#
+# This target entry uses Suffix Replacement within a macro: 
+# $(name:string1=string2)
+#      In the words in the macro named 'name' replace 'string1' with 'string2'
+# Below we are replacing the suffix .java of all words in the macro CLASSES 
+# with the .class suffix
+#
+
+classes: $(SOURCES:.java=.class)
+
+jar:
+       jar cve $(JAR_PKG) $(CLASSES)
+
+tar:
+       tar czpf $(TARBALL) $(SOURCES) Makefile
+
+
+#
+# RM is a predefined macro in make (RM = rm -f)
+#
+
+clean:
+       $(RM) *.class
+
diff --git a/packetcable-driver/pom.xml b/packetcable-driver/pom.xml
new file mode 100644 (file)
index 0000000..00b09e4
--- /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.controller.packetcable</groupId>
+               <artifactId>packetcable-plugin</artifactId>
+               <version>1.1-SNAPSHOT</version>
+       </parent>
+       <artifactId>packetcable-driver</artifactId>
+       <packaging>bundle</packaging>
+       
+       <description>
+        A lightweight implementation of PCMM COPS PDP client
+    </description>
+
+       <url></url>
+       <inceptionYear>2013</inceptionYear>
+
+       <licenses>
+               <license>
+               </license>
+       </licenses>
+
+       <mailingLists>
+               <mailingList>
+               </mailingList>
+       </mailingLists>
+
+       <developers>
+               <developer>
+               </developer>
+       </developers>
+
+       <contributors>
+               <contributor>
+               </contributor>
+       </contributors>
+
+       <scm>
+               <connection></connection>
+               <developerConnection></developerConnection>
+               <url></url>
+       </scm>
+
+       <issueManagement>
+               <system></system>
+               <url></url>
+       </issueManagement>
+
+       <properties>
+               <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+               <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
+               <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+               <nexus.repository.snapshot>opendaylight.snapshot</nexus.repository.snapshot>
+               <nexus.repository.release>opendaylight.release</nexus.repository.release>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>4.11</version>
+               </dependency>
+               <dependency>
+                       <groupId>ch.qos.logback</groupId>
+                       <artifactId>logback-core</artifactId>
+                       <version>1.0.9</version>
+               </dependency>
+               <dependency>
+                       <groupId>ch.qos.logback</groupId>
+                       <artifactId>logback-classic</artifactId>
+                       <version>1.0.9</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.guava</groupId>
+                       <artifactId>guava</artifactId>
+                       <version>13.0.1</version>
+               </dependency>
+               <dependency>
+                       <groupId>javax.sip</groupId>
+                       <artifactId>jain-sip-ri</artifactId>
+                       <version>1.2.158</version>
+               </dependency>
+               <dependency>
+                       <groupId>commons-primitives</groupId>
+                       <artifactId>commons-primitives</artifactId>
+                       <version>20041207.202534</version>
+               </dependency>
+       </dependencies>
+
+       <modules></modules>
+
+       <build>
+               <directory>${project.basedir}/target</directory>
+               <outputDirectory>${project.build.directory}/classes</outputDirectory>
+               <finalName>${project.artifactId}-${project.version}</finalName>
+               <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
+               <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
+               <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
+               <resources>
+                       <resource>
+                               <directory>${project.basedir}/src/main/resources</directory>
+                       </resource>
+               </resources>
+               <testResources>
+                       <testResource>
+                               <directory>${project.basedir}/src/test/resources</directory>
+                       </testResource>
+               </testResources>
+               <plugins>
+                       <plugin>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                               <version>3.0</version>
+                               <configuration>
+                                       <source>1.7</source>
+                                       <target>1.7</target>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMConstants.java b/packetcable-driver/src/main/java/org/pcmm/PCMMConstants.java
new file mode 100644 (file)
index 0000000..accce63
--- /dev/null
@@ -0,0 +1,19 @@
+package org.pcmm;
+
+public interface PCMMConstants {
+
+       // Port used by the PCMM
+       public static final String PCMM_PORT = "pcmm.port";
+       // Pool size, determining the number of connections that could be
+       // established with CMTSs
+       public static final String PS_POOL_SIZE = "pcmm.ps.pool.size";
+       // Default keep-alive timer value (secs)
+       public static final String KA_TIMER = "pcmm.keep.alive.timer";
+       // Default accounting timer value (secs)
+       public static final String ACC_TIMER = "pcmm.accounting.timer";
+       // default ip mask
+       public static final String DEFAULT_MASK = "pcmm.default.mask";
+       // default timeout
+       public static final String DEFAULT_TIEMOUT = "pcmm.default.timeout";
+
+}
\ No newline at end of file
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMDef.java b/packetcable-driver/src/main/java/org/pcmm/PCMMDef.java
new file mode 100644 (file)
index 0000000..3b5758e
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+import org.umu.cops.common.COPS_def;
+
+public class PCMMDef extends COPS_def {
+
+    public static final short C_PCMM = (short) 0x800A;
+
+    /**
+     * Get a representative string for an COPS Client Type.
+     *
+     * @param cType
+     *            COPS Client Type
+     * @return A representative <tt>String</tt>
+     *
+     */
+    public String strClientType(short cType) {
+        switch (cType) {
+        case C_PCMM:
+            return ("C_PCMM");
+        default:
+            return super.strClientType(cType);
+        }
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMGlobalConfig.java b/packetcable-driver/src/main/java/org/pcmm/PCMMGlobalConfig.java
new file mode 100644 (file)
index 0000000..4f7f605
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+public class PCMMGlobalConfig {
+    // System
+    public static int Debug = 0;
+    public static int LogLevel = 0;
+    public static int DefaultBestEffortTrafficRate = 2500000;
+    // Service Flow Attributes Defaults
+    public static int DefaultBestEffortClassPriority = 69;
+    public static int DefaultUnsolicatedGrantSize = 1000;
+    public static int DefaultUnsolicatedGrantsPerInterval = 3;
+    public static int DefaultUnsolicatedGrantInterval = 8000;
+    // Gate Specification Defaults
+    public static int DSCPToSMark = 0;
+    public static int Priority = 0;
+    public static int PreEmption = 0;
+    public static int GateFlags = 0;
+    public static int GateTOSField = 0;
+    public static int GateTOSMask = 0;
+    public static int GateClass = 0;
+    // Authorization life timer
+    public static short GateT1 = 200;
+    // Authorization renew timer
+    public static short GateT2 = 300;
+    // Reservation life timer
+    public static short GateT3 = 0;
+    // Reservation renew timer
+    public static short GateT4 = 0;
+
+    // XXX - A new home for some of these @ org.pcmm.gates.impl.BestEffortService
+    public static int UGSTransmissionPolicy = 0x037F;
+    public static int BETransmissionPolicy = 0x0;
+    public static int BETrafficPriority = 0x0;
+    public static byte EClassifierPriority = 0x45;
+
+    // Temporary Configure Items For Demo or Lacking Design
+    public static int DefaultLowBestEffortTrafficRate = 500000;
+    public static int DefaultVideoSourcePort = 8081;
+    public static int DefaultAlternateSourcePort = 1369;
+    // public static String DefaultCMTS = "127.0.0.1"
+
+/*  Demo Kit Layout
+    public static String DefaultCMTS = "10.32.4.3";
+    public static String SubscriberID = "10.32.104.2";
+    public static String dstIP = "10.32.4.208";
+    public static String srcIP = "10.32.154.2";
+*/
+
+/*  LAB Bench Layout */
+    public static String DefaultCMTS = "10.32.15.3";
+    public static String SubscriberID = "10.32.115.143";
+    public static String dstIP = "10.32.0.234";
+    public static String srcIP = "10.32.215.111";
+
+    public static String DefautRadius = "192.168.50.2";
+    public static short srcPort = 8081;
+    public static short dstPort = 0;
+    public static int GateID1 = 0;
+    public static int GateID2 = 0;
+    public static void setGateID1(int n) {
+        GateID1 = n;
+    }
+    public static int getGateID1() {
+        return GateID1;
+    }
+    public static void setGateID2(int n) {
+        GateID2 = n;
+    }
+    public static int getGateID2() {
+        return GateID2;
+    }
+}
+
+/*
+ *
+ * // if(Constants.DEBUG.isEnabled()) { } public enum Constants { DEBUG(true),
+ * PRINT_VARS(false);
+ *
+ * private boolean enabled;
+ *
+ * private Constants(boolean enabled) { this.enabled = enabled; }
+ *
+ * public boolean isEnabled() { return enabled; } }
+ */
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpAgent.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpAgent.java
new file mode 100644 (file)
index 0000000..dbe6b07
--- /dev/null
@@ -0,0 +1,411 @@
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import org.umu.cops.common.COPSDebug;
+import org.umu.cops.ospep.COPSPepException;
+import org.umu.cops.prpdp.COPSPdpAgent;
+import org.umu.cops.prpdp.COPSPdpException;
+import org.umu.cops.stack.COPSAcctTimer;
+import org.umu.cops.stack.COPSClientAcceptMsg;
+import org.umu.cops.stack.COPSClientCloseMsg;
+import org.umu.cops.stack.COPSClientOpenMsg;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSKATimer;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSPepId;
+import org.umu.cops.stack.COPSReqMsg;
+import org.umu.cops.stack.COPSTransceiver;
+// import org.umu.cops.prpdp.COPSPdpDataProcess;
+import org.pcmm.objects.MMVersionInfo;
+
+
+/**
+ * Core PDP agent for provisioning
+ */
+public class PCMMPdpAgent extends COPSPdpAgent {
+    /** 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;
+
+    /**
+     * PEP port
+     */
+    private int psPort;
+
+    private Socket socket;
+
+    /**
+     * Policy data processing object
+     */
+    private PCMMPdpDataProcess _process;
+    private MMVersionInfo _mminfo;
+    private COPSHandle _handle;
+    private short _transactionID;
+
+    /**
+     * Creates a PDP Agent
+     *
+     * @param clientType
+     *            COPS Client-type
+     * @param process
+     *            Object to perform policy data processing
+     */
+    public PCMMPdpAgent(short clientType, PCMMPdpDataProcess process) {
+        this(clientType, null, WELL_KNOWN_PDP_PORT, process);
+    }
+
+    /**
+     * 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
+     */
+    public PCMMPdpAgent(short clientType, String psHost, int psPort, PCMMPdpDataProcess process) {
+        super(psPort, clientType, null);
+        this._process = process;
+        this.psHost = psHost;
+    }
+
+    /**
+     * XXX -tek- This is the retooled connect. Not sure if the while forever
+     * loop is needed. Socket accept --> handleClientOpenMsg --> pdpConn.run()
+     *
+     * Below is new Thread(pdpConn).start(); Does that do it?
+     *
+     */
+    /**
+     * 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 COPSPepException
+     */
+    public boolean connect(String psHost, int psPort)
+    throws UnknownHostException, IOException, COPSException,
+                COPSPdpException {
+
+        this.psHost = psHost;
+        this.psPort = psPort;
+        // Create Socket and send OPN
+        InetAddress addr = InetAddress.getByName(psHost);
+        try {
+            socket = new Socket(addr, psPort);
+        } catch (IOException e) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);
+            return (false);
+        }
+        COPSDebug.err(getClass().getName(), "PDP Socket Opened");
+        // Loop through for Incoming messages
+
+        // server infinite loop
+        // while(true)
+        {
+
+            // We're waiting for an message
+            try {
+                COPSDebug.err(getClass().getName(),
+                              "PDP  COPSTransceiver.receiveMsg ");
+                COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+                if (msg.getHeader().isAClientOpen()) {
+                    COPSDebug.err(getClass().getName(),
+                                  "PDP msg.getHeader().isAClientOpen");
+                    handleClientOpenMsg(socket, msg);
+                } else {
+                    // COPSDebug.err(getClass().getName(),
+                    // COPSDebug.ERROR_NOEXPECTEDMSG);
+                    try {
+                        socket.close();
+                    } catch (Exception ex) {
+                    }
+                    ;
+                }
+            } catch (Exception e) { // COPSException, IOException
+                // COPSDebug.err(getClass().getName(),
+                // COPSDebug.ERROR_EXCEPTION,
+                // "(" + socket.getInetAddress() + ":" + socket.getPort() + ")",
+                // e);
+                try {
+                    socket.close();
+                } catch (Exception 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(Socket conn, COPSMsg msg)
+    throws COPSException, IOException {
+        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
+        COPSPepId pepId = cMsg.getPepId();
+
+        // Validate Client Type
+        if (msg.getHeader().getClientType() != getClientType()) {
+            // Unsupported client type
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
+                                             .getHeader().getClientType());
+            COPSError err = new COPSError(
+                COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
+            closeMsg.add(cHdr);
+            closeMsg.add(err);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+            }
+
+            throw new COPSException("Unsupported client type");
+        }
+
+        // PEPId is mandatory
+        if (pepId == null) {
+            // Mandatory COPS object missing
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
+                                             .getHeader().getClientType());
+            COPSError err = new COPSError(
+                COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
+            closeMsg.add(cHdr);
+            closeMsg.add(err);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+            }
+
+            throw new COPSException("Mandatory COPS object missing (PEPId)");
+        }
+        setPepId(pepId);
+        // Support
+        if ((cMsg.getClientSI() != null) ) {
+            _mminfo = new MMVersionInfo(cMsg
+                                        .getClientSI().getData().getData());
+            System.out.println("CMTS sent MMVersion info : major:"
+                               + _mminfo.getMajorVersionNB() + "  minor:"
+                               + _mminfo.getMinorVersionNB());
+
+        } else {
+            // Unsupported objects
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
+                                             .getHeader().getClientType());
+            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT,
+                                          (short) 0);
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
+            closeMsg.add(cHdr);
+            closeMsg.add(err);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+            }
+
+            throw new COPSException("Unsupported objects (PdpAddress, Integrity)");
+        }
+        /*
+        */
+
+        // Connection accepted
+        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg
+                                         .getHeader().getClientType());
+        COPSKATimer katimer = new COPSKATimer(getKaTimer());
+        COPSAcctTimer acctTimer = new COPSAcctTimer(getAcctTimer());
+        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();
+        acceptMsg.add(ahdr);
+        acceptMsg.add(katimer);
+        if (getAcctTimer() != 0)
+            acceptMsg.add(acctTimer);
+        acceptMsg.writeData(conn);
+        // XXX - handleRequestMsg
+        try {
+            COPSDebug.err(getClass().getName(), "PDP COPSTransceiver.receiveMsg ");
+            COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
+            // Client-Close
+            if (rmsg.getHeader().isAClientClose()) {
+                System.out.println(((COPSClientCloseMsg) rmsg)
+                                   .getError().getDescription());
+                // close the socket
+                COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg
+                                                 .getHeader().getClientType());
+                COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT,
+                                              (short) 0);
+                COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
+                closeMsg.add(cHdr);
+                closeMsg.add(err);
+                try {
+                    closeMsg.writeData(conn);
+                } catch (IOException unae) {
+                }
+                throw new COPSException("CMTS requetsed Client-Close");
+            } else {
+                // Request
+                if (rmsg.getHeader().isARequest()) {
+                    COPSReqMsg rMsg = (COPSReqMsg) rmsg;
+                    _handle = rMsg.getClientHandle();
+                } else
+                    throw new COPSException("Can't understand request");
+
+            }
+        } catch (Exception e) { // COPSException, IOException
+            throw new COPSException("Error COPSTransceiver.receiveMsg");
+        }
+
+        COPSDebug.err(getClass().getName(), "PDPCOPSConnection");
+        PCMMPdpConnection pdpConn = new PCMMPdpConnection(pepId, conn, _process);
+        pdpConn.setKaTimer(getKaTimer());
+        if (getAcctTimer() != 0)
+            pdpConn.setAccTimer(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);
+        try {
+            man.initRequestState(conn);
+        } catch (COPSPdpException unae) {
+        }
+        // XXX - End handleRequestMsg
+
+        COPSDebug.err(getClass().getName(), "PDP Thread(pdpConn).start");
+        new Thread(pdpConn).start();
+        getConnectionMap().put(pepId.getData().str(), pdpConn);
+    }
+
+    /**
+     * @return the _psHost
+     */
+    public String getPsHost() {
+        return psHost;
+    }
+
+    /**
+     * @param _psHost
+     *            the _psHost to set
+     */
+    public void setPsHost(String _psHost) {
+        this.psHost = _psHost;
+    }
+
+    /**
+     * @return the _psPort
+     */
+    public int getPsPort() {
+        return psPort;
+    }
+
+    /**
+     * @param _psPort
+     *            the _psPort to set
+     */
+    public void setPsPort(int _psPort) {
+        this.psPort = _psPort;
+    }
+
+    /**
+     * @return the socket
+     */
+    public Socket getSocket() {
+        return socket;
+    }
+
+    /**
+     * @param socket
+     *            the socket to set
+     */
+    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;
+    }
+
+    /**
+      * Sets the PepId
+      * @param   <tt>COPSPepId</tt>
+      */
+    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();
+    }
+
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpConnection.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpConnection.java
new file mode 100644 (file)
index 0000000..ceb5ccd
--- /dev/null
@@ -0,0 +1,553 @@
+/*\r
+ @header@\r
+ */\r
+\r
+package org.pcmm;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Date;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.prpdp.COPSPdpException;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKAMsg;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * Class for managing an provisioning connection at the PDP side.\r
+ */\r
+public class PCMMPdpConnection implements Runnable {\r
+\r
+    /**\r
+    Socket connected to PEP\r
+     */\r
+    private Socket _sock;\r
+\r
+    /**\r
+    PEP identifier\r
+    */\r
+    private COPSPepId _pepId;\r
+\r
+    /**\r
+    Time of the latest keep-alive sent\r
+     */\r
+    private Date _lastKa;\r
+\r
+    /**\r
+   Opcode of the latest message sent\r
+    */\r
+    private byte _lastmessage;\r
+\r
+    /**\r
+     *  Time of the latest keep-alive received\r
+     */\r
+    protected Date _lastRecKa;\r
+\r
+    /**\r
+   Maps a Client Handle to a Handler\r
+     */\r
+    protected Hashtable _managerMap;\r
+    // map < String(COPSHandle), COPSPdpHandler> HandlerMap;\r
+\r
+    /**\r
+     *  PDP policy data processor class\r
+     */\r
+    protected PCMMPdpDataProcess _process;\r
+\r
+    /**\r
+   Accounting timer value (secs)\r
+     */\r
+    protected short _acctTimer;\r
+\r
+    /**\r
+   Keep-alive timer value (secs)\r
+     */\r
+    protected short _kaTimer;\r
+\r
+    /**\r
+   COPS error returned by PEP\r
+     */\r
+    protected COPSError _error;\r
+\r
+    /**\r
+     * Creates a new PDP connection\r
+     *\r
+     * @param pepId PEP-ID of the connected PEP\r
+     * @param sock Socket connected to PEP\r
+     * @param process Object for processing policy data\r
+     */\r
+    public PCMMPdpConnection(COPSPepId pepId, Socket sock, PCMMPdpDataProcess process) {\r
+        _sock = sock;\r
+        _pepId = pepId;\r
+\r
+        _lastKa = new Date();\r
+        _lastmessage = COPSHeader.COPS_OP_OPN;\r
+        _managerMap = new Hashtable(20);\r
+\r
+        _kaTimer = 120;\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Gets the time of that latest keep-alive sent\r
+     * @return Time of that latest keep-alive sent\r
+     */\r
+    public Date getLastKAlive() {\r
+        return _lastKa;\r
+    }\r
+\r
+    /**\r
+     * Sets the keep-alive timer value\r
+     * @param kaTimer Keep-alive timer value (secs)\r
+     */\r
+    public void setKaTimer(short kaTimer) {\r
+        _kaTimer = kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the keep-alive timer value\r
+     * @return Keep-alive timer value (secs)\r
+     */\r
+    public short getKaTimer() {\r
+        return _kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Sets the accounting timer value\r
+     * @param acctTimer Accounting timer value (secs)\r
+     */\r
+    public void setAccTimer(short acctTimer) {\r
+        _acctTimer = acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the accounting timer value\r
+     * @return Accounting timer value (secs)\r
+     */\r
+    public short getAcctTimer() {\r
+        return _acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the latest COPS message\r
+     * @return   Code of the latest message sent\r
+     */\r
+    public byte getLastMessage() {\r
+        return _lastmessage;\r
+    }\r
+\r
+    /**\r
+     * Gets active handles\r
+     * @return   An <tt>Enumeration</tt> holding all active handles\r
+     */\r
+    public Enumeration getHandles() {\r
+        return _managerMap.keys();\r
+    }\r
+\r
+    /**\r
+     * Gets the handle map\r
+     * @return   A <tt>Hashtable</tt> holding the handle map\r
+     */\r
+    public Hashtable getReqStateMans() {\r
+        return _managerMap;\r
+    }\r
+\r
+    /**\r
+     * Gets the PEP-ID\r
+     * @return   The ID of the PEP, as a <tt>String</tt>\r
+     */\r
+    public String getPepId() {\r
+        return _pepId.getData().str();\r
+    }\r
+\r
+    /**\r
+     * Checks whether the socket to the PEP is closed or not\r
+     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise\r
+     */\r
+    public boolean isClosed() {\r
+        return _sock.isClosed();\r
+    }\r
+\r
+    /**\r
+     * Closes the socket to the PEP\r
+     * @throws IOException\r
+     */\r
+    protected void close()\r
+    throws IOException {\r
+        _sock.close();\r
+    }\r
+\r
+    /**\r
+     * Gets the socket to the PEP\r
+     * @return   Socket connected to the PEP\r
+     */\r
+    public Socket getSocket() {\r
+        return _sock;\r
+    }\r
+\r
+    /**\r
+     * Main loop\r
+     */\r
+    public void run () {\r
+        Date _lastSendKa = new Date();\r
+        _lastRecKa = new Date();\r
+        try {\r
+            while (!_sock.isClosed()) {\r
+                if (_sock.getInputStream().available() != 0) {\r
+                    _lastmessage = processMessage(_sock);\r
+                    _lastRecKa = new Date();\r
+                }\r
+\r
+                // Keep Alive\r
+                if (_kaTimer > 0) {\r
+                    // Timeout at PDP\r
+                    int _startTime = (int) (_lastRecKa.getTime());\r
+                    int cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
+                        _sock.close();\r
+                        // Notify all Request State Managers\r
+                        notifyNoKAAllReqStateMan();\r
+                    }\r
+\r
+                    // Send to PEP\r
+                    _startTime = (int) (_lastSendKa.getTime());\r
+                    cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > ((_kaTimer*3/4)*1000)) {\r
+                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
+                        COPSKAMsg msg = new COPSKAMsg();\r
+\r
+                        msg.add(hdr);\r
+\r
+                        COPSTransceiver.sendMsg(msg, _sock);\r
+                        _lastSendKa = new Date();\r
+                    }\r
+                }\r
+\r
+                try {\r
+                    Thread.sleep(500);\r
+                } catch (Exception e) {};\r
+\r
+            }\r
+        } catch (Exception e) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+        }\r
+\r
+        // connection closed by server\r
+        // COPSDebug.out(getClass().getName(),"Connection closed by client");\r
+        try {\r
+            _sock.close();\r
+        } catch (IOException e) {};\r
+\r
+        // Notify all Request State Managers\r
+        try {\r
+            notifyCloseAllReqStateMan();\r
+        } catch (COPSPdpException e) {};\r
+    }\r
+\r
+    /**\r
+     * Gets a COPS message from the socket and processes it\r
+     * @param    conn Socket connected to the PEP\r
+     * @return Type of COPS message\r
+     */\r
+    private byte processMessage(Socket conn)\r
+    throws COPSPdpException, COPSException, IOException {\r
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
+\r
+        if (msg.getHeader().isAClientClose()) {\r
+            handleClientCloseMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_CC;\r
+        } else if (msg.getHeader().isAKeepAlive()) {\r
+            handleKeepAliveMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_KA;\r
+        } else if (msg.getHeader().isARequest()) {\r
+            handleRequestMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_REQ;\r
+        } else if (msg.getHeader().isAReport()) {\r
+            handleReportMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_RPT;\r
+        } else if (msg.getHeader().isADeleteReq()) {\r
+            handleDeleteRequestMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_DRQ;\r
+        } else if (msg.getHeader().isASyncComplete()) {\r
+            handleSyncComplete(conn, msg);\r
+            return COPSHeader.COPS_OP_SSC;\r
+        } else {\r
+            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Handle Client Close Message, close the passed connection\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     *\r
+     * <Client-Close> ::= <Common Header>\r
+     *  <Error>\r
+     *  [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     */\r
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
+        _error = cMsg.getError();\r
+\r
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
+\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+            }\r
+\r
+            conn.close();\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Gets the occurred COPS Error\r
+     * @return   <tt>COPSError</tt> object\r
+     */\r
+    protected COPSError getError()  {\r
+        return _error;\r
+    }\r
+\r
+    /**\r
+     * Handle Keep Alive Message\r
+     *\r
+     * <Keep-Alive> ::= <Common Header>\r
+     *                  [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
+        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
+\r
+        COPSKAMsg kaMsg = (COPSKAMsg) msg;\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+            }\r
+\r
+            kaMsg.writeData(conn);\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Handle Delete Request Message\r
+     *\r
+     * <Delete Request> ::= <Common Header>\r
+     *                      <Client Handle>\r
+     *                      <Reason>\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;\r
+        // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        // Delete clientHandler\r
+        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {\r
+            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +\r
+            //  cMsg.getClientHandle().getId().getData());\r
+        }\r
+\r
+        PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processDeleteRequestState(cMsg);\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * Handle Request Message\r
+     *\r
+     * <Request> ::= <Common Header>\r
+     *  <Client Handle>\r
+     *  <Context>\r
+     *  *(<Named ClientSI>)\r
+     *  [<Integrity>]\r
+     * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleRequestMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+\r
+        COPSReqMsg reqMsg = (COPSReqMsg) msg;\r
+        COPSContext cntxt = reqMsg.getContext();\r
+        COPSHeader header = reqMsg.getHeader();\r
+        //short reqType = cntxt.getRequestType();\r
+        short cType   = header.getClientType();\r
+\r
+        // Support\r
+        if (reqMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        PCMMPdpReqStateMan man;\r
+        man = (PCMMPdpReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+\r
+            man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());\r
+            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);\r
+            man.setDataProcess(_process);\r
+            man.initRequestState(_sock);\r
+\r
+            // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +\r
+            //    header.getClientType() + " msgType=" +\r
+            //    cntxt.getMessageType() + ", connId=" + conn.toString());\r
+        }\r
+\r
+        man.processRequest(reqMsg);\r
+    }\r
+\r
+    /**\r
+     * Handle Report Message\r
+     *\r
+     * <Report State> ::= <Common Header>\r
+     *  <Client Handle>\r
+     *  <Report Type>\r
+     *  *(<Named ClientSI>)\r
+     *  [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleReportMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSReportMsg repMsg = (COPSReportMsg) msg;\r
+        // COPSHandle handle = repMsg.getClientHandle();\r
+        // COPSHeader header = repMsg.getHeader();\r
+\r
+        // Support\r
+        if (repMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processReport(repMsg);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Method handleSyncComplete\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleSyncComplete(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
+        // COPSHandle handle = cMsg.getClientHandle();\r
+        // COPSHeader header = cMsg.getHeader();\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processSyncComplete(cMsg);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Requests a COPS sync from the PEP\r
+     * @throws COPSException\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void syncAllRequestState()\r
+    throws COPSException, COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(handle);\r
+\r
+                man.syncRequestState();\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyCloseAllReqStateMan()\r
+    throws COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processClosedConnection(_error);\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyNoKAAllReqStateMan()\r
+    throws COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                PCMMPdpReqStateMan man = (PCMMPdpReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processNoKAConnection();\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java
new file mode 100644 (file)
index 0000000..e1e162a
--- /dev/null
@@ -0,0 +1,208 @@
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+import java.util.Hashtable;
+
+import org.pcmm.gates.ITransactionID;
+import org.pcmm.gates.impl.PCMMGateReq;
+// import org.umu.cops.prpdp.COPSPdpDataProcess;
+import org.umu.cops.stack.COPSError;
+
+
+public class PCMMPdpDataProcess { // extends COPSPdpDataProcess
+    private Hashtable installPolicy;
+    private Hashtable removePolicy;
+
+    public PCMMPdpDataProcess() {
+    }
+
+    /**
+     * PDPAgent gets the policies to delete from PEP
+     *
+     * @param man
+     * @return
+     */
+    public Hashtable getRemovePolicy(PCMMPdpReqStateMan man) {
+        return removePolicy;
+    }
+
+    /**
+     * PDPAgent gets the policies to be installed in PEP
+     *
+     * @param man
+     * @return
+     */
+    public Hashtable getInstallPolicy(PCMMPdpReqStateMan man) {
+        return installPolicy;
+    }
+
+    /**
+     * PEP configuration items for sending inside the request
+     *
+     * @param man
+     * @param reqSIs
+     */
+    public void setClientData(PCMMPdpReqStateMan man, Hashtable reqSIs) {
+
+        System.out.println(getClass().getName() + ": " + "Request Info");
+        /*
+                for (Enumeration e = reqSIs.keys() ; e.hasMoreElements() ;) {
+                    String strprid = (String) e.nextElement();
+                    String strepd = (String) reqSIs.get(strprid);
+
+                    // Check PRID-EPD
+                    // ....
+                    System.out.println(getClass().getName() + ": " + "PRID: " + strprid);
+                    System.out.println(getClass().getName() + ": " + "EPD: " + strepd);
+                }
+
+                // Create policies to be deleted
+                // ....
+
+                // Create policies to be installed
+                String prid = new String("<XPath>");
+                String epd = new String("<?xml this is an XML policy>");
+                installPolicy.put(prid, epd);
+        */
+    }
+
+    /**
+     * Fail report received
+     *
+     * @param man
+     * @param reportSIs
+     */
+    public void failReport(PCMMPdpReqStateMan man, PCMMGateReq gateMsg) {
+
+        System.out.println(getClass().getName()+ ": " + "Fail Report notified.");
+        System.out.println(getClass().getName()+ ": " + gateMsg.getError().toString());
+
+        /*
+
+                System.out.println(getClass().getName() + ": " + "Report Info");
+                for (Enumeration e = reportSIs.keys() ; e.hasMoreElements() ;) {
+                    String strprid = (String) e.nextElement();
+                    String strepd = (String) reportSIs.get(strprid);
+
+                    // Check PRID-EPD
+                    // ....
+                    System.out.println(getClass().getName()+ ": " + "PRID: " + strprid);
+                    System.out.println(getClass().getName()+ ": " + "EPD: " + strepd);
+                }
+        */
+    }
+
+    /**
+     * Positive report received
+     *
+     * @param man
+     * @param reportSIs
+     */
+    public void successReport(PCMMPdpReqStateMan man, PCMMGateReq gateMsg) {
+        System.out.println(getClass().getName()+ ": " + "Success Report notified.");
+
+        if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck ) {
+            System.out.println(getClass().getName()+ ": GateDeleteAck ");
+            System.out.println(getClass().getName()+ ": 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 ) {
+            System.out.println(getClass().getName()+ ": GateSetAck ");
+            System.out.println(getClass().getName()+ ": GateID = " + gateMsg.getGateID().getGateID());
+            if (0 == PCMMGlobalConfig.getGateID1())
+                PCMMGlobalConfig.setGateID1(gateMsg.getGateID().getGateID());
+            if (0 == PCMMGlobalConfig.getGateID2())
+                PCMMGlobalConfig.setGateID2(gateMsg.getGateID().getGateID());
+        }
+
+        /*
+                System.out.println(getClass().getName()+ ": " + "Report Info");
+                for (Enumeration e = reportSIs.keys() ; e.hasMoreElements() ;) {
+                    String strprid = (String) e.nextElement();
+                    String strepd = (String) reportSIs.get(strprid);
+
+                    // Check PRID-EPD
+                    // ....
+                    System.out.println(getClass().getName()+ ": " + "PRID: " + strprid);
+                    System.out.println(getClass().getName()+ ": " + "EPD: " + strepd);
+                }
+        */
+
+    }
+
+    /**
+     * Accounting report received
+     *
+     * @param man
+     * @param reportSIs
+     */
+    public void acctReport(PCMMPdpReqStateMan man, PCMMGateReq gateMsg) {
+        System.out.println(getClass().getName()+ ": " + "Acct Report notified.");
+
+        /*
+                System.out.println(getClass().getName()+ ": " + "Report Info");
+                for (Enumeration e = reportSIs.keys() ; e.hasMoreElements() ;) {
+                    String strprid = (String) e.nextElement();
+                    String strepd = (String) reportSIs.get(strprid);
+
+                    // Check PRID-EPD
+                    // ....
+                    System.out.println(getClass().getName()+ ": " + "PRID: " + strprid);
+                    System.out.println(getClass().getName()+ ": " + "EPD: " + strepd);
+                }
+        */
+    }
+
+    /**
+     * Notifies that an Accounting report is missing
+     *
+     * @param man
+     */
+    public void notifyNoAcctReport(PCMMPdpReqStateMan man) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    /**
+     * Notifies that a KeepAlive message is missing
+     *
+     * @param man
+     */
+    public void notifyNoKAliveReceived(PCMMPdpReqStateMan man) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    /**
+     * PEP closed the connection
+     *
+     * @param man
+     * @param error
+     */
+    public void notifyClosedConnection(PCMMPdpReqStateMan man, COPSError error) {
+        System.out.println(getClass().getName() + ": " + "Connection was closed by PEP");
+    }
+
+    /**
+     * Delete request state received
+     *
+     * @param man
+     */
+    public void notifyDeleteRequestState(PCMMPdpReqStateMan man) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    /**
+     * Closes request state
+     *
+     * @param man
+     */
+    public void closeRequestState(PCMMPdpReqStateMan man) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java
new file mode 100644 (file)
index 0000000..89e7f44
--- /dev/null
@@ -0,0 +1,981 @@
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import org.pcmm.gates.IAMID;
+import org.pcmm.gates.IClassifier;
+import org.pcmm.gates.IExtendedClassifier;
+import org.pcmm.gates.IGateID;
+import org.pcmm.gates.IGateSpec;
+import org.pcmm.gates.IGateSpec.DSCPTOS;
+import org.pcmm.gates.IGateSpec.Direction;
+import org.pcmm.gates.IPCMMGate;
+import org.pcmm.gates.ISubscriberID;
+import org.pcmm.gates.ITrafficProfile;
+import org.pcmm.gates.ITransactionID;
+import org.pcmm.gates.impl.AMID;
+import org.pcmm.gates.impl.BestEffortService;
+import org.pcmm.gates.impl.Classifier;
+import org.pcmm.gates.impl.ExtendedClassifier;
+import org.pcmm.gates.impl.GateID;
+import org.pcmm.gates.impl.GateSpec;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.pcmm.gates.impl.SubscriberID;
+import org.pcmm.gates.impl.TransactionID;
+import org.umu.cops.prpdp.COPSPdpException;
+import org.umu.cops.stack.COPSClientSI;
+import org.umu.cops.stack.COPSContext;
+import org.umu.cops.stack.COPSData;
+import org.umu.cops.stack.COPSDecision;
+import org.umu.cops.stack.COPSDecisionMsg;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSObjHeader;
+//temp
+import org.umu.cops.stack.COPSReportMsg;
+import org.umu.cops.stack.COPSSyncStateMsg;
+import org.umu.cops.stack.COPSTransceiver;
+//pcmm
+/*
+ * 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-Set>      = <Decision Header> <TransactionID> <AMID> <SubscriberID> [<GateID>] <GateSpec>
+ *                   <Traffic Profile> <classifier> [<classifier...>] [<Event Generation Info>]
+ *                   [<Volume-Based Usage Limit>] [<Time-Based Usage Limit>][<Opaque Data>] [<UserID>]
+ */
+
+/**
+ * COPS message transceiver class for provisioning connections at the PDP side.
+ */
+public class PCMMPdpMsgSender {
+
+    /**
+     * 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;
+    // XXX - this does not need to be here
+    protected int _gateID;
+
+    /**
+     * Creates a PCMMPdpMsgSender
+     *
+     * @param clientType
+     *            COPS client-type
+     * @param clientHandle
+     *            Client handle
+     * @param sock
+     *            Socket to the PEP
+     */
+    public PCMMPdpMsgSender(short clientType, COPSHandle clientHandle,
+                            Socket sock) {
+        // COPS Handle
+        _handle = clientHandle;
+        _clientType = clientType;
+
+        _transactionID = 0;
+        _classifierID = 0;
+        _sock = sock;
+    }
+
+    public PCMMPdpMsgSender(short clientType, short tID,
+                            COPSHandle clientHandle, Socket sock) {
+        // COPS Handle
+        _handle = clientHandle;
+        _clientType = clientType;
+        _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;
+    }
+
+    /**
+     * Gets the transaction-id
+     *
+     * @return transaction-id value
+     */
+    public short getTransactionID() {
+        return _transactionID;
+    }
+
+
+    /**
+     * Sends a PCMM GateSet COPS Decision message
+     *
+     * @param
+     * @throws COPSPdpException
+     */
+    public void sendGateSet(IPCMMGate gate)
+    throws COPSPdpException {
+        // Common Header with the same ClientType as the request
+
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle handle = new COPSHandle();
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
+        ITransactionID trID = new TransactionID();
+
+        handle.setId(getClientHandle().getId());
+
+        // set transaction ID to gate set
+        trID.setGateCommandType(ITransactionID.GateSet);
+        _transactionID = (short) (_transactionID == 0 ? (short) (Math.random() * hashCode())
+                                  : _transactionID);
+        trID.setTransactionIdentifier(_transactionID);
+
+        gate.setTransactionID(trID);
+
+
+        // new pcmm specific clientsi
+        COPSClientSI clientSD = new COPSClientSI(COPSObjHeader.COPS_DEC, (byte) 4);
+        byte[] data = gate.getData();
+        clientSD.setData(new COPSData(data, 0, data.length));
+        try {
+            decisionMsg.add(hdr);
+            decisionMsg.add(handle);
+            // Decisions (no flags supplied)
+            // <Context>
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
+            COPSDecision install = new COPSDecision();
+            install.setCmdCode(COPSDecision.DEC_INSTALL);
+            install.setFlags(COPSDecision.F_REQERROR);
+            decisionMsg.addDecision(install, cntxt);
+            decisionMsg.add(clientSD); // setting up the gate
+            /*
+                        try {
+                            decisionMsg.dump(System.out);
+                        } catch (IOException unae) {
+                            System.out.println("Error dumping " + unae.getMessage());
+                        }
+            */
+
+        } catch (COPSException e) {
+            System.out.println("Error making Msg" + e.getMessage());
+        }
+
+        // ** Send the GateSet Decision
+        // **
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            System.out.println("Failed to send the decision, reason: "
+                               + e.getMessage());
+        }
+
+    }
+
+    /**
+     * Sends a PCMM GateSet COPS Decision message
+     *
+     * @param
+     * @throws COPSPdpException
+     */
+    public void sendGateSetDemo(int num)
+    throws COPSPdpException {
+
+        // Common Header with the same ClientType as the request
+
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle handle = new COPSHandle();
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
+
+        IPCMMGate gate = new PCMMGateReq();
+        ITransactionID trID = new TransactionID();
+
+        IAMID amid = new AMID();
+        ISubscriberID subscriberID = new SubscriberID();
+        IGateSpec gateSpec = new GateSpec();
+        IClassifier classifier = new Classifier();
+        IExtendedClassifier eclassifier = new ExtendedClassifier();
+        int TrafficRate = 0;
+
+        if (num == 1)
+            TrafficRate =   PCMMGlobalConfig.DefaultBestEffortTrafficRate;
+        else
+            TrafficRate =   PCMMGlobalConfig.DefaultLowBestEffortTrafficRate;
+
+        ITrafficProfile trafficProfile = new BestEffortService(
+            (byte) 7); //BestEffortService.DEFAULT_ENVELOP);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setMaximumSustainedTrafficRate(
+            TrafficRate);
+        //  PCMMGlobalConfig.DefaultLowBestEffortTrafficRate );
+        //  PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setMaximumSustainedTrafficRate(
+            TrafficRate);
+        //  PCMMGlobalConfig.DefaultLowBestEffortTrafficRate );
+        //  PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setMaximumSustainedTrafficRate(
+            TrafficRate);
+        //  PCMMGlobalConfig.DefaultLowBestEffortTrafficRate );
+        //  PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+
+
+        // new pcmm specific clientsi
+        COPSClientSI clientSD = new COPSClientSI(COPSObjHeader.COPS_DEC, (byte) 4);
+
+        handle.setId(getClientHandle().getId());
+
+        // set transaction ID to gate set
+        trID.setGateCommandType(ITransactionID.GateSet);
+        _transactionID = (short) (_transactionID == 0 ? (short) (Math.random() * hashCode())
+                                  : _transactionID);
+        trID.setTransactionIdentifier(_transactionID);
+
+        amid.setApplicationType((short) 1);
+        amid.setApplicationMgrTag((short) 1);
+        gateSpec.setDirection(Direction.UPSTREAM);
+        gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE);
+        gateSpec.setTimerT1(PCMMGlobalConfig.GateT1);
+        gateSpec.setTimerT2(PCMMGlobalConfig.GateT2);
+        gateSpec.setTimerT3(PCMMGlobalConfig.GateT3);
+        gateSpec.setTimerT4(PCMMGlobalConfig.GateT4);
+
+        // 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);
+            try {
+                InetAddress subIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.SubscriberID);
+                InetAddress srcIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.srcIP);
+                InetAddress dstIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.dstIP);
+                InetAddress mask = InetAddress.getByName("0.0.0.0");
+                subscriberID.setSourceIPAddress(subIP);
+                eclassifier.setSourceIPAddress(srcIP);
+                eclassifier.setDestinationIPAddress(dstIP);
+                eclassifier.setIPDestinationMask(mask);
+                eclassifier.setIPSourceMask(mask);
+            } catch (UnknownHostException unae) {
+                System.out.println("Error getByName" + unae.getMessage());
+            }
+            eclassifier.setSourcePortStart(PCMMGlobalConfig.srcPort);
+            eclassifier.setSourcePortEnd(PCMMGlobalConfig.srcPort);
+            eclassifier.setDestinationPortStart(PCMMGlobalConfig.dstPort);
+            eclassifier.setDestinationPortEnd(PCMMGlobalConfig.dstPort);
+            eclassifier.setActivationState((byte) 0x01);
+            // check if we have a stored value of classifierID else we just
+            // create
+            // one
+            // eclassifier.setClassifierID((short) 0x01);
+            eclassifier.setClassifierID((short) (_classifierID == 0 ? Math
+                                                 .random() * hashCode() : _classifierID));
+            // XXX - testie
+            // eclassifier.setClassifierID((short) 1);
+
+            eclassifier.setAction((byte) 0x00);
+            // XXX - temp default until Gate Modify is hacked in
+            // eclassifier.setPriority(PCMMGlobalConfig.EClassifierPriority);
+            eclassifier.setPriority((byte) 65);
+
+        } else {
+            classifier.setProtocol(IClassifier.Protocol.TCP);
+            try {
+                InetAddress subIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.SubscriberID);
+                InetAddress srcIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.srcIP);
+                InetAddress dstIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.dstIP);
+                subscriberID.setSourceIPAddress(subIP);
+                classifier.setSourceIPAddress(srcIP);
+                classifier.setDestinationIPAddress(dstIP);
+            } catch (UnknownHostException unae) {
+                System.out.println("Error getByName" + unae.getMessage());
+            }
+            classifier.setSourcePort(PCMMGlobalConfig.srcPort);
+            classifier.setDestinationPort(PCMMGlobalConfig.dstPort);
+        }
+
+        gate.setTransactionID(trID);
+        gate.setAMID(amid);
+        gate.setSubscriberID(subscriberID);
+        gate.setGateSpec(gateSpec);
+        gate.setTrafficProfile(trafficProfile);
+        gate.setClassifier(eclassifier);
+
+        byte[] data = gate.getData();
+
+        // new pcmm specific clientsi
+        clientSD.setData(new COPSData(data, 0, data.length));
+        try {
+            decisionMsg.add(hdr);
+            decisionMsg.add(handle);
+            // Decisions (no flags supplied)
+            // <Context>
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
+            COPSDecision install = new COPSDecision();
+            install.setCmdCode(COPSDecision.DEC_INSTALL);
+            install.setFlags(COPSDecision.F_REQERROR);
+            decisionMsg.addDecision(install, cntxt);
+            decisionMsg.add(clientSD); // setting up the gate
+            /*
+                        try {
+                            decisionMsg.dump(System.out);
+                        } catch (IOException unae) {
+                            System.out.println("Error dumping " + unae.getMessage());
+                        }
+            */
+
+        } catch (COPSException e) {
+            System.out.println("Error making Msg" + e.getMessage());
+        }
+
+        // ** Send the GateSet Decision
+        // **
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            System.out.println("Failed to send the decision, reason: "
+                               + e.getMessage());
+        }
+
+    }
+    /**
+     * Sends a PCMM GateSet COPS Decision message
+     *
+     * @param
+     * @throws COPSPdpException
+     */
+    public void sendGateSetBestEffortWithExtendedClassifier()
+    throws COPSPdpException {
+        // Common Header with the same ClientType as the request
+
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle handle = new COPSHandle();
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
+
+        IPCMMGate gate = new PCMMGateReq();
+        ITransactionID trID = new TransactionID();
+
+        IAMID amid = new AMID();
+        ISubscriberID subscriberID = new SubscriberID();
+        IGateSpec gateSpec = new GateSpec();
+        IClassifier classifier = new Classifier();
+        IExtendedClassifier eclassifier = new ExtendedClassifier();
+
+        // XXX check if other values should be provided
+        //
+        ITrafficProfile trafficProfile = new BestEffortService(
+            (byte) 7); //BestEffortService.DEFAULT_ENVELOP);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setMaximumSustainedTrafficRate(
+            PCMMGlobalConfig.DefaultLowBestEffortTrafficRate );
+        //  PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+        ((BestEffortService) trafficProfile).getReservedEnvelop()
+        .setMaximumSustainedTrafficRate(
+            PCMMGlobalConfig.DefaultLowBestEffortTrafficRate );
+        //  PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+        ((BestEffortService) trafficProfile).getCommittedEnvelop()
+        .setMaximumSustainedTrafficRate(
+            PCMMGlobalConfig.DefaultLowBestEffortTrafficRate );
+        //  PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+
+
+        // new pcmm specific clientsi
+        COPSClientSI clientSD = new COPSClientSI(COPSObjHeader.COPS_DEC,
+                (byte) 4);
+
+        handle.setId(getClientHandle().getId());
+
+        // set transaction ID to gate set
+        trID.setGateCommandType(ITransactionID.GateSet);
+        _transactionID = (short) (_transactionID == 0 ? (short) (Math.random() * hashCode())
+                                  : _transactionID);
+        trID.setTransactionIdentifier(_transactionID);
+
+        amid.setApplicationType((short) 1);
+        amid.setApplicationMgrTag((short) 1);
+        gateSpec.setDirection(Direction.UPSTREAM);
+        gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE);
+        gateSpec.setTimerT1(PCMMGlobalConfig.GateT1);
+        gateSpec.setTimerT2(PCMMGlobalConfig.GateT2);
+        gateSpec.setTimerT3(PCMMGlobalConfig.GateT3);
+        gateSpec.setTimerT4(PCMMGlobalConfig.GateT4);
+
+        // 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);
+            try {
+                InetAddress subIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.SubscriberID);
+                InetAddress srcIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.srcIP);
+                InetAddress dstIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.dstIP);
+                InetAddress mask = InetAddress.getByName("0.0.0.0");
+                subscriberID.setSourceIPAddress(subIP);
+                eclassifier.setSourceIPAddress(srcIP);
+                eclassifier.setDestinationIPAddress(dstIP);
+                eclassifier.setIPDestinationMask(mask);
+                eclassifier.setIPSourceMask(mask);
+            } catch (UnknownHostException unae) {
+                System.out.println("Error getByName" + unae.getMessage());
+            }
+            eclassifier.setSourcePortStart(PCMMGlobalConfig.srcPort);
+            eclassifier.setSourcePortEnd(PCMMGlobalConfig.srcPort);
+            eclassifier.setDestinationPortStart(PCMMGlobalConfig.dstPort);
+            eclassifier.setDestinationPortEnd(PCMMGlobalConfig.dstPort);
+            eclassifier.setActivationState((byte) 0x01);
+            // check if we have a stored value of classifierID else we just
+            // create
+            // one
+            // eclassifier.setClassifierID((short) 0x01);
+            eclassifier.setClassifierID((short) (_classifierID == 0 ? Math
+                                                 .random() * hashCode() : _classifierID));
+            // XXX - testie
+            // eclassifier.setClassifierID((short) 1);
+
+            eclassifier.setAction((byte) 0x00);
+            // XXX - temp default until Gate Modify is hacked in
+            // eclassifier.setPriority(PCMMGlobalConfig.EClassifierPriority);
+            eclassifier.setPriority((byte) 65);
+
+        } else {
+            classifier.setProtocol(IClassifier.Protocol.TCP);
+            try {
+                InetAddress subIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.SubscriberID);
+                InetAddress srcIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.srcIP);
+                InetAddress dstIP = InetAddress
+                                    .getByName(PCMMGlobalConfig.dstIP);
+                subscriberID.setSourceIPAddress(subIP);
+                classifier.setSourceIPAddress(srcIP);
+                classifier.setDestinationIPAddress(dstIP);
+            } catch (UnknownHostException unae) {
+                System.out.println("Error getByName" + unae.getMessage());
+            }
+            classifier.setSourcePort(PCMMGlobalConfig.srcPort);
+            classifier.setDestinationPort(PCMMGlobalConfig.dstPort);
+        }
+
+        gate.setTransactionID(trID);
+        gate.setAMID(amid);
+        gate.setSubscriberID(subscriberID);
+        gate.setGateSpec(gateSpec);
+        gate.setTrafficProfile(trafficProfile);
+        gate.setClassifier(eclassifier);
+
+        byte[] data = gate.getData();
+
+        // new pcmm specific clientsi
+        clientSD.setData(new COPSData(data, 0, data.length));
+        try {
+            decisionMsg.add(hdr);
+            decisionMsg.add(handle);
+            // Decisions (no flags supplied)
+            // <Context>
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
+            COPSDecision install = new COPSDecision();
+            install.setCmdCode(COPSDecision.DEC_INSTALL);
+            install.setFlags(COPSDecision.F_REQERROR);
+            decisionMsg.addDecision(install, cntxt);
+            decisionMsg.add(clientSD); // setting up the gate
+            /*
+                        try {
+                            decisionMsg.dump(System.out);
+                        } catch (IOException unae) {
+                            System.out.println("Error dumping " + unae.getMessage());
+                        }
+            */
+
+        } catch (COPSException e) {
+            System.out.println("Error making Msg" + e.getMessage());
+        }
+
+        // ** Send the GateSet Decision
+        // **
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            System.out.println("Failed to send the decision, reason: "
+                               + e.getMessage());
+        }
+
+    }
+
+
+    public boolean handleGateReport(Socket socket) throws COPSPdpException {
+        try {
+            // waits for the gate-set-ack or error
+            COPSMsg responseMsg = COPSTransceiver.receiveMsg(socket);
+            if (responseMsg.getHeader().isAReport()) {
+                System.out.println("processing received report from CMTS");
+                COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
+                if (reportMsg.getClientSI().size() == 0) {
+                    return false;
+                }
+                COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI()
+                                        .elementAt(0);
+                IPCMMGate responseGate = new PCMMGateReq(clientSI.getData()
+                        .getData());
+                if (responseGate.getTransactionID() != null
+                        && responseGate.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck) {
+                    System.out.println("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();
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+            return false;
+        } catch (Exception e) { // COPSException, IOException
+            throw new COPSPdpException("Error COPSTransceiver.receiveMsg");
+        }
+    }
+
+
+    /**
+     * Sends a PCMM GateSet COPS Decision message
+     *
+     * @param
+     * @throws COPSPdpException
+     */
+    public void sendGateSet() throws COPSPdpException {
+        // Common Header with the same ClientType as the request
+
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle handle = new COPSHandle();
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
+
+        IPCMMGate gate = new PCMMGateReq();
+        ITransactionID trID = new TransactionID();
+
+        IAMID amid = new AMID();
+        ISubscriberID subscriberID = new SubscriberID();
+        IGateSpec gateSpec = new GateSpec();
+        IClassifier classifier = new Classifier();
+        // XXX check if other values should be provided
+        ITrafficProfile trafficProfile = new BestEffortService(
+            BestEffortService.DEFAULT_ENVELOP);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setMaximumTrafficBurst(
+            BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+        ((BestEffortService) trafficProfile).getAuthorizedEnvelop()
+        .setRequestTransmissionPolicy(
+            PCMMGlobalConfig.BETransmissionPolicy);
+
+        // new pcmm specific clientsi
+        COPSClientSI clientSD = new COPSClientSI(COPSObjHeader.COPS_DEC,
+                (byte) 4);
+
+        handle.setId(getClientHandle().getId());
+        // byte[] content = "1234".getBytes();
+
+        // handle.setId(new COPSData(content, 0, content.length));
+
+        // set transaction ID to gate set
+        trID.setGateCommandType(ITransactionID.GateSet);
+        _transactionID = (short) (_transactionID == 0 ? (short) (Math.random() * hashCode())
+                                  : _transactionID);
+        trID.setTransactionIdentifier(_transactionID);
+
+        amid.setApplicationType((short) 1);
+        amid.setApplicationMgrTag((short) 1);
+        gateSpec.setDirection(Direction.UPSTREAM);
+        gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE);
+        gateSpec.setTimerT1(PCMMGlobalConfig.GateT1);
+        gateSpec.setTimerT2(PCMMGlobalConfig.GateT2);
+        gateSpec.setTimerT3(PCMMGlobalConfig.GateT3);
+        gateSpec.setTimerT4(PCMMGlobalConfig.GateT4);
+
+        /*
+         * ((DOCSISServiceClassNameTrafficProfile) trafficProfile)
+         * .setServiceClassName("S_up");
+         */
+
+        classifier.setProtocol(IClassifier.Protocol.TCP);
+        try {
+            InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
+            InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
+            InetAddress dstIP = InetAddress.getByName(PCMMGlobalConfig.dstIP);
+            subscriberID.setSourceIPAddress(subIP);
+            classifier.setSourceIPAddress(srcIP);
+            classifier.setDestinationIPAddress(dstIP);
+        } catch (UnknownHostException unae) {
+            System.out.println("Error getByName" + unae.getMessage());
+        }
+        classifier.setSourcePort(PCMMGlobalConfig.srcPort);
+        classifier.setDestinationPort(PCMMGlobalConfig.dstPort);
+
+        gate.setTransactionID(trID);
+        gate.setAMID(amid);
+        gate.setSubscriberID(subscriberID);
+        gate.setGateSpec(gateSpec);
+        gate.setTrafficProfile(trafficProfile);
+        gate.setClassifier(classifier);
+
+        byte[] data = gate.getData();
+
+        // new pcmm specific clientsi
+        clientSD.setData(new COPSData(data, 0, data.length));
+
+        try {
+            decisionMsg.add(hdr);
+            decisionMsg.add(handle);
+            // Decisions (no flags supplied)
+            // <Context>
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
+            COPSDecision install = new COPSDecision();
+            install.setCmdCode(COPSDecision.DEC_INSTALL);
+            install.setFlags(COPSDecision.F_REQERROR);
+            decisionMsg.addDecision(install, cntxt);
+            decisionMsg.add(clientSD); // setting up the gate
+            /*
+                        try {
+                            decisionMsg.dump(System.out);
+                        } catch (IOException unae) {
+                            System.out.println("Error dumping " + unae.getMessage());
+                        }
+            */
+
+        } catch (COPSException e) {
+            System.out.println("Error making Msg" + e.getMessage());
+        }
+
+        // ** Send the GateSet Decision
+        // **
+        try {
+            decisionMsg.writeData(_sock);
+        } catch (IOException e) {
+            System.out.println("Failed to send the decision, reason: "
+                               + e.getMessage());
+        }
+
+    }
+
+    /**
+     * Sends a message asking that the request state be deleted
+     *
+     * @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
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle handle = new COPSHandle();
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
+
+        IPCMMGate gate = new PCMMGateReq();
+        ITransactionID trID = new TransactionID();
+
+        IAMID amid = new AMID();
+        ISubscriberID subscriberID = new SubscriberID();
+        IGateSpec gateSpec = new GateSpec();
+        IGateID gateID = new GateID();
+
+        // new pcmm specific clientsi
+        COPSClientSI clientSD = new COPSClientSI(COPSObjHeader.COPS_DEC, (byte) 4);
+
+        handle.setId(getClientHandle().getId());
+
+        // set transaction ID to gate set
+        trID.setGateCommandType(ITransactionID.GateDelete);
+        _transactionID = (short) (_transactionID == 0 ? (short) (Math.random() * hashCode())
+                                  : _transactionID);
+        trID.setTransactionIdentifier(_transactionID);
+
+        amid.setApplicationType((short) 1);
+        amid.setApplicationMgrTag((short) 1);
+        gateID.setGateID(gID);
+
+        try {
+            InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
+            subscriberID.setSourceIPAddress(subIP);
+        } catch (UnknownHostException unae) {
+            System.out.println("Error getByName" + unae.getMessage());
+        }
+
+        gate.setTransactionID(trID);
+        gate.setAMID(amid);
+        gate.setSubscriberID(subscriberID);
+        gate.setGateID(gateID);
+
+        // XXX - GateID
+        byte[] data = gate.getData();
+
+        // new pcmm specific clientsi
+        clientSD.setData(new COPSData(data, 0, data.length));
+
+        try {
+            decisionMsg.add(hdr);
+            decisionMsg.add(handle);
+            // Decisions (no flags supplied)
+            // <Context>
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
+            COPSDecision install = new COPSDecision();
+            install.setCmdCode(COPSDecision.DEC_INSTALL);
+            install.setFlags(COPSDecision.F_REQERROR);
+            decisionMsg.addDecision(install, cntxt);
+            decisionMsg.add(clientSD); // setting up the gate
+            /*
+                        try {
+                            decisionMsg.dump(System.out);
+                        } catch (IOException unae) {
+                            System.out.println("Error dumping " + unae.getMessage());
+                        }
+            */
+
+        } catch (COPSException e) {
+            System.out.println("Error making Msg" + e.getMessage());
+        }
+
+        // ** Send the GateDelete Decision
+        // **
+        try {
+            decisionMsg.writeData(_sock);
+            // decisionMsg.writeData(socket_id);
+        } catch (IOException e) {
+            System.out.println("Failed to send the decision, reason: "
+                               + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a request asking that a new request state be created
+     *
+     * @throws COPSPdpException
+     */
+    public void sendOpenNewRequestState() throws COPSPdpException {
+        /*
+         * <Decision Message> ::= <Common Header: Flag UNSOLICITED> <Client
+         * Handle> *(<Decision>) [<Integrity>] <Decision> ::= <Context>
+         * <Decision: Flags> <Decision: Flags> ::= Install Request-State
+         */
+
+        // Common Header with the same ClientType as the request (default
+        // UNSOLICITED)
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle clienthandle = new COPSHandle();
+        clienthandle.setId(_handle.getId());
+
+        // Decisions
+        // <Context>
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);
+        // <Decision: Flags>
+        COPSDecision dec = new COPSDecision();
+        dec.setCmdCode(COPSDecision.DEC_INSTALL);
+        dec.setFlags(COPSDecision.F_REQSTATE);
+
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();
+        try {
+            decisionMsg.add(hdr);
+            decisionMsg.add(clienthandle);
+            decisionMsg.addDecision(dec, cntxt);
+        } catch (COPSException e) {
+            throw new COPSPdpException("Error making Msg");
+        }
+
+        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 sendGateInfo() throws COPSPdpException {
+        /*
+         * <Gate-Info> ::= <Common Header> [<Client Handle>] [<Integrity>]
+         */
+
+        // Common Header with the same ClientType as the request
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_SSQ, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle clienthandle = new COPSHandle();
+        clienthandle.setId(_handle.getId());
+
+        COPSSyncStateMsg msg = new COPSSyncStateMsg();
+        try {
+            msg.add(hdr);
+            msg.add(clienthandle);
+        } catch (Exception e) {
+            throw new COPSPdpException("Error making Msg");
+        }
+
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException(
+                "Failed to send the GateInfo request, reason: "
+                + e.getMessage());
+        }
+    }
+
+    /**
+     * Sends a message asking for a COPS sync operation
+     *
+     * @throws COPSPdpException
+     */
+    public void sendSyncRequest() throws COPSPdpException {
+        /*
+         * <Synchronize State Request> ::= <Common Header> [<Client Handle>]
+         * [<Integrity>]
+         */
+
+        // Common Header with the same ClientType as the request
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_SSQ, getClientType());
+
+        // Client Handle with the same clientHandle as the request
+        COPSHandle clienthandle = new COPSHandle();
+        clienthandle.setId(_handle.getId());
+
+        COPSSyncStateMsg msg = new COPSSyncStateMsg();
+        try {
+            msg.add(hdr);
+            msg.add(clienthandle);
+        } catch (Exception e) {
+            throw new COPSPdpException("Error making Msg");
+        }
+
+        try {
+            msg.writeData(_sock);
+        } catch (IOException e) {
+            throw new COPSPdpException(
+                "Failed to send the sync state request, reason: "
+                + e.getMessage());
+        }
+    }
+    // XXX - Temp
+    public void sendSyncRequestState() throws COPSPdpException {
+    }
+    // XXX - Temp
+    public void sendDeleteRequestState() throws COPSPdpException {
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java
new file mode 100644 (file)
index 0000000..6ef939b
--- /dev/null
@@ -0,0 +1,461 @@
+/**\r
+ @header@\r
+ */\r
+\r
+package org.pcmm;\r
+\r
+/*\r
+import java.io.*;\r
+import java.util.UUID.*;\r
+*/\r
+import java.net.Socket;\r
+import java.util.Arrays;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+import org.pcmm.gates.ITransactionID;\r
+import org.pcmm.gates.impl.PCMMGateReq;\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.prpdp.COPSPdpException;\r
+import org.umu.cops.stack.COPSClientSI;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSPrObjBase;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReportType;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+/*\r
+import org.pcmm.base.IPCMMBaseObject;\r
+import org.pcmm.gates.IAMID;\r
+import org.pcmm.gates.IGateID;\r
+import org.pcmm.gates.ISubscriberID;\r
+import org.pcmm.gates.IPCError;\r
+import org.pcmm.gates.impl.AMID;\r
+import org.pcmm.gates.impl.GateID;\r
+import org.pcmm.gates.impl.SubscriberID;\r
+import org.pcmm.gates.impl.TransactionID;\r
+import org.pcmm.gates.impl.PCError;\r
+*/\r
+\r
+\r
+\r
+\r
+/**\r
+ * State manager class for provisioning requests, at the PDP side.\r
+ */\r
+public class PCMMPdpReqStateMan {\r
+\r
+    /**\r
+     * Request State created\r
+     */\r
+    public final static short ST_CREATE = 1;\r
+    /**\r
+     * Request received\r
+     */\r
+    public final static short ST_INIT = 2;\r
+    /**\r
+     * Decisions sent\r
+     */\r
+    public final static short ST_DECS = 3;\r
+    /**\r
+     * Report received\r
+     */\r
+    public final static short ST_REPORT = 4;\r
+    /**\r
+     * Request State finalized\r
+     */\r
+    public final static short ST_FINAL = 5;\r
+    /**\r
+     * New Request State solicited\r
+     */\r
+    public final static short ST_NEW = 6;\r
+    /**\r
+     * Delete Request State solicited\r
+     */\r
+    public final static short ST_DEL = 7;\r
+    /**\r
+     * SYNC request sent\r
+     */\r
+    public final static short ST_SYNC = 8;\r
+    /**\r
+     * SYNC completed\r
+     */\r
+    public final static short ST_SYNCALL = 9;\r
+    /**\r
+     * Close connection received\r
+     */\r
+    public final static short ST_CCONN = 10;\r
+    /**\r
+     * Keep-alive timeout\r
+     */\r
+    public final static short ST_NOKA = 11;\r
+    /**\r
+     * Accounting timeout\r
+     */\r
+    public final static short ST_ACCT = 12;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     *  COPS client handle used to uniquely identify a particular\r
+     *  PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Object for performing policy data processing\r
+     */\r
+    protected PCMMPdpDataProcess _process;\r
+\r
+    /**\r
+     *  Current state of the request being managed\r
+     */\r
+    protected short _status;\r
+\r
+    /** COPS message transceiver used to send COPS messages */\r
+    protected PCMMPdpMsgSender _sender;\r
+\r
+    /**\r
+     * Creates a request state manager\r
+     * @param clientType    Client-type\r
+     * @param clientHandle  Client handle\r
+     */\r
+    public PCMMPdpReqStateMan(short clientType, String clientHandle) {\r
+        // COPS Handle\r
+        _handle = new COPSHandle();\r
+        COPSData id = new COPSData(clientHandle);\r
+        _handle.setId(id);\r
+        // client-type\r
+        _clientType = clientType;\r
+\r
+        _status = ST_CREATE;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return   Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets the status of the request\r
+     * @return      Request state value\r
+     */\r
+    public short getStatus() {\r
+        return _status;\r
+    }\r
+\r
+    /**\r
+     * Gets the policy data processing object\r
+     * @return   Policy data processing object\r
+     */\r
+    public PCMMPdpDataProcess getDataProcess() {\r
+        return _process;\r
+    }\r
+\r
+    /**\r
+     * Sets the policy data processing object\r
+     * @param   process Policy data processing object\r
+     */\r
+    public void setDataProcess(PCMMPdpDataProcess process) {\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Called when COPS sync is completed\r
+     * @param    repMsg              COPS sync message\r
+     * @throws   COPSPdpException\r
+     */\r
+    protected void processSyncComplete(COPSSyncStateMsg repMsg)\r
+    throws COPSPdpException {\r
+\r
+        _status = ST_SYNCALL;\r
+\r
+        // maybe we should notifySyncComplete ...\r
+    }\r
+\r
+    /**\r
+     * Initializes a new request state over a socket\r
+     * @param sock  Socket to the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void initRequestState(Socket sock)\r
+    throws COPSPdpException {\r
+        // Inits an object for sending COPS messages to the PEP\r
+        _sender = new PCMMPdpMsgSender(_clientType, _handle, sock);\r
+\r
+        // Initial state\r
+        _status = ST_INIT;\r
+    }\r
+\r
+\r
+\r
+    /**\r
+     * Processes a COPS request\r
+     * @param msg   COPS request received from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processRequest(COPSReqMsg msg)\r
+    throws COPSPdpException {\r
+\r
+        COPSHeader hdrmsg = msg.getHeader();\r
+        COPSHandle handlemsg = msg.getClientHandle();\r
+        COPSContext contextmsg = msg.getContext();\r
+\r
+        //** Analyze the request\r
+        //**\r
+\r
+        /* <Request> ::= <Common Header>\r
+        *                   <Client Handle>\r
+        *                   <Context>\r
+        *                   *(<Named ClientSI>)\r
+        *                   [<Integrity>]\r
+        * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
+        *\r
+        * Very important, this is actually being treated like this:\r
+        * <Named ClientSI> ::= <PRID> | <EPD>\r
+        *\r
+\r
+        // Named ClientSI\r
+        Vector clientSIs = msg.getClientSI();\r
+        Hashtable reqSIs = new Hashtable(40);\r
+        String strobjprid = new String();\r
+        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+\r
+            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());\r
+            switch (obj.getSNum())\r
+            {\r
+                case COPSPrObjBase.PR_PRID:\r
+                    strobjprid = obj.getData().str();\r
+                    break;\r
+                case COPSPrObjBase.PR_EPD:\r
+                    reqSIs.put(strobjprid, obj.getData().str());\r
+                    // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);\r
+                    // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());\r
+                    break;\r
+                default:\r
+                    break;\r
+            }\r
+        }\r
+\r
+        //** Here we must retrieve a decision depending on\r
+        //** the supplied ClientSIs\r
+        // reqSIs is a hashtable with the prid and epds\r
+\r
+        // ................\r
+        //\r
+        Hashtable removeDecs = new Hashtable();\r
+        Hashtable installDecs = new Hashtable();\r
+        _process.setClientData(this, reqSIs);\r
+\r
+        removeDecs = _process.getRemovePolicy(this);\r
+        installDecs = _process.getInstallPolicy(this);\r
+\r
+        //** We create the SOLICITED decision\r
+        //**\r
+        _sender.sendDecision(removeDecs, installDecs);\r
+        _status = ST_DECS;\r
+        */\r
+    }\r
+\r
+    /**\r
+     * Processes a report\r
+     * @param msg   Report message from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processReport(COPSReportMsg msg)\r
+    throws COPSPdpException {\r
+\r
+        //** Analyze the report\r
+        //**\r
+\r
+        /*\r
+           * <Report State> ::= <Common Header>\r
+           *                        <Client Handle>\r
+          *                     <Report Type>\r
+         *                      *(<Named ClientSI>)\r
+          *                     [<Integrity>]\r
+         * <Named ClientSI: Report> ::= <[<GPERR>] *(<report>)>\r
+         * <report> ::= <ErrorPRID> <CPERR> *(<PRID><EPD>)\r
+         *\r
+         * Important, <Named ClientSI> is not parsed\r
+        */\r
+\r
+        // COPSHeader hdrmsg = msg.getHeader();\r
+        // COPSHandle handlemsg = msg.getClientHandle();\r
+\r
+        // WriteBinaryDump("COPSReportMessage", msg.getData().getData());\r
+        // Report Type\r
+        COPSReportType rtypemsg = msg.getReport();\r
+\r
+        // Named ClientSI\r
+        Vector clientSIs = msg.getClientSI();\r
+        COPSClientSI myclientSI = (COPSClientSI) msg.getClientSI().elementAt(0);\r
+        byte[] data = Arrays.copyOfRange(myclientSI.getData().getData(), 0, myclientSI.getData().getData().length );\r
+\r
+        // PCMMUtils.WriteBinaryDump("COPSReportClientSI", data);\r
+        System.out.println("PCMMGateReq Parse Gate Message");\r
+        PCMMGateReq gateMsg = new PCMMGateReq(data);\r
+\r
+        Hashtable repSIs = new Hashtable(40);\r
+        String strobjprid = new String();\r
+        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+\r
+            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());\r
+            switch (obj.getSNum()) {\r
+            case COPSPrObjBase.PR_PRID:\r
+                System.out.println("COPSPrObjBase.PR_PRID");\r
+                strobjprid = obj.getData().str();\r
+                break;\r
+            case COPSPrObjBase.PR_EPD:\r
+                System.out.println("COPSPrObjBase.PR_EPD");\r
+                repSIs.put(strobjprid, obj.getData().str());\r
+                // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);\r
+                // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());\r
+                break;\r
+            default:\r
+                COPSDebug.err(getClass().getName(),"Object s-num: " + obj.getSNum() + "stype " + obj.getSType());\r
+                COPSDebug.err(getClass().getName(),"PRID: " + strobjprid);\r
+                COPSDebug.err(getClass().getName(),"EPD: " + obj.getData().str());\r
+                break;\r
+            }\r
+        }\r
+\r
+        System.out.println("rtypemsg process");\r
+        //** Here we must act in accordance with\r
+        //** the report received\r
+        if (rtypemsg.isSuccess()) {\r
+        System.out.println("rtypemsg success");\r
+            _status = ST_REPORT;\r
+            if (_process != null)\r
+            _process.successReport(this, gateMsg);\r
+            else\r
+{\r
+       if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck ) {\r
+            System.out.println(getClass().getName()+ ": GateDeleteAck ");\r
+            System.out.println(getClass().getName()+ ": GateID = " + gateMsg.getGateID().getGateID());\r
+            if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID1())\r
+                PCMMGlobalConfig.setGateID1(0);\r
+            if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID2())\r
+                PCMMGlobalConfig.setGateID2(0);\r
+\r
+        }\r
+        if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck ) {\r
+            System.out.println(getClass().getName()+ ": GateSetAck ");\r
+            System.out.println(getClass().getName()+ ": GateID = " + gateMsg.getGateID().getGateID());\r
+            if (0 == PCMMGlobalConfig.getGateID1())\r
+                PCMMGlobalConfig.setGateID1(gateMsg.getGateID().getGateID());\r
+            if (0 == PCMMGlobalConfig.getGateID2())\r
+                PCMMGlobalConfig.setGateID2(gateMsg.getGateID().getGateID());\r
+        }\r
+\r
+}\r
+        } else if (rtypemsg.isFailure()) {\r
+        System.out.println("rtypemsg failure");\r
+            _status = ST_REPORT;\r
+            if (_process != null)\r
+            _process.failReport(this, gateMsg);\r
+else\r
+{\r
+        System.out.println(getClass().getName()+ ": " + gateMsg.getError().toString());\r
+}\r
+\r
+        } else if (rtypemsg.isAccounting()) {\r
+        System.out.println("rtypemsg account");\r
+            _status = ST_ACCT;\r
+            if (_process != null)\r
+            _process.acctReport(this, gateMsg);\r
+        }\r
+        System.out.println("Out processReport");\r
+    }\r
+\r
+    /**\r
+    * Called when connection is closed\r
+    * @param error  Reason\r
+    * @throws COPSPdpException\r
+    */\r
+    protected void processClosedConnection(COPSError error)\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.notifyClosedConnection(this, error);\r
+\r
+        _status = ST_CCONN;\r
+    }\r
+\r
+    /**\r
+     * Called when no keep-alive is received\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processNoKAConnection()\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.notifyNoKAliveReceived(this);\r
+\r
+        _status = ST_NOKA;\r
+    }\r
+\r
+    /**\r
+    * Deletes the request state\r
+    * @throws COPSPdpException\r
+    */\r
+    protected void finalizeRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendDeleteRequestState();\r
+        _status = ST_FINAL;\r
+    }\r
+\r
+    /**\r
+    * Asks for a COPS sync\r
+    * @throws COPSPdpException\r
+    */\r
+    protected void syncRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendSyncRequestState();\r
+        _status = ST_SYNC;\r
+    }\r
+\r
+    /**\r
+     * Opens a new request state\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void openNewRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendOpenNewRequestState();\r
+        _status = ST_NEW;\r
+    }\r
+\r
+    /**\r
+     * Processes a COPS delete message\r
+     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processDeleteRequestState(COPSDeleteMsg dMsg)\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.closeRequestState(this);\r
+\r
+        _status = ST_DEL;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPepAgent.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPepAgent.java
new file mode 100644 (file)
index 0000000..394bdf1
--- /dev/null
@@ -0,0 +1,252 @@
+/**
+ @header@
+ */
+
+package org.pcmm;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import org.umu.cops.common.COPSDebug;
+import org.umu.cops.prpep.COPSPepAgent;
+import org.umu.cops.prpep.COPSPepConnection;
+import org.umu.cops.prpep.COPSPepException;
+import org.umu.cops.stack.COPSAcctTimer;
+import org.umu.cops.stack.COPSClientAcceptMsg;
+import org.umu.cops.stack.COPSClientCloseMsg;
+import org.umu.cops.stack.COPSClientOpenMsg;
+import org.umu.cops.stack.COPSData;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSKATimer;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSPepId;
+import org.umu.cops.stack.COPSTransceiver;
+
+/**
+ * This is a provisioning COPS PEP. Responsible for making connection to the PDP
+ * and maintaining it
+ */
+public class PCMMPepAgent extends COPSPepAgent implements Runnable {
+
+    /** Well-known port for COPS */
+    public static final int WELL_KNOWN_CMTS_PORT = 3918;
+
+    /**
+     * PDP host IP
+     */
+    private ServerSocket serverSocket;
+
+    /**
+     * PDP host port
+     */
+    private int serverPort;
+
+    /**
+     * COPS error returned by PDP
+     */
+    private COPSError error;
+
+    /**
+     * Creates a PEP agent
+     *
+     * @param pepID
+     *            PEP-ID
+     * @param clientType
+     *            Client-type
+     */
+    public PCMMPepAgent(String pepID, short clientType) {
+        super(pepID, clientType);
+        serverPort = WELL_KNOWN_CMTS_PORT;
+    }
+
+    /**
+     * Creates a PEP agent with a PEP-ID equal to "noname"
+     *
+     * @param clientType
+     *            Client-type
+     */
+    public PCMMPepAgent(short clientType) {
+        super(clientType);
+        serverPort = WELL_KNOWN_CMTS_PORT;
+    }
+
+    /**
+     * Runs the PEP process XXX - not sure of the exception throwing
+     */
+    public void run() {
+        try {
+
+            COPSDebug.err(getClass().getName(), "Create Server Socket on Port "
+                          + serverPort);
+
+            serverSocket = new ServerSocket(serverPort);
+            // Loop through for Incoming messages
+
+            // server infinite loop
+            while (true) {
+
+                // Wait for an incoming connection from a PEP
+                Socket socket = serverSocket.accept();
+
+                COPSDebug.err(getClass().getName(), "New connection accepted "
+                              + socket.getInetAddress() + ":" + socket.getPort());
+
+                processConnection(socket);
+                /**
+                 * XXX - processConnection handles the open request from PEP And
+                 * a thread is created for conn = new
+                 * COPSPepConnection(_clientType, socket); the main processing
+                 * loop for PEP
+                 */
+
+            }
+        } catch (IOException e) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);
+        } catch (COPSException e) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);
+        } catch (COPSPepException e) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);
+        }
+    }
+
+    /**
+     * Establish connection to PDP's IP address
+     *
+     * <Client-Open> ::= <Common Header> <PEPID> [<ClientSI>] [<LastPDPAddr>]
+     * [<Integrity>]
+     *
+     * Not support [<ClientSI>], [<LastPDPAddr>], [<Integrity>]
+     *
+     * <Client-Accept> ::= <Common Header> <KA Timer> [<ACCT Timer>]
+     * [<Integrity>]
+     *
+     * Not send [<Integrity>]
+     *
+     * <Client-Close> ::= <Common Header> <Error> [<PDPRedirAddr>] [<Integrity>]
+     *
+     * Not send [<PDPRedirAddr>], [<Integrity>]
+     *
+     * @throws UnknownHostException
+     * @throws IOException
+     * @throws COPSException
+     * @throws COPSPepException
+     *
+     */
+    private COPSPepConnection processConnection(Socket socket)
+    throws UnknownHostException, IOException, COPSException,
+                COPSPepException {
+        // Build OPN
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, getClientType());
+
+        COPSPepId pepId = new COPSPepId();
+        COPSData d = new COPSData(getPepID());
+        pepId.setData(d);
+
+        COPSClientOpenMsg msg = new COPSClientOpenMsg();
+        msg.add(hdr);
+        msg.add(pepId);
+
+        // Create Socket and send OPN
+        /*
+         * InetAddress addr = InetAddress.getByName(psHost); Socket socket = new
+         * Socket(addr,psPort);
+         */
+        COPSDebug.err(getClass().getName(), "Send COPSClientOpenMsg to PDP");
+        msg.writeData(socket);
+
+        // Receive the response
+        COPSDebug.err(getClass().getName(), "Receive the resposne from PDP");
+        COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
+
+        if (recvmsg.getHeader().isAClientAccept()) {
+            COPSDebug.err(getClass().getName(), "isAClientAccept from PDP");
+            COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
+
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                throw new COPSPepException("Unsupported object (Integrity)");
+            }
+
+            // Mandatory KATimer
+            COPSKATimer kt = cMsg.getKATimer();
+            if (kt == null)
+                throw new COPSPepException(
+                    "Mandatory COPS object missing (KA Timer)");
+            short _kaTimeVal = kt.getTimerVal();
+
+            // ACTimer
+            COPSAcctTimer at = cMsg.getAcctTimer();
+            short _acctTimer = 0;
+            if (at != null)
+                _acctTimer = at.getTimerVal();
+
+            // Create the connection manager
+            COPSPepConnection conn = new COPSPepConnection(getClientType(),
+                    socket);
+            conn.setKaTimer(_kaTimeVal);
+            conn.setAcctTimer(_acctTimer);
+            COPSDebug.err(getClass().getName(), "Thread(conn).start");
+            new Thread(conn).start();
+
+            return conn;
+        } else if (recvmsg.getHeader().isAClientClose()) {
+            COPSDebug.err(getClass().getName(), "isAClientClose from PDP");
+            COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
+            error = cMsg.getError();
+            socket.close();
+            return null;
+        } else { // messages of other types are not expected
+            throw new COPSPepException(
+                "Message not expected. Closing connection for "
+                + socket.toString());
+        }
+    }
+
+    /**
+     * Gets the COPS error returned by the PDP
+     *
+     * @return <tt>COPSError</tt> returned by PDP
+     */
+    public COPSError getConnectionError() {
+        return error;
+    }
+
+    public void setConnectionError(COPSError _error) {
+        this.error = _error;
+    }
+
+    /**
+     * @return the serverSocket
+     */
+    public ServerSocket getServerSocket() {
+        return serverSocket;
+    }
+
+    /**
+     * @param serverSocket
+     *            the serverSocket to set
+     */
+    public void setServerSocket(ServerSocket serverSocket) {
+        this.serverSocket = serverSocket;
+    }
+
+    /**
+     * @return the serverPort
+     */
+    public int getServerPort() {
+        return serverPort;
+    }
+
+    /**
+     * @param serverPort
+     *            the serverPort to set
+     */
+    public void setServerPort(int serverPort) {
+        this.serverPort = serverPort;
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMProperties.java b/packetcable-driver/src/main/java/org/pcmm/PCMMProperties.java
new file mode 100644 (file)
index 0000000..62e4678
--- /dev/null
@@ -0,0 +1,60 @@
+package org.pcmm;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Loads the PCMM Properties file.
+ * 
+ */
+public class PCMMProperties implements PCMMConstants {
+
+       private static Properties properties;
+       private static Logger logger = LoggerFactory.getLogger(PCMMProperties.class);
+
+       static {
+               try {
+                       InputStream in = PCMMProperties.class.getClassLoader().getResourceAsStream("pcmm.properties");
+                       properties = new Properties();
+                       properties.load(in);
+                       in.close();
+               } catch (IOException ie) {
+                       logger.error(ie.getMessage());
+               }
+       }
+
+       protected static String get(String key) {
+               return properties.getProperty(key);
+       }
+
+       @SuppressWarnings("unchecked")
+       public static <T> T get(String key, Class<T> type, Object _default) {
+               String prop = get(key);
+               if (prop != null && !prop.isEmpty()) {
+                       if (Boolean.class.isAssignableFrom(type))
+                               return (T) Boolean.valueOf(prop);
+                       else if (Integer.class.isAssignableFrom(type))
+                               return (T) Integer.valueOf(prop);
+                       else if (Short.class.isAssignableFrom(type))
+                               return (T) Short.valueOf(prop);
+                       if (Float.class.isAssignableFrom(type))
+                               return (T) Float.valueOf(prop);
+                       if (Long.class.isAssignableFrom(type))
+                               return (T) Long.valueOf(prop);
+                       if (Double.class.isAssignableFrom(type))
+                               return (T) Double.valueOf(prop);
+                       else if (String.class.isAssignableFrom(type))
+                               return (T) prop;
+               }
+               return (T) _default;
+       }
+
+       public static <T> T get(String key, Class<T> type) {
+               return get(key, type, null);
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/base/IAdapter.java b/packetcable-driver/src/main/java/org/pcmm/base/IAdapter.java
new file mode 100644 (file)
index 0000000..42cdd47
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ * 
+ */
+package org.pcmm.base;
+
+/**
+ * Adapter interface
+ * 
+ */
+public interface IAdapter<Type> {
+
+       Object adapt(Object object, Class<?> clazz);
+
+       Type adapt(Object object);
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java b/packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java
new file mode 100644 (file)
index 0000000..2114004
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ @header@
+ */
+
+package org.pcmm.base;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import org.umu.cops.stack.COPSData;
+
+/**
+ * Base interface for all PCMM objects, it define the {@code S-Type},
+ * {@code S-Num} and the data length
+ * 
+ */
+public interface IPCMMBaseObject {
+
+    /**
+     * sets the S-Type
+     *
+     * @param stype
+     */
+    void setSType(byte stype);
+
+    /**
+     *
+     * @return S-Type
+     */
+    byte getSType();
+
+    /**
+     * sets the S-Num
+     *
+     * @param snum
+     *            S-Num
+     */
+    void setSNum(byte snum);
+
+    /**
+     * gets the S-Num
+     *
+     * @return S-Num
+     */
+    byte getSNum();
+
+    /**
+     * sets the length;
+     *
+     * @param len
+     */
+    void setLength(short len);
+
+    /**
+     * gets the length;
+     *
+     * @return length
+     */
+    short getLength();
+
+    /**
+     * sets the COPS data
+     *
+     * @param data
+     *            COPS data
+     */
+    void setData(COPSData data);
+
+    /**
+     * gets the COPS data
+     *
+     * @return COPS data
+     */
+    COPSData getData();
+
+    void writeData(Socket id) throws IOException;
+
+       byte[] getAsBinaryArray();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java b/packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java
new file mode 100644 (file)
index 0000000..79e26de
--- /dev/null
@@ -0,0 +1,244 @@
+/**
+ * 
+ */
+package org.pcmm.base.impl;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.Arrays;
+
+import org.pcmm.base.IPCMMBaseObject;
+import org.umu.cops.stack.COPSData;
+
+/**
+ * 
+ * Implementation of the base class {@link IPCMMBaseObject}
+ * 
+ */
+public class PCMMBaseObject /* extends COPSPrObjBase */implements
+               IPCMMBaseObject {
+
+       private byte sType;
+       private byte sNum;
+       private short len;
+       private COPSData copsData;
+       private COPSData pad;
+       protected final short offset = (short) 4;
+
+       public PCMMBaseObject(byte[] data) {
+               parse(data);
+       }
+
+       public PCMMBaseObject(short len, byte sType, byte sNum) {
+               this.len = (len);
+               this.sType = (sType);
+               this.sNum = (sNum);
+               byte[] array = new byte[len - offset];
+               Arrays.fill(array, (byte) 0);
+               setData(new COPSData(array, 0, array.length));
+       }
+
+       protected COPSData getPadding(int len) {
+               byte[] padBuf = new byte[len];
+               Arrays.fill(padBuf, (byte) 0);
+               COPSData d = new COPSData(padBuf, 0, len);
+               return d;
+       }
+
+       /**
+        * Add head padding to the specified byte array filled with zeros
+        * 
+        * @param off
+        *            offset
+        * @param array
+        *            input array
+        * @return byte array
+        */
+       protected byte[] headPadding(int off, byte[] array) {
+               byte[] returnArray = new byte[array.length + off];
+               Arrays.fill(returnArray, (byte) 0);
+               System.arraycopy(array, 0, returnArray, off, array.length);
+               return returnArray;
+       }
+
+       protected void parse(byte[] data) {
+               if (data == null || data.length == 0)
+                       throw new IllegalArgumentException("data could not be null");
+               len = 0;
+               len |= ((short) data[0]) << 8;
+               len |= ((short) data[1]) & 0xFF;
+               sNum = data[2];
+               sType = data[3];
+               copsData = new COPSData(data, offset, data.length - offset);
+       }
+
+       protected void setShort(short value, short startPos) {
+               byte[] data = getData().getData();
+               data[startPos] = (byte) (value >> 8);
+               data[startPos + 1] = (byte) value;
+               setData(new COPSData(data, 0, data.length));
+       }
+
+       protected short getShort(short startPos) {
+               byte[] data = getData().getData();
+               short retVal = 0;
+               retVal |= ((short) data[startPos]) << 8;
+               retVal |= ((short) data[startPos + 1]) & 0xFF;
+               return retVal;
+       }
+
+       protected void setInt(int value, short startPos) {
+               byte[] data = getData().getData();
+               data[startPos] = (byte) (value >> 24);
+               data[startPos + 1] = (byte) (value >> 16);
+               data[startPos + 2] = (byte) (value >> 8);
+               data[startPos + 3] = (byte) value;
+               setData(new COPSData(data, 0, data.length));
+       }
+
+       protected int getInt(short startPos) {
+               byte[] data = getData().getData();
+               int retVal = 0;
+               retVal |= ((short) data[startPos]) << 24;
+               retVal |= ((short) data[startPos + 1]) << 16;
+               retVal |= ((short) data[startPos + 2]) << 8;
+               retVal |= ((short) data[startPos + 3]) & 0xFF;
+               return retVal;
+       }
+
+       protected void setBytes(byte[] value, short startPos) {
+               byte[] data = getData().getData();
+               for (byte b : value)
+                       data[startPos++] = b;
+               setData(new COPSData(data, 0, data.length));
+       }
+
+       protected byte[] getBytes(short startPos, short size) {
+               return Arrays.copyOfRange(getData().getData(), startPos, startPos
+                               + size);
+       }
+
+       protected void setByte(byte value, short startPos) {
+               setBytes(new byte[] { value }, startPos);
+       }
+
+       protected byte getByte(short startPos) {
+               return getBytes(startPos, (short) 1)[0];
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#setSType(byte)
+        */
+       @Override
+       public void setSType(byte stype) {
+               this.sType = stype;
+
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#getSType()
+        */
+       @Override
+       public byte getSType() {
+               return sType;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#setSNum(byte)
+        */
+       @Override
+       public void setSNum(byte snum) {
+               this.sNum = snum;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#getSNum()
+        */
+       @Override
+       public byte getSNum() {
+               return sNum;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#setLength(short)
+        */
+       @Override
+       public void setLength(short len) {
+               this.len = len;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#getLength()
+        */
+       @Override
+       public short getLength() {
+               return (short) (len + (pad != null ? pad.length() : 0));
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#setData(org.umu.cops.stack.COPSData)
+        */
+       @Override
+       public void setData(COPSData data) {
+               this.copsData = data;
+               if (data.length() % offset != 0) {
+                       int padLen = offset - (data.length() % offset);
+                       pad = getPadding(padLen);
+               }
+               len = (short) (data.length() + offset);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#getData()
+        */
+       @Override
+       public COPSData getData() {
+               return copsData;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#writeData(java.net.Socket)
+        */
+       public void writeData(Socket id) throws IOException {
+               byte[] data = getAsBinaryArray();
+               id.getOutputStream().write(data, 0, data.length);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.base.IPCMMBaseObject#getAsBinaryArray()
+        */
+       @Override
+       public byte[] getAsBinaryArray() {
+               byte[] array = new byte[getLength()];
+               array[0] = (byte) (len >> 8);
+               array[1] = (byte) len;
+               array[2] = sNum;
+               array[3] = sType;
+               System.arraycopy(getData().getData(), 0, array, offset, getData()
+                               .length());
+               if (pad != null)
+                       System.arraycopy(pad.getData(), 0, array, offset
+                                       + getData().length(), pad.length());
+               return array;
+       }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/concurrent/IWorker.java b/packetcable-driver/src/main/java/org/pcmm/concurrent/IWorker.java
new file mode 100644 (file)
index 0000000..1a89605
--- /dev/null
@@ -0,0 +1,28 @@
+package org.pcmm.concurrent;
+
+import java.util.concurrent.Callable;
+/**
+ * 
+ */
+public interface IWorker extends Runnable {
+
+       /**
+        * defines the task to be performed by this worker
+        * 
+        * @param c
+        */
+       void task(Callable<?> c);
+
+       /**
+        * defines wait time before start working on the task
+        * 
+        * @param t
+        */
+       void shouldWait(int t);
+
+       /**
+        * ends the current working task.
+        */
+       void done();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/concurrent/IWorkerPool.java b/packetcable-driver/src/main/java/org/pcmm/concurrent/IWorkerPool.java
new file mode 100644 (file)
index 0000000..e97cc21
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * 
+ */
+package org.pcmm.concurrent;
+
+import org.pcmm.base.IAdapter;
+
+/**
+ * 
+ */
+public interface IWorkerPool extends IAdapter<IWorker> {
+       // handles 32 workers
+       static int DEFAULT_MAX_WORKERS = 32;
+
+       /**
+        * schedules a worker for beginning its task after t milliseconds.
+        * 
+        * @param worker
+        *            : the worker
+        * @param t
+        *            : time to wait
+        * @return the id of the worker (PID) to be used for killing the worker if
+        *         needed
+        */
+       int schedule(IWorker worker, int t);
+
+       /**
+        * schedules a worker for immediate execution.
+        * 
+        * @param worker
+        *            : the worker
+        * @return the id of the worker (PID) to be used for killing the worker if
+        *         needed
+        */
+       int schedule(IWorker worker);
+
+       /**
+        * kills the worker with the specified pid
+        * 
+        * @param pid
+        */
+       void sendKillSignal(int pid);
+
+       /**
+        * sends a terminate signal for all active workers and recycles the pool.
+        */
+       void killAll();
+
+       /**
+        * cleans up the pool from finished tasks
+        */
+       void recycle();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/concurrent/impl/Worker.java b/packetcable-driver/src/main/java/org/pcmm/concurrent/impl/Worker.java
new file mode 100644 (file)
index 0000000..1080692
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * 
+ */
+package org.pcmm.concurrent.impl;
+
+import java.util.concurrent.Callable;
+
+import org.pcmm.concurrent.IWorker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ */
+public class Worker implements IWorker {
+
+       private int waitTimer;
+
+       private Callable<?> task;
+       private Logger logger = LoggerFactory.getLogger(IWorker.class);
+
+       public Worker() {
+
+       }
+
+       public Worker(Callable<?> task) {
+               this.task = task;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see java.lang.Runnable#run()
+        */
+       @Override
+       public void run() {
+               try {
+                       if (waitTimer > 0)
+                               Thread.sleep(waitTimer);
+                       task.call();
+               } catch (Throwable e) {
+                       logger.error(e.getMessage());
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.threading.IWorker#task(java.util.concurrent.Callable)
+        */
+       @Override
+       public void task(Callable<?> c) {
+               logger.debug("Task added " + c);
+               this.task = c;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.threading.IWorker#shouldWait(int)
+        */
+       @Override
+       public void shouldWait(int t) {
+               logger.debug("Worker will start after :" + t + " ms");
+               waitTimer = t;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.threading.IWorker#done()
+        */
+       @Override
+       public void done() {
+               logger.debug("worker finished tasks");
+
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/concurrent/impl/WorkerPool.java b/packetcable-driver/src/main/java/org/pcmm/concurrent/impl/WorkerPool.java
new file mode 100644 (file)
index 0000000..b6fb429
--- /dev/null
@@ -0,0 +1,158 @@
+package org.pcmm.concurrent.impl;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.pcmm.concurrent.IWorker;
+import org.pcmm.concurrent.IWorkerPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Pool to manage PCMM workers
+ */
+public class WorkerPool implements IWorkerPool {
+
+       /**
+        * 
+        */
+       private Map<Integer, WeakReference<IWorker>> workersMap;
+
+       private Logger logger = LoggerFactory.getLogger(IWorkerPool.class);
+       private ExecutorService executor;
+
+       public WorkerPool() {
+               this(DEFAULT_MAX_WORKERS);
+       }
+
+       public WorkerPool(int size) {
+               logger.info("Pool size :" + size);
+               workersMap = new HashMap<Integer, WeakReference<IWorker>>();
+               executor = Executors.newFixedThreadPool(size);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.threading.IWorkerPool#schedule(org.pcmm.threading.IWorker,
+        * int)
+        */
+       @Override
+       public int schedule(IWorker worker, int t) {
+               if (worker == null)
+                       return -1;
+               logger.debug("woker[" + worker + "] added, starts in " + t + " ms");
+               WeakReference<IWorker> workerRef = new WeakReference<IWorker>(worker);
+               int ref = workerRef.hashCode();
+               workersMap.put(ref, workerRef);
+               worker.shouldWait(t);
+               executor.execute(worker);
+               return ref;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.pcmm.concurrent.IWorkerPool#schedule(org.pcmm.concurrent.IWorker)
+        */
+       @Override
+       public int schedule(IWorker worker) {
+               return schedule(worker, 0);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.concurrent.IWorkerPool#sendKillSignal(int)
+        */
+       @Override
+       public void sendKillSignal(int pid) {
+               if (workersMap.size() > 0) {
+                       WeakReference<IWorker> weakRef = workersMap.get(pid);
+                       if (weakRef != null) {
+                               IWorker ref = weakRef.get();
+                               if (ref != null)
+                                       ref.done();
+                               if (!weakRef.isEnqueued()) {
+                                       weakRef.clear();
+                                       weakRef.enqueue();
+                               }
+                       }
+               }
+
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.threading.IWorkerPool#killAll()
+        */
+       @Override
+       public void killAll() {
+               for (WeakReference<IWorker> weakRef : workersMap.values()) {
+                       IWorker ref = weakRef.get();
+                       if (ref != null)
+                               ref.done();
+                       if (!weakRef.isEnqueued()) {
+                               weakRef.clear();
+                               weakRef.enqueue();
+                       }
+               }
+               recycle();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.threading.IWorkerPool#recycle()
+        */
+       @Override
+       public void recycle() {
+               for (Iterator<Integer> pids = workersMap.keySet().iterator(); pids.hasNext();) {
+                       WeakReference<IWorker> weakRef = workersMap.get(pids.next());
+                       IWorker ref = weakRef.get();
+                       if (ref == null) {
+                               if (!weakRef.isEnqueued()) {
+                                       weakRef.clear();
+                                       weakRef.enqueue();
+                               }
+                               workersMap.remove(weakRef);
+                       }
+               }
+
+       }
+
+       @Override
+       public Object adapt(Object object, Class<?> clazz) {
+               if (clazz.isAssignableFrom(object.getClass()))
+                       return object;
+               return null;
+       }
+
+       @Override
+       public IWorker adapt(Object object) {
+               IWorker worker = (IWorker) adapt(object, IWorker.class);
+               if (worker == null) {
+                       if (object instanceof Callable)
+                               worker = new Worker((Callable<?>) object);
+                       else if (object instanceof Runnable) {
+                               final Runnable runner = (Runnable) object;
+                               worker = new Worker(new Callable<Object>() {
+                                       @Override
+                                       public Object call() throws Exception {
+                                               ((Runnable) runner).run();
+                                               return null;
+                                       }
+                               });
+                       }
+               }
+               return worker;
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java b/packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java
new file mode 100644 (file)
index 0000000..71e8116
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+/**
+ * <p>
+ * The AMID consists of two fields: the Application Manager Tag and Application
+ * Type. Each Application Manager is pre-provisioned with an Application Manager
+ * Tag that is unique within the universe of a single service provider. The
+ * Application Manager may also be pre-provisioned with a set of Application
+ * Type values that can be used to identify the particular application that a
+ * gate is associated with. The Application Manager includes the AMID in all
+ * messages that it issues to the Policy Server. The Policy Server transparently
+ * passes this information to the CMTS via Gate Control messages. The CMTS MUST
+ * return the AMID associated with the Gate to the Policy Server. The Policy
+ * Server uses this information to associate Gate messages with a particular
+ * Application Manager and Application Type.
+ * </p>
+ * <p>
+ * The Application Manager Tag MUST be a globally unique value assigned to the
+ * Application Manager by the service provider. The Application Manager MUST use
+ * the assigned Application Manager Tag in all its interactions with Policy
+ * Servers. Note that since the Application Manager may be operated by a third
+ * party, and a single Application Manager could interact with multiple service
+ * provider operators, a single physical Application Manager may be provisioned
+ * with multiple Application Manager Tags, and multiple Application Type sets
+ * (one for each configured Application Manager Tag).
+ * </p>
+ *
+ *
+ */
+public interface IAMID extends IPCMMBaseObject {
+
+    static final short LENGTH = 8;
+    static final byte SNUM = 2;
+    static final byte STYPE = 1;
+
+    void setApplicationType(short type);
+
+    short getApplicationType();
+
+    void setApplicationMgrTag(short type);
+
+    short getApplicationMgrTag();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java
new file mode 100644 (file)
index 0000000..6aea0ae
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+import java.net.InetAddress;
+
+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;
+
+    static enum Protocol {
+        /*ICMP((short) 1), IGMP((short) 2), */
+        NONE((short)0), TCP((short) 6), UDP((short) 17);
+
+        Protocol(short v) {
+            this.value = v;
+        }
+
+        public static Protocol valueOf(short v) {
+            switch (v) {
+            case 0:
+                return NONE;
+          /*
+            case 1:
+                return ICMP;
+            case 2:
+                return IGMP;
+          */
+            case 6:
+                return TCP;
+            default:
+                return UDP;
+            }
+        }
+        private short value;
+
+        public short getValue() {
+            return value;
+        }
+    }
+
+    /**
+     * IP Destination Address or IPv6 Destination Address is the termination
+     * point for the IP flow
+     *
+     * @return destination IP address.
+     */
+    InetAddress getDestinationIPAddress();
+
+    void setDestinationIPAddress(InetAddress address);
+
+    short getDestinationPort();
+
+    void setDestinationPort(short p);
+
+    /**
+     * Source IP, IP Source Address, or IPv6 Source Address (in the case of
+     * Extended Classifier or IPv6 Classifier) is the IP address (as seen at the
+     * CMTS) of the originator of the IP flow.
+     *
+     * @return source IP address.
+     */
+    InetAddress getSourceIPAddress();
+
+    void setSourceIPAddress(InetAddress a);
+
+    short getSourcePort();
+
+    void setSourcePort(short p);
+
+    /**
+     * Protocol field, in a legacy Classifier or Extended Classifier, identifies
+     * the type of protocol (e.g., IP, ICMP, etc.). The Next Header Type field
+     * serves a similar function in the IPv6 Classifier.
+     *
+     * @return the protocol.
+     */
+    Protocol getProtocol();
+
+    /**
+     * @see <a
+     *      href="http://www.iana.org/assignments/protocol-numbers/protocol-numbers.txt">protocols</a>
+     * @param p
+     */
+    void setProtocol(Protocol p);
+
+    /**
+     * Priority may be used to distinguish between multiple classifiers that
+     * match a particular packet. This is typically set to a default value since
+     * classifiers are generally intended to be unique.
+     *
+     * @return priority.
+     */
+    byte getPriority();
+
+    /**
+     * sets the priority;
+     *
+     * @param p
+     *            priority
+     */
+    void setPriority(byte p);
+
+    byte getDSCPTOS();
+
+    void setDSCPTOS(byte v);
+
+    byte getDSCPTOSMask();
+
+    void setDSCPTOSMask(byte v);
+
+    // DSCP/TOS Field
+    // ï‚·
+    // DSCP/TOS Mask
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java
new file mode 100644 (file)
index 0000000..635bf25
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+import java.net.InetAddress;
+
+public interface IExtendedClassifier extends IClassifier {
+
+    static final short LENGTH = 40;
+    static final byte SNUM = 6;
+    static final byte STYPE = 2;
+
+    void setIPSourceMask(InetAddress a);
+
+    void setIPDestinationMask(InetAddress m);
+
+    void setSourcePortStart(short p);
+
+    void setSourcePortEnd(short p);
+
+    void setDestinationPortStart(short p);
+
+    void setDestinationPortEnd(short p);
+
+    void setClassifierID(short p);
+
+    /**
+     * <pre>
+     * 0x00 Inactive
+     * 0x01 Active
+     * </pre>
+     *
+     * @param s
+     */
+    void setActivationState(byte s);
+
+    /**
+     * <pre>
+     * 0x00 Add classifier
+     * 0x01 Replace classifier
+     * 0x02 Delete classifier
+     * 0x03 No change
+     * </pre>
+     *
+     * @param a
+     */
+    void setAction(byte a);
+
+    InetAddress getIPSourceMask();
+
+    InetAddress getIPDestinationMask();
+
+    short getSourcePortStart();
+
+    short getSourcePortEnd();
+
+    short getDestinationPortStart();
+
+    short getDestinationPortEnd();
+
+    short getClassifierID();
+
+    byte getActivationState();
+
+    byte getAction();
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java b/packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java
new file mode 100644 (file)
index 0000000..d6d9582
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ @header@
+ */
+package org.pcmm.gates;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+/**
+ *
+ */
+public interface IGateID extends IPCMMBaseObject {
+    static final short LENGTH = 8;
+    static final byte SNUM = 4;
+    static final byte STYPE = 1;
+
+    void setGateID(int gateID);
+
+    int getGateID();
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java b/packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java
new file mode 100644 (file)
index 0000000..10f4500
--- /dev/null
@@ -0,0 +1,246 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+/**
+ * <p>
+ * The GateSpec describes some high-level attributes of the Gate, and contains
+ * 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;
+
+    /**
+     * <p>
+     * Direction indicates whether the Gate is for an upstream or downstream
+     * flow. Depending on this direction, the CMTS MUST reserve and activate the
+     * DOCSIS flows accordingly. For Multicast Gates the CMTS needs to only
+     * support flows or gates in the downstream direction.
+     * </p>
+     *
+     *
+     */
+    public enum Direction {
+
+        UPSTREAM((byte) 1), DOWNSTREAM((byte) 0);
+
+        private Direction(byte value) {
+            this.value = value;
+        }
+
+        public byte getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            switch (value) {
+            case 1:
+                return "Upstream";
+            default:
+                return "Downstream";
+            }
+        }
+
+        private byte value;
+
+        public static Direction valueOf(byte v) {
+            switch (v) {
+            case 0:
+                return Direction.DOWNSTREAM;
+            case 1:
+                return Direction.UPSTREAM;
+            default:
+                throw new IllegalArgumentException("not supported value");
+            }
+        }
+
+    };
+
+    /**
+     *
+     */
+    public enum DSCPTOS {
+
+        ENABLE((byte) 1), OVERRIDE((byte) 0);
+
+        private DSCPTOS(byte value) {
+            this.value = value;
+        }
+
+        public byte getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            switch (value) {
+            case 1:
+                return "Enable";
+            default:
+                return "Override";
+            }
+        }
+
+        public static DSCPTOS valueOf(byte v) {
+            switch (v) {
+            case 0:
+                return DSCPTOS.OVERRIDE;
+            case 1:
+                return DSCPTOS.ENABLE;
+            default:
+                throw new IllegalArgumentException("not supported value");
+            }
+        }
+
+        private byte value;
+
+    };
+
+    /**
+     * <p>
+     * provides a way for the Application Manager and the Policy Server to group
+     * Gates into different classes with different authorization
+     * characteristics. For example, one could use the SessionClassID to
+     * represent some prioritization or preemption scheme that would allow
+     * either the Policy Server or the CMTS to preempt a pre-authorized Gate in
+     * favor of allowing a new Gate with a higher priority to be authorized.
+     * </p>
+     *
+     * @return session class ID;
+     */
+    ISessionClassID getSessionClassID();
+
+    /**
+     * <p>
+     * sets the session class ID;
+     * </p>
+     * <p>
+     * SessionClassID is a 1-byte unsigned integer value which identifies the
+     * proper admission control policy or parameters to be applied for this
+     * Gate. The SessionClassID is a bit field, defined as follows: Bit 0-2:
+     * Priority, a number from 0 to 7, where 0 is low priority and 7 is high.
+     * Bit 3: Preemption, set to enable preemption of bandwidth allocated to
+     * lower priority sessions if necessary (if supported). Bit 4-7:
+     * Configurable, default to 0
+     * </p>
+     */
+    void setSessionClassID(ISessionClassID id);
+
+    /**
+     *
+     * @return direction.
+     */
+    Direction getDirection();
+
+    /**
+     * sets the direction
+     *
+     * @param direction
+     *            Direction
+     */
+    void setDirection(Direction direction);
+
+    /**
+     * Authorized Timer limits the amount of time the authorization must remain
+     * valid before it is reserved
+     *
+     * @return time in ms;
+     */
+    short getTimerT1();
+
+    /**
+     * sets the authorized timer
+     *
+     * @param authTimer
+     *            : authorized timer
+     */
+    void setTimerT1(short authTimer);
+
+    /**
+     * Reserved Timer limits the amount of time the reservation must remain
+     * valid before the resources are committed
+     *
+     * @return time in ms;
+     */
+    short getTimerT2();
+
+    /**
+     * sets the reserved timer.
+     *
+     * @param timer
+     */
+    void setTimerT2(short timer);
+
+    /**
+     * Committed Timer limits the amount of time a committed service flow may
+     * remain idle.
+     *
+     * @return time in ms;
+     */
+    short getTimerT3();
+
+    /**
+     * sets the committed timer.
+     *
+     * @param t
+     *            timer
+     */
+    void setTimerT3(short t);
+
+    /**
+     * Committed Recovery Timer limits the amount of time that a committed
+     * service flow can remain without a subsequent refresh message from the
+     * PS/AM once the PS/AM has been notified of inactivity
+     *
+     * @return time in ms;
+     */
+    short getTimerT4();
+
+    /**
+     * sets the Committed Recovery Timer.
+     *
+     * @param t
+     *            timer
+     */
+    void setTimerT4(short t);
+
+    /**
+     *
+     * @param dscpTos
+     */
+    void setDSCP_TOSOverwrite(DSCPTOS dscpTos);
+
+    /**
+     *
+     * @return DSCP/TOS
+     */
+    DSCPTOS getDSCP_TOSOverwrite();
+
+    /**
+     *
+     * @return
+     */
+    byte getDSCP_TOSMask();
+
+    /**
+     *
+     * @param dscp_tos_mask
+     */
+    void setDSCP_TOSMask(byte dscp_tos_mask);
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java
new file mode 100644 (file)
index 0000000..a9d689f
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+public interface IIPv6Classifier extends IExtendedClassifier {
+    static final short LENGTH = 64;
+    static final byte SNUM = 6;
+    static final byte STYPE = 3;
+
+    // Tc-low
+    // Tc-high
+    // Tc-mask
+    // Flow Label
+    // Next Header Type
+    // Source Prefix Length
+    // Destination Prefix Length
+    // IPv6 Source Address
+    // IPv6 Destination Address
+    // Source Port Start
+    // Source Port End
+    // Destination Port Start
+    // Destination Port End
+    // ClassifierID
+    // Priority
+    // Activation State
+    // Action
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java b/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java
new file mode 100644 (file)
index 0000000..bd0b47a
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ @header@
+ */
+package org.pcmm.gates;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+/**
+ *
+ */
+public interface IPCMMError extends IPCMMBaseObject {
+       static final short LENGTH = 8;
+       static final byte SNUM = 14;
+       static final byte STYPE = 1;
+       final String[] errors = { "Insufficient Resources", "Unknown GateID",
+                       "Missing Required Object", "Invalid Object",
+                       "Volume Based Usage Limit Exceeded",
+                       "Time Based Usage Limit Exceeded", "Session Class Limit Exceeded",
+                       "Undefined Service Class Name", "Incompatible Envelope",
+                       "Invalid SubscriberID", "Unauthorized AMID",
+                       "Number of Classifiers Not Supported", "Policy Exception",
+                       "Invalid Field Value in Object", "Transport Error",
+                       "Unknown Gate Command", "DOCSIS 1.0 CM",
+                       "Number of SIDs exceeded in CM", "Number of SIDs exceeded in CMTS",
+                       "Unauthorized PSID", "No State for PDP", "Unsupported Synch Type",
+                       "State Data Incomplete", "Upstream Drop Unsupported",
+                       "Multicast Gate Error", "Multicast Volume Limit Unsupported",
+                       "Uncommitted Multicast Not Supported",
+                       "Multicast Gate Modification Not Supported",
+                       "Upstream Multicast Not Supported",
+                       "Multicast GateSpec incompatibility", "Multicast QoS Error",
+                       "Multicast Downstream Resequencing mismatch",
+                       "Other, Unspecified Error" };
+
+       static enum Description {
+               ERROR_01((short) 1, errors[0]), ERROR_02((short) 2, errors[1]), ERROR_06(
+                               (short) 6, errors[2]), ERROR_07((short) 7, errors[3]), ERROR_08(
+                               (short) 8, errors[4]), ERROR_09((short) 9, errors[5]), ERROR_10(
+                               (short) 10, errors[6]), ERROR_11((short) 11, errors[7]), ERROR_12(
+                               (short) 12, errors[8]), ERROR_13((short) 13, errors[9]), ERROR_14(
+                               (short) 14, errors[10]), ERROR_15((short) 15, errors[11]), ERROR_16(
+                               (short) 16, errors[12]), ERROR_17((short) 17, errors[13]), ERROR_18(
+                               (short) 18, errors[14]), ERROR_19((short) 19, errors[15]), ERROR_20(
+                               (short) 20, errors[16]), ERROR_21((short) 21, errors[17]), ERROR_22(
+                               (short) 22, errors[18]), ERROR_23((short) 23, errors[19]), ERROR_24(
+                               (short) 24, errors[20]), ERROR_25((short) 25, errors[21]), ERROR_26(
+                               (short) 26, errors[22]), ERROR_27((short) 27, errors[23]), ERROR_28(
+                               (short) 28, errors[24]), ERROR_29((short) 29, errors[25]), ERROR_30(
+                               (short) 30, errors[26]), ERROR_31((short) 31, errors[27]), ERROR_32(
+                               (short) 32, errors[28]), ERROR_33((short) 33, errors[29]), ERROR_34(
+                               (short) 34, errors[30]), ERROR_35((short) 35, errors[31]), ERROR_127(
+                               (short) 127, errors[28]);
+
+               private final short code;
+               private final String description;
+
+               private Description(short code, String description) {
+                       this.code = code;
+                       this.description = description;
+               }
+
+               public String getDescription() {
+                       return description;
+               }
+
+               public short getCode() {
+                       return code;
+               }
+
+               public static String valueOf(short errCode) {
+                       switch (errCode) {
+                       case 1:
+                       case 2:
+                               return errors[errCode - 1];
+                       case 127:
+                               return errors[32];
+                       default:
+                               if (errCode > 35 || errCode < 1)
+                                       throw new IllegalArgumentException("unrecongnized error code : " + errCode);
+                               return errors[errCode - 4];
+                       }
+               }
+       }
+
+       void setErrorCode(short ErrorCode);
+
+       short getErrorCode();
+
+       void setErrorSubcode(short ErrorSubcode);
+
+       short getErrorSubcode();
+
+       String getDescription();
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java b/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java
new file mode 100644 (file)
index 0000000..ada6a51
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+
+/**
+ * <p>
+ * A PacketCable Multimedia Gate is a logical representation of a policy
+ * decision that has been installed on the CMTS. A Gate is used to control
+ * access by a single IP flow to enhanced QoS Services provided by a DOCSIS
+ * cable network. Gates are unidirectional; a single Gate controls access to a
+ * flow in either the upstream or the downstream direction, but not both. For a
+ * bi-directional IP session, two Gates are required, one for upstream and one
+ * for downstream, each identified by a unique GateID. It is important to
+ * recognize that this is a fundamental difference from PacketCable 1.x, in
+ * which a single GateID may reference both an upstream and a downstream Gate.
+ * </p>
+ * <p>
+ * In PacketCable Multimedia, each Gate has a separate GateID. The Gate defines
+ * </p>
+ * <p>
+ *
+ * </p>
+ *
+ *
+ */
+public interface IPCMMGate {
+
+
+    /**
+     *
+     * @return whether this gate is multicast or unicast.
+     */
+    boolean isMulticast();
+
+    /**
+     * GateID is the handle for the Gate.
+     *
+     */
+    void setGateID(IGateID gateid);
+
+    /**
+     * AMID is the handle that identifies the Application Manager and
+     * Application Type
+     *
+     */
+    void setAMID(IAMID iamid);
+
+    /**
+     * SubscriberID uniquely identifies the Client for which the policy is being
+     * set.
+     *
+     */
+    void setSubscriberID(ISubscriberID subscriberID);
+
+    /**
+     * (i.e., QoS limits, timers, etc.).
+     *
+     */
+    void setGateSpec(IGateSpec gateSpec);
+
+    /**
+     * Classifier describes the IP flow(s) that will be mapped to the DOCSIS
+     * Service Flow.
+     *
+     */
+    void setClassifier(IClassifier classifier);
+
+    /**
+     * Traffic Profile describes the QoS attributes of the Service Flow used to
+     * support the IP flow.
+     */
+    void setTrafficProfile(ITrafficProfile profile);
+
+    void setTransactionID(ITransactionID transactionID);
+
+    void setError(IPCMMError error);
+
+    ITransactionID getTransactionID();
+
+    /**
+     * GateID is the handle for the Gate.
+     *
+     * @return gateID
+     */
+    IGateID getGateID();
+
+    /**
+     * AMID is the handle that identifies the Application Manager and
+     * Application Type
+     *
+     * @return AMID handle.
+     */
+    IAMID getAMID();
+
+    /**
+     * SubscriberID uniquely identifies the Client for which the policy is being
+     * set.
+     *
+     * @return unique subscriber ID.
+     */
+    ISubscriberID getSubscriberID();
+
+    /**
+     * (i.e., QoS limits, timers, etc.).
+     *
+     * @return gateSpec object.
+     */
+    IGateSpec getGateSpec();
+
+    /**
+     * Classifier describes the IP flow(s) that will be mapped to the DOCSIS
+     * Service Flow.
+     *
+     * @return Classifier object.
+     */
+    IClassifier getClassifier();
+
+    /**
+     * Traffic Profile describes the QoS attributes of the Service Flow used to
+     * support the IP flow.
+     */
+    ITrafficProfile getTrafficProfile();
+
+    /**
+     * The PacketCable Error object contains information on the type of error that has occurred.
+     */
+    IPCMMError getError();
+
+
+    /**
+     *
+     * @return cops data
+     */
+    byte[] getData();
+    // Event Generation Info (optional)
+    // Time-Based Usage Limit (optional)
+    // Volume-Based Usage Limit (optional)
+    // Opaque Data (optional)
+    // UserID (optional)
+    // SharedResourceID (optional)
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java b/packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java
new file mode 100644 (file)
index 0000000..11ca7f2
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ @header@
+ */
+package org.pcmm.gates;
+
+/**
+ *
+ */
+public interface ISessionClassID {
+
+    /**
+     * gets the priority bits
+     *
+     * @return O-7 priority value
+     */
+    byte getPriority();
+
+    /**
+     * sets the priority value (0-7)
+     *
+     * @param value
+     *            priority
+     */
+    void setPriority(byte value);
+
+    /**
+     * gets the preemption value;
+     *
+     * @return peemption
+     */
+    byte getPreemption();
+
+    /**
+     * * sets the preemption
+     *
+     * @param value
+     *            preemption
+     */
+    void setPreemption(byte value);
+
+    /**
+     * compress the priority and preemption to a single byte value;
+     *
+     * @return SessionClassID as byte
+     */
+    byte toSingleByte();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java b/packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java
new file mode 100644 (file)
index 0000000..d71e194
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+import java.net.InetAddress;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+/**
+ * <p>
+ * The SubscriberID, consisting of the IPv4 or IPv6 address of either the CM or
+ * client CPE device (either directly connected to the CM or on a routable
+ * network behind the CM), identifies the user requesting the service. In
+ * complex network environments this address may be used to route Gate Control
+ * messages between a number of Policy Servers and to determine which CMTS is
+ * providing service to a particular endpoint. In addition to the IPv4 or IPv6
+ * address, a subscriber may also be identified via a FQDN or some opaque data
+ * (object defined below) relevant to the service in question.
+ * </p>
+ * <p>
+ * For a Multicast Gates the CMTS uses the SubscriberID to decide where the
+ * Multicast replication needs to be created. The CMTS treats the SubscriberID
+ * as the source IP address of a JoinMulticastSession [1]. If the SubscriberID
+ * is on an IP subnet that is not directly connected to the CMTS, the CMTS MAY
+ * reject the Gate as having an invalid SubscriberID see 6.4.2.14 PacketCable
+ * Error.
+ * </p>
+ *
+ *
+ */
+
+public interface ISubscriberID extends IPCMMBaseObject {
+    static final short LENGTH = 8;
+    static final byte SNUM = 3;
+    static final byte STYPE = 1;
+
+    /**
+     * source IP address for the PCMM gate.
+     *
+     * @return IP v4 or v6 ip address.
+     */
+    InetAddress getSourceIPAddress();
+
+    void setSourceIPAddress(InetAddress address);
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java b/packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java
new file mode 100644 (file)
index 0000000..9e21675
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.gates;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+public interface ITrafficProfile extends IPCMMBaseObject {
+
+    static final byte SNUM = 7;
+
+    /**
+     * 0x001, 0x011 and 0x111 (Authorized, Reserved, and Committed) are allowed
+     *
+     * @param en
+     */
+    void setEnvelop(byte en);
+
+    byte getEnvelop();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java b/packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java
new file mode 100644 (file)
index 0000000..e835b39
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ @header@
+ */
+package org.pcmm.gates;
+
+import org.pcmm.base.IPCMMBaseObject;
+
+/**
+ */
+public interface ITransactionID extends IPCMMBaseObject {
+
+    static final byte SNUM = 1;
+    static final byte STYPE = 1;
+    static final short LENGTH = 8;
+
+    static final short GateSet = 4;
+    static final short GateSetAck = 5;
+    static final short GateSetErr = 6;
+    static final short GateInfo = 7;
+    static final short GateInfoAck = 8;
+    static final short GateInfoErr = 9;
+    static final short GateDelete = 10;
+    static final short GateDeleteAck = 11;
+    static final short GateDeleteErr = 12;
+    static final short GateReportState = 15;
+    static final short GateCmdErr = 16;
+    static final short PDPConfig = 17;
+    static final short PDPConfigAck = 18;
+    static final short PDPConfigErr = 19;
+    static final short SynchRequest = 20;
+    static final short SynchReport = 21;
+    static final short SynchComplete = 22;
+    static final short MsgReceipt = 23;
+
+    void setTransactionIdentifier(short id);
+
+    short getTransactionIdentifier();
+
+    void setGateCommandType(short type);
+
+    short getGateCommandType();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java
new file mode 100644 (file)
index 0000000..4f1c3af
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IAMID;
+
+/**
+ *
+ */
+public class AMID extends PCMMBaseObject implements IAMID {
+
+    /**
+     *
+     */
+    public AMID() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public AMID(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public AMID(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IAMID#setApplicationType(short)
+     */
+    @Override
+    public void setApplicationType(short type) {
+        setShort(type, (short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IAMID#getApplicationType()
+     */
+    @Override
+    public short getApplicationType() {
+        return getShort((short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IAMID#setApplicationMgrTag(short)
+     */
+    @Override
+    public void setApplicationMgrTag(short type) {
+        setShort(type, (short) 2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IAMID#getApplicationMgrTag()
+     */
+    @Override
+    public short getApplicationMgrTag() {
+        return getShort((short) 2);
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java
new file mode 100644 (file)
index 0000000..4e0e9b0
--- /dev/null
@@ -0,0 +1,211 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import java.util.Arrays;
+
+// import org.junit.Assert;
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.ITrafficProfile;
+import org.umu.cops.stack.COPSData;
+
+/**
+ *
+ */
+public class BestEffortService extends PCMMBaseObject implements
+               ITrafficProfile {
+       public static final byte STYPE = 3;
+       // XXX -> 60=0x3C, 112 = 0x70, 164=0xA4
+       // Length = 44=0x2C, 80=0x50 or 116=0x74
+       public static final short LENGTH = 44;
+
+       public static final byte DEFAULT_TRAFFIC_PRIORITY = 0;
+       // Authorized
+       public static final byte DEFAULT_ENVELOP = 0x7;
+
+       public static final int DEFAULT_MAX_TRAFFIC_BURST = 3044;
+
+       private BEEnvelop authorizedEnvelop;
+
+       private BEEnvelop reservedEnvelop;
+
+       private BEEnvelop committedEnvelop;
+
+       /**
+        * 
+        * @param e
+        *            envelop
+        */
+       public BestEffortService(byte e) {
+               super((short) (e == 1 ? LENGTH : (e == 7 ? 116 : 80)), STYPE, SNUM);
+               setEnvelop(e);
+               authorizedEnvelop = new BEEnvelop();
+               if (e > 1) {
+                       reservedEnvelop = new BEEnvelop();
+                       if (e == 7)
+                               committedEnvelop = new BEEnvelop();
+               }
+       }
+
+       public BestEffortService(byte[] bytes) {
+               super(bytes);
+               byte e = getEnvelop();
+               authorizedEnvelop = new BEEnvelop(headPadding(offset, Arrays.copyOfRange(bytes, 8, LENGTH)));
+               if (e > 1) {
+                       reservedEnvelop = new BEEnvelop(headPadding(offset, Arrays.copyOfRange(bytes, LENGTH, 80)));
+                       if (e == 7)
+                               committedEnvelop = new BEEnvelop(headPadding(offset, Arrays.copyOfRange(bytes, 80, 116)));
+               }
+       }
+
+       @Override
+       public void setEnvelop(byte e) {
+               setLength((short) (e == 1 ? LENGTH : (e == 7 ? 116 : 80)));
+               // reset cops data to fit the new length
+               byte[] array = new byte[getLength() - offset];
+               Arrays.fill(array, (byte) 0);
+               setData(new COPSData(array, 0, array.length));
+               setByte(e, (short) 0);
+       }
+
+       @Override
+       public byte getEnvelop() {
+               return getByte((short) 0);
+       }
+
+       public BEEnvelop getAuthorizedEnvelop() {
+               return authorizedEnvelop;
+       }
+
+       public BEEnvelop getReservedEnvelop() {
+               return reservedEnvelop;
+       }
+
+       public BEEnvelop getCommittedEnvelop() {
+               return committedEnvelop;
+       }
+
+       @Override
+       public byte[] getAsBinaryArray() {
+               byte[] returnBuffer = super.getAsBinaryArray();
+
+               {// fill buffer with the Authorized Envelop
+                       byte[] authEnv = Arrays.copyOfRange(getAuthorizedEnvelop().getAsBinaryArray(), offset, BEEnvelop.LENGHT);
+                       // offset + 4 since the Envelop data begin from byte nb 8
+                       System.arraycopy(authEnv, 0, returnBuffer, offset + 4, authEnv.length);
+               }
+               if (getReservedEnvelop() != null) {
+                       byte[] reservedEnv = Arrays.copyOfRange(getReservedEnvelop().getAsBinaryArray(), offset, BEEnvelop.LENGHT);
+                       System.arraycopy(reservedEnv, 0, returnBuffer, LENGTH, reservedEnv.length);
+               }
+               if (getCommittedEnvelop() != null) {
+                       byte[] commitEnv = Arrays.copyOfRange(getCommittedEnvelop().getAsBinaryArray(), offset, BEEnvelop.LENGHT);
+                       System.arraycopy(commitEnv, 0, returnBuffer, LENGTH + 36, commitEnv.length);
+               }
+               return returnBuffer;
+       }
+
+       /**
+     *
+     *
+     */
+       public static class BEEnvelop extends PCMMBaseObject {
+               // basically we need 36 bytes but since PCMMBasedObject needs 4 bytes
+               // more we allocate 40 bytes and then subtract them when setting BE
+               // data.
+               private final static short LENGHT = 40;
+
+               protected BEEnvelop() {
+                       super(LENGHT, (byte) 0, (byte) 0);
+                       setTrafficPriority(DEFAULT_TRAFFIC_PRIORITY);
+               }
+
+               protected BEEnvelop(byte[] buffer) {
+                       super(buffer);
+               }
+
+               public void setTrafficPriority(byte p) {
+                       setByte(p, (short) 0);
+               }
+
+               public byte getTrafficPriority() {
+                       return getByte((short) 0);
+               }
+
+               //
+               public void setRequestTransmissionPolicy(int p) {
+                       setInt(p, (short) 4);
+               }
+
+               public int getRequestTransmissionPolicy() {
+                       return getInt((short) 4);
+               }
+
+               public int getMaximumSustainedTrafficRate() {
+                       return getInt((short) 8);
+               }
+
+               public void setMaximumSustainedTrafficRate(int p) {
+                       setInt(p, (short) 8);
+               }
+
+               public int getMaximumTrafficBurst() {
+                       return getInt((short) 12);
+               }
+
+               public void setMaximumTrafficBurst(int p) {
+                       setInt(p, (short) 12);
+               }
+
+               public int getMinimumReservedTrafficRate() {
+                       return getInt((short) 16);
+               }
+
+               public void setMinimumReservedTrafficRate(int p) {
+                       setInt(p, (short) 16);
+               }
+
+               public short getAssumedMinimumReservedTrafficRatePacketSize() {
+                       return getShort((short) 20);
+               }
+
+               public void setAssumedMinimumReservedTrafficRatePacketSize(short p) {
+                       setShort(p, (short) 20);
+               }
+
+               public short getMaximumConcatenatedBurst() {
+                       return getShort((short) 22);
+               }
+
+               public void setMaximumConcatenatedBurst(short p) {
+                       setShort(p, (short) 22);
+               }
+
+               public int getRequiredAttributeMask() {
+                       return getInt((short) 24);
+               }
+
+               public void setRequiredAttributeMask(int p) {
+                       setInt(p, (short) 24);
+               }
+
+               public int getForbiddenAttributeMask() {
+                       return getInt((short) 28);
+               }
+
+               public void setForbiddenAttributeMask(int p) {
+                       setInt(p, (short) 28);
+               }
+
+               public int getAttributeAggregationRuleMask() {
+                       return getInt((short) 32);
+               }
+
+               public void setAttributeAggregationRuleMask(int p) {
+                       setInt(p, (short) 32);
+               }
+
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java
new file mode 100644 (file)
index 0000000..8384722
--- /dev/null
@@ -0,0 +1,193 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IClassifier;
+
+/**
+ *
+ */
+public class Classifier extends PCMMBaseObject implements IClassifier {
+
+    /**
+     *
+     */
+    public Classifier() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public Classifier(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public Classifier(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getDestinationIPAddress()
+     */
+    @Override
+    public InetAddress getDestinationIPAddress() {
+        try {
+            return Inet4Address.getByAddress(getBytes((short) 8, (short) 4));
+        } catch (UnknownHostException e) {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.IClassifier#setDestinationIPAddress(java.net.InetAddress)
+     */
+    @Override
+    public void setDestinationIPAddress(InetAddress address) {
+        setBytes(address.getAddress(), (short) 8);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getDestinationPort()
+     */
+    @Override
+    public short getDestinationPort() {
+        return getShort((short) 14);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setDestinationPort(short)
+     */
+    @Override
+    public void setDestinationPort(short p) {
+        setShort(p, (short) 14);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getSourceIPAddress()
+     */
+    @Override
+    public InetAddress getSourceIPAddress() {
+        try {
+            return Inet4Address.getByAddress(getBytes((short) 4, (short) 4));
+        } catch (UnknownHostException e) {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setSourceIPAddress(java.net.InetAddress)
+     */
+    @Override
+    public void setSourceIPAddress(InetAddress a) {
+        setBytes(a.getAddress(), (short) 4);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getSourcePort()
+     */
+    @Override
+    public short getSourcePort() {
+        return getShort((short) 12);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setSourcePort(short)
+     */
+    @Override
+    public void setSourcePort(short p) {
+        setShort(p, (short) 12);
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getProtocol()
+     */
+    @Override
+    public Protocol getProtocol() {
+        return Protocol.valueOf(getShort((short) 0));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setProtocol(short)
+     */
+    @Override
+    public void setProtocol(Protocol p) {
+        setShort(p.getValue(), (short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getPriority()
+     */
+    @Override
+    public byte getPriority() {
+        return getBytes((short) 16, (short) 1)[0];
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setPriority(byte)
+     */
+    @Override
+    public void setPriority(byte p) {
+        setBytes(new byte[] { p }, (short) 16);
+    }
+
+    @Override
+    public byte getDSCPTOS() {
+        return getBytes((short) 2, (short) 1)[0];
+    }
+
+    @Override
+    public void setDSCPTOS(byte v) {
+        setBytes(new byte[] { v }, (short) 2);
+
+    }
+
+    @Override
+    public byte getDSCPTOSMask() {
+        return getBytes((short) 3, (short) 1)[0];
+    }
+
+    @Override
+    public void setDSCPTOSMask(byte v) {
+        setBytes(new byte[] { v }, (short) 3);
+
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java
new file mode 100644 (file)
index 0000000..854d543
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.ITrafficProfile;
+
+/**
+ *
+ */
+public class DOCSISServiceClassNameTrafficProfile extends PCMMBaseObject
+            implements ITrafficProfile {
+
+    public static final byte STYPE = 2;
+    public static final short LENGTH = 12;
+
+    /**
+     *
+     */
+    public DOCSISServiceClassNameTrafficProfile() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public DOCSISServiceClassNameTrafficProfile(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public DOCSISServiceClassNameTrafficProfile(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+        setEnvelop((byte) 0x7);
+    }
+
+    /**
+     * @return the serviceClassName
+     */
+    public String getServiceClassName() {
+        return new String(getBytes((short) 4, (short) 4));
+    }
+
+    /**
+     * @param serviceClassName
+     *            the serviceClassName to set
+     */
+    public void setServiceClassName(String serviceClassName) {
+        setBytes(serviceClassName.getBytes(), (short) 4);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ITrafficProfile#getEnvelop()
+     */
+    @Override
+    public byte getEnvelop() {
+        return getBytes((short) 0, (short) 1)[0];
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ITrafficProfile#setEnvelop(byte)
+     */
+    @Override
+    public void setEnvelop(byte en) {
+        setBytes(new byte[] { en }, (short) 0);
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java
new file mode 100644 (file)
index 0000000..0e68f50
--- /dev/null
@@ -0,0 +1,347 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IExtendedClassifier;
+
+/**
+ *
+ */
+public class ExtendedClassifier extends PCMMBaseObject implements
+            IExtendedClassifier {
+
+    public ExtendedClassifier() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public ExtendedClassifier(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public ExtendedClassifier(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getDestinationIPAddress()
+     */
+    @Override
+    public InetAddress getDestinationIPAddress() {
+        try {
+            return InetAddress.getByAddress(getBytes((short) 12, (short) 4));
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.IClassifier#setDestinationIPAddress(java.net.InetAddress)
+     */
+    @Override
+    public void setDestinationIPAddress(InetAddress address) {
+        setBytes(address.getAddress(), (short) 12);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getDestinationPort()
+     */
+    @Override
+    public short getDestinationPort() {
+        return getShort((short) 24);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setDestinationPort(short)
+     */
+    @Override
+    public void setDestinationPort(short p) {
+        setShort(p, (short) 24);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getSourceIPAddress()
+     */
+    @Override
+    public InetAddress getSourceIPAddress() {
+        try {
+            return InetAddress.getByAddress(getBytes((short) 4, (short) 4));
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setSourceIPAddress(java.net.InetAddress)
+     */
+    @Override
+    public void setSourceIPAddress(InetAddress a) {
+        setBytes(a.getAddress(), (short) 4);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getSourcePort()
+     */
+    @Override
+    public short getSourcePort() {
+        return getShort((short) 20);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setSourcePort(short)
+     */
+    @Override
+    public void setSourcePort(short p) {
+        setShort(p, (short) 20);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getProtocol()
+     */
+    @Override
+    public Protocol getProtocol() {
+        return Protocol.valueOf(getShort((short) 0));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setProtocol(short)
+     */
+    @Override
+    public void setProtocol(Protocol p) {
+        setShort(p.getValue(), (short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#getPriority()
+     */
+    @Override
+    public byte getPriority() {
+        return getByte((short) 30);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IClassifier#setPriority(byte)
+     */
+    @Override
+    public void setPriority(byte p) {
+        setByte(p, (short) 30);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getIPSourceMask()
+     */
+    @Override
+    public InetAddress getIPSourceMask() {
+        try {
+            return InetAddress.getByAddress(getBytes((short) 8, (short) 4));
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.IExtendedClassifier#setIPSourceMask(java.net.InetAddress)
+     */
+    @Override
+    public void setIPSourceMask(InetAddress a) {
+        setBytes(a.getAddress(), (short) 8);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getIPDestinationMask()
+     */
+    @Override
+    public InetAddress getIPDestinationMask() {
+        try {
+            return InetAddress.getByAddress(getBytes((short) 16, (short) 4));
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.IExtendedClassifier#setIPDestinationMask(java.net.InetAddress
+     * )
+     */
+    @Override
+    public void setIPDestinationMask(InetAddress m) {
+        setBytes(m.getAddress(), (short) 16);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getSourcePortStart()
+     */
+    @Override
+    public short getSourcePortStart() {
+        return getShort((short) 20);
+    }
+
+    @Override
+    public void setSourcePortStart(short p) {
+        setShort(p, (short) 20);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getSourcePortEnd()
+     */
+    @Override
+    public short getSourcePortEnd() {
+        return getShort((short) 22);
+    }
+
+    @Override
+    public void setSourcePortEnd(short p) {
+        setShort(p, (short) 22);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getDestinationPortStart()
+     */
+    @Override
+    public short getDestinationPortStart() {
+        return getShort((short) 24);
+    }
+
+    @Override
+    public void setDestinationPortStart(short p) {
+        setShort(p, (short) 24);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getDestinationPortEnd()
+     */
+    @Override
+    public short getDestinationPortEnd() {
+        return getShort((short) 26);
+    }
+
+    @Override
+    public void setDestinationPortEnd(short p) {
+        setShort(p, (short) 26);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getClassifierID()
+     */
+    @Override
+    public short getClassifierID() {
+        return getShort((short) 28);
+    }
+
+    @Override
+    public void setClassifierID(short p) {
+        setShort(p, (short) 28);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getActivationState()
+     */
+    @Override
+    public byte getActivationState() {
+        return getByte((short) 31);
+    }
+
+    @Override
+    public void setActivationState(byte s) {
+        setByte(s, (short) 31);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IExtendedClassifier#getAction()
+     */
+    @Override
+    public byte getAction() {
+        return getByte((short) 32);
+    }
+
+    @Override
+    public void setAction(byte a) {
+        setByte(a, (short) 32);
+    }
+
+    @Override
+    public byte getDSCPTOS() {
+        return getByte((short) 2);
+    }
+
+    @Override
+    public void setDSCPTOS(byte v) {
+        setByte(v, (short) 2);
+    }
+
+    @Override
+    public byte getDSCPTOSMask() {
+        return getByte((short) 3);
+    }
+
+    @Override
+    public void setDSCPTOSMask(byte v) {
+        setByte(v, (short) 3);
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java
new file mode 100644 (file)
index 0000000..26153a6
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IGateID;
+
+/**
+ *
+ */
+public class GateID extends PCMMBaseObject implements IGateID {
+
+    /**
+     *
+     */
+    public GateID() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public GateID(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public GateID(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IGateID#setGateID(int)
+     */
+    @Override
+    public void setGateID(int gateID) {
+        setInt(gateID, (short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IGateID#getGateID()
+     */
+    @Override
+    public int getGateID() {
+        return getInt((short) 0);
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java
new file mode 100644 (file)
index 0000000..dce286e
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IGateSpec;
+import org.pcmm.gates.ISessionClassID;
+
+/**
+ *
+ */
+public class GateSpec extends PCMMBaseObject implements IGateSpec {
+
+    public GateSpec() {
+        super(LENGTH, STYPE, SNUM);
+    }
+
+    public GateSpec(byte[] data) {
+        super(data);
+    }
+
+    @Override
+    public ISessionClassID getSessionClassID() {
+        return new SessionClassID(getByte((short) 3));
+    }
+
+    @Override
+    public void setSessionClassID(ISessionClassID id) {
+        setByte(id.toSingleByte(), (short) 3);
+    }
+
+    @Override
+    public Direction getDirection() {
+        return Direction.valueOf(getByte((short) 0));
+    }
+
+    @Override
+    public void setDirection(Direction direction) {
+        setByte(direction.getValue(), (short) 0);
+    }
+
+    @Override
+    public short getTimerT1() {
+        return getShort((short) 4);
+    }
+
+    @Override
+    public void setTimerT1(short authTimer) {
+        setShort(authTimer, (short) 4);
+    }
+
+    @Override
+    public short getTimerT2() {
+        return getShort((short) 6);
+    }
+
+    @Override
+    public void setTimerT2(short timer) {
+        setShort(timer, (short) 6);
+
+    }
+
+    @Override
+    public short getTimerT3() {
+        return getShort((short) 8);
+    }
+
+    @Override
+    public void setTimerT3(short t) {
+        setShort(t, (short) 8);
+
+    }
+
+    @Override
+    public short getTimerT4() {
+        return getShort((short) 10);
+    }
+
+    @Override
+    public void setTimerT4(short t) {
+        setShort(t, (short) 10);
+    }
+
+    @Override
+    public void setDSCP_TOSOverwrite(DSCPTOS dscpTos) {
+        setByte(dscpTos.getValue(), (short) 1);
+    }
+
+    @Override
+    public DSCPTOS getDSCP_TOSOverwrite() {
+        return DSCPTOS.valueOf(getByte((short) 1));
+    }
+
+    @Override
+    public byte getDSCP_TOSMask() {
+        return getByte((short) 2);
+    }
+
+    @Override
+    public void setDSCP_TOSMask(byte dscp_tos_mask) {
+        setByte(dscp_tos_mask, (short) 2);
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java
new file mode 100644 (file)
index 0000000..da686ef
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IPCMMError;
+
+/**
+ *
+ */
+public class PCMMError extends PCMMBaseObject implements IPCMMError {
+    /**
+     *
+     */
+    public PCMMError() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    public PCMMError(short errorCode, short subErrCode) {
+        this();
+        setErrorCode(errorCode);
+        setErrorSubcode(subErrCode);
+    }
+
+    /**
+     * @param data
+     */
+    public PCMMError(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public PCMMError(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCError#setErrorCode(int)
+     */
+    @Override
+    public void setErrorCode(short errorCode) {
+        setShort(errorCode, (short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCError#getErrorCode()
+     */
+    @Override
+    public short getErrorCode() {
+        return getShort((short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCError#setErrorSubcode(int)
+     */
+    @Override
+    public void setErrorSubcode(short errorSubcode) {
+        setShort(errorSubcode, (short) 2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCError#getErrorCode()
+     */
+    @Override
+    public short getErrorSubcode() {
+        return getShort((short) 2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCError#getDescription()
+     */
+    @Override
+    public String getDescription() {
+        String hex = Integer.toHexString(getErrorSubcode() & 0xFFFF);
+        return "Error Code: " + getErrorCode() + " Error Subcode : " + hex
+               + "  " + Description.valueOf(getErrorCode());
+    }
+
+    @Override
+    public String toString() {
+        return getDescription();
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java
new file mode 100644 (file)
index 0000000..0630a9f
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import java.util.Arrays;
+
+import org.pcmm.base.IPCMMBaseObject;
+import org.pcmm.gates.IAMID;
+import org.pcmm.gates.IClassifier;
+import org.pcmm.gates.IGateID;
+import org.pcmm.gates.IGateSpec;
+import org.pcmm.gates.IPCMMError;
+import org.pcmm.gates.IPCMMGate;
+import org.pcmm.gates.ISubscriberID;
+import org.pcmm.gates.ITrafficProfile;
+import org.pcmm.gates.ITransactionID;
+
+/**
+ * <p>
+ * <Gate-set>=<Decision Header><TransactionID><AMID> <SubscriberID> [<GateI>]
+ * <GateSpec> <Traffic Profile> <classifier>
+ * </p>
+ */
+public class PCMMGateReq implements IPCMMGate {
+
+    private boolean multicast;
+    private IGateID gateID;
+    private IAMID iamid;
+    private IPCMMError error;
+    private ISubscriberID subscriberID;
+    private ITransactionID transactionID;
+    private IGateSpec gateSpec;
+    private ITrafficProfile trafficProfile;
+    private IClassifier classifier;
+
+    public PCMMGateReq() {
+    }
+
+    public PCMMGateReq(byte[] data) {
+        short len, offset;
+        byte sNum, sType;
+        len = offset = 0;
+        sNum = sType = (byte) 0;
+        while (offset + 5 < data.length) {
+            len = 0;
+            len |= ((short) data[offset]) << 8;
+            len |= ((short) data[offset + 1]) & 0xFF;
+            sNum = data[offset + 2];
+            sType = data[offset + 3];
+            byte[] dataBuffer = Arrays.copyOfRange(data, offset, offset + len);
+            switch (sNum) {
+            case IGateID.SNUM:
+                setGateID(new GateID(dataBuffer));
+                break;
+            case IAMID.SNUM:
+                setAMID(new AMID(dataBuffer));
+                break;
+            case ISubscriberID.SNUM:
+                setSubscriberID(new SubscriberID(dataBuffer));
+                break;
+            case ITransactionID.SNUM:
+                setTransactionID(new TransactionID(dataBuffer));
+                break;
+            case IGateSpec.SNUM:
+                setGateSpec(new GateSpec(dataBuffer));
+                break;
+            case ITrafficProfile.SNUM:
+                setTrafficProfile(new BestEffortService(dataBuffer));
+                break;
+            case IClassifier.SNUM:
+                setClassifier(new Classifier(dataBuffer));
+                break;
+            case IPCMMError.SNUM:
+                error = new PCMMError(dataBuffer);
+                break;
+            default:
+                System.out.println("unhandled Object skept : S-NUM=" + sNum
+                                   + "  S-TYPE=" + sType + "  LEN=" + len);
+            }
+            offset += len;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#isMulticast()
+     */
+    @Override
+    public boolean isMulticast() {
+        // TODO Auto-generated method stub
+        return multicast;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#setGateID(short)
+     */
+    @Override
+    public void setGateID(IGateID gateid) {
+        this.gateID = gateid;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#setAMID(org.pcmm.gates.IAMID)
+     */
+    @Override
+    public void setAMID(IAMID iamid) {
+        this.iamid = iamid;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.IPCMMGate#getSubscriberID(org.pcmm.gates.ISubscriberID)
+     */
+    @Override
+    public void setSubscriberID(ISubscriberID subscriberID) {
+        this.subscriberID = subscriberID;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getGateSpec(org.pcmm.gates.IGateSpec)
+     */
+    @Override
+    public void setGateSpec(IGateSpec gateSpec) {
+        this.gateSpec = gateSpec;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getClassifier(org.pcmm.gates.IClassifier)
+     */
+    @Override
+    public void setClassifier(IClassifier classifier) {
+        this.classifier = classifier;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.IPCMMGate#getTrafficProfile(org.pcmm.gates.ITrafficProfile
+     * )
+     */
+    @Override
+    public void setTrafficProfile(ITrafficProfile profile) {
+        this.trafficProfile = profile;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getGateID()
+     */
+    @Override
+    public IGateID getGateID() {
+        return gateID;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getAMID()
+     */
+    @Override
+    public IAMID getAMID() {
+        return iamid;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getSubscriberID()
+     */
+    @Override
+    public ISubscriberID getSubscriberID() {
+        return subscriberID;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getGateSpec()
+     */
+    @Override
+    public IGateSpec getGateSpec() {
+        return gateSpec;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getClassifier()
+     */
+    @Override
+    public IClassifier getClassifier() {
+        return classifier;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.IPCMMGate#getTrafficProfile()
+     */
+    @Override
+    public ITrafficProfile getTrafficProfile() {
+        return trafficProfile;
+    }
+
+    @Override
+    public void setTransactionID(ITransactionID transactionID) {
+        this.transactionID = transactionID;
+    }
+
+    @Override
+    public ITransactionID getTransactionID() {
+        return transactionID;
+    }
+
+    public IPCMMError getError() {
+        return error;
+    }
+
+    public void setError(IPCMMError error) {
+        this.error = error;
+    }
+
+    @Override
+    public byte[] getData() {
+        byte[] array = new byte[0];
+        if (getTransactionID() != null) {
+            array = fill(array, getTransactionID());
+        }
+        if (getGateID() != null) {
+            array = fill(array, getGateID());
+        }
+        if (getAMID() != null) {
+            array = fill(array, getAMID());
+
+        }
+        if (getSubscriberID() != null) {
+            array = fill(array, getSubscriberID());
+        }
+        if (getGateSpec() != null) {
+            array = fill(array, getGateSpec());
+        }
+        if (getTrafficProfile() != null) {
+            array = fill(array, getTrafficProfile());
+        }
+        if (getClassifier() != null) {
+            array = fill(array, getClassifier());
+        }
+        return array;
+    }
+
+    private byte[] fill(byte[] array, IPCMMBaseObject obj) {
+        byte[] a = obj.getAsBinaryArray();
+        int offset = array.length;
+        array = Arrays.copyOf(array, offset + a.length);
+        System.arraycopy(a, 0, array, offset, a.length);
+        return array;
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java
new file mode 100644 (file)
index 0000000..7b3ff20
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.gates.ISessionClassID;
+
+/**
+ *
+ */
+public class SessionClassID implements ISessionClassID {
+
+    private byte priority;
+    private byte preemption;
+
+    // TODO check this;
+    private byte session;
+
+    public SessionClassID() {
+        this((byte) 0);
+    }
+
+    public SessionClassID(byte value) {
+        session = value;
+        priority = 0;
+        preemption = 0;
+        priority |= value >> 2;
+        preemption |= value >> 3;
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ISessionClassID#getPriority()
+     */
+    @Override
+    public byte getPriority() {
+        return priority;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ISessionClassID#setPriority(byte)
+     */
+    @Override
+    public void setPriority(byte value) {
+        this.priority = value;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ISessionClassID#getPreemption()
+     */
+    @Override
+    public byte getPreemption() {
+        return preemption;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ISessionClassID#setPreemption(byte)
+     */
+    @Override
+    public void setPreemption(byte value) {
+        this.preemption = value;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ISessionClassID#toSingleByte()
+     */
+    @Override
+    public byte toSingleByte() {
+        // byte ret = 0;
+        // ret |= (priority << 2);
+        // ret |= (preemption & 0xf);
+        // return ret;
+        return session;
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java
new file mode 100644 (file)
index 0000000..e933bb2
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.ISubscriberID;
+
+/**
+ *
+ */
+public class SubscriberID extends PCMMBaseObject implements ISubscriberID {
+
+    /**
+     *
+     */
+    public SubscriberID() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public SubscriberID(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public SubscriberID(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ISubscriberID#getSourceIPAddress()
+     */
+    @Override
+    public InetAddress getSourceIPAddress() {
+        try {
+            return Inet4Address.getByAddress(getBytes((short) 0, (short) 4));
+        } catch (UnknownHostException e) {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.pcmm.gates.ISubscriberID#setSourceIPAddress(java.net.InetAddress)
+     */
+    @Override
+    public void setSourceIPAddress(InetAddress address) {
+        setBytes(address.getAddress(), (short) 0);
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java
new file mode 100644 (file)
index 0000000..16ae63d
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ @header@
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.ITransactionID;
+
+/**
+ *
+ */
+public class TransactionID extends PCMMBaseObject implements ITransactionID {
+
+    /**
+     *
+     */
+    public TransactionID() {
+        this(LENGTH, STYPE, SNUM);
+    }
+
+    /**
+     * @param data
+     */
+    public TransactionID(byte[] data) {
+        super(data);
+    }
+
+    /**
+     * @param len
+     * @param sType
+     * @param sNum
+     */
+    public TransactionID(short len, byte sType, byte sNum) {
+        super(len, sType, sNum);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ITransactionID#setTransactionIdentifier(short)
+     */
+    @Override
+    public void setTransactionIdentifier(short id) {
+        setShort(id, (short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ITransactionID#getTransactionIdentifier()
+     */
+    @Override
+    public short getTransactionIdentifier() {
+        return getShort((short) 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ITransactionID#setGateCommandType(short)
+     */
+    @Override
+    public void setGateCommandType(short type) {
+        setShort(type, (short) 2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.pcmm.gates.ITransactionID#getGateCommandType()
+     */
+    @Override
+    public short getGateCommandType() {
+        return getShort((short) 2);
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/package-info.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/package-info.java
new file mode 100644 (file)
index 0000000..d845cbf
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ *
+ */
+/**
+ *
+ */
+package org.pcmm.gates.impl;
diff --git a/packetcable-driver/src/main/java/org/pcmm/messages/IMessage.java b/packetcable-driver/src/main/java/org/pcmm/messages/IMessage.java
new file mode 100644 (file)
index 0000000..e7e5407
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ @header@
+ */
+
+package org.pcmm.messages;
+
+/**
+ * This defines the messages exchanged between client and server.
+ * 
+ * 
+ * <pre>
+ * 1 = Request                 (REQ)
+ * 2 = Decision                (DEC)
+ * 3 = Report State            (RPT)
+ * 4 = Delete Request State    (DRQ)
+ * 5 = Synchronize State Req   (SSQ)
+ * 6 = Client-Open             (OPN)
+ * 7 = Client-Accept           (CAT)
+ * 8 = Client-Close            (CC)
+ * 9 = Keep-Alive              (KA)
+ * 10= Synchronize Complete    (SSC)
+ * </pre>
+ * 
+ */
+public interface IMessage {
+
+       public static enum MessageProperties {
+               CLIENT_TYPE("Client-Type"), PEP_ID("Pep-ID"), KA_TIMER("KA-Timer"), ACCEPT_TIMER(
+                               "Accept-Timer"), ERR_MESSAGE("Error-Message"), ERR_MESSAGE_SUB_CODE(
+                               "Error-Message-Code"), MM_MAJOR_VERSION_INFO(
+                               "MM-Major-Version-info"), MM_MINOR_VERSION_INFO(
+                               "MM-Minor-Version-info"), R_TYPE("R-Type"), M_TYPE("M-Type"), CLIENT_HANDLE(
+                               "Client-Handle"), GATE_CONTROL("Gate-Control"), DECISION_CMD_CODE(
+                               "Decision-Type"), DECISION_FLAG("Decision-Flag");
+
+               private MessageProperties(String valueString) {
+                       this.value = valueString;
+               }
+
+               private String value;
+
+               public String getValue() {
+                       return value;
+               }
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/messages/IMessageFactory.java b/packetcable-driver/src/main/java/org/pcmm/messages/IMessageFactory.java
new file mode 100644 (file)
index 0000000..3a77579
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ @header@
+ */
+package org.pcmm.messages;
+
+import java.util.Properties;
+
+import org.umu.cops.stack.COPSMsg;
+
+/**
+ * 
+ * Factory used to create {@code COPSMsg} based on message type input and a list
+ * of properties.
+ * 
+ */
+public interface IMessageFactory {
+
+    /**
+     * creates a new message with the specified message type.
+     *
+     * @param messageType
+     *            message type
+     * @return new message.
+     */
+    COPSMsg create(byte messageType);
+
+    /**
+     * creates a new message with the specified message type and content
+     *
+     * @param messageType
+     *            message type
+     * @param properties
+     *            message content.
+     * @return new message.
+     */
+    COPSMsg create(byte messageType, Properties properties);
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/messages/impl/COPSDecisionMsgEX.java b/packetcable-driver/src/main/java/org/pcmm/messages/impl/COPSDecisionMsgEX.java
new file mode 100644 (file)
index 0000000..7b22b9c
--- /dev/null
@@ -0,0 +1,476 @@
+/**
+ @header@
+ */
+package org.pcmm.messages.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.umu.cops.stack.COPSClientSI;
+import org.umu.cops.stack.COPSContext;
+import org.umu.cops.stack.COPSDecision;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSIntegrity;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSObjHeader;
+
+/**
+ * COPS Decision Message
+ *
+ *
+ */
+
+public class COPSDecisionMsgEX extends COPSMsg {
+
+    /* COPSHeader coming from base class */
+    private COPSHandle _clientHandle;
+    private COPSError _error;
+    private Hashtable _decisions;
+    private COPSIntegrity _integrity;
+    private COPSContext _decContext;
+    private COPSClientSI clientSI;
+
+    // /
+    public COPSDecisionMsgEX() {
+        _clientHandle = null;
+        _error = null;
+        _decisions = new Hashtable(20);
+        _integrity = null;
+        _decContext = null;
+        clientSI = null;
+    }
+
+    /**
+     * Checks the sanity of COPS message and throw an COPSBadDataException when
+     * data is bad.
+     */
+    public void checkSanity() throws COPSException {
+        if ((_hdr == null) || (_clientHandle == null)
+                || ((_error == null) && (_decisions.size() == 0))) {
+            throw new COPSException("Bad message format");
+        }
+    }
+
+    // /
+    protected COPSDecisionMsgEX(byte[] data) throws COPSException {
+        _decisions = new Hashtable(20);
+        _clientHandle = null;
+        _error = null;
+        _integrity = null;
+        _decContext = null;
+        clientSI = null;
+        parse(data);
+    }
+
+    /**
+     * Parses the data and fills COPSDecisionMsg with its constituents
+     *
+     * @param data
+     *            a byte[]
+     *
+     * @throws COPSException
+     *
+     */
+    protected void parse(byte[] data) throws COPSException {
+        super.parseHeader(data);
+
+        while (_dataStart < _dataLength) {
+            byte[] buf = new byte[data.length - _dataStart];
+            System.arraycopy(data, _dataStart, buf, 0, data.length - _dataStart);
+
+            COPSObjHeader objHdr = new COPSObjHeader(buf) {
+            };
+            switch (objHdr.getCNum()) {
+            case COPSObjHeader.COPS_HANDLE: {
+                _clientHandle = new COPSHandle(buf) {
+                };
+                _dataStart += _clientHandle.getDataLength();
+            }
+            break;
+            case COPSObjHeader.COPS_CONTEXT: {
+                // dec context
+                _decContext = new COPSContext(buf) {
+                };
+                _dataStart += _decContext.getDataLength();
+            }
+            break;
+            case COPSObjHeader.COPS_ERROR: {
+                _error = new COPSError(buf) {
+                };
+                _dataStart += _error.getDataLength();
+            }
+            break;
+            case COPSObjHeader.COPS_DEC: {
+                COPSDecision decs = new COPSDecision(buf) {
+                };
+                _dataStart += decs.getDataLength();
+                addDecision(decs, _decContext);
+            }
+            break;
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {
+                _integrity = new COPSIntegrity(buf);
+                _dataStart += _integrity.getDataLength();
+            }
+            break;
+            case COPSObjHeader.COPS_CSI: {
+                clientSI = new COPSClientSI(buf) {
+                };
+                _dataStart += clientSI.getDataLength();
+            }
+            break;
+            default: {
+                throw new COPSException(
+                    "Bad Message format, unknown object type");
+            }
+            }
+        }
+        checkSanity();
+    }
+
+    /**
+     * Parses the data and fills that follows the header hdr and fills
+     * COPSDecisionMsg
+     *
+     * @param hdr
+     *            a COPSHeader
+     * @param data
+     *            a byte[]
+     *
+     * @throws COPSException
+     *
+     */
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {
+        _hdr = hdr;
+        parse(data);
+        setMsgLength();
+    }
+
+    /**
+     * Add message header
+     *
+     * @param hdr
+     *            a COPSHeader
+     *
+     * @throws COPSException
+     *
+     */
+    public void add(COPSHeader hdr) throws COPSException {
+        if (hdr == null)
+            throw new COPSException("Null Header");
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC)
+            throw new COPSException("Error Header (no COPS_OP_DEC)");
+        _hdr = hdr;
+        setMsgLength();
+    }
+
+    /**
+     * Add client handle to the message
+     *
+     * @param handle
+     *            a COPSHandle
+     *
+     * @throws COPSException
+     *
+     */
+    public void add(COPSHandle handle) throws COPSException {
+        if (handle == null)
+            throw new COPSException("Null Handle");
+        _clientHandle = handle;
+        setMsgLength();
+    }
+
+    /**
+     * Add an Error object
+     *
+     * @param error
+     *            a COPSError
+     *
+     * @throws COPSException
+     *
+     */
+    public void add(COPSError error) throws COPSException {
+        if (_decisions.size() != 0)
+            throw new COPSException("No null decisions");
+        if (_error != null)
+            throw new COPSException("No null error");
+        // Message integrity object should be the very last one
+        // If it is already added
+        if (_integrity != null)
+            throw new COPSException("No null integrity");
+        _error = error;
+        setMsgLength();
+    }
+
+    /**
+     * Add one or more local decision object for a given decision context the
+     * context is optional, if null all decision object are tided to message
+     * context
+     *
+     * @param decision
+     *            a COPSDecision
+     * @param context
+     *            a COPSContext
+     *
+     * @throws COPSException
+     *
+     */
+    public void addDecision(COPSDecision decision, COPSContext context)
+    throws COPSException {
+        // Either error or decision can be added
+        // If error is aleady there assert
+        if (_error != null)
+            throw new COPSException("No null error");
+
+        if (decision.isLocalDecision())
+            throw new COPSException("Is local decision");
+
+        Vector v = (Vector) _decisions.get(context);
+        if (v == null)
+            v = new Vector();
+
+        if (decision.isFlagSet()) {// Commented out as advised by Felix
+            // if (v.size() != 0)
+            // {
+            // Only one set of decision flags is allowed
+            // for each context
+            // throw new COPSException
+            // ("Bad Message format, only one set of decision flags is allowed.");
+            // }
+        } else {
+            if (v.size() == 0) {
+                // The flags decision must precede any other
+                // decision message, since the decision is not
+                // flags throw exception
+                throw new COPSException(
+                    "Bad Message format, flags decision must precede any other decision object.");
+            }
+        }
+        v.add(decision);
+        _decisions.put(context, v);
+
+        setMsgLength();
+    }
+
+    /**
+     * Add integrity object
+     *
+     * @param integrity
+     *            a COPSIntegrity
+     *
+     * @throws COPSException
+     *
+     */
+    public void add(COPSIntegrity integrity) throws COPSException {
+        if (integrity == null)
+            throw new COPSException("Null Integrity");
+        if (!integrity.isMessageIntegrity())
+            throw new COPSException("Error Integrity");
+        _integrity = integrity;
+        setMsgLength();
+    }
+
+    /**
+     * Add a client specific informations
+     *
+     * @param clientSI
+     *            a COPSClientSI
+     *
+     * @throws COPSException
+     *
+     */
+    public void add(COPSClientSI clientSI) throws COPSException {
+        if (clientSI == null)
+            throw new COPSException("Null ClientSI");
+        this.clientSI = clientSI;
+        setMsgLength();
+    }
+
+    /**
+     * Writes data to given socket
+     *
+     * @param id
+     *            a Socket
+     *
+     * @throws IOException
+     *
+     */
+    public void writeData(Socket id) throws IOException {
+        // checkSanity();
+        if (_hdr != null)
+            _hdr.writeData(id);
+        if (_clientHandle != null)
+            _clientHandle.writeData(id);
+        if (_error != null)
+            _error.writeData(id);
+
+        // Display decisions
+        // Display any local decisions
+        for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
+
+            COPSContext context = (COPSContext) e.nextElement();
+            Vector v = (Vector) _decisions.get(context);
+            context.writeData(id);
+
+            for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
+                COPSDecision decision = (COPSDecision) ee.nextElement();
+                decision.writeData(id);
+            }
+        }
+        if (clientSI != null)
+            clientSI.writeData(id);
+        if (_integrity != null)
+            _integrity.writeData(id);
+    }
+
+    /**
+     * Method getHeader
+     *
+     * @return a COPSHeader
+     *
+     */
+    public COPSHeader getHeader() {
+        return _hdr;
+    }
+
+    /**
+     * Method getClientHandle
+     *
+     * @return a COPSHandle
+     *
+     */
+    public COPSHandle getClientHandle() {
+        return _clientHandle;
+    }
+
+    public COPSClientSI getClientSI() {
+        return clientSI;
+    }
+
+    /**
+     * Returns true if it has error object
+     *
+     * @return a boolean
+     *
+     */
+    public boolean hasError() {
+        return (_error != null);
+    };
+
+    /**
+     * Should check hasError() before calling
+     *
+     * @return a COPSError
+     *
+     */
+    public COPSError getError() {
+        return _error;
+    };
+
+    /**
+     * Returns a map of decision for which is an arry of context and vector of
+     * associated decision object.
+     *
+     * @return a Hashtable
+     *
+     */
+    public Hashtable getDecisions() {
+        return _decisions;
+    };
+
+    /**
+     * Returns true if it has integrity object
+     *
+     * @return a boolean
+     *
+     */
+    public boolean hasIntegrity() {
+        return (_integrity != null);
+    };
+
+    /**
+     * Should check hasIntegrity() before calling
+     *
+     * @return a COPSIntegrity
+     *
+     */
+    public COPSIntegrity getIntegrity() {
+        return _integrity;
+    };
+
+    /**
+     * Method setMsgLength
+     *
+     * @throws COPSException
+     *
+     */
+    protected void setMsgLength() throws COPSException {
+        short len = 0;
+        if (_clientHandle != null)
+            len += _clientHandle.getDataLength();
+        if (_error != null)
+            len += _error.getDataLength();
+
+        // Display any local decisions
+        for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
+
+            COPSContext context = (COPSContext) e.nextElement();
+            Vector v = (Vector) _decisions.get(context);
+            len += context.getDataLength();
+
+            for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
+                COPSDecision decision = (COPSDecision) ee.nextElement();
+                len += decision.getDataLength();
+            }
+        }
+        if (clientSI != null)
+            len += clientSI.getDataLength();
+        if (_integrity != null) {
+            len += _integrity.getDataLength();
+        }
+
+        _hdr.setMsgLength((int) len);
+    }
+
+    /**
+     * Write an object textual description in the output stream
+     *
+     * @param os
+     *            an OutputStream
+     *
+     * @throws IOException
+     *
+     */
+    public void dump(OutputStream os) throws IOException {
+        _hdr.dump(os);
+
+        if (_clientHandle != null)
+            _clientHandle.dump(os);
+        if (_error != null)
+            _error.dump(os);
+
+        // Display any local decisions
+        for (Enumeration e = _decisions.keys(); e.hasMoreElements();) {
+
+            COPSContext context = (COPSContext) e.nextElement();
+            Vector v = (Vector) _decisions.get(context);
+            context.dump(os);
+
+            for (Enumeration ee = v.elements(); ee.hasMoreElements();) {
+                COPSDecision decision = (COPSDecision) ee.nextElement();
+                decision.dump(os);
+            }
+        }
+        if (clientSI != null)
+            clientSI.dump(os);
+        if (_integrity != null) {
+            _integrity.dump(os);
+        }
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/messages/impl/MessageFactory.java b/packetcable-driver/src/main/java/org/pcmm/messages/impl/MessageFactory.java
new file mode 100644 (file)
index 0000000..25d26f9
--- /dev/null
@@ -0,0 +1,299 @@
+/**
+ * @header@
+ */
+package org.pcmm.messages.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Properties;
+
+import org.pcmm.messages.IMessage.MessageProperties;
+import org.pcmm.messages.IMessageFactory;
+import org.pcmm.objects.MMVersionInfo;
+import org.pcmm.rcd.ICMTS;
+import org.pcmm.rcd.IPCMMClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.COPSAcctTimer;
+import org.umu.cops.stack.COPSClientAcceptMsg;
+import org.umu.cops.stack.COPSClientCloseMsg;
+import org.umu.cops.stack.COPSClientOpenMsg;
+import org.umu.cops.stack.COPSClientSI;
+import org.umu.cops.stack.COPSContext;
+import org.umu.cops.stack.COPSData;
+import org.umu.cops.stack.COPSDecision;
+import org.umu.cops.stack.COPSDecisionMsg;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSKAMsg;
+import org.umu.cops.stack.COPSKATimer;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSObjHeader;
+import org.umu.cops.stack.COPSPepId;
+import org.umu.cops.stack.COPSReqMsg;
+
+/**
+ * 
+ * 
+ */
+public class MessageFactory implements IMessageFactory {
+
+       /** 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;
+
+       private Logger logger = LoggerFactory.getLogger(getClass().getName());
+
+       private static MessageFactory instance;
+
+       private MessageFactory() {
+       }
+
+       public static MessageFactory getInstance() {
+               if (instance == null)
+                       instance = new MessageFactory();
+               return instance;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.messages.IMessageFactory#create(pcmm.messages.MessageType)
+        */
+       public COPSMsg create(byte messageType) {
+               return create(messageType, new Properties());
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.messages.IMessageFactory#create(org.pcmm.messages.IMessage.
+        * MessageType, java.util.Properties)
+        */
+       public COPSMsg create(byte messageType, Properties properties) {
+               // return new PCMMMessage(messageType, content);
+               switch (messageType) {
+               case COPSHeader.COPS_OP_OPN:
+                       return createOPNMessage(properties);
+               case COPSHeader.COPS_OP_REQ:
+                       return createREQMessage(properties);
+               case COPSHeader.COPS_OP_CAT:
+                       return createCATMessage(properties);
+               case COPSHeader.COPS_OP_CC:
+                       return createCCMessage(properties);
+               case COPSHeader.COPS_OP_DEC:
+                       return createDECMessage(properties);
+               case COPSHeader.COPS_OP_DRQ:
+               break;
+               case COPSHeader.COPS_OP_KA:
+                       return createKAMessage(properties);
+               case COPSHeader.COPS_OP_RPT:
+               break;
+               case COPSHeader.COPS_OP_SSC:
+               break;
+               case COPSHeader.COPS_OP_SSQ:
+               break;
+               }
+               return null;
+       }
+
+       /**
+        * 
+        * @param prop
+        * @return
+        */
+       protected COPSMsg createDECMessage(Properties prop) {
+               COPSDecisionMsg msg = new COPSDecisionMsg();
+               // ===common part between all gate control messages
+               COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DEC, IPCMMClient.CLIENT_TYPE);
+               // handle
+               COPSHandle handle = new COPSHandle();
+               // context
+               COPSContext context = new COPSContext(COPSContext.CONFIG, (short) 0);
+               // decision
+               COPSDecision decision = new COPSDecision();
+               if (prop.get(MessageProperties.DECISION_CMD_CODE) != null)
+                       decision.setCmdCode((byte) prop.get(MessageProperties.DECISION_CMD_CODE));
+               if (prop.get(MessageProperties.DECISION_FLAG) != null)
+                       decision.setFlags((short) prop.get(MessageProperties.DECISION_FLAG));
+               COPSClientSI si = new COPSClientSI(COPSObjHeader.COPS_DEC, (byte) 4);
+               if (prop.get(MessageProperties.GATE_CONTROL) != null)
+                       si.setData((COPSData) prop.get(MessageProperties.GATE_CONTROL));
+               try {
+                       msg.add(hdr);
+                       if (prop.get(MessageProperties.CLIENT_HANDLE) != null)
+                               handle.setId(new COPSData((String) prop.get(MessageProperties.CLIENT_HANDLE)));
+                       msg.add(handle);
+                       msg.addDecision(decision, context);
+                       msg.add(si);
+                       // try {
+                       // msg.dump(System.out);
+                       // } catch (IOException unae) {
+                       // }
+
+               } catch (COPSException e) {
+                       logger.error(e.getMessage());
+               }
+
+               return msg;
+       }
+
+       /**
+        * creates a Client-Open message.
+        * 
+        * @param prop
+        *            properties
+        * @return COPS message
+        */
+       protected COPSMsg createOPNMessage(Properties prop) {
+               COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, IPCMMClient.CLIENT_TYPE);
+               COPSPepId pepId = new COPSPepId();
+               // version infor object
+               short majorVersion = MMVersionInfo.DEFAULT_MAJOR_VERSION_INFO;
+               short minorVersion = MMVersionInfo.DEFAULT_MINOR_VERSION_INFO;
+               if (prop.get(MessageProperties.MM_MAJOR_VERSION_INFO) != null)
+                       majorVersion = (Short) prop.get(MessageProperties.MM_MAJOR_VERSION_INFO);
+               if (prop.get(MessageProperties.MM_MINOR_VERSION_INFO) != null)
+                       minorVersion = (Short) prop.get(MessageProperties.MM_MINOR_VERSION_INFO);
+               // Mandatory MM version.
+               COPSClientSI clientSI = new COPSClientSI((byte) 1);
+               byte[] versionInfo = new MMVersionInfo(majorVersion, minorVersion).getAsBinaryArray();
+               clientSI.setData(new COPSData(versionInfo, 0, versionInfo.length));
+               COPSClientOpenMsg msg = new COPSClientOpenMsg();
+               try {
+                       COPSData d = null;
+                       if (prop.get(MessageProperties.PEP_ID) != null)
+                               d = new COPSData((String) prop.get(MessageProperties.PEP_ID));
+                       else
+                               d = new COPSData(InetAddress.getLocalHost().getHostName());
+                       pepId.setData(d);
+                       msg.add(hdr);
+                       msg.add(pepId);
+                       msg.add(clientSI);
+               } catch (COPSException e) {
+                       logger.error(e.getMessage());
+               } catch (UnknownHostException e) {
+                       logger.error(e.getMessage());
+               }
+               return msg;
+       }
+
+       /**
+        * creates a Client-Accept message.
+        * 
+        * @param prop
+        *            properties
+        * @return COPS message
+        */
+       protected COPSMsg createCATMessage(Properties prop) {
+               COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_CAT, IPCMMClient.CLIENT_TYPE);
+               COPSKATimer katimer = null;
+               COPSAcctTimer acctTimer = null;
+               if (prop.get(MessageProperties.KA_TIMER) != null)
+                       katimer = new COPSKATimer((short) prop.get(MessageProperties.KA_TIMER));
+               else
+                       katimer = new COPSKATimer((short) KA_TIMER_VALUE);
+               if (prop.get(MessageProperties.ACCEPT_TIMER) != null)
+                       acctTimer = new COPSAcctTimer((short) prop.get(MessageProperties.ACCEPT_TIMER));
+               else
+                       acctTimer = new COPSAcctTimer(ACCT_TIMER_VALUE);
+               COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();
+               try {
+                       acceptMsg.add(hdr);
+                       acceptMsg.add(katimer);
+                       if (acctTimer.getTimerVal() != 0)
+                               acceptMsg.add(acctTimer);
+               } catch (COPSException e) {
+                       logger.error(e.getMessage());
+               }
+               return acceptMsg;
+       }
+
+       /**
+        * creates a Client-Close message.
+        * 
+        * @param prop
+        *            properties
+        * @return COPS message
+        */
+       protected COPSMsg createCCMessage(Properties prop) {
+               COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, IPCMMClient.CLIENT_TYPE);
+               COPSError err = null;
+               if (prop.get(MessageProperties.ERR_MESSAGE) != null) {
+                       short code = (short) 0;
+                       short error = (short) prop.get(MessageProperties.ERR_MESSAGE);
+                       if (prop.get(MessageProperties.ERR_MESSAGE_SUB_CODE) != null)
+                               code = (short) prop.get(MessageProperties.ERR_MESSAGE_SUB_CODE);
+                       err = new COPSError(error, code);
+               } else
+                       err = new COPSError(COPSError.COPS_ERR_UNKNOWN, (short) 0);
+               COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
+               try {
+                       closeMsg.add(cHdr);
+                       closeMsg.add(err);
+               } catch (COPSException e) {
+                       logger.error(e.getMessage());
+               }
+               return closeMsg;
+       }
+
+       /**
+        * creates a Request message
+        * 
+        * @param prop
+        *            properties
+        * @return Request message
+        */
+       protected COPSMsg createREQMessage(Properties prop) {
+               COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_REQ, IPCMMClient.CLIENT_TYPE);
+               COPSReqMsg req = new COPSReqMsg();
+               short rType = ICMTS.DEFAULT_R_TYPE;
+               short mType = ICMTS.DEFAULT_M_TYPE;
+               if (prop.get(MessageProperties.R_TYPE) != null)
+                       rType = (Short) prop.get(MessageProperties.R_TYPE);
+               if (prop.get(MessageProperties.M_TYPE) != null)
+                       mType = (Short) prop.get(MessageProperties.M_TYPE);
+               COPSContext copsContext = new COPSContext(rType, mType);
+               COPSHandle copsHandle = new COPSHandle();
+               if (prop.get(MessageProperties.CLIENT_HANDLE) != null)
+                       copsHandle.setId(new COPSData((String) prop.get(MessageProperties.CLIENT_HANDLE)));
+               else
+                       // just a random handle
+                       copsHandle.setId(new COPSData("" + Math.random() * 82730));
+               try {
+                       req.add(cHdr);
+                       req.add(copsContext);
+                       req.add(copsHandle);
+               } catch (COPSException e) {
+                       logger.error(e.getMessage());
+               }
+               return req;
+       }
+
+       /**
+        * creates a Keep-Alive message.
+        * 
+        * @param prop
+        *            properties
+        * @return COPS message
+        */
+       protected COPSMsg createKAMessage(Properties prop) {
+               COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_KA, (short) 0);
+               COPSKAMsg kaMsg = new COPSKAMsg();
+               COPSKATimer timer = null;
+               if (prop.get(MessageProperties.KA_TIMER) != null)
+                       timer = new COPSKATimer((Short) prop.get(MessageProperties.KA_TIMER));
+               else
+                       timer = new COPSKATimer();
+               try {
+                       kaMsg.add(cHdr);
+               } catch (COPSException e) {
+                       logger.error(e.getMessage());
+               }
+               return kaMsg;
+       }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/messages/package-info.java b/packetcable-driver/src/main/java/org/pcmm/messages/package-info.java
new file mode 100644 (file)
index 0000000..66ddf11
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * Package defining the messages exchanged between PCMM client and server.
+ */
+/**
+ *
+ */
+package org.pcmm.messages;
diff --git a/packetcable-driver/src/main/java/org/pcmm/nio/PCMMChannel.java b/packetcable-driver/src/main/java/org/pcmm/nio/PCMMChannel.java
new file mode 100644 (file)
index 0000000..f87677a
--- /dev/null
@@ -0,0 +1,172 @@
+/**
+ * 
+ */
+package org.pcmm.nio;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.util.Date;
+
+import org.pcmm.PCMMProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSMsgParser;
+
+/**
+ * this class provides a set of utilities to efficiently read/write data from a
+ * stream, it could parameterized with a reading timeout or -1 for blocking
+ * until get a message
+ * 
+ */
+public class PCMMChannel {
+
+       private Logger logger = LoggerFactory.getLogger(getClass().getName());
+       private ByteBuffer dataBuffer;
+       private Socket socket;
+       private int timeout;
+       public static final int DEFAULT_BYTE_BUFFER_SIZE = 2048;
+       public static final int DEFAULT_READ_TIMEOUT = -1;
+
+       public PCMMChannel(Socket socket) {
+               this(socket, PCMMProperties.get(PCMMProperties.DEFAULT_TIEMOUT,
+                               Integer.class, DEFAULT_READ_TIMEOUT));
+       }
+
+       public PCMMChannel(Socket socket, int timeout) {
+               this.socket = socket;
+               dataBuffer = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);
+               logger.info("Allocated byte buffer with size = "
+                               + DEFAULT_BYTE_BUFFER_SIZE);
+               this.timeout = timeout;
+               logger.info("Set read/write timeout to : " + timeout);
+
+       }
+
+       public int readData(byte[] dataRead, int nchar) throws IOException {
+               InputStream input;
+               input = getSocket().getInputStream();
+               int nread = 0;
+               int startTime = (int) (new Date().getTime());
+               do {
+                       if (timeout == -1 || input.available() != 0) {
+                               nread += input.read(dataRead, nread, nchar - nread);
+                               startTime = (int) (new Date().getTime());
+                       } else {
+                               int nowTime = (int) (new Date().getTime());
+                               if ((nowTime - startTime) > timeout)
+                                       break;
+                       }
+               } while (nread != nchar);
+               return nread;
+       }
+
+       /**
+        * Method sendMsg
+        * 
+        * @param msg
+        *            a COPSMsg
+        * 
+        * @throws IOException
+        * @throws COPSException
+        * 
+        */
+       public void sendMsg(COPSMsg msg) throws IOException, COPSException {
+               logger.debug("sendMsg({})==>{}", getSocket(), msg);
+               msg.checkSanity();
+               msg.writeData(getSocket());
+       }
+
+       /**
+        * Method receiveMessage
+        * 
+        * @return a COPSMsg
+        * 
+        * @throws IOException
+        * @throws COPSException
+        * 
+        */
+       public COPSMsg receiveMessage() throws IOException, COPSException {
+               int nread = 0;
+               byte[] hBuf = new byte[8];
+
+               logger.debug("receiveMessage({})", getSocket());
+
+               nread = readData(hBuf, 8);
+
+               if (nread == 0) {
+                       throw new COPSException("Error reading connection");
+               }
+
+               if (nread != 8) {
+                       throw new COPSException("Bad COPS message");
+               }
+
+               COPSHeader hdr = new COPSHeader(hBuf);
+               int dataLen = hdr.getMsgLength() - hdr.getHdrLength();
+               logger.debug("COPS Msg length :[" + dataLen + "]\n");
+               byte[] buf = new byte[dataLen + 1];
+               nread = 0;
+
+               nread = readData(buf, dataLen);
+               buf[dataLen] = (byte) '\0';
+               logger.debug("Data read length:[" + nread + "]\n");
+
+               if (nread != dataLen) {
+                       throw new COPSException("Bad COPS message");
+               }
+               COPSMsgParser prser = new COPSMsgParser();
+               COPSMsg msg = prser.parse(hdr, buf);
+               return msg;
+       }
+
+       /**
+        * @return the dataBuffer
+        */
+       public ByteBuffer getDataBuffer() {
+               return dataBuffer;
+       }
+
+       /**
+        * @param dataBuffer
+        *            the dataBuffer to set
+        */
+       public void setDataBuffer(ByteBuffer dataBuffer) {
+               this.dataBuffer = dataBuffer;
+       }
+
+       /**
+        * @return the socket
+        */
+       public Socket getSocket() {
+               return socket;
+       }
+
+       /**
+        * @param socket
+        *            the socket to set
+        */
+       public void setSocket(Socket socket) {
+               this.socket = socket;
+       }
+
+       /**
+        * @return the timeout
+        */
+       public int getTimeout() {
+               return timeout;
+       }
+
+       /**
+        * @param timeout
+        *            the timeout to set
+        */
+       public void setTimeout(int timeout) {
+               this.timeout = timeout;
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java b/packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java
new file mode 100644 (file)
index 0000000..4fa90a5
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ @header@
+ */
+package org.pcmm.objects;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+
+/**
+ *
+ * PCMM MM version info Object
+ *
+ */
+public class MMVersionInfo extends PCMMBaseObject {
+
+    private short majorVersionNB;
+    private short minorVersionNB;
+    public static final short DEFAULT_MAJOR_VERSION_INFO = (short) 5;
+    public static final short DEFAULT_MINOR_VERSION_INFO = (short) 0;
+
+    public MMVersionInfo() {
+        this(DEFAULT_MAJOR_VERSION_INFO, DEFAULT_MINOR_VERSION_INFO);
+    }
+
+    public MMVersionInfo(short majorVersionNB, short minorVersionNB) {
+        super((short) 8, (byte) 1, (byte) 16);
+        setShort(this.majorVersionNB = majorVersionNB, (short) 0);
+        setShort(this.minorVersionNB = minorVersionNB, (short) 2);
+    }
+
+    /**
+     * Parse data and create COPSHandle object
+     */
+    public MMVersionInfo(byte[] dataPtr) {
+        super(dataPtr);
+        majorVersionNB = getShort((short) 0);
+        minorVersionNB = getShort((short) 2);
+    }
+
+    /**
+     * @return the majorVersionNB
+     */
+    public short getMajorVersionNB() {
+        return majorVersionNB;
+    }
+
+    /**
+     * @param majorVersionNB
+     *            the majorVersionNB to set
+     */
+    public void setMajorVersionNB(short majorVersionNB) {
+        this.majorVersionNB = majorVersionNB;
+    }
+
+    /**
+     * @return the minorVersionNB
+     */
+    public short getMinorVersionNB() {
+        return minorVersionNB;
+    }
+
+    /**
+     * @param minorVersionNB
+     *            the minorVersionNB to set
+     */
+    public void setMinorVersionNB(short minorVersionNB) {
+        this.minorVersionNB = minorVersionNB;
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/PCMMIDHolder.java b/packetcable-driver/src/main/java/org/pcmm/objects/PCMMIDHolder.java
new file mode 100644 (file)
index 0000000..ce35dee
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ @header@
+ */
+package org.pcmm.objects;
+
+/**
+ * this class holds and maps flow ID to PCMM gate ID and Transaction ID
+ *
+ */
+public class PCMMIDHolder extends PCMMResource {
+
+    /**
+     * flow id.
+     */
+    private int flowID;
+    /**
+     * gate id.
+     */
+    private int gateID;
+    /**
+     * transaction id.
+     */
+    private short transactionID;
+
+    public PCMMIDHolder(int flowID, int gateID, short transactionID) {
+        this.flowID = flowID;
+        this.gateID = gateID;
+        this.transactionID = transactionID;
+
+    }
+
+    public PCMMIDHolder() {
+
+    }
+
+    public int getFlowID() {
+        return flowID;
+    }
+
+    public void setFlowID(int flowID) {
+        this.flowID = flowID;
+    }
+
+    public int getGateID() {
+        return gateID;
+    }
+
+    public void setGateID(int gateID) {
+        this.gateID = gateID;
+    }
+
+    public short getTransactionID() {
+        return transactionID;
+    }
+
+    public void setTransactionID(short transactionID) {
+        this.transactionID = transactionID;
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/PCMMResource.java b/packetcable-driver/src/main/java/org/pcmm/objects/PCMMResource.java
new file mode 100644 (file)
index 0000000..5fc7966
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ @header@
+ */
+package org.pcmm.objects;
+
+/**
+ *
+ * This class is a holder for PCMM objects. This class is intended to be
+ * sub-classed
+ *
+ */
+public class PCMMResource {
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/PCMMResourceSet.java b/packetcable-driver/src/main/java/org/pcmm/objects/PCMMResourceSet.java
new file mode 100644 (file)
index 0000000..a401fe8
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ @header@
+ */
+package org.pcmm.objects;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This stores and handles the PCMM resources.
+ *
+ */
+public class PCMMResourceSet {
+
+    private Map<Object, PCMMResourcesMapper<?, ?>> mapper;
+
+    private static PCMMResourceSet instance;
+
+    private PCMMResourceSet() {
+        mapper = new HashMap<Object, PCMMResourcesMapper<?, ?>>();
+    }
+
+    public static PCMMResourceSet getInstance() {
+        if (instance == null)
+            instance = new PCMMResourceSet();
+        return instance;
+    }
+
+    /**
+     * adds a new mapping
+     *
+     * @param key
+     *            to be used for identifying mapped structure
+     * @return resource mapper
+     */
+    @SuppressWarnings("unchecked")
+    public <M, T extends PCMMResource> PCMMResourcesMapper<M, T> getMappedResources(
+        Object key) {
+        return (PCMMResourcesMapper<M, T>) mapper.get(key);
+    }
+
+    public <M, T extends PCMMResource> void mapResources(Object key,
+            PCMMResourcesMapper<M, T> resources) {
+        mapper.put(key, resources);
+    }
+
+    public void removeMapping(Object key) {
+        mapper.remove(key);
+    }
+
+    public void removeAllMappings() {
+        mapper.clear();
+    }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/PCMMResourcesMapper.java b/packetcable-driver/src/main/java/org/pcmm/objects/PCMMResourcesMapper.java
new file mode 100644 (file)
index 0000000..69468fd
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ @header@
+ */
+package org.pcmm.objects;
+
+/**
+ *
+ * Resources mapper used to associate a key to a set of values
+ */
+public class PCMMResourcesMapper<M, T extends PCMMResource> {
+
+    private M key;
+
+    private T value;
+
+    public PCMMResourcesMapper() {
+    }
+
+    public PCMMResourcesMapper(M key, T value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public M getKey() {
+        return key;
+    }
+
+    public void setKey(M key) {
+        this.key = key;
+    }
+
+    public T getValue() {
+        return value;
+    }
+
+    public void setValue(T value) {
+        this.value = value;
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java b/packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java
new file mode 100644 (file)
index 0000000..409862b
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ @header@
+ */
+package org.pcmm.objects;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+
+/**
+ * 
+ * PCMM SyncOptions object
+ * 
+ */
+public class SyncOptions extends PCMMBaseObject {
+
+       private byte synchType;
+
+       private byte reportType;
+
+       public static final byte STANDARD_REPORT_DATA = (byte) 0;
+       public static final byte COMPLETE_GATE_DATA = (byte) 1;
+       public static final byte FULL_SYNCHRONIZATION = (byte) 0;
+       public static final byte INCREMENTAL_SYNCHRONIZATION = (byte) 1;
+
+       public SyncOptions() {
+               this(STANDARD_REPORT_DATA, FULL_SYNCHRONIZATION);
+       }
+
+       public SyncOptions(byte reportType, byte synchType) {
+               super((short) 8, (byte) 1, (byte) 18);
+               setByte(this.reportType = reportType, (short) 4);
+               setByte(this.synchType = synchType, (short) 6);
+       }
+
+       /**
+        * Parse data and create COPSHandle object
+        */
+       public SyncOptions(byte[] dataPtr) {
+               super(dataPtr);
+               reportType = getByte((short) 4);
+               synchType = getByte((short) 6);
+       }
+
+       /**
+        * @return the synchType
+        */
+       public byte getSynchType() {
+               return synchType;
+       }
+
+       /**
+        * @param synchType
+        *            the synchType to set
+        */
+       public void setSynchType(byte synchType) {
+               this.synchType = synchType;
+       }
+
+       /**
+        * @return the reportType
+        */
+       public byte getReportType() {
+               return reportType;
+       }
+
+       /**
+        * @param reportType
+        *            the reportType to set
+        */
+       public void setReportType(byte reportType) {
+               this.reportType = reportType;
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/ICMTS.java b/packetcable-driver/src/main/java/org/pcmm/rcd/ICMTS.java
new file mode 100644 (file)
index 0000000..580ea2c
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ @header@
+ */
+
+package org.pcmm.rcd;
+
+/**
+ * <p>
+ * In describing the role of the CMTS network element, it is important to
+ * consider the relation among DOCSIS, PacketCable 1.x and PacketCable
+ * Multimedia functionality. While each of these suites of specifications
+ * addresses a specific set of functional requirements, each has also been
+ * defined in such a way that corresponding implementations may be constructed
+ * in a modular manner; either PacketCable 1.x or PacketCable Multimedia Gate
+ * Control may be layered on top of a DOCSIS 1.1 or greater CMTS foundation,
+ * with the option of adding additional, complementary functionality as business
+ * indicates. Further, it should be emphasized that it is a significant asset of
+ * the PacketCable architecture that both telephony and Multimedia variants
+ * employ considerable architectural similarity, leading to potential reuse in
+ * the underlying Gate management models.
+ * </p>
+ * <p>
+ * The PacketCable Multimedia CMTS is a generalized version of the PacketCable
+ * 1.x CMTS that has been defined in order to deliver telephony services in
+ * PacketCable 1.x networks. The CMTS is responsible for fulfilling requests for
+ * QoS that are received from one or more Policy Servers. It performs this
+ * function by installing Gates, which are similar to the Gates defined in [14];
+ * Gates allow the subscriber's cable modem to request network resources from
+ * the CMTS through the creation of dynamic DOCSIS flows with guaranteed levels
+ * of QoS. The CMTS also sends Event Messages detailing actual usage of QoS
+ * resources to the Record Keeping Server.
+ * </p>
+ * <p>
+ * The CMTS acts as a server (PS should send OPN message to CMTS to initiate
+ * communication), and acts as a client for the rest of the exchange process.
+ * </p>
+ * 
+ * 
+ */
+public interface ICMTS extends IPCMMServer {
+
+       // generates a GateID and assigns it to the IPCMMGate.
+
+       static final short DEFAULT_R_TYPE = (short) 0x08;
+       static final short DEFAULT_M_TYPE = (short) 0;
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMClient.java b/packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMClient.java
new file mode 100644 (file)
index 0000000..d1b1341
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ @header@
+ */
+
+package org.pcmm.rcd;
+
+import java.net.InetAddress;
+
+import org.umu.cops.stack.COPSMsg;
+
+/**
+ * <p>
+ * This is a Client Type 1, which represents existing "legacy" endpoints (e.g.,
+ * PC applications, gaming consoles) that lack specific QoS awareness or
+ * signaling capabilities. This client has no awareness of DOCSIS, CableHome, or
+ * PacketCable messaging, and hence no related requirements can be placed upon
+ * it. Client Type 1 communicates with an Application Manager to request
+ * service, and does not (cannot) request QoS resources directly from the MSO
+ * access network.
+ * </p>
+ * 
+ * 
+ */
+public interface IPCMMClient {
+
+       /**
+        * PCMM client-type
+        */
+       static final short CLIENT_TYPE = (short) 0x800A;
+
+       /**
+        * sends a message to the server.
+        * 
+        * @param requestMessage
+        *            request message.
+        */
+       void sendRequest(COPSMsg requestMessage);
+
+       /**
+        * Reads message from server
+        * 
+        * @return COPS message
+        */
+       COPSMsg readMessage();
+
+       /**
+        * tries to connect to the server.
+        * 
+        * @param address
+        *            server address
+        * @param port
+        *            server port
+        * @return connection state
+        */
+       boolean tryConnect(String address, int port);
+
+       /**
+        * tries to connect to the server.
+        * 
+        * @param address
+        *            server address
+        * @param port
+        *            server port
+        * @return connection state
+        */
+       boolean tryConnect(InetAddress address, int port);
+
+       /**
+        * disconnects from server.
+        * 
+        * @return disconnection status.
+        */
+       boolean disconnect();
+
+       /**
+        * 
+        * @return whether the client is connected to the server of not.
+        */
+       boolean isConnected();
+
+       /**
+        * gets the client handle
+        * 
+        * @return client handle
+        */
+       String getClientHandle();
+
+       /**
+        * 
+        * sets the client handle
+        * 
+        * @param handle
+        *            cleint hanlde
+        */
+       void setClientHandle(String handle);
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMPolicyServer.java b/packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMPolicyServer.java
new file mode 100644 (file)
index 0000000..b23c83e
--- /dev/null
@@ -0,0 +1,222 @@
+/**
+ @header@
+ */
+
+package org.pcmm.rcd;
+
+import java.net.InetAddress;
+
+import org.pcmm.objects.MMVersionInfo;
+import org.pcmm.state.IStateful;
+
+/**
+ * <i>PKT-SP-MM-I05-091029 PacketCableTM Specification</i>
+ * <p>
+ * As discussed in RFC 2753 [11], the policy management framework underlying
+ * PacketCable Multimedia is based on the work of the IETF's Resource Allocation
+ * Protocol (RAP) working group. Since the Policy Server is situated between the
+ * Application Manager and the CMTS, it simultaneously plays a dual role as a
+ * "proxy" for AM-initiated session requests and as a "sentry" for defining and
+ * enforcing Resource Control Domain policy. As described in [11] and in keeping
+ * with the PacketCable 1.x DQoS model, the Policy Server serves as Policy
+ * Decision Point (PDP) in relation to the CMTS in that the Policy Server
+ * implements MSO-defined authorization and resource-management procedures.
+ * Conversely, the Policy Server assumes the role of Policy Enforcement Point
+ * (PEP) in relation to the Application Manager as it proxies Gate Control
+ * messages to and from the CMTS element. To revisit the interaction scenario,
+ * the Application Manager issues policy requests to the Policy Server. The
+ * Policy Server acting as a "sentry" for these requests, and applies a set of
+ * policy rules that have been pre-provisioned by the MSO. Upon passing the
+ * checks, the Policy Server then acts as a "proxy" with respect to the
+ * Application Manager and the CMTS, forwarding the policy request and returning
+ * any associated response. Each policy request transaction must be processed
+ * individually. Policy decisions may be based on a number of factors, such as:
+ * <ul>
+ * <li>Parameters associated with the request and the status of available
+ * resources</li>
+ * <li>Identity of the particular client and associated profile information</li>
+ * <li>Application parameters</li>
+ * <li>Security considerations</li>
+ * <li>Time-of-day</li>
+ * </ul>
+ * The primary functions of the Policy Server include:
+ * <ul>
+ * <li>A policy decision request mechanism, invoked by Application Managers</li>
+ * <li>A policy decision request 'policing' mechanism, enforcing installed
+ * Policy Rules</li>
+ * <li>A policy decision delivery mechanism, used to install policy decisions on
+ * the CMTS</li>
+ * <li>A mechanism to allow for the proxying of QoS management messages to the
+ * CMTS on behalf of the Application Manager</li>
+ * <li>An event recording interface to a Record Keeping Server that is used to
+ * log policy requests, which may in turn be correlated with network resource
+ * usage records</li>·
+ * </ul>
+ * Since the Policy Server functions as a proxy between the AM and CMTS elements
+ * (with complementary client and server interfaces) some MSOs may elect to
+ * deploy multiple layers of Policy Servers and to delegate certain policy
+ * decisions among these servers in order to satisfy requirements associated
+ * with scalability and fault-tolerance.
+ * </p>
+ * <p>
+ * <i>Stateful & Stateless Policy Servers</i> There are two basic classes of
+ * Policy Servers â€“ Stateful and Stateless. A Stateless Policy Server is a
+ * slight misnomer since it does maintain enough state to map Application
+ * Manager requests to the proper CMTS and maintain COPS ï¿¼session state, while a
+ * pure Stateless Policy Server maintains no state on any of the media sessions.
+ * Stateful Policy Servers come in several varieties â€“ some participate in
+ * admission control and thus monitor the QoS attributes of active media
+ * sessions, some leave QoS and admission control to the CMTS but monitor
+ * time-based or volume-based service requests from the Application Manager, and
+ * some Policy Servers are somewhere between these extremes. The reason there is
+ * a variety of Policy Server types is that there is a variety of environments
+ * that operators are trying to support. For example, some operators may wish to
+ * support PacketCable Multimedia over the same CMTSs that they use for
+ * PacketCable telephony, and they may want a single CMS/Policy Server that has
+ * a more global view of the network resources being used. On the other hand,
+ * some operators may wish to run a PacketCable Multimedia- only environment, or
+ * they may utilize simpler CMTS-driven mechanisms for partitioning PacketCable
+ * Multimedia and telephony resources. These simpler configurations have more
+ * modest requirements on the amount of state that a Policy Server maintains.
+ * Policy Server state requirements can also be driven by the level of trust
+ * between the Policy Server and Application Manager; a Stateful Policy Server
+ * can more readily police Application Manager session control behavior than can
+ * a Stateless Policy Server. So a Stateful Policy Server may be more
+ * appropriate for operators supporting third party Application Managers. Other
+ * operators may rely on economics to enforce their trust relationships with
+ * Application Managers, or they may control the Application Managers
+ * themselves. In such cases a Stateless Policy Server may be more appropriate.
+ * Since it is impossible to categorize all the various components of media
+ * session and network QoS state that a Policy Server is maintaining, the
+ * protocol is designed to be independent of this complexity. A Stateful Policy
+ * Server gleans PacketCable Multimedia media session information from the
+ * Application Manager requests it proxies; any other information it requires is
+ * gathered via mechanisms that are outside the scope of this specification. The
+ * CMTS and the Application Manager make no distinction as to the type of Policy
+ * Server to which they are connected, and the protocol is designed in such a
+ * manner that the type of Policy Server is transparent to the end point. The
+ * type of Policy Server is only of importance to the operator. Since some types
+ * of Policy Servers attempt to assist with admission control and may have a
+ * larger view of the network and its resources, additional state
+ * synchronization issues may arise in design in a network which contains more
+ * than one of these types of Policy Servers. It is the responsibility of the
+ * operator to ensure that the efforts of these Policy Servers are not
+ * undermined by a network that includes other autonomous Policy Servers.
+ * </p>
+ * <p>
+ * <i>Modification of Requests and Responses by Policy Servers</i> Although
+ * nominally a part of the Resource Control Domain, the Policy Server can be an
+ * intermediary between the Service and the Resource Control Domains, in
+ * addition to its normal role of implementing MSO-defined authorization and
+ * resource management procedures. In either of these capacities it may modify
+ * the incoming request before forwarding it to the CMTS. In acting as an
+ * intermediary between the SCD and RCD, the Policy Server may translate fields
+ * from formats or scales used in the SCD into formats or scales used in the
+ * RCD. For example, the Policy Server may modify the "priority" of a request
+ * coming from an Application Manager (especially important to do for an AM
+ * outside of the MSO network) so that this priority field uses a consistent
+ * scale throughout the operator's RCD. In its capacity as an intermediary, the
+ * Policy Server may use bidirectional translation â€“ in other words, it should
+ * translate requests from the AM to the CMTS and "untranslate" the responses
+ * from the CMTS to the AM. This capability can be supported by stateful policy
+ * servers by remembering the original request, and it can be supported by
+ * stateless Policy Servers if the translation function is invertible.
+ * Modification of certain objects, specifically the Classifier and Traffic
+ * Profile objects, may cause operational problems in the originating AM. As
+ * such, these objects MUST NOT be modified by the policy server. Aside from
+ * these exceptions, all other objects may be policed and modified at the PS's
+ * discretion based on provisioned policy rules.
+ * </p>
+ * 
+ */
+public interface IPCMMPolicyServer extends IPCMMServer, IStateful {
+
+       /**
+        * establishes COPS connection with the CMTS
+        * 
+        * @param host
+        *            : remote host name or ip address
+        * @return connected socket.
+        */
+       IPSCMTSClient requestCMTSConnection(String host);
+
+       /**
+        * establishes COPS connection with the CMTS
+        * 
+        * @param host
+        *            : remote ip address‚
+        * @return connected socket.
+        */
+       IPSCMTSClient requestCMTSConnection(InetAddress host);
+
+       /**
+        * <p>
+        * In the PacketCable model, the CMTS (PEP) is the one that listens on the
+        * assigned port 3918, and it is the Policy Server that MUST initiate the
+        * TCP connection to the CMTS, thus we implement the IPCMMClient interface.
+        * </p>
+        */
+       public static interface IPSCMTSClient extends IPCMMClient {
+
+               /**
+                * 
+                * @return Classifier Id.
+                */
+               short getClassifierId();
+
+               /**
+                * 
+                * @return the transaction Id.
+                */
+               short getTransactionId();
+
+               /**
+                * Gate id transmitted by the CMTS to the PS.
+                * 
+                * @return the Gate Id.
+                */
+               int getGateId();
+
+               /**
+                * initiates a Gate-Set with the CMTS
+                * 
+                * @return
+                */
+               boolean gateSet();
+
+               /**
+                * initiates a Gate-Info with the CMTS
+                * 
+                * @return
+                */
+               boolean gateInfo();
+
+               /**
+                * initiates a Gate-Delete with the CMTS
+                * 
+                * @return
+                */
+               boolean gateDelete();
+
+               /**
+                * sends synch request
+                * 
+                * @return
+                */
+               boolean gateSynchronize();
+
+               /**
+                * Sets the value of the multi-media version info.
+                * 
+                * @param MM
+                *            version info
+                */
+               void setVersionInfo(MMVersionInfo vInfo);
+
+               /**
+                * 
+                * @return MM version info
+                */
+               MMVersionInfo getVersionInfo();
+       }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMServer.java b/packetcable-driver/src/main/java/org/pcmm/rcd/IPCMMServer.java
new file mode 100644 (file)
index 0000000..794af06
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.rcd;
+
+import org.pcmm.concurrent.IWorker;
+import org.pcmm.state.IStateful;
+
+/**
+ * <p>
+ * As discussed in RFC 2753 [11], the policy management framework underlying
+ * PacketCable Multimedia is based on the work of the IETF's Resource Allocation
+ * Protocol (RAP) working group. Since the Policy Server is situated between the
+ * Application Manager and the CMTS, it simultaneously plays a dual role as a
+ * "proxy" for AM-initiated session requests and as a "sentry" for defining and
+ * enforcing Resource Control Domain policy.
+ * </p>
+ * <p>
+ * As described in [11] and in keeping with the PacketCable 1.x DQoS model, the
+ * Policy Server serves as Policy Decision Point (PDP) in relation to the CMTS
+ * resource-management procedures. Conversely, the Policy Server assumes the
+ * role of Policy Enforcement Point (PEP) in relation to the Application Manager
+ * as it proxies Gate Control messages to and from the CMTS element.
+ * </p>
+ * <p>
+ * To revisit the interaction scenario, the Application Manager issues policy
+ * requests to the Policy Server. The Policy Server acting as a "sentry" for
+ * these requests, and applies a set of policy rules that have been
+ * pre-provisioned by the MSO. Upon passing the checks, the Policy Server then
+ * acts as a "proxy" with respect to the Application Manager and the CMTS,
+ * forwarding the policy request and returning any associated response. Each
+ * policy request transaction must be processed individually.
+ * </p>
+ * <p>
+ * Policy decisions may be based on a number of factors, such as:
+ * <ul>
+ * <li>Parameters associated with the request and the status of available
+ * resources</li>
+ * <li>Identity of the particular client and associated profile information</li>
+ * <li>Application parameters</li>
+ * <li>Security considerations</li>
+ * <li>Time-of-day</li>
+ * </ul>
+ * The primary functions of the Policy Server include:
+ * <ul>
+ * <li>A policy decision request mechanism, invoked by Application Managers</li>
+ * <li>A policy decision request 'policing' mechanism, enforcing installed
+ * Policy Rules</li>
+ * <li>A policy decision delivery mechanism, used to install policy decisions on
+ * the CMTS</li>
+ * <li>A mechanism to allow for the proxying of QoS management messages to the
+ * CMTS on behalf of the Application Manager</li>
+ * <li>An event recording interface to a Record Keeping Server that is used to
+ * log policy requests, which may in turn be correlated with network resource
+ * usage records</li>
+ * </ul>
+ * <p>
+ * Since the Policy Server functions as a proxy between the AM and CMTS elements
+ * (with complementary client and server interfaces) some MSOs may elect to
+ * deploy multiple layers of Policy Servers and to delegate certain policy
+ * decisions among these servers in order to satisfy requirements associated
+ * with scalability and fault-tolerance.
+ * </p>
+ * </p>
+ *
+ *
+ */
+public interface IPCMMServer extends IStateful {
+
+    /**
+     *
+     */
+    void startServer();
+
+    /**
+     *
+     */
+    void stopServer();
+
+    /**
+     * When a client connects to the server, a handler is needed to manage the
+     * exchange of the messages between this client and the server.
+     *
+     *
+     */
+    public static interface IPCMMClientHandler extends IWorker, IPCMMClient {
+
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMClient.java b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMClient.java
new file mode 100644 (file)
index 0000000..6a29743
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ @header@
+ */
+package org.pcmm.rcd.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import org.pcmm.nio.PCMMChannel;
+// import org.junit.Assert;
+import org.pcmm.objects.MMVersionInfo;
+import org.pcmm.rcd.IPCMMClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.COPSMsg;
+
+/**
+ * 
+ * default implementation for {@link IPCMMClient}
+ * 
+ * 
+ */
+public class AbstractPCMMClient implements IPCMMClient {
+
+       protected Logger logger = LoggerFactory.getLogger(AbstractPCMMClient.class);
+       /**
+        * socket used to communicated with server.
+        */
+       private Socket socket;
+
+       private String clientHanlde;
+
+       private MMVersionInfo versionInfo;
+
+       private PCMMChannel channel;
+
+       public AbstractPCMMClient() {
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMClient#sendRequest(pcmm.messages.IMessage)
+        */
+       public void sendRequest(COPSMsg requestMessage) {
+               try {
+                       channel.sendMsg(requestMessage);
+               } catch (Exception e) {
+                       logger.error(e.getMessage(), getSocket());
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.rcd.IPCMMClient#readMessage()
+        */
+       public COPSMsg readMessage() {
+               try {
+                       COPSMsg recvdMsg = channel.receiveMessage();
+                       // logger.debug("received message : " + recvdMsg.getHeader());
+                       return recvdMsg;
+               } catch (Exception e) {
+                       logger.error(e.getMessage(), getSocket());
+               }
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMClient#tryConnect(java.lang.String, int)
+        */
+       public boolean tryConnect(String address, int port) {
+               try {
+                       InetAddress addr = InetAddress.getByName(address);
+                       tryConnect(addr, port);
+               } catch (UnknownHostException e) {
+                       logger.error(e.getMessage());
+                       return false;
+               }
+               return true;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMClient#tryConnect(java.net.InetAddress, int)
+        */
+       public boolean tryConnect(InetAddress address, int port) {
+               try {
+                       setSocket(new Socket(address, port));
+               } catch (IOException e) {
+                       logger.error(e.getMessage());
+                       return false;
+               }
+               return true;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMClient#disconnect()
+        */
+       public boolean disconnect() {
+               if (isConnected()) {
+                       try {
+                               socket.close();
+                               channel = null;
+                       } catch (IOException e) {
+                               logger.error(e.getMessage());
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * @return the socket
+        */
+       public Socket getSocket() {
+               return socket;
+       }
+
+       public PCMMChannel getChannel() {
+               return channel;
+       }
+
+       /**
+        * @param socket
+        *            the socket to set
+        */
+       public void setSocket(Socket socket) {
+               this.socket = socket;
+               if (this.socket != null
+                               && (this.channel == null || !this.channel.getSocket().equals(
+                                               this.socket)))
+                       channel = new PCMMChannel(this.socket);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.pcmm.rcd.IPCMMClient#isConnected()
+        */
+       public boolean isConnected() {
+               return socket != null && socket.isConnected();
+       }
+
+       /**
+        * @return the versionInfo
+        */
+       public MMVersionInfo getVersionInfo() {
+               return versionInfo;
+       }
+
+       /**
+        * @param versionInfo
+        *            the versionInfo to set
+        */
+       public void setVersionInfo(MMVersionInfo versionInfo) {
+               this.versionInfo = versionInfo;
+       }
+
+       @Override
+       public String getClientHandle() {
+               return clientHanlde;
+       }
+
+       @Override
+       public void setClientHandle(String handle) {
+               this.clientHanlde = handle;
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMServer.java b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/AbstractPCMMServer.java
new file mode 100644 (file)
index 0000000..bac4979
--- /dev/null
@@ -0,0 +1,214 @@
+/**
+ @header@
+ */
+package org.pcmm.rcd.impl;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.Executors;
+
+import org.pcmm.PCMMConstants;
+import org.pcmm.PCMMProperties;
+import org.pcmm.concurrent.IWorkerPool;
+import org.pcmm.concurrent.impl.WorkerPool;
+// import org.junit.Assert;
+import org.pcmm.messages.impl.MessageFactory;
+import org.pcmm.rcd.IPCMMServer;
+import org.pcmm.state.IState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSMsg;
+
+/*
+ * (non-Javadoc)
+ *
+ * @see pcmm.rcd.IPCMMServer
+ */
+public abstract class AbstractPCMMServer implements IPCMMServer {
+       protected Logger logger;
+       /*
+        * A ServerSocket to accept messages ( OPN requests)
+        */
+       private ServerSocket serverSocket;
+
+       private Socket stopSocket;
+
+       private volatile boolean keepAlive;
+       /*
+     *
+     */
+       private int port;
+
+       IWorkerPool pool;
+
+       protected AbstractPCMMServer() {
+               this(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
+       }
+
+       protected AbstractPCMMServer(int port) {
+               // XXX - Assert.assertTrue(port >= 0 && port <= 65535);
+               this.port = port;
+               keepAlive = true;
+               logger = LoggerFactory.getLogger(getClass().getName());
+               int poolSize = PCMMProperties.get(PCMMConstants.PS_POOL_SIZE, Integer.class);
+               pool = new WorkerPool(poolSize);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMServer#startServer()
+        */
+       public void startServer() {
+               if (serverSocket != null)
+                       return;
+               try {
+                       serverSocket = new ServerSocket(port);
+                       logger.info("Server started and listening on port :" + port);
+               } catch (IOException e) {
+                       logger.error(e.getMessage());
+               }
+               // execute this in a single thread executor
+               Executors.newSingleThreadExecutor().execute(new Runnable() {
+                       public void run() {
+                               while (keepAlive) {
+                                       try {
+                                               Socket socket = serverSocket.accept();
+                                               logger.info("Accepted a new connection from :" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
+                                               if (keepAlive) {
+                                                       pool.schedule(getPCMMClientHandler(socket));
+                                                       logger.info("Handler attached tp : " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
+                                               } else {
+                                                       logger.info("connection to be closed : " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
+                                                       socket.close();
+                                               }
+                                       } catch (IOException e) {
+                                               logger.error(e.getMessage());
+                                       }
+                               }
+                               try {
+                                       if (stopSocket != null && stopSocket.isConnected()) {
+                                               logger.info("Cleaning up");
+                                               stopSocket.close();
+                                       }
+                                       if (serverSocket != null && serverSocket.isBound()) {
+                                               logger.info("Server about to stop");
+                                               serverSocket.close();
+                                               logger.info("Server stopped");
+                                       }
+                               } catch (IOException e) {
+                                       logger.error(e.getMessage());
+                               }
+                       }
+               });
+       }
+
+       /**
+        * This client is used to handle requests from within the Application
+        * Manager
+        * 
+        * @param socket
+        * @return client handler
+        */
+       protected abstract IPCMMClientHandler getPCMMClientHandler(Socket socket);
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMServer#stopServer()
+        */
+       public void stopServer() {
+               // set to stop
+               keepAlive = false;
+               try {
+                       if (serverSocket != null) {
+                               stopSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort());
+                               logger.info("STOP socket created and attached");
+                       }
+               } catch (Exception e) {
+                       logger.error(e.getMessage());
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.state.IStateful#recordState()
+        */
+       public void recordState() {
+
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.state.IStateful#getRecoredState()
+        */
+       public IState getRecoredState() {
+               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
+        */
+       public int getPort() {
+               return port;
+       }
+
+       /**
+        * @param port
+        *            the port to set
+        */
+       public void setPort(int port) {
+               this.port = port;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see pcmm.rcd.IPCMMServer.IPCMMClientHandler
+        */
+       public abstract class AbstractPCMMClientHandler extends AbstractPCMMClient
+                       implements IPCMMClientHandler {
+
+               protected boolean sendCCMessage = false;
+
+               public AbstractPCMMClientHandler(Socket socket) {
+                       super();
+                       setSocket(socket);
+               }
+
+               @Override
+               public boolean disconnect() {
+                       // XXX send CC message
+                       sendCCMessage = true;
+                       /*
+                        * is this really needed ?
+                        */
+                       // if (getSocket() != null)
+                       // handlersPool.remove(getSocket());
+                       COPSMsg message = MessageFactory.getInstance().create(COPSHeader.COPS_OP_CC);
+                       sendRequest(message);
+                       return super.disconnect();
+               }
+
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CMTS.java b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CMTS.java
new file mode 100644 (file)
index 0000000..fa89754
--- /dev/null
@@ -0,0 +1,355 @@
+/**
+ @header@
+ */
+package org.pcmm.rcd.impl;
+
+import java.net.Socket;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+
+import org.pcmm.gates.IPCMMGate;
+import org.pcmm.gates.ITransactionID;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.pcmm.messages.impl.MessageFactory;
+import org.pcmm.rcd.ICMTS;
+import org.umu.cops.prpep.COPSPepConnection;
+import org.umu.cops.prpep.COPSPepDataProcess;
+import org.umu.cops.prpep.COPSPepException;
+import org.umu.cops.prpep.COPSPepReqStateMan;
+import org.umu.cops.stack.COPSAcctTimer;
+import org.umu.cops.stack.COPSClientAcceptMsg;
+import org.umu.cops.stack.COPSClientCloseMsg;
+import org.umu.cops.stack.COPSContext;
+import org.umu.cops.stack.COPSData;
+import org.umu.cops.stack.COPSDecision;
+import org.umu.cops.stack.COPSDecisionMsg;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSKATimer;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSPrObjBase;
+import org.umu.cops.stack.COPSReqMsg;
+
+/**
+ *
+ */
+public class CMTS extends AbstractPCMMServer implements ICMTS {
+
+       public CMTS() {
+               super();
+       }
+
+       @Override
+       protected IPCMMClientHandler getPCMMClientHandler(final Socket socket) {
+
+               return new AbstractPCMMClientHandler(socket) {
+
+                       private String handle;
+
+                       public void run() {
+                               try {
+                                       // send OPN message
+                                       // set the major version info and minor version info to
+                                       // default (5,0)
+                                       logger.info("Send OPN message to the PS");
+                                       sendRequest(MessageFactory.getInstance().create(COPSHeader.COPS_OP_OPN, new Properties()));
+                                       // wait for CAT
+                                       COPSMsg recvMsg = readMessage();
+
+                                       if (recvMsg.getHeader().isAClientClose()) {
+                                               COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvMsg;
+                                               logger.info("PS requested Client-Close" + cMsg.getError().getDescription());
+                                               // send a CC message and close the socket
+                                               disconnect();
+                                               return;
+                                       }
+                                       if (recvMsg.getHeader().isAClientAccept()) {
+                                               logger.info("received Client-Accept from PS");
+                                               COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvMsg;
+                                               // Support
+                                               if (cMsg.getIntegrity() != null) {
+                                                       throw new COPSPepException("Unsupported object (Integrity)");
+                                               }
+
+                                               // Mandatory KATimer
+                                               COPSKATimer kt = cMsg.getKATimer();
+                                               if (kt == null)
+                                                       throw new COPSPepException("Mandatory COPS object missing (KA Timer)");
+                                               short kaTimeVal = kt.getTimerVal();
+
+                                               // ACTimer
+                                               COPSAcctTimer at = cMsg.getAcctTimer();
+                                               short acctTimer = 0;
+                                               if (at != null)
+                                                       acctTimer = at.getTimerVal();
+
+                                               logger.info("Send a REQ message to the PS");
+                                               {
+                                                       Properties prop = new Properties();
+                                                       COPSMsg reqMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_REQ, prop);
+                                                       handle = ((COPSReqMsg) reqMsg).getClientHandle().getId().str();
+                                                       sendRequest(reqMsg);
+                                               }
+                                               // Create the connection manager
+                                               PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
+                                               // pcmm specific handler
+                                               // conn.addReqStateMgr(handle, new
+                                               // PCMMPSReqStateMan(CLIENT_TYPE, handle));
+                                               conn.addRequestState(handle, new CmtsDataProcessor());
+                                               conn.setKaTimer(kaTimeVal);
+                                               conn.setAcctTimer(acctTimer);
+                                               logger.info(getClass().getName() + " Thread(conn).start");
+                                               new Thread(conn).start();
+                                       } else {
+                                               // messages of other types are not expected
+                                               throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());
+                                       }
+                               } catch (Exception e) {
+                                       logger.error(e.getMessage());
+                               }
+                       }
+
+                       @Override
+                       public void task(Callable<?> c) {
+                               // TODO Auto-generated method stub
+
+                       }
+
+                       @Override
+                       public void shouldWait(int t) {
+                               // TODO Auto-generated method stub
+
+                       }
+
+                       @Override
+                       public void done() {
+                               // TODO Auto-generated method stub
+
+                       }
+
+               };
+       }
+
+       /* public */class PCMMCmtsConnection extends COPSPepConnection {
+
+               public PCMMCmtsConnection(short clientType, Socket sock) {
+                       super(clientType, sock);
+               }
+
+               public COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process)
+                               throws COPSException, COPSPepException {
+                       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(short clientType, String clientHandle) {
+                       super(clientType, clientHandle);
+                       _process = new CmtsDataProcessor();
+
+               }
+
+               @Override
+               protected void processDecision(COPSDecisionMsg dMsg)
+                               throws COPSPepException {
+
+                       // COPSHandle handle = dMsg.getClientHandle();
+                       Hashtable decisions = dMsg.getDecisions();
+
+                       Hashtable<String, String> removeDecs = new Hashtable<String, String>(10);
+                       Hashtable<String, String> installDecs = new Hashtable<String, String>(10);
+                       Hashtable<String, String> errorDecs = new Hashtable<String, String>(10);
+                       for (Enumeration e = decisions.keys(); e.hasMoreElements();) {
+
+                               COPSContext context = (COPSContext) e.nextElement();
+                               Vector v = (Vector) decisions.get(context);
+                               Enumeration ee = v.elements();
+                               COPSDecision cmddecision = (COPSDecision) ee.nextElement();
+
+                               // cmddecision --> we must check whether it is an error!
+
+                               if (cmddecision.isInstallDecision()) {
+                                       String prid = new String();
+                                       for (; ee.hasMoreElements();) {
+                                               COPSDecision decision = (COPSDecision) ee.nextElement();
+                                               COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                                               switch (obj.getSNum()) {
+                                               // TODO when there is install request only the PR_PRID
+                                               // is git but the ClientSI object containing the PR_EPD
+                                               // is null??? this is why the tests fail and so I set
+                                               // the assertion to NOT true....
+                                               case COPSPrObjBase.PR_PRID:
+                                                       prid = obj.getData().str();
+                                               break;
+                                               case COPSPrObjBase.PR_EPD:
+                                                       installDecs.put(prid, obj.getData().str());
+                                               break;
+                                               default:
+                                               break;
+                                               }
+                                       }
+                               }
+                               if (cmddecision.isRemoveDecision()) {
+                                       String prid = new String();
+                                       for (; ee.hasMoreElements();) {
+                                               COPSDecision decision = (COPSDecision) ee.nextElement();
+                                               COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                                               switch (obj.getSNum()) {
+                                               case COPSPrObjBase.PR_PRID:
+                                                       prid = obj.getData().str();
+                                               break;
+                                               case COPSPrObjBase.PR_EPD:
+                                                       removeDecs.put(prid, obj.getData().str());
+                                               break;
+                                               default:
+                                               break;
+                                               }
+                                       }
+                               }
+                       }
+                       if (_process != null) {
+                               // ** Apply decisions to the configuration
+                               _process.setDecisions(this, removeDecs, installDecs, errorDecs);
+                               _status = ST_DECS;
+                               if (_process.isFailReport(this)) {
+                                       // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
+                                       _sender.sendFailReport(_process.getReportData(this));
+                               } else {
+                                       // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
+                                       _sender.sendSuccessReport(_process.getReportData(this));
+                               }
+                               _status = ST_REPORT;
+                       }
+               }
+       }
+
+       @SuppressWarnings("rawtypes")
+       class CmtsDataProcessor extends COPSPepDataProcess {
+
+               private Hashtable<String, String> removeDecs;
+               private Hashtable<String, String> installDecs;
+               private Hashtable<String, String> errorDecs;
+               private COPSPepReqStateMan stateManager;
+
+               public CmtsDataProcessor() {
+                       setRemoveDecs(new Hashtable<String, String>(10));
+                       setInstallDecs(new Hashtable<String, String>(10));
+                       setErrorDecs(new Hashtable<String, String>(10));
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public void setDecisions(COPSPepReqStateMan man, Hashtable removeDecs, Hashtable installDecs, Hashtable errorDecs) {
+                       setRemoveDecs(removeDecs);
+                       setInstallDecs(installDecs);
+                       setErrorDecs(errorDecs);
+                       setStateManager(man);
+               }
+
+               @Override
+               public boolean isFailReport(COPSPepReqStateMan man) {
+                       return (errorDecs != null && errorDecs.size() > 0);
+               }
+
+               @Override
+               public Hashtable getReportData(COPSPepReqStateMan man) {
+                       if (isFailReport(man)) {
+                               return errorDecs;
+                       } else {
+                               ITransactionID transactionID = null;
+                               String key = null;
+                               Hashtable<String, String> siDataHashTable = new Hashtable<String, String>();
+                               if (installDecs.size() > 0) {
+                                       String data = "";
+                                       for (String k : installDecs.keySet()) {
+                                               data = installDecs.get(k);
+                                               break;
+                                       }
+                                       transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
+                                       IPCMMGate responseGate = new PCMMGateReq();
+                                       responseGate.setTransactionID(transactionID);
+                                       siDataHashTable.put(key, new String(responseGate.getData()));
+                               }
+                               return siDataHashTable;
+                       }
+               }
+
+               @Override
+               public Hashtable getClientData(COPSPepReqStateMan man) {
+                       // TODO Auto-generated method stub
+                       return new Hashtable<String, String>();
+               }
+
+               @Override
+               public Hashtable getAcctData(COPSPepReqStateMan man) {
+                       // TODO Auto-generated method stub
+                       return new Hashtable<String, String>();
+               }
+
+               @Override
+               public void notifyClosedConnection(COPSPepReqStateMan man, COPSError error) {
+
+               }
+
+               @Override
+               public void notifyNoKAliveReceived(COPSPepReqStateMan man) {
+                       // TODO Auto-generated method stub
+
+               }
+
+               @Override
+               public void closeRequestState(COPSPepReqStateMan man) {
+                       // TODO Auto-generated method stub
+
+               }
+
+               @Override
+               public void newRequestState(COPSPepReqStateMan man) {
+                       // TODO Auto-generated method stub
+
+               }
+
+               public Hashtable<String, String> getRemoveDecs() {
+                       return removeDecs;
+               }
+
+               public void setRemoveDecs(Hashtable<String, String> removeDecs) {
+                       this.removeDecs = removeDecs;
+               }
+
+               public Hashtable<String, String> getInstallDecs() {
+                       return installDecs;
+               }
+
+               public void setInstallDecs(Hashtable<String, String> installDecs) {
+                       this.installDecs = installDecs;
+               }
+
+               public Hashtable<String, String> getErrorDecs() {
+                       return errorDecs;
+               }
+
+               public void setErrorDecs(Hashtable<String, String> errorDecs) {
+                       this.errorDecs = errorDecs;
+               }
+
+               public COPSPepReqStateMan getStateManager() {
+                       return stateManager;
+               }
+
+               public void setStateManager(COPSPepReqStateMan stateManager) {
+                       this.stateManager = stateManager;
+               }
+       }
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/PCMMPolicyServer.java b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/PCMMPolicyServer.java
new file mode 100644 (file)
index 0000000..bd763eb
--- /dev/null
@@ -0,0 +1,652 @@
+/**
+ * @header@
+ */
+package org.pcmm.rcd.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.Properties;
+
+import org.pcmm.PCMMConstants;
+import org.pcmm.PCMMGlobalConfig;
+import org.pcmm.PCMMProperties;
+import org.pcmm.gates.IAMID;
+import org.pcmm.gates.IClassifier;
+import org.pcmm.gates.IExtendedClassifier;
+import org.pcmm.gates.IGateID;
+import org.pcmm.gates.IGateSpec;
+import org.pcmm.gates.IGateSpec.DSCPTOS;
+import org.pcmm.gates.IGateSpec.Direction;
+import org.pcmm.gates.IPCMMError;
+import org.pcmm.gates.IPCMMGate;
+import org.pcmm.gates.ISubscriberID;
+import org.pcmm.gates.ITrafficProfile;
+import org.pcmm.gates.ITransactionID;
+import org.pcmm.gates.impl.AMID;
+import org.pcmm.gates.impl.BestEffortService;
+import org.pcmm.gates.impl.Classifier;
+import org.pcmm.gates.impl.ExtendedClassifier;
+import org.pcmm.gates.impl.GateID;
+import org.pcmm.gates.impl.GateSpec;
+import org.pcmm.gates.impl.PCMMError;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.pcmm.gates.impl.SubscriberID;
+import org.pcmm.gates.impl.TransactionID;
+import org.pcmm.messages.IMessage.MessageProperties;
+import org.pcmm.messages.impl.MessageFactory;
+import org.pcmm.objects.MMVersionInfo;
+import org.pcmm.rcd.IPCMMPolicyServer;
+import org.pcmm.utils.PCMMException;
+import org.umu.cops.prpdp.COPSPdpConnection;
+import org.umu.cops.prpdp.COPSPdpDataProcess;
+import org.umu.cops.stack.COPSClientAcceptMsg;
+import org.umu.cops.stack.COPSClientCloseMsg;
+import org.umu.cops.stack.COPSClientOpenMsg;
+import org.umu.cops.stack.COPSClientSI;
+import org.umu.cops.stack.COPSData;
+import org.umu.cops.stack.COPSDecision;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSReportMsg;
+import org.umu.cops.stack.COPSReqMsg;
+
+/**
+ * 
+ * PCMM policy server
+ * 
+ */
+public class PCMMPolicyServer extends AbstractPCMMServer implements
+               IPCMMPolicyServer {
+       /**
+        * since PCMMPolicyServer can connect to multiple CMTS (PEP) we need to
+        * manage each connection in a separate thread.
+        */
+
+       public PCMMPolicyServer() {
+               super();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.pcmm.rcd.IPCMMPolicyServer#requestCMTSConnection(java.lang.String)
+        */
+       public IPSCMTSClient requestCMTSConnection(String host) {
+               try {
+                       InetAddress address = InetAddress.getByName(host);
+                       return requestCMTSConnection(address);
+               } catch (UnknownHostException e) {
+                       logger.error(e.getMessage());
+               }
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.pcmm.rcd.IPCMMPolicyServer#requestCMTSConnection(java.net.InetAddress
+        * )
+        */
+       public IPSCMTSClient requestCMTSConnection(InetAddress host) {
+               IPSCMTSClient client = new PSCMTSClient();
+               try {
+                       if (client.tryConnect(host, PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class))) {
+                               boolean endNegotiation = false;
+                               while (!endNegotiation) {
+                                       logger.debug("waiting for OPN message from CMTS");
+                                       COPSMsg opnMessage = client.readMessage();
+                                       // Client-Close
+                                       if (opnMessage.getHeader().isAClientClose()) {
+                                               COPSError error = ((COPSClientCloseMsg) opnMessage).getError();
+                                               logger.debug("CMTS requetsed Client-Close");
+                                               throw new PCMMException(new PCMMError(error.getErrCode(), error.getErrSubCode()));
+                                       } else // Client-Open
+                                       if (opnMessage.getHeader().isAClientOpen()) {
+                                               logger.debug("OPN message received from CMTS");
+                                               COPSClientOpenMsg opn = (COPSClientOpenMsg) opnMessage;
+                                               if (opn.getClientSI() == null)
+                                                       throw new COPSException("CMTS shoud have sent MM version info in Client-Open message");
+                                               else {
+                                                       // set the version info
+                                                       MMVersionInfo vInfo = new MMVersionInfo(opn.getClientSI().getData().getData());
+                                                       client.setVersionInfo(vInfo);
+                                                       logger.debug("CMTS sent MMVersion info : major:" + vInfo.getMajorVersionNB() + "  minor:" + vInfo.getMinorVersionNB()); //
+                                                       if (client.getVersionInfo().getMajorVersionNB() == client.getVersionInfo().getMinorVersionNB()) {
+                                                               // send a CC since CMTS has exhausted all
+                                                               // protocol selection attempts
+                                                               throw new COPSException("CMTS exhausted all protocol selection attempts");
+                                                       }
+                                               }
+                                               // send CAT response
+                                               Properties prop = new Properties();
+                                               logger.debug("send CAT to the CMTS ");
+                                               COPSMsg catMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_CAT, prop);
+                                               client.sendRequest(catMsg);
+                                               // wait for REQ msg
+                                               COPSMsg reqMsg = client.readMessage();
+                                               // Client-Close
+                                               if (reqMsg.getHeader().isAClientClose()) {
+                                                       COPSError error = ((COPSClientCloseMsg) opnMessage).getError();
+                                                       logger.debug("CMTS requetsed Client-Close");
+                                                       throw new PCMMException(new PCMMError(error.getErrCode(), error.getErrSubCode()));
+                                               } else // Request
+                                               if (reqMsg.getHeader().isARequest()) {
+                                                       logger.debug("Received REQ message form CMTS");
+                                                       // end connection attempts
+                                                       COPSReqMsg req = (COPSReqMsg) reqMsg;
+                                                       // set the client handle to be used later by the
+                                                       // gate-set
+                                                       client.setClientHandle(req.getClientHandle().getId().str());
+                                                       COPSPdpDataProcess processor = null;
+                                                       COPSPdpConnection copsPdpConnection = new COPSPdpConnection(opn.getPepId(), ((AbstractPCMMClient) client).getSocket(), processor);
+                                                       copsPdpConnection.setKaTimer(((COPSClientAcceptMsg) catMsg).getKATimer().getTimerVal());
+                                                       pool.schedule(pool.adapt(copsPdpConnection));
+                                                       endNegotiation = true;
+                                               } else
+                                                       throw new COPSException("Can't understand request");
+                                       } else {
+                                               throw new COPSException("Can't understand request");
+                                       }
+                               }
+                       }
+                       // else raise exception.
+               } catch (Exception e) {
+                       logger.error(e.getMessage());
+                       // no need to keep connection.
+                       client.disconnect();
+                       return null;
+               }
+               return client;
+       }
+
+       @Override
+       protected IPCMMClientHandler getPCMMClientHandler(Socket socket) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       /**
+        * 
+        * @see {@link IPSCMTSClient}
+        */
+       /* public */static class PSCMTSClient extends AbstractPCMMClient implements
+                       IPSCMTSClient {
+               /**
+                * Transaction id is
+                */
+               private short transactionID;
+               private short classifierID;
+               private int gateID;
+
+               public PSCMTSClient() {
+                       super();
+                       logger.info("Client " + getClass() + hashCode() + " crated and started");
+               }
+
+               public PSCMTSClient(Socket socket) {
+                       setSocket(socket);
+               }
+
+               public boolean gateSet() {
+                       logger.debug("Sending Gate-Set message");
+                       if (!isConnected())
+                               throw new IllegalArgumentException("Not connected");
+                       // XXX check if other values should be provided
+                       //
+                       ITrafficProfile trafficProfile = buildTrafficProfile();
+                       // PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+                       ITransactionID trID = new TransactionID();
+                       // set transaction ID to gate set
+                       trID.setGateCommandType(ITransactionID.GateSet);
+                       transactionID = (short) (transactionID == 0 ? (short) (Math.random() * hashCode()) : transactionID);
+                       trID.setTransactionIdentifier(transactionID);
+                       // AMID
+                       IAMID amid = getAMID();
+                       // GATE SPEC
+                       IGateSpec gateSpec = getGateSpec();
+                       ISubscriberID subscriberID = new SubscriberID();
+                       // Classifier if MM version <4, Extended Classifier else
+                       IClassifier eclassifier = getClassifier(subscriberID);
+
+                       IPCMMGate gate = new PCMMGateReq();
+                       gate.setTransactionID(trID);
+                       gate.setAMID(amid);
+                       gate.setSubscriberID(subscriberID);
+                       gate.setGateSpec(gateSpec);
+                       gate.setTrafficProfile(trafficProfile);
+                       gate.setClassifier(eclassifier);
+                       byte[] data = gate.getData();
+
+                       // configure message properties
+                       Properties prop = new Properties();
+                       prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
+                       prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
+                       prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+                       prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
+                       COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+                       // ** Send the GateSet Decision
+                       // **
+                       sendRequest(decisionMsg);
+                       // TODO check on this ?
+                       // waits for the gate-set-ack or error
+                       COPSMsg responseMsg = readMessage();
+                       if (responseMsg.getHeader().isAReport()) {
+                               logger.info("processing received report from CMTS");
+                               COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
+                               if (reportMsg.getClientSI().size() == 0) {
+                                       logger.debug("CMTS responded with an empty SI");
+                                       return false;
+                               }
+                               COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                               IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
+                               IPCMMError error = ((PCMMGateReq) responseGate).getError();
+                               if (error != null) {
+                                       logger.error(error.toString());
+                                       return false;
+                               }
+                               logger.info("the CMTS has sent TransactionID :"+responseGate.getTransactionID());
+                               if (responseGate.getTransactionID() != null && responseGate.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck) {
+                                       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();
+                                       return true;
+                               } else {
+                                       return false;
+                               }
+                       }
+                       return false;
+               }
+
+               /*
+                * (non-Javadoc)
+                * 
+                * @see org.pcmm.rcd.IPCMMPolicyServer#gateDelete()
+                */
+               @Override
+               public boolean gateDelete() {
+                       if (!isConnected()) {
+                               logger.error("Not connected");
+                               return false;
+                       }
+                       ITransactionID trID = new TransactionID();
+                       // set transaction ID to gate set
+                       trID.setGateCommandType(ITransactionID.GateDelete);
+                       trID.setTransactionIdentifier(transactionID);
+                       // AMID
+                       IAMID amid = getAMID();
+                       // GATE SPEC
+                       ISubscriberID subscriberID = new SubscriberID();
+                       try {
+                               subscriberID.setSourceIPAddress(InetAddress.getLocalHost());
+                       } catch (UnknownHostException e1) {
+                               logger.error(e1.getMessage());
+                       }
+
+                       IGateID gateIdObj = new GateID();
+                       gateIdObj.setGateID(gateID);
+
+                       IPCMMGate gate = new PCMMGateReq();
+                       gate.setTransactionID(trID);
+                       gate.setAMID(amid);
+                       gate.setSubscriberID(subscriberID);
+                       gate.setGateID(gateIdObj);
+
+                       // configure message properties
+                       Properties prop = new Properties();
+                       prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
+                       prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
+                       prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+                       byte[] data = gate.getData();
+                       prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
+                       COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+                       // ** Send the GateSet Decision
+                       // **
+                       try {
+                               decisionMsg.writeData(getSocket());
+                       } catch (IOException e) {
+                               logger.error("Failed to send the decision, reason: " + e.getMessage());
+                               return false;
+                       }
+                       // waits for the gate-delete-ack or error
+                       COPSMsg responseMsg = readMessage();
+                       if (responseMsg.getHeader().isAReport()) {
+                               logger.info("processing received report from CMTS");
+                               COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
+                               if (reportMsg.getClientSI().size() == 0) {
+                                       return false;
+                               }
+                               COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                               IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
+                               IPCMMError error = ((PCMMGateReq) responseGate).getError();
+                               if (error != null) {
+                                       logger.error(error.toString());
+                                       return false;
+                               }
+                               // here CMTS responded that he acknowledged the Gate-delete
+                               // message
+                               ITransactionID responseTransactionID = responseGate.getTransactionID();
+                               if (responseTransactionID != null && responseTransactionID.getGateCommandType() == ITransactionID.GateDeleteAck) {
+                                       // TODO check : Is this test needed ??
+                                       if (responseGate.getGateID().getGateID() == gateID && responseTransactionID.getTransactionIdentifier() == transactionID) {
+                                               logger.info("the CMTS has sent a Gate-Delete-Ack response");
+                                               return true;
+                                       }
+                               }
+
+                       }
+                       return false;
+               }
+
+               /*
+                * (non-Javadoc)
+                * 
+                * @see org.pcmm.rcd.IPCMMPolicyServer#gateInfo()
+                */
+               @Override
+               public boolean gateInfo() {
+                       if (!isConnected()) {
+                               logger.error("Not connected");
+                               return false;
+                       }
+                       ITransactionID trID = new TransactionID();
+                       // set transaction ID to gate set
+                       trID.setGateCommandType(ITransactionID.GateInfo);
+                       trID.setTransactionIdentifier(transactionID);
+                       // AMID
+                       IAMID amid = getAMID();
+                       // GATE SPEC
+                       ISubscriberID subscriberID = new SubscriberID();
+                       try {
+                               subscriberID.setSourceIPAddress(InetAddress.getLocalHost());
+                       } catch (UnknownHostException e1) {
+                               logger.error(e1.getMessage());
+                       }
+                       IGateID gateIdObj = new GateID();
+                       gateIdObj.setGateID(gateID);
+
+                       IPCMMGate gate = new PCMMGateReq();
+                       gate.setTransactionID(trID);
+                       gate.setAMID(amid);
+                       gate.setSubscriberID(subscriberID);
+                       gate.setGateID(gateIdObj);
+
+                       // configure message properties
+                       Properties prop = new Properties();
+                       prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
+                       prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
+                       prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+                       byte[] data = gate.getData();
+                       prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
+                       COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+                       // ** Send the GateSet Decision
+                       // **
+                       try {
+                               decisionMsg.writeData(getSocket());
+                       } catch (IOException e) {
+                               logger.error("Failed to send the decision, reason: " + e.getMessage());
+                               return false;
+                       }
+                       // waits for the gate-Info-ack or error
+                       COPSMsg responseMsg = readMessage();
+                       if (responseMsg.getHeader().isAReport()) {
+                               logger.info("processing received report from CMTS");
+                               COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
+                               if (reportMsg.getClientSI().size() == 0) {
+                                       return false;
+                               }
+                               COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                               IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
+                               IPCMMError error = ((PCMMGateReq) responseGate).getError();
+                               ITransactionID responseTransactionID = responseGate.getTransactionID();
+                               if (error != null) {
+                                       logger.debug(responseTransactionID != null ? responseTransactionID.toString() : "returned Transaction ID is null");
+                                       logger.error(error.toString());
+                                       return false;
+                               }
+                               // here CMTS responded that he acknowledged the Gate-Info
+                               // message
+                               /*
+                                * <Gate-Info-Ack> = <ClientSI Header> <TransactionID> <AMID>
+                                * <SubscriberID> <GateID> [<Event Generation Info>] <Gate-Spec>
+                                * <classifier> <classifier...>] <Traffic Profile> <Gate Time
+                                * Info> <Gate Usage Info> [<Volume-Based Usage Limit>] [<PSID>]
+                                * [<Msg-Receipt-Key>] [<UserID>] [<Time-Based Usage Limit>]
+                                * [<Opaque Data>] <GateState> [<SharedResourceID>]
+                                */
+                               if (responseTransactionID != null && responseTransactionID.getGateCommandType() == ITransactionID.GateInfoAck) {
+                                       // TODO need to implement missing data wrapper
+                                       logger.info("TransactionID : " + responseTransactionID.toString());
+                                       logger.info("AMID :" + String.valueOf(responseGate.getAMID()));
+                                       logger.info("SubscriberID :" + String.valueOf(responseGate.getSubscriberID()));
+                                       logger.info("Traffic Profile :" + String.valueOf(responseGate.getTrafficProfile()));
+                                       logger.info("Gate Time Info :");
+                                       logger.info("Gate Usage Info :");
+                                       logger.info("GateState :");
+                                       return true;
+                               }
+
+                       }
+                       return false;
+               }
+
+               /*
+                * (non-Javadoc)
+                * 
+                * @see org.pcmm.rcd.IPCMMPolicyServer#synchronize()
+                */
+               @Override
+               public boolean gateSynchronize() {
+                       if (!isConnected()) {
+                               logger.error("Not connected");
+                               return false;
+                       }
+                       ITransactionID trID = new TransactionID();
+                       // set transaction ID to gate set
+                       trID.setGateCommandType(ITransactionID.SynchRequest);
+                       trID.setTransactionIdentifier(transactionID);
+                       // AMID
+                       IAMID amid = getAMID();
+                       // GATE SPEC
+                       ISubscriberID subscriberID = new SubscriberID();
+                       try {
+                               subscriberID.setSourceIPAddress(InetAddress.getLocalHost());
+                       } catch (UnknownHostException e1) {
+                               logger.error(e1.getMessage());
+                       }
+                       IGateID gateIdObj = new GateID();
+                       gateIdObj.setGateID(gateID);
+
+                       IPCMMGate gate = new PCMMGateReq();
+                       gate.setTransactionID(trID);
+                       gate.setAMID(amid);
+                       gate.setSubscriberID(subscriberID);
+                       gate.setGateID(gateIdObj);
+
+                       // configure message properties
+                       Properties prop = new Properties();
+                       prop.put(MessageProperties.CLIENT_HANDLE, getClientHandle());
+                       prop.put(MessageProperties.DECISION_CMD_CODE, COPSDecision.DEC_INSTALL);
+                       prop.put(MessageProperties.DECISION_FLAG, (short) COPSDecision.DEC_NULL);
+                       byte[] data = gate.getData();
+                       prop.put(MessageProperties.GATE_CONTROL, new COPSData(data, 0, data.length));
+                       COPSMsg decisionMsg = MessageFactory.getInstance().create(COPSHeader.COPS_OP_DEC, prop);
+                       // ** Send the GateSet Decision
+                       // **
+                       try {
+                               decisionMsg.writeData(getSocket());
+                       } catch (IOException e) {
+                               logger.error("Failed to send the decision, reason: " + e.getMessage());
+                               return false;
+                       }
+                       // waits for the gate-Info-ack or error
+                       COPSMsg responseMsg = readMessage();
+                       if (responseMsg.getHeader().isAReport()) {
+                               logger.info("processing received report from CMTS");
+                               COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
+                               if (reportMsg.getClientSI().size() == 0) {
+                                       return false;
+                               }
+                               COPSClientSI clientSI = (COPSClientSI) reportMsg.getClientSI().elementAt(0);
+                               IPCMMGate responseGate = new PCMMGateReq(clientSI.getData().getData());
+                               IPCMMError error = ((PCMMGateReq) responseGate).getError();
+                               ITransactionID responseTransactionID = responseGate.getTransactionID();
+                               if (error != null) {
+                                       logger.debug(responseTransactionID != null ? responseTransactionID.toString() : "returned Transaction ID is null");
+                                       logger.error(error.toString());
+                                       return false;
+                               }
+                               // here CMTS responded that he acknowledged the Gate-Info
+                               // message
+                               /*
+                                * <Gate-Info-Ack> = <ClientSI Header> <TransactionID> <AMID>
+                                * <SubscriberID> <GateID> [<Event Generation Info>] <Gate-Spec>
+                                * <classifier> <classifier...>] <Traffic Profile> <Gate Time
+                                * Info> <Gate Usage Info> [<Volume-Based Usage Limit>] [<PSID>]
+                                * [<Msg-Receipt-Key>] [<UserID>] [<Time-Based Usage Limit>]
+                                * [<Opaque Data>] <GateState> [<SharedResourceID>]
+                                */
+                               if (responseTransactionID != null && responseTransactionID.getGateCommandType() == ITransactionID.SynchReport) {
+                                       // TODO need to implement missing data wrapper
+                                       logger.info("TransactionID : " + responseTransactionID.toString());
+                                       logger.info("AMID :" + String.valueOf(responseGate.getAMID()));
+                                       logger.info("SubscriberID :" + String.valueOf(responseGate.getSubscriberID()));
+                                       logger.info("Traffic Profile :" + String.valueOf(responseGate.getTrafficProfile()));
+                                       logger.info("Gate Time Info :");
+                                       logger.info("Gate Usage Info :");
+                                       logger.info("GateState :");
+                                       return true;
+                               }
+
+                       }
+                       return false;
+               }
+
+               private IAMID getAMID() {
+                       IAMID amid = new AMID();
+                       amid.setApplicationType((short) 1);
+                       amid.setApplicationMgrTag((short) 1);
+                       return amid;
+               }
+
+               private IClassifier getClassifier(ISubscriberID subscriberID) {
+                       IClassifier classifier = null;
+                       // if the version major is less than 4 we need to use Classifier
+                       if (getVersionInfo().getMajorVersionNB() >= 4) {
+                               classifier = new ExtendedClassifier();
+                               // eclassifier.setProtocol(IClassifier.Protocol.NONE);
+                               classifier.setProtocol(IClassifier.Protocol.TCP);
+                               try {
+                                       InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
+                                       InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
+                                       InetAddress dstIP = InetAddress.getByName(PCMMGlobalConfig.dstIP);
+                                       InetAddress mask = InetAddress.getByName(PCMMProperties.get(PCMMConstants.DEFAULT_MASK, String.class));
+                                       subscriberID.setSourceIPAddress(subIP);
+                                       classifier.setSourceIPAddress(srcIP);
+                                       classifier.setDestinationIPAddress(dstIP);
+                                       ((IExtendedClassifier) classifier).setIPDestinationMask(mask);
+                                       ((IExtendedClassifier) classifier).setIPSourceMask(mask);
+                               } catch (UnknownHostException unae) {
+                                       System.out.println("Error getByName" + unae.getMessage());
+                               }
+                               ((IExtendedClassifier) classifier).setSourcePortStart(PCMMGlobalConfig.srcPort);
+                               ((IExtendedClassifier) classifier).setSourcePortEnd(PCMMGlobalConfig.srcPort);
+                               ((IExtendedClassifier) classifier).setDestinationPortStart(PCMMGlobalConfig.dstPort);
+                               ((IExtendedClassifier) classifier).setDestinationPortEnd(PCMMGlobalConfig.dstPort);
+                               ((IExtendedClassifier) classifier).setActivationState((byte) 0x01);
+                               /*
+                                * check if we have a stored value of classifierID else we just
+                                * create one eclassifier.setClassifierID((short) 0x01);
+                                */
+                               ((IExtendedClassifier) classifier).setClassifierID((short) (classifierID == 0 ? Math.random() * hashCode() : classifierID));
+                               // XXX - testie
+                               // eclassifier.setClassifierID((short) 1);
+                               ((IExtendedClassifier) classifier).setAction((byte) 0x00);
+                               // XXX - temp default until Gate Modify is hacked in
+                               // eclassifier.setPriority(PCMMGlobalConfig.EClassifierPriority);
+                               classifier.setPriority((byte) 65);
+
+                       } else {
+                               classifier = new Classifier();
+                               classifier.setProtocol(IClassifier.Protocol.TCP);
+                               try {
+                                       InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
+                                       InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
+                                       InetAddress dstIP = InetAddress.getByName(PCMMGlobalConfig.dstIP);
+                                       subscriberID.setSourceIPAddress(subIP);
+                                       classifier.setSourceIPAddress(srcIP);
+                                       classifier.setDestinationIPAddress(dstIP);
+                               } catch (UnknownHostException unae) {
+                                       System.out.println("Error getByName" + unae.getMessage());
+                               }
+                               classifier.setSourcePort(PCMMGlobalConfig.srcPort);
+                               classifier.setDestinationPort(PCMMGlobalConfig.dstPort);
+                       }
+                       return classifier;
+               }
+
+               /**
+                * 
+                * @return GateSpec object
+                */
+               private IGateSpec getGateSpec() {
+                       IGateSpec gateSpec = new GateSpec();
+                       gateSpec.setDirection(Direction.UPSTREAM);
+                       gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE);
+                       gateSpec.setTimerT1(PCMMGlobalConfig.GateT1);
+                       gateSpec.setTimerT2(PCMMGlobalConfig.GateT2);
+                       gateSpec.setTimerT3(PCMMGlobalConfig.GateT3);
+                       gateSpec.setTimerT4(PCMMGlobalConfig.GateT4);
+                       return gateSpec;
+               }
+
+               /**
+                * creates a traffic profile with 3 envelops (Authorized, Reserved and
+                * Committed).
+                * 
+                * @return Traffic profile
+                */
+               private ITrafficProfile buildTrafficProfile() {
+                       ITrafficProfile trafficProfile = new BestEffortService(BestEffortService.DEFAULT_ENVELOP);
+                       ((BestEffortService) trafficProfile).getAuthorizedEnvelop().setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+                       ((BestEffortService) trafficProfile).getAuthorizedEnvelop().setMaximumTrafficBurst(BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+                       ((BestEffortService) trafficProfile).getAuthorizedEnvelop().setRequestTransmissionPolicy(PCMMGlobalConfig.BETransmissionPolicy);
+                       ((BestEffortService) trafficProfile).getAuthorizedEnvelop().setMaximumSustainedTrafficRate(PCMMGlobalConfig.DefaultLowBestEffortTrafficRate);
+                       // PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+                       ((BestEffortService) trafficProfile).getReservedEnvelop().setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+                       ((BestEffortService) trafficProfile).getReservedEnvelop().setMaximumTrafficBurst(BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+                       ((BestEffortService) trafficProfile).getReservedEnvelop().setRequestTransmissionPolicy(PCMMGlobalConfig.BETransmissionPolicy);
+                       ((BestEffortService) trafficProfile).getReservedEnvelop().setMaximumSustainedTrafficRate(PCMMGlobalConfig.DefaultLowBestEffortTrafficRate);
+                       // PCMMGlobalConfig.DefaultBestEffortTrafficRate);
+
+                       ((BestEffortService) trafficProfile).getCommittedEnvelop().setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY);
+                       ((BestEffortService) trafficProfile).getCommittedEnvelop().setMaximumTrafficBurst(BestEffortService.DEFAULT_MAX_TRAFFIC_BURST);
+                       ((BestEffortService) trafficProfile).getCommittedEnvelop().setRequestTransmissionPolicy(PCMMGlobalConfig.BETransmissionPolicy);
+                       ((BestEffortService) trafficProfile).getCommittedEnvelop().setMaximumSustainedTrafficRate(PCMMGlobalConfig.DefaultLowBestEffortTrafficRate);
+                       return trafficProfile;
+               }
+
+               @Override
+               public short getClassifierId() {
+                       return classifierID;
+               }
+
+               @Override
+               public short getTransactionId() {
+                       return transactionID;
+               }
+
+               @Override
+               public int getGateId() {
+                       return gateID;
+               }
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/package-info.java b/packetcable-driver/src/main/java/org/pcmm/rcd/package-info.java
new file mode 100644 (file)
index 0000000..0d21830
--- /dev/null
@@ -0,0 +1,11 @@
+
+/**
+ * <p>
+ * The Resource Control Domain (RCD) may be defined as a logical grouping of elements that provide connectivity and network resource level policy management along the packet forwarding paths to and from an end host.
+ * The RCD consists of CMTS and Policy Server entities whose responsibilities include management of resources along the packet forwarding paths.
+ * </p>
+ *
+ *
+ */
+package org.pcmm.rcd;
+
diff --git a/packetcable-driver/src/main/java/org/pcmm/scd/IApplicationServer.java b/packetcable-driver/src/main/java/org/pcmm/scd/IApplicationServer.java
new file mode 100644 (file)
index 0000000..a0862b3
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ @header@
+ */
+
+package org.pcmm.scd;
+
+/**
+ * <p>
+ * The Application Server is a network entity that interfaces with the
+ * Application Manager that requests PacketCable Multimedia services on behalf
+ * of clients. The AS may reside on the MSO's network or it may reside outside
+ * of this domain and interact with the MSO network via a particular trust
+ * relationship. Similarly, the AS may be under direct control of the operator
+ * or it may be controlled by a third-party. Any given AS may communicate with
+ * one or more Application Managers.
+ * </p>
+ * <p>
+ * The AS will communicate with a client via a signaling protocol that is
+ * outside the scope of this specification. Using this unspecified protocol, the
+ * Domain policies. For client requests that pass these checks, the AS
+ * determines the particular QoS parameters necessary to deliver the service to
+ * the client, based upon its knowledge of the requested service. It then sends
+ * a request for these resources to the appropriate Application Manager, which
+ * may deny the request based upon additional Service Control Domain policies or
+ * may pass the request on to the Policy Server.
+ * </p>
+ * 
+ * 
+ */
+public interface IApplicationServer {
+
+       /**
+        * sets the Application Server's id
+        * 
+        * @param id
+        *            : the id of the AS
+        */
+       void setASId(String id);
+
+       /**
+        * gets the AS id
+        * 
+        * @return AS id
+        */
+       String getASId();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/scd/impl/package-info.java b/packetcable-driver/src/main/java/org/pcmm/scd/impl/package-info.java
new file mode 100644 (file)
index 0000000..41213d0
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ *
+ */
+/**
+ *
+ */
+package org.pcmm.scd.impl;
diff --git a/packetcable-driver/src/main/java/org/pcmm/scd/package-info.java b/packetcable-driver/src/main/java/org/pcmm/scd/package-info.java
new file mode 100644 (file)
index 0000000..b6c8651
--- /dev/null
@@ -0,0 +1,10 @@
+/**
+ * <p>
+ * The Service Control Domain (SCD) is defined as a logical grouping of elements that offer applications and content to service subscribers.
+ * The Application Manager resides in the SCD. Note that there may be one or more SCDs related to a single RCD. Conversely, each RCD may interact with one or more SCDs.
+ * </p>
+ *
+ *
+ */
+package org.pcmm.scd;
+
diff --git a/packetcable-driver/src/main/java/org/pcmm/state/IPCMMRecordKeepingServer.java b/packetcable-driver/src/main/java/org/pcmm/state/IPCMMRecordKeepingServer.java
new file mode 100644 (file)
index 0000000..b4d4f1f
--- /dev/null
@@ -0,0 +1,11 @@
+/**
+ @header@
+ */
+package org.pcmm.state;
+
+/**
+ *
+ */
+public interface IPCMMRecordKeepingServer {
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/state/IState.java b/packetcable-driver/src/main/java/org/pcmm/state/IState.java
new file mode 100644 (file)
index 0000000..5f3cb6e
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.state;
+
+/**
+ * <p>
+ * Object serving as a state holder, each stateful server should keep record of
+ * clients' state
+ * </p>
+ *
+ *
+ *
+ */
+public interface IState {
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/state/IStateful.java b/packetcable-driver/src/main/java/org/pcmm/state/IStateful.java
new file mode 100644 (file)
index 0000000..e0a64f7
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ @header@
+ */
+
+
+package org.pcmm.state;
+
+/**
+ * <p>
+ * Each stateful server should implement this interface, to be able to save and
+ * retrieve clients' state
+ * </p>
+ *
+ *
+ *
+ */
+public interface IStateful {
+
+    /**
+     * records the collected client state
+     */
+    void recordState();
+
+    /**
+     *
+     * @return recorded state.
+     */
+    IState getRecoredState();
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/state/package-info.java b/packetcable-driver/src/main/java/org/pcmm/state/package-info.java
new file mode 100644 (file)
index 0000000..76b19c0
--- /dev/null
@@ -0,0 +1,4 @@
+/**
+ */
+package org.pcmm.state;
+
diff --git a/packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java b/packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java
new file mode 100644 (file)
index 0000000..01e23e4
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ @header@
+ */
+
+package org.pcmm.utils;
+
+import org.pcmm.gates.IPCMMError;
+
+/**
+ * Defines the Exception that could be thrown by the API.
+ * 
+ */
+public class PCMMException extends Exception {
+
+       public PCMMException(IPCMMError error) {
+               this(error.getDescription(), error.getErrorCode());
+       }
+
+       public PCMMException(String message, int code) {
+               super("error code [" + code + "]" + message);
+       }
+
+}
diff --git a/packetcable-driver/src/main/java/org/pcmm/utils/PCMMUtils.java b/packetcable-driver/src/main/java/org/pcmm/utils/PCMMUtils.java
new file mode 100644 (file)
index 0000000..4762370
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ @header@
+ */
+package org.pcmm.utils;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class PCMMUtils {
+
+    public static void WriteBinaryDump(String rootFileName, byte[] buffer) {
+        // Make this Unique
+        String fileName = "/tmp/" + rootFileName + "-" + java.util.UUID.randomUUID() + ".bin";
+        try {
+
+            System.out.println("Open fileName " + fileName);
+            FileOutputStream outputStream = new FileOutputStream(fileName);
+
+            // write() writes as many bytes from the buffer
+            // as the length of the buffer. You can also
+            // use
+            // write(buffer, offset, length)
+            // if you want to write a specific number of
+            // bytes, or only part of the buffer.
+            outputStream.write(buffer);
+
+            // Always close files.
+            outputStream.close();
+
+            System.out.println("Wrote " + buffer.length + " bytes");
+        } catch (IOException ex) {
+            System.out.println("Error writing file '" + fileName + "'");
+            // Or we could just do this:
+            // ex.printStackTrace();
+        }
+    }
+
+    public static byte[] ReadBinaryDump(String fileName) {
+        // The name of the file to open.
+        // String fileName = "COPSReportMessage.txt";
+        try {
+            FileInputStream inputStream = new FileInputStream(fileName);
+            // Use this for reading the data.
+            byte[] buffer = new byte[inputStream.available()];
+            // read fills buffer with data and returns
+            // the number of bytes read (which of course
+            // may be less than the buffer size, but
+            // it will never be more).
+            int total = inputStream.read(buffer);
+
+            // Always close files.
+            inputStream.close();
+
+            System.out.println("Read " + total + " bytes");
+            return buffer;
+        } catch (FileNotFoundException ex) {
+            System.out.println("Unable to open file '" + fileName + "'");
+        } catch (IOException ex) {
+            System.out.println("Error reading file '" + fileName + "'");
+            // Or we could just do this:
+            // ex.printStackTrace();
+        }
+        return null;
+    }
+}
diff --git a/packetcable-driver/src/main/java/org/umu/cops/common/COPSDebug.java b/packetcable-driver/src/main/java/org/umu/cops/common/COPSDebug.java
new file mode 100644 (file)
index 0000000..400eeb0
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+package org.umu.cops.common;\r
+\r
+import java.io.PrintStream;\r
+\r
+/**\r
+ * Class to print debug and error messages.\r
+ *\r
+ * @version COPSDebug.java, v 3.00 2004\r
+ *\r
+ */\r
+public class COPSDebug {\r
+\r
+    static public final String ERROR_NOEXPECTEDMSG = "Message not expected";\r
+    static public final String ERROR_EXCEPTION = "Exception not expected";\r
+    static public final String ERROR_SOCKET = "Error socket";\r
+    static public final String ERROR_NOSUPPORTED = "Object not supported";\r
+\r
+    static public PrintStream _err = System.err;\r
+\r
+    /** Prints an error message.\r
+        *\r
+        * @param          cname           Name of class that generated the error\r
+     * @param          str                Error message\r
+     *\r
+       */\r
+    public static void err (String cname, String str) {\r
+        if (_err != null)\r
+            _err.println(cname + ":" + str);\r
+    }\r
+\r
+    /** Prints an error message.\r
+        *\r
+        * @param          cname           Name of class that generated the error\r
+     * @param          str                Error message\r
+     * @param           e                  Exception\r
+     *\r
+       */\r
+    public static void err (String cname, String str, Exception e) {\r
+        if (_err != null) {\r
+            _err.println(cname + ":" + str);\r
+            _err.println(" -Reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /** Prints an error message.\r
+        *\r
+        * @param          cname           Name of class that generated the error\r
+     * @param          str                Error message\r
+     * @param          extra           Information\r
+     * @param           e                  Exception\r
+     *\r
+       */\r
+    public static void err (String cname, String str, String extra, Exception e) {\r
+        if (_err != null) {\r
+            _err.println(cname + ":" + str);\r
+            _err.println(" -Info: " + extra);\r
+            _err.println(" -Reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /** Prints an error message.\r
+        *\r
+        * @param          cname           Name of class that generated the error\r
+     * @param          str                Error message\r
+     * @param          extra           Information\r
+     *\r
+       */\r
+    public static void err (String cname, String str, String extra) {\r
+        if (_err != null) {\r
+            _err.println(cname + ":" + str);\r
+            _err.println(" -Info: " + extra);\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/common/COPS_def.java b/packetcable-driver/src/main/java/org/umu/cops/common/COPS_def.java
new file mode 100644 (file)
index 0000000..654bd9a
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+package org.umu.cops.common;\r
+\r
+/**\r
+ * Class containing keywords supported by the client types.\r
+ *\r
+ * @version COPS_def.java, v 2.00 2004\r
+ *\r
+ */\r
+public class COPS_def {\r
+\r
+    /** COPS Client Type for RSVP\r
+     */\r
+    public final static short C_RSVP = 1;\r
+\r
+    /** COPS Client Type for SIP\r
+     */\r
+    public final static short C_SIP = 100;\r
+\r
+    /** COPS Client Type for IPSec\r
+     */\r
+    public final static short C_IPSEC = (short) 0x8001;\r
+\r
+    /** Maximum COPS Client Type\r
+     */\r
+    public final static short C_MAX = (short) 0xFFFF;\r
+\r
+    /** Get a representative string for an COPS Client Type.\r
+        *\r
+        * @param     cType    COPS Client Type\r
+     * @return A representative <tt>String</tt>\r
+     *\r
+       */\r
+    public String strClientType(short cType) {\r
+        switch (cType) {\r
+        case C_RSVP:\r
+            return ("C_RSVP");\r
+        case C_SIP:\r
+            return ("C_SIP");\r
+        case C_IPSEC:\r
+            return ("C_IPSEC");\r
+        default:\r
+            return "Unknown";\r
+        }\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpException.java b/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpException.java
new file mode 100644 (file)
index 0000000..9375888
--- /dev/null
@@ -0,0 +1,47 @@
+/*\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.ospdp;\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
+\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
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSAgent.java b/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSAgent.java
new file mode 100644 (file)
index 0000000..354bf76
--- /dev/null
@@ -0,0 +1,317 @@
+package org.umu.cops.ospdp;\r
+\r
+import java.io.IOException;\r
+import java.net.ServerSocket;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.stack.COPSAcctTimer;\r
+import org.umu.cops.stack.COPSClientAcceptMsg;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSClientOpenMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKATimer;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * Core PDP agent for outsourcing.\r
+ */\r
+public class COPSPdpOSAgent extends Thread {\r
+    /** Well-known port for COPS */\r
+    public static final int WELL_KNOWN_PDP_PORT = 3288;\r
+    /** Default keep-alive timer value (secs) */\r
+    public static final short KA_TIMER_VALUE = 30;\r
+    /** Default accounting timer value (secs) */\r
+    public static final short ACCT_TIMER_VALUE = 0;\r
+\r
+    /**\r
+        PDP host IP\r
+     */\r
+    private ServerSocket _serverSocket;\r
+\r
+    /**\r
+        PDP host port\r
+     */\r
+    private int _serverPort;\r
+\r
+    /**\r
+        Client-type of connecting PEP\r
+     */\r
+    private short _clientType;\r
+\r
+    /**\r
+        Accounting timer (secs)\r
+     */\r
+    private short _acctTimer;\r
+\r
+    /**\r
+        Keep-alive timer (secs)\r
+     */\r
+    private short _kaTimer;\r
+\r
+    /**\r
+        Maps a PEP-ID to a connection\r
+     */\r
+    private Hashtable _connectionMap;\r
+    // map < String(PEPID), COPSPdpOSConnection > ConnectionMap;\r
+\r
+    /**\r
+     *  Policy data processing object\r
+     */\r
+    private COPSPdpOSDataProcess _process;\r
+\r
+    /**\r
+     * Creates a PDP Agent\r
+     *\r
+     * @param clientType    COPS Client-type\r
+     * @param process       Object to perform policy data processing\r
+     */\r
+    public COPSPdpOSAgent(short clientType, COPSPdpOSDataProcess process) {\r
+        _serverPort = WELL_KNOWN_PDP_PORT;\r
+        _kaTimer = KA_TIMER_VALUE;\r
+        _acctTimer = ACCT_TIMER_VALUE;\r
+\r
+        _clientType = clientType;\r
+        _connectionMap = new Hashtable(40);\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Creates a PDP Agent\r
+     *\r
+     * @param port  Port to listen to\r
+     * @param clientType    COPS Client-type\r
+     * @param process   Object to perform policy data processing\r
+     */\r
+    public COPSPdpOSAgent(int port, short clientType, COPSPdpOSDataProcess process) {\r
+        _serverPort = port;\r
+\r
+        _kaTimer = KA_TIMER_VALUE;\r
+        _acctTimer = ACCT_TIMER_VALUE;\r
+\r
+        _clientType = clientType;\r
+        _connectionMap = new Hashtable(40);\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Sets the keep-alive timer value\r
+     * @param    kaTimer    Keep alive timer value (secs)\r
+     */\r
+    public void setKaTimer (short kaTimer) {\r
+        _kaTimer = kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Sets the accounting timer value\r
+     * @param    acctTimer  Accounting timer value (secs)\r
+     */\r
+    public void setAcctTimer (short acctTimer) {\r
+        _acctTimer = acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the value of the keep-alive timer\r
+     * @return   Keep-alive timer value (secs)\r
+     */\r
+    public short getKaTimer () {\r
+        return _kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the accounting timer value\r
+     * @return   Accounting timer value (secs)\r
+     */\r
+    public short getAcctTimer () {\r
+        return _acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the PEPs connected to this PDP\r
+     * @return   An <tt>Enumeration</tt> of all connected PEPs\r
+     */\r
+    public Enumeration getConnectedPEPIds() {\r
+        return _connectionMap.keys();\r
+    }\r
+\r
+    /**\r
+     * Gets the connection map\r
+     * @return   A <tt>Hashtable</tt> holding the connection map\r
+     */\r
+    public Hashtable getConnectionMap() {\r
+        return _connectionMap;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   The client-type\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Disconnects a PEP\r
+     * @param pepID PEP-ID of the PEP to be disconnected\r
+     * @param error COPS Error to be reported as a reason\r
+     * @throws COPSException\r
+     * @throws IOException\r
+     */\r
+    public void disconnect (String pepID, COPSError error) throws COPSException, IOException {\r
+        COPSPdpOSConnection pdpConn = (COPSPdpOSConnection) _connectionMap.get(pepID);\r
+\r
+        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
+        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+        closeMsg.add(cHdr);\r
+        if (error != null)\r
+            closeMsg.add(error);\r
+\r
+        closeMsg.writeData(pdpConn.getSocket());\r
+        pdpConn.close();\r
+        pdpConn = null;\r
+    }\r
+\r
+    /**\r
+     * Requests a COPS sync for a PEP\r
+     * @param pepID PEP-ID of the PEP to be synced\r
+     * @throws COPSException\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sync(String pepID) throws COPSException, COPSPdpException {\r
+        COPSPdpOSConnection pdpConn = (COPSPdpOSConnection) _connectionMap.get(pepID);\r
+        pdpConn.syncAllRequestState();\r
+    }\r
+\r
+    /**\r
+     * Removes a PEP from the connection map\r
+     * @param pepID PEP-ID of the PEP to be removed\r
+     */\r
+    public void delete (String pepID) {\r
+        _connectionMap.remove(pepID);\r
+    }\r
+\r
+    /**\r
+     * Runs the PDP process\r
+     */\r
+    public void run() {\r
+        try {\r
+            _serverSocket = new ServerSocket (_serverPort);\r
+\r
+            //Loop through for Incoming messages\r
+\r
+            // server infinite loop\r
+            while (true) {\r
+                // Wait for an incoming connection from a PEP\r
+                Socket socket = _serverSocket.accept();\r
+\r
+                // COPSDebug.out(getClass().getName(),"New connection accepted " +\r
+                //           socket.getInetAddress() +\r
+                //           ":" + socket.getPort());\r
+\r
+                // We're waiting for an OPN message\r
+                try {\r
+                    COPSMsg msg = COPSTransceiver.receiveMsg(socket);\r
+                    if (msg.getHeader().isAClientOpen()) {\r
+                        handleClientOpenMsg(socket, msg);\r
+                    } else {\r
+                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+                        try {\r
+                            socket.close();\r
+                        } catch (Exception ex) {};\r
+                    }\r
+                } catch (Exception e) { // COPSException, IOException\r
+                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,\r
+                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);\r
+                    try {\r
+                        socket.close();\r
+                    } catch (Exception ex) {};\r
+                }\r
+            }\r
+        } catch (IOException e) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+            return;\r
+        }\r
+    }\r
+\r
+    /**\r
+      * Handles a COPS client-open message\r
+      * @param    conn Socket to the PEP\r
+      * @param    msg <tt>COPSMsg</tt> holding the client-open message\r
+      * @throws COPSException\r
+      * @throws IOException\r
+      */\r
+    private void handleClientOpenMsg(Socket conn, COPSMsg msg) throws COPSException, IOException {\r
+        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;\r
+        COPSPepId pepId = cMsg.getPepId();\r
+\r
+        // Validate Client Type\r
+        if (msg.getHeader().getClientType() != _clientType) {\r
+            // Unsupported client type\r
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
+            COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);\r
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+            closeMsg.add(cHdr);\r
+            closeMsg.add(err);\r
+            try {\r
+                closeMsg.writeData(conn);\r
+            } catch (IOException unae) {}\r
+\r
+            throw new COPSException("Unsupported client type");\r
+        }\r
+\r
+        // PEPId is mandatory\r
+        if (pepId == null) {\r
+            // Mandatory COPS object missing\r
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
+            COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);\r
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+            closeMsg.add(cHdr);\r
+            closeMsg.add(err);\r
+            try {\r
+                closeMsg.writeData(conn);\r
+            } catch (IOException unae) {}\r
+\r
+            throw new COPSException("Mandatory COPS object missing (PEPId)");\r
+        }\r
+\r
+        // Support\r
+        if ( (cMsg.getClientSI() != null) ||\r
+                (cMsg.getPdpAddress() != null) ||\r
+                (cMsg.getIntegrity() != null)) {\r
+\r
+            // Unsupported objects\r
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
+            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);\r
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+            closeMsg.add(cHdr);\r
+            closeMsg.add(err);\r
+            try {\r
+                closeMsg.writeData(conn);\r
+            } catch (IOException unae) {}\r
+\r
+            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");\r
+        }\r
+\r
+        // Connection accepted\r
+        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());\r
+        COPSKATimer katimer = new COPSKATimer(_kaTimer);\r
+        COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);\r
+        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();\r
+        acceptMsg.add(ahdr);\r
+        acceptMsg.add(katimer) ;\r
+        if (_acctTimer != 0) acceptMsg.add(acctTimer);\r
+        acceptMsg.writeData(conn);\r
+\r
+        COPSPdpOSConnection pdpConn = new COPSPdpOSConnection(pepId, conn, _process);\r
+        pdpConn.setKaTimer(_kaTimer);\r
+        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);\r
+        new Thread(pdpConn).start();\r
+        _connectionMap.put(pepId.getData().str(),pdpConn);\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSConnection.java b/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSConnection.java
new file mode 100644 (file)
index 0000000..39890b7
--- /dev/null
@@ -0,0 +1,544 @@
+package org.umu.cops.ospdp;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Date;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKAMsg;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * Class for managing an outsourcing connection at the PDP side.\r
+ */\r
+public class COPSPdpOSConnection implements Runnable {\r
+    /**\r
+        Socket connected to PEP\r
+     */\r
+    private Socket _sock;\r
+\r
+    /**\r
+        PEP identifier\r
+    */\r
+    private COPSPepId _pepId;\r
+\r
+    /**\r
+        Time of the latest keep-alive sent\r
+     */\r
+    private Date _lastKa;\r
+\r
+    /**\r
+        Opcode of the latest message sent\r
+    */\r
+    private byte _lastmessage;\r
+\r
+    /**\r
+     *  Time of the latest keep-alive received\r
+     */\r
+    protected Date _lastRecKa;\r
+\r
+    /**\r
+        Maps a Client Handle to a Handler\r
+     */\r
+    protected Hashtable _managerMap;\r
+    // map < String(COPSHandle), COPSPdpHandler> HandlerMap;\r
+\r
+    /**\r
+     *  PDP policy data processor class\r
+     */\r
+    protected COPSPdpOSDataProcess _process;\r
+\r
+    /**\r
+        Accounting timer value (secs)\r
+     */\r
+    protected short _acctTimer;\r
+\r
+    /**\r
+        Keep-alive timer value (secs)\r
+     */\r
+    protected short _kaTimer;\r
+\r
+    /**\r
+        COPS error returned by PEP\r
+     */\r
+    protected COPSError _error;\r
+\r
+    /**\r
+     * Creates a new PDP connection\r
+     *\r
+     * @param pepId PEP-ID of the connected PEP\r
+     * @param sock  Socket connected to PEP\r
+     * @param process   Object for processing policy data\r
+     */\r
+    public COPSPdpOSConnection(COPSPepId pepId, Socket sock, COPSPdpOSDataProcess process) {\r
+        _sock = sock;\r
+        _pepId = pepId;\r
+\r
+        _lastKa = new Date();\r
+        _lastmessage = COPSHeader.COPS_OP_OPN;\r
+        _managerMap = new Hashtable(20);\r
+\r
+        _kaTimer = 0;\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Gets the time of that latest keep-alive sent\r
+     * @return Time of that latest keep-alive sent\r
+     */\r
+    public Date getLastKAlive() {\r
+        return _lastKa;\r
+    }\r
+\r
+    /**\r
+     * Sets the keep-alive timer value\r
+     * @param kaTimer Keep-alive timer value (secs)\r
+     */\r
+    public void setKaTimer(short kaTimer) {\r
+        _kaTimer = kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the keep-alive timer value\r
+     * @return Keep-alive timer value (secs)\r
+     */\r
+    public short getKaTimer() {\r
+        return _kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Sets the accounting timer value\r
+     * @param acctTimer Accounting timer value (secs)\r
+     */\r
+    public void setAccTimer(short acctTimer) {\r
+        _acctTimer = acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the accounting timer value\r
+     * @return Accounting timer value (secs)\r
+     */\r
+    public short getAcctTimer() {\r
+        return _acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the latest COPS message\r
+     * @return   Code of the latest message sent\r
+     */\r
+    public byte getLastMessage() {\r
+        return _lastmessage;\r
+    }\r
+\r
+    /**\r
+     * Gets active handles\r
+     * @return   An <tt>Enumeration</tt> holding all active handles\r
+     */\r
+    public Enumeration getHandles() {\r
+        return _managerMap.keys();\r
+    }\r
+\r
+    /**\r
+     * Gets the handle map\r
+     * @return   A <tt>Hashtable</tt> holding the handle map\r
+     */\r
+    public Hashtable getReqStateMans() {\r
+        return _managerMap;\r
+    }\r
+\r
+    /**\r
+     * Gets the PEP-ID\r
+     * @return   The ID of the PEP, as a <tt>String</tt>\r
+     */\r
+    public String getPepId() {\r
+        return _pepId.getData().str();\r
+    }\r
+\r
+    /**\r
+     * Checks whether the socket to the PEP is closed or not\r
+     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise\r
+     */\r
+    public boolean isClosed() {\r
+        return _sock.isClosed();\r
+    }\r
+\r
+    /**\r
+     * Closes the socket to the PEP\r
+     * @throws IOException\r
+     */\r
+    protected void close()\r
+    throws IOException {\r
+        _sock.close();\r
+    }\r
+\r
+    /**\r
+     * Gets the socket to the PEP\r
+     * @return   Socket connected to the PEP\r
+     */\r
+    public Socket getSocket() {\r
+        return _sock;\r
+    }\r
+\r
+    /**\r
+     * Main loop\r
+     */\r
+    public void run () {\r
+        Date _lastSendKa = new Date();\r
+        _lastRecKa = new Date();\r
+        try {\r
+            while (!_sock.isClosed()) {\r
+                if (_sock.getInputStream().available() != 0) {\r
+                    _lastmessage = processMessage(_sock);\r
+                    _lastRecKa = new Date();\r
+                }\r
+\r
+                // Keep Alive\r
+                if (_kaTimer > 0) {\r
+                    // Timeout at PDP\r
+                    int _startTime = (int) (_lastRecKa.getTime());\r
+                    int cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
+                        _sock.close();\r
+                        // Notify all Request State Managers\r
+                        notifyNoKAAllReqStateMan();\r
+                    }\r
+\r
+                    // Send to PEP\r
+                    _startTime = (int) (_lastSendKa.getTime());\r
+                    cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > ((_kaTimer*3/4)*1000)) {\r
+                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
+                        COPSKAMsg msg = new COPSKAMsg();\r
+\r
+                        msg.add(hdr);\r
+\r
+                        COPSTransceiver.sendMsg(msg, _sock);\r
+                        _lastSendKa = new Date();\r
+                    }\r
+                }\r
+\r
+                try {\r
+                    Thread.sleep(500);\r
+                } catch (Exception e) {};\r
+\r
+            }\r
+        } catch (Exception e) {\r
+            e.printStackTrace();\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+        }\r
+\r
+        // connection closed by server\r
+        // COPSDebug.out(getClass().getName(),"Connection closed by client");\r
+        try {\r
+            _sock.close();\r
+        } catch (IOException e) {};\r
+\r
+        // Notify all Request State Managers\r
+        try {\r
+            notifyCloseAllReqStateMan();\r
+        } catch (COPSPdpException e) {};\r
+    }\r
+\r
+    /**\r
+     * Gets a COPS message from the socket and processes it\r
+     * @param    conn Socket connected to the PEP\r
+     * @return Type of COPS message\r
+     */\r
+    private byte processMessage(Socket conn)\r
+    throws COPSPdpException, COPSException, IOException {\r
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
+\r
+        if (msg.getHeader().isAClientClose()) {\r
+            handleClientCloseMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_CC;\r
+        } else if (msg.getHeader().isAKeepAlive()) {\r
+            handleKeepAliveMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_KA;\r
+        } else if (msg.getHeader().isARequest()) {\r
+            handleRequestMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_REQ;\r
+        } else if (msg.getHeader().isAReport()) {\r
+            handleReportMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_RPT;\r
+        } else if (msg.getHeader().isADeleteReq()) {\r
+            handleDeleteRequestMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_DRQ;\r
+        } else if (msg.getHeader().isASyncComplete()) {\r
+            handleSyncComplete(conn, msg);\r
+            return COPSHeader.COPS_OP_SSC;\r
+        } else {\r
+            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Handle Client Close Message, close the passed connection\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     *\r
+     * <Client-Close> ::= <Common Header>\r
+     *                      <Error>\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     */\r
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
+        _error = cMsg.getError();\r
+\r
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
+\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+            }\r
+\r
+            conn.close();\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Gets the occurred COPS Error\r
+     * @return   <tt>COPSError</tt> object\r
+     */\r
+    protected COPSError getError()  {\r
+        return _error;\r
+    }\r
+\r
+    /**\r
+     * Handle Keep Alive Message\r
+     *\r
+     * <Keep-Alive> ::= <Common Header>\r
+     *                  [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
+        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
+\r
+        COPSKAMsg kaMsg = (COPSKAMsg) msg;\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+            }\r
+\r
+            kaMsg.writeData(conn);\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Handle Delete Request Message\r
+     *\r
+     * <Delete Request> ::= <Common Header>\r
+     *                      <Client Handle>\r
+     *                      <Reason>\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;\r
+        // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        // Delete clientHandler\r
+        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {\r
+            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +\r
+            //  cMsg.getClientHandle().getId().getData());\r
+        }\r
+\r
+        COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processDeleteRequestState(cMsg);\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * Handle Request Message\r
+     *\r
+     * <Request> ::= <Common Header>\r
+     *                  <Client Handle>\r
+     *                  <Context>\r
+     *                  *(<Named ClientSI>)\r
+     *                  [<Integrity>]\r
+     * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {\r
+        COPSReqMsg reqMsg = (COPSReqMsg) msg;\r
+        COPSContext cntxt = reqMsg.getContext();\r
+        COPSHeader header = reqMsg.getHeader();\r
+        //short reqType = cntxt.getRequestType();\r
+        short cType   = header.getClientType();\r
+\r
+        // Support\r
+        if (reqMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        COPSPdpOSReqStateMan man;\r
+        man = (COPSPdpOSReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle().getId().str());\r
+            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);\r
+            man.setDataProcess(_process);\r
+            man.initRequestState(_sock);\r
+\r
+            // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +\r
+            //    header.getClientType() + " msgType=" +\r
+            //    cntxt.getMessageType() + ", connId=" + conn.toString());\r
+        }\r
+\r
+        man.processRequest(reqMsg);\r
+    }\r
+\r
+    /**\r
+     * Handle Report Message\r
+     *\r
+     * <Report State> ::= <Common Header>\r
+     *                      <Client Handle>\r
+     *                      <Report Type>\r
+     *                      *(<Named ClientSI>)\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleReportMsg(Socket conn, COPSMsg msg) throws COPSPdpException {\r
+        COPSReportMsg repMsg = (COPSReportMsg) msg;\r
+        // COPSHandle handle = repMsg.getClientHandle();\r
+        // COPSHeader header = repMsg.getHeader();\r
+\r
+        // Support\r
+        if (repMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processReport(repMsg);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Method handleSyncComplete\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleSyncComplete(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
+        // COPSHandle handle = cMsg.getClientHandle();\r
+        // COPSHeader header = cMsg.getHeader();\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processSyncComplete(cMsg);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Requests a COPS sync from the PEP\r
+     * @throws COPSException\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void syncAllRequestState()\r
+    throws COPSException, COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);\r
+\r
+                man.syncRequestState();\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyCloseAllReqStateMan()\r
+    throws COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processClosedConnection(_error);\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyNoKAAllReqStateMan()\r
+    throws COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processNoKAConnection();\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSDataProcess.java b/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSDataProcess.java
new file mode 100644 (file)
index 0000000..4a5e438
--- /dev/null
@@ -0,0 +1,78 @@
+package org.umu.cops.ospdp;\r
+\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSError;\r
+\r
+/**\r
+ * Abstract class for implementing policy data processing classes for outsourcing PDPs.\r
+ */\r
+abstract public class COPSPdpOSDataProcess {\r
+    /**\r
+     * Gets the policies to be uninstalled\r
+     * @param man   The associated request state manager\r
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
+     */\r
+    abstract public Vector getRemovePolicy(COPSPdpOSReqStateMan man);\r
+    /**\r
+     * Gets the policies to be installed\r
+     * @param man   The associated request state manager\r
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
+     */\r
+    abstract public Vector getInstallPolicy(COPSPdpOSReqStateMan man);\r
+    /**\r
+     * Makes a decision from the supplied request data\r
+     * @param man   The associated request state manager\r
+     * @param reqSIs    Client specific data suppplied in the COPS request\r
+     */\r
+    abstract public void setClientData(COPSPdpOSReqStateMan man, Vector reqSIs);\r
+    /**\r
+     * Builds a failure report\r
+     * @param man   The associated request state manager\r
+     * @param reportSIs Report data\r
+     */\r
+    abstract public void failReport (COPSPdpOSReqStateMan man, Vector reportSIs);\r
+    /**\r
+     * Builds a success report\r
+     * @param man   The associated request state manager\r
+     * @param reportSIs Report data\r
+     */\r
+    abstract public void successReport (COPSPdpOSReqStateMan man, Vector reportSIs);\r
+    /**\r
+     * Builds an accounting report\r
+     * @param man   The associated request state manager\r
+     * @param reportSIs Report data\r
+     */\r
+    abstract public void acctReport (COPSPdpOSReqStateMan man, Vector reportSIs);\r
+    /**\r
+     * Notifies that no accounting report has been received\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void notifyNoAcctReport (COPSPdpOSReqStateMan man);\r
+\r
+    /**\r
+     * Notifies a keep-alive timeout\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void notifyNoKAliveReceived (COPSPdpOSReqStateMan man);\r
+\r
+    /**\r
+      * Notifies that the connection has been closed\r
+      * @param man  The associated request state manager\r
+      * @param error Reason\r
+      */\r
+    public abstract void notifyClosedConnection (COPSPdpOSReqStateMan man, COPSError error);\r
+\r
+    /**\r
+     * Notifies that a request state has been deleted\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void notifyDeleteRequestState (COPSPdpOSReqStateMan man);\r
+\r
+    /**\r
+     * Notifies that a request state has been closed\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void closeRequestState(COPSPdpOSReqStateMan man);\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSMsgSender.java b/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSMsgSender.java
new file mode 100644 (file)
index 0000000..c341328
--- /dev/null
@@ -0,0 +1,288 @@
+package org.umu.cops.ospdp;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSDecision;\r
+import org.umu.cops.stack.COPSDecisionMsg;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * COPS message transceiver class for outsourcing connections at the PDP side.\r
+ */\r
+public class COPSPdpOSMsgSender {\r
+    /**\r
+     * Socket connected to PEP\r
+     */\r
+    protected Socket _sock;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     * COPS client handle used to uniquely identify a particular\r
+     * PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Creates a COPSPepMsgSender\r
+     *\r
+     * @param clientType        COPS client-type\r
+     * @param clientHandle      Client handle\r
+     * @param sock              Socket to the PEP\r
+     */\r
+    public COPSPdpOSMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
+        // COPS Handle\r
+        _handle = clientHandle;\r
+        _clientType = clientType;\r
+\r
+        _sock = sock;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return   Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Sends a decision message which was requested by the PEP\r
+     * @param removeDecs    Decisions to be removed\r
+     * @param installDecs   Decisions to be installed\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendSolicitedDecision(Vector removeDecs, Vector installDecs) throws COPSPdpException {\r
+        sendDecision(removeDecs, installDecs, true);\r
+    }\r
+\r
+    /**\r
+     * Sends a decision message which was not requested by the PEP\r
+     * @param removeDecs    Decisions to be removed\r
+     * @param installDecs   Decisions to be installed\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendUnsolicitedDecision(Vector removeDecs, Vector installDecs) throws COPSPdpException {\r
+        sendDecision(removeDecs, installDecs, false);\r
+    }\r
+\r
+    /**\r
+     * Sends a decision message to the PEP\r
+     * @param removeDecs    Decisions to be removed\r
+     * @param installDecs   Decisions to be installed\r
+     * @param solicited     <tt>true</tt> if the PEP requested this decision, <tt>false</tt> otherwise\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendDecision(Vector removeDecs, Vector installDecs, boolean solicited) throws COPSPdpException {\r
+        // Common Header holding the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+\r
+        if (solicited)\r
+            hdr.setFlag(COPSHeader.COPS_FLAG_SOLICITED);\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle handle = new COPSHandle();\r
+        handle.setId(getClientHandle().getId());\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(handle);\r
+\r
+            // Decisions (no flags supplied)\r
+            //  <Context>\r
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+\r
+            // Remove Decisions\r
+            //  <Decision: Flags>\r
+            if (removeDecs.size() > 0) {\r
+                COPSDecision rdec1 = new COPSDecision();\r
+                rdec1.setCmdCode(COPSDecision.DEC_REMOVE);\r
+\r
+                decisionMsg.addDecision(rdec1, cntxt);\r
+\r
+                Enumeration removeDecsEnum = removeDecs.elements();\r
+                while (removeDecsEnum.hasMoreElements())\r
+                    decisionMsg.addDecision((COPSDecision) removeDecsEnum.nextElement(), cntxt);\r
+            }\r
+\r
+            // Install Decisions\r
+            //  <Decision: Flags>\r
+            if (installDecs.size() > 0) {\r
+                COPSDecision idec1 = new COPSDecision();\r
+                idec1.setCmdCode(COPSDecision.DEC_INSTALL);\r
+\r
+                decisionMsg.addDecision(idec1, cntxt);\r
+\r
+                Enumeration installDecsEnum = installDecs.elements();\r
+                while (installDecsEnum.hasMoreElements())\r
+                    decisionMsg.addDecision((COPSDecision) installDecsEnum.nextElement(), cntxt);\r
+                /**\r
+                COPSIntegrity intr = new COPSIntegrity();\r
+                intr.setKeyId(19);\r
+                intr.setSeqNum(9);\r
+                intr.setKeyDigest(new COPSData("KEY DIGEST"));\r
+                decisionMsg.add(intr);\r
+                /**/\r
+            }\r
+        } catch (COPSException e) {\r
+            e.printStackTrace();\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        //** Send decision\r
+        //**\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**FIXME: unused?\r
+     * Sends a message asking that the request state be deleted\r
+     * @throws   COPSPdpException\r
+     */\r
+    public void sendDeleteRequestState() throws COPSPdpException {\r
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
+         *                          <Client Handle>\r
+         *                          *(<Decision>)\r
+         *                          [<Integrity>]\r
+         * <Decision> ::= <Context>\r
+         *                  <Decision: Flags>\r
+         * <Decision: Flags> ::= Remove Request-State\r
+         *\r
+        */\r
+\r
+        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = new COPSHandle();\r
+        clienthandle.setId(_handle.getId());\r
+\r
+        // Decisions\r
+        //  <Context>\r
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+        //  <Decision: Flags>\r
+        COPSDecision dec = new COPSDecision();\r
+        dec.setCmdCode(COPSDecision.DEC_REMOVE);\r
+        dec.setFlags(COPSDecision.F_REQSTATE);\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(clienthandle);\r
+            decisionMsg.addDecision(dec, cntxt);\r
+        } catch (COPSException e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Method sendOpenNewRequestState\r
+     *\r
+     * @throws   COPSPdpException\r
+     *\r
+     */\r
+    //FIXME: Unused?\r
+    public void sendOpenNewRequestState() throws COPSPdpException {\r
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
+         *                          <Client Handle>\r
+         *                          *(<Decision>)\r
+         *                          [<Integrity>]\r
+         * <Decision> ::= <Context>\r
+         *                  <Decision: Flags>\r
+         * <Decision: Flags> ::= Install Request-State\r
+         *\r
+        */\r
+\r
+        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = new COPSHandle();\r
+        clienthandle.setId(_handle.getId());\r
+\r
+        // Decisions\r
+        //  <Context>\r
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+        //  <Decision: Flags>\r
+        COPSDecision dec = new COPSDecision();\r
+        dec.setCmdCode(COPSDecision.DEC_INSTALL);\r
+        dec.setFlags(COPSDecision.F_REQSTATE);\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(clienthandle);\r
+            decisionMsg.addDecision(dec, cntxt);\r
+        } catch (COPSException e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a message asking for a COPS sync operation\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendSyncRequestState()\r
+    throws COPSPdpException {\r
+        /* <Synchronize State Request>  ::= <Common Header>\r
+         *                                  [<Client Handle>]\r
+         *                                  [<Integrity>]\r
+         */\r
+\r
+        // Common Header with the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSQ, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = new COPSHandle();\r
+        clienthandle.setId(_handle.getId());\r
+\r
+        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
+        try {\r
+            msg.add(hdr);\r
+            msg.add(clienthandle);\r
+        } catch (Exception e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSReqStateMan.java b/packetcable-driver/src/main/java/org/umu/cops/ospdp/COPSPdpOSReqStateMan.java
new file mode 100644 (file)
index 0000000..ffd379c
--- /dev/null
@@ -0,0 +1,310 @@
+package org.umu.cops.ospdp;\r
+\r
+import java.net.Socket;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReportType;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * State manager class for outsourcing requests, at the PDP side.\r
+ */\r
+public class COPSPdpOSReqStateMan {\r
+    /**\r
+     * Request State created\r
+     */\r
+    public final static short ST_CREATE = 1;\r
+    /**\r
+     * Request received\r
+     */\r
+    public final static short ST_INIT = 2;\r
+    /**\r
+     * Decisions sent\r
+     */\r
+    public final static short ST_DECS = 3;\r
+    /**\r
+     * Report received\r
+     */\r
+    public final static short ST_REPORT = 4;\r
+    /**\r
+     * Request state finalized\r
+     */\r
+    public final static short ST_FINAL = 5;\r
+    /**\r
+     * New request state solicited\r
+     */\r
+    public final static short ST_NEW = 6;\r
+    /**\r
+     * Delete request state solicited\r
+     */\r
+    public final static short ST_DEL = 7;\r
+    /**\r
+     * SYNC request sent\r
+     */\r
+    public final static short ST_SYNC = 8;\r
+    /**\r
+     * SYNC completed\r
+     */\r
+    public final static short ST_SYNCALL = 9;\r
+    /**\r
+     * Close connection received\r
+     */\r
+    public final static short ST_CCONN = 10;\r
+    /**\r
+     * Keep-alive timeout\r
+     */\r
+    public final static short ST_NOKA = 11;\r
+    /**\r
+     * Accounting timeout\r
+     */\r
+    public final static short ST_ACCT = 12;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     *  COPS client handle used to uniquely identify a particular\r
+     *  PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Object for performing policy data processing\r
+     */\r
+    protected COPSPdpOSDataProcess _process;\r
+\r
+    /**\r
+     *  Current state of the request being managed\r
+     */\r
+    protected short _status;\r
+\r
+    /** COPS message transceiver used to send COPS messages */\r
+    protected COPSPdpOSMsgSender _sender;\r
+\r
+    /**\r
+     * Creates a request state manager\r
+     * @param clientType    Client-type\r
+     * @param clientHandle  Client handle\r
+     */\r
+    public COPSPdpOSReqStateMan(short clientType, String clientHandle) {\r
+        // COPS Handle\r
+        _handle = new COPSHandle();\r
+        COPSData id = new COPSData(clientHandle);\r
+        _handle.setId(id);\r
+        // client-type\r
+        _clientType = clientType;\r
+\r
+        _status = ST_CREATE;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return   Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets the status of the request\r
+     * @return      Request state value\r
+     */\r
+    public short getStatus() {\r
+        return _status;\r
+    }\r
+\r
+    /**\r
+     * Gets the policy data processing object\r
+     * @return   Policy data processing object\r
+     */\r
+    public COPSPdpOSDataProcess getDataProcess() {\r
+        return _process;\r
+    }\r
+\r
+    /**\r
+     * Sets the policy data processing object\r
+     * @param   process Policy data processing object\r
+     */\r
+    public void setDataProcess(COPSPdpOSDataProcess process) {\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Called when COPS sync is completed\r
+     * @param    repMsg              COPS sync message\r
+     * @throws   COPSPdpException\r
+     */\r
+    protected void processSyncComplete(COPSSyncStateMsg repMsg)\r
+    throws COPSPdpException {\r
+\r
+        _status = ST_SYNCALL;\r
+\r
+        // maybe we should notifySyncComplete ...\r
+    }\r
+\r
+    /**\r
+     * Initializes a new request state over a socket\r
+     * @param sock  Socket to the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void initRequestState(Socket sock)\r
+    throws COPSPdpException {\r
+        // Inits an object for sending COPS messages to the PDP\r
+        _sender = new COPSPdpOSMsgSender(_clientType, _handle, sock);\r
+\r
+        // Initial state\r
+        _status = ST_INIT;\r
+    }\r
+\r
+    /**\r
+     * Processes a COPS request\r
+     * @param msg   COPS request received from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processRequest(COPSReqMsg msg) throws COPSPdpException {\r
+        Vector clientSIs = msg.getClientSI();\r
+\r
+        //** Here we must retrieve a decision depending on the\r
+        //** supplied ClientSIs\r
+        /*Vector removeDecs = new Vector();\r
+        Vector installDecs = new Vector();*/\r
+        _process.setClientData(this, clientSIs);\r
+\r
+        Vector removeDecs = _process.getRemovePolicy(this);\r
+        Vector installDecs = _process.getInstallPolicy(this);\r
+\r
+        //** We create a SOLICITED decision\r
+        //**\r
+        _sender.sendSolicitedDecision(removeDecs, installDecs);\r
+        _status = ST_DECS;\r
+    }\r
+\r
+    /**\r
+     * Processes a report\r
+     * @param msg   Report message from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processReport(COPSReportMsg msg) throws COPSPdpException {\r
+        //** Analyze the report\r
+        //**\r
+\r
+        /*\r
+         * <Report State> ::= <Common Header>\r
+         *                      <Client Handle>\r
+         *                      <Report Type>\r
+         *                      *(<Named ClientSI>)\r
+         *                      [<Integrity>]\r
+         * <Named ClientSI: Report> ::= <[<GPERR>] *(<report>)>\r
+         * <report> ::= <ErrorPRID> <CPERR> *(<PRID><EPD>)\r
+         *\r
+         * Important, <Named ClientSI> is not parsed\r
+        */\r
+\r
+        // COPSHeader hdrmsg = msg.getHeader();\r
+        // COPSHandle handlemsg = msg.getClientHandle();\r
+\r
+        // Report Type\r
+        COPSReportType rtypemsg = msg.getReport();\r
+\r
+        // Named ClientSI\r
+        Vector clientSIs = msg.getClientSI();\r
+\r
+        //** We should act here in accordance with\r
+        //** the received report\r
+        if (rtypemsg.isSuccess()) {\r
+            _status = ST_REPORT;\r
+            _process.successReport(this, clientSIs);\r
+        } else if (rtypemsg.isFailure()) {\r
+            _status = ST_REPORT;\r
+            _process.failReport(this, clientSIs);\r
+        } else if (rtypemsg.isAccounting()) {\r
+            _status = ST_ACCT;\r
+            _process.acctReport(this, clientSIs);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Called when connection is closed\r
+     * @param error Reason\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processClosedConnection(COPSError error)\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.notifyClosedConnection(this, error);\r
+\r
+        _status = ST_CCONN;\r
+    }\r
+\r
+    /**\r
+     * Called when no keep-alive is received\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processNoKAConnection()\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.notifyNoKAliveReceived(this);\r
+\r
+        _status = ST_NOKA;\r
+    }\r
+\r
+    /**\r
+     * Deletes the request state\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void finalizeRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendDeleteRequestState();\r
+        _status = ST_FINAL;\r
+    }\r
+\r
+    /**\r
+     * Asks for a COPS sync\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void syncRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendSyncRequestState();\r
+        _status = ST_SYNC;\r
+    }\r
+\r
+    /**\r
+     * Opens a new request state\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void openNewRequestState()//FIXME: unused?\r
+    throws COPSPdpException {\r
+        _sender.sendOpenNewRequestState();\r
+        _status = ST_NEW;\r
+    }\r
+\r
+    /**\r
+     * Processes a COPS delete message\r
+     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processDeleteRequestState(COPSDeleteMsg dMsg)\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.closeRequestState(this);\r
+\r
+        _status = ST_DEL;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepException.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepException.java
new file mode 100644 (file)
index 0000000..6f3fde7
--- /dev/null
@@ -0,0 +1,50 @@
+/*\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.ospep;\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
+\r
+    public COPSPepException(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 COPSPepException(String msg, int retCode) {\r
+        super(msg);\r
+        rc = 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
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSAgent.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSAgent.java
new file mode 100644 (file)
index 0000000..9c80a38
--- /dev/null
@@ -0,0 +1,329 @@
+package org.umu.cops.ospep;\r
+\r
+import java.io.IOException;\r
+import java.net.InetAddress;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSAcctTimer;\r
+import org.umu.cops.stack.COPSClientAcceptMsg;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSClientOpenMsg;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKATimer;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * This is a outsourcing COPS PEP. Responsible for making\r
+ * connection to the PDP and maintaining it\r
+ */\r
+public class COPSPepOSAgent {\r
+    /**\r
+        PEP's identifier\r
+     */\r
+    private String _pepID;\r
+\r
+    /**\r
+        PEP's client-type\r
+     */\r
+    private short _clientType;\r
+\r
+    /**\r
+        PDP host name\r
+     */\r
+    private String _psHost;\r
+\r
+    /**\r
+        PDP port\r
+     */\r
+    private int _psPort;\r
+\r
+    /**\r
+        PEP-PDP connection manager\r
+     */\r
+    private COPSPepOSConnection _conn;\r
+\r
+    /**\r
+        COPS error returned by the PDP\r
+     */\r
+    private COPSError _error;\r
+\r
+    /**\r
+     * Policy data processor class\r
+     */\r
+    private COPSPepOSDataProcess _process;\r
+\r
+    /**\r
+     * Creates a PEP agent\r
+     * @param    pepID              PEP-ID\r
+     * @param    clientType         Client-type\r
+     */\r
+    public COPSPepOSAgent(String pepID, short clientType) {\r
+        _pepID = pepID;\r
+        _clientType = clientType;\r
+    }\r
+\r
+    /**\r
+     * Creates a PEP agent with a PEP-ID equal to "noname"\r
+     * @param    clientType         Client-type\r
+     */\r
+    public COPSPepOSAgent(short clientType) {\r
+        // PEPId\r
+        try {\r
+            _pepID = InetAddress.getLocalHost().getHostName();\r
+        } catch (Exception e) {\r
+            _pepID = "noname";\r
+        }\r
+\r
+        _clientType = clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets the identifier of the PEP\r
+     * @return  PEP-ID\r
+     */\r
+    public String getPepID() {\r
+        return _pepID;\r
+    }\r
+\r
+    /**\r
+     * Sets the policy data processor\r
+     * @param aDataProcess  Data processor class\r
+     */\r
+    public void setDataProcess(COPSPepOSDataProcess aDataProcess) {\r
+        this._process = aDataProcess;\r
+    }\r
+\r
+    /**\r
+     * Gets the COPS client-type\r
+     * @return  PEP's client-type\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets PDP host name\r
+     * @return  PDP host name\r
+     */\r
+    public String getPDPName() {\r
+        return _psHost;\r
+    }\r
+\r
+    /**\r
+     * Gets the port of the PDP\r
+     * @return  PDP port\r
+     */\r
+    public int getPDPPort() {\r
+        return _psPort;\r
+    }\r
+\r
+    /**\r
+     * Connects to a PDP\r
+     * @param    psHost              PDP host name\r
+     * @param    psPort              PDP port\r
+     * @return   <tt>true</tt> if PDP accepts the connection; <tt>false</tt> otherwise\r
+     * @throws   java.net.UnknownHostException\r
+     * @throws   java.io.IOException\r
+     * @throws   COPSException\r
+     * @throws   COPSPepException\r
+     */\r
+    public boolean connect(String psHost, int psPort) throws UnknownHostException, IOException, COPSException, COPSPepException {\r
+        // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");\r
+        _psHost = psHost;\r
+        _psPort = psPort;\r
+\r
+        // Check whether it already exists\r
+        if (_conn == null)\r
+            _conn = processConnection(psHost,psPort);\r
+        else {\r
+            // Check whether it's closed\r
+            if (_conn.isClosed())\r
+                _conn = processConnection(psHost,psPort);\r
+            else {\r
+                disconnect(null);\r
+                _conn = processConnection(psHost,psPort);\r
+            }\r
+        }\r
+\r
+        return (_conn != null);\r
+    }\r
+\r
+    /**\r
+     * Gets the connection manager\r
+     * @return  PEP-PDP connection manager object\r
+     */\r
+    public COPSPepOSConnection getConnection() {\r
+        return (_conn);\r
+    }\r
+\r
+    /**\r
+     * Gets the COPS error returned by the PDP\r
+     * @return   <tt>COPSError</tt> returned by PDP\r
+     */\r
+    public COPSError getConnectionError() {\r
+        return _error;\r
+    }\r
+\r
+    /**\r
+     * Disconnects from the PDP\r
+     * @param error Reason\r
+     * @throws COPSException\r
+     * @throws IOException\r
+     */\r
+    public void disconnect(COPSError error) throws COPSException, IOException {\r
+        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
+        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+        closeMsg.add(cHdr);\r
+        if (error != null)\r
+            closeMsg.add(error);\r
+\r
+        closeMsg.writeData(_conn.getSocket());\r
+        _conn.close();\r
+        _conn = null;\r
+    }\r
+\r
+    /**\r
+     * Adds a request state to the connection manager.\r
+     * @param clientSIs The client data from the outsourcing event\r
+     * @return  The newly created connection manager\r
+     * @throws COPSPepException\r
+     * @throws COPSException\r
+     */\r
+    public COPSPepOSReqStateMan addRequestState(COPSHandle handle, Vector clientSIs) throws COPSPepException, COPSException {\r
+        if (_conn != null)\r
+            return _conn.addRequestState(handle.getId().str(), _process, clientSIs);\r
+\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Queries the connection manager to delete a request state\r
+     * @param man   Request state manager\r
+     * @throws COPSPepException\r
+     * @throws COPSException\r
+     */\r
+    public void deleteRequestState (COPSPepOSReqStateMan man) throws COPSPepException, COPSException {\r
+        if (_conn != null)\r
+            _conn.deleteRequestState(man);\r
+    }\r
+\r
+    /**\r
+     * Gets all the request state managers\r
+     * @return  A <tt>Hashtable</tt> holding all active request state managers\r
+     */\r
+    public Hashtable getReqStateMans() {\r
+        if (_conn != null)\r
+            return _conn.getReqStateMans();\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Establish connection to PDP's IP address\r
+     *\r
+     * <Client-Open> ::= <Common Header>\r
+     *                  <PEPID>\r
+     *                  [<ClientSI>]\r
+     *                  [<LastPDPAddr>]\r
+     *                  [<Integrity>]\r
+     *\r
+     * Not support [<ClientSI>], [<LastPDPAddr>], [<Integrity>]\r
+     *\r
+     * <Client-Accept> ::= <Common Header>\r
+     *                      <KA Timer>\r
+     *                      [<ACCT Timer>]\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not send [<Integrity>]\r
+     *\r
+     * <Client-Close> ::= <Common Header>\r
+     *                      <Error>\r
+     *                      [<PDPRedirAddr>]\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not send [<PDPRedirAddr>], [<Integrity>]\r
+     *\r
+     * @throws   UnknownHostException\r
+     * @throws   IOException\r
+     * @throws   COPSException\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    private COPSPepOSConnection processConnection(String psHost, int psPort) throws UnknownHostException, IOException, COPSException, COPSPepException {\r
+        // Build OPN\r
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, _clientType);\r
+\r
+        COPSPepId pepId = new COPSPepId();\r
+        COPSData d = new COPSData(_pepID);\r
+        pepId.setData(d);\r
+\r
+        COPSClientOpenMsg msg = new COPSClientOpenMsg();\r
+        msg.add(hdr);\r
+        msg.add(pepId);\r
+\r
+        // Create socket and send OPN\r
+        InetAddress addr = InetAddress.getByName(psHost);\r
+        Socket socket = new Socket(addr,psPort);\r
+        msg.writeData(socket);\r
+\r
+        // Get response\r
+        COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);\r
+\r
+        if (recvmsg.getHeader().isAClientAccept()) {\r
+            COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;\r
+\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                throw new COPSPepException("Unsupported object (Integrity)");\r
+            }\r
+\r
+            // Mandatory KATimer\r
+            COPSKATimer kt = cMsg.getKATimer();\r
+            if (kt == null)\r
+                throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");\r
+            short _kaTimeVal = kt.getTimerVal();\r
+\r
+            // ACTimer\r
+            COPSAcctTimer at = cMsg.getAcctTimer();\r
+            short _acctTimer = 0;\r
+            if (at != null)\r
+                _acctTimer = at.getTimerVal();\r
+\r
+            // Create connection manager\r
+            COPSPepOSConnection conn = new COPSPepOSConnection(_clientType, socket);\r
+            conn.setKaTimer(_kaTimeVal);\r
+            conn.setAcctTimer(_acctTimer);\r
+            new Thread(conn).start();\r
+\r
+            return conn;\r
+        } else if (recvmsg.getHeader().isAClientClose()) {\r
+            COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;\r
+            _error = cMsg.getError();\r
+            socket.close();\r
+            return null;\r
+        } else { // other message types are unexpected\r
+            throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Creates a new request state when the outsourcing event is detected.\r
+     * @param handle The COPS handle for this request\r
+     * @param clientSIs The client specific data for this request\r
+     */\r
+    public void dispatchEvent(COPSHandle handle, Vector clientSIs) {\r
+        try {\r
+            addRequestState(handle, clientSIs);\r
+        } catch (Exception e) {\r
+            System.err.println("COPSPepOSAgent: " + e.toString());\r
+        }\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSConnection.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSConnection.java
new file mode 100644 (file)
index 0000000..31a0b64
--- /dev/null
@@ -0,0 +1,469 @@
+package org.umu.cops.ospep;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Date;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSDecisionMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKAMsg;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * COPSPepConnection represents a PEP-PDP Connection Manager.\r
+ * Responsible for processing messages received from PDP.\r
+ */\r
+public class COPSPepOSConnection implements Runnable {\r
+    /** Socket connected to PDP */\r
+    protected Socket _sock;\r
+\r
+    /** Time to wait responses (milliseconds), default is 10 seconds */\r
+    protected int _responseTime;\r
+\r
+    /** COPS Client-type */\r
+    protected short _clientType;\r
+\r
+    /**\r
+        Accounting timer value (secs)\r
+     */\r
+    protected short _acctTimer;\r
+\r
+    /**\r
+        Keep-alive timer value (secs)\r
+     */\r
+    protected short _kaTimer;\r
+\r
+    /**\r
+     *  Time of the latest keep-alive received\r
+     */\r
+    protected Date _lastRecKa;\r
+\r
+    /**\r
+        Opcode of the latest message sent\r
+    */\r
+    protected byte _lastmessage;\r
+\r
+    /**\r
+        Maps a COPS Client Handle to a Request State Manager\r
+     */\r
+    protected Hashtable _managerMap;\r
+    // map < String(COPSHandle), COPSPepOSReqStateMan>;\r
+\r
+    /**\r
+        COPS error returned by PDP\r
+     */\r
+    protected COPSError _error;\r
+\r
+    /**\r
+     * Creates a new PEP connection\r
+     * @param clientType    PEP's client-type\r
+     * @param sock          Socket connected to PDP\r
+     */\r
+    public COPSPepOSConnection(short clientType, Socket sock) {\r
+        _clientType = clientType;\r
+        _sock = sock;\r
+\r
+        // Timers\r
+        _acctTimer = 0;\r
+        _kaTimer = 0;\r
+        _responseTime = 10000;\r
+        _lastmessage = COPSHeader.COPS_OP_CAT;\r
+\r
+        _managerMap = new Hashtable(20);\r
+    }\r
+\r
+    /**\r
+     * Gets the response time\r
+     * @return  Response time value (msecs)\r
+     */\r
+    public int getResponseTime() {\r
+        return _responseTime;\r
+    }\r
+\r
+    /**\r
+     * Gets the socket connected to the PDP\r
+     * @return  Socket connected to PDP\r
+     */\r
+    public Socket getSocket() {\r
+        return _sock;\r
+    }\r
+\r
+    /**\r
+     * Gets keep-alive timer\r
+     * @return  Keep-alive timer value (secs)\r
+     */\r
+    public short getKaTimer () {\r
+        return _kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets accounting timer\r
+     * @return  Accounting timer value (secs)\r
+     */\r
+    public short getAcctTimer () {\r
+        return _acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets active COPS handles\r
+     * @return  An <tt>Enumeration</tt> holding all active handles\r
+     */\r
+    protected Enumeration getHandles() {\r
+        return _managerMap.keys();\r
+    }\r
+\r
+    /**\r
+     * Gets all request state managers\r
+     * @return  A <tt>Hashatable</tt> holding all request state managers\r
+     */\r
+    protected Hashtable getReqStateMans() {\r
+        return _managerMap;\r
+    }\r
+\r
+    /**\r
+     * Checks whether the socket to the PDP is closed or not\r
+     * @return  <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise\r
+     */\r
+    public boolean isClosed() {\r
+        return _sock.isClosed();\r
+    }\r
+\r
+    /**\r
+     * Closes the socket\r
+     *\r
+     * @throws java.io.IOException\r
+     */\r
+    protected void close() throws IOException {\r
+        _sock.close();\r
+    }\r
+\r
+    /**\r
+     * Gets the opcode of the lastest message sent\r
+     * @return  Message opcode\r
+     */\r
+    public byte getLastmessage() {\r
+        return _lastmessage;\r
+    }\r
+\r
+    /**\r
+     * Sets response time\r
+     * @param respTime  Response time value (msecs)\r
+     */\r
+    public void setResponseTime(int respTime) {\r
+        _responseTime = respTime;\r
+    };\r
+\r
+    /**\r
+     * Sets keep-alive timer\r
+     * @param kaTimer   Keep-alive timer value (secs)\r
+     */\r
+    public void setKaTimer(short kaTimer) {\r
+        _kaTimer = kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Sets accounting timer\r
+     * @param acctTimer Accounting timer value (secs)\r
+     */\r
+    public void setAcctTimer(short acctTimer) {\r
+        _acctTimer = acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Message-processing loop\r
+     */\r
+    public void run () {\r
+        Date _lastSendKa = new Date();\r
+        Date _lastSendAcc = new Date();\r
+        _lastRecKa = new Date();\r
+\r
+        try {\r
+            while (!_sock.isClosed()) {\r
+                if (_sock.getInputStream().available() != 0) {\r
+                    _lastmessage = processMessage(_sock);\r
+                    _lastRecKa = new Date();\r
+                }\r
+\r
+                // Keep Alive\r
+                if (_kaTimer > 0) {\r
+                    // Timeout del PDP\r
+                    int _startTime = (int) (_lastRecKa.getTime());\r
+                    int cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
+                        _sock.close();\r
+                        // Notify all Request State Managers\r
+                        notifyNoKAAllReqStateMan();\r
+                    }\r
+\r
+                    // Send to PEP\r
+                    _startTime = (int) (_lastSendKa.getTime());\r
+                    cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {\r
+                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
+                        COPSKAMsg msg = new COPSKAMsg();\r
+\r
+                        msg.add(hdr);\r
+\r
+                        COPSTransceiver.sendMsg(msg, _sock);\r
+                        _lastSendKa = new Date();\r
+                    }\r
+                }\r
+\r
+                // Accounting\r
+                if (_acctTimer > 0) {\r
+                    int _startTime = (int) (_lastSendAcc.getTime());\r
+                    int cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > ((_acctTimer*3/4)*1000)) {\r
+                        // Notify all Request State Managers\r
+                        notifyAcctAllReqStateMan();\r
+                        _lastSendAcc = new Date();\r
+                    }\r
+                }\r
+\r
+                try {\r
+                    Thread.sleep(500);\r
+                } catch (Exception e) {};\r
+            }\r
+        } catch (Exception e) {\r
+            e.printStackTrace();\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+        }\r
+\r
+        // connection closed by server\r
+        // COPSDebug.out(getClass().getName(),"Connection closed by server");\r
+        try {\r
+            _sock.close();\r
+        } catch (IOException e) {};\r
+\r
+        // Notify all Request State Managers\r
+        try {\r
+            notifyCloseAllReqStateMan();\r
+        } catch (COPSPepException e) {};\r
+    }\r
+\r
+    /**\r
+     * Gets a COPS message from the socket and processes it\r
+     * @param conn  Socket connected to the PDP\r
+     * @return COPS message type\r
+     * @throws COPSPepException\r
+     * @throws COPSException\r
+     * @throws IOException\r
+     */\r
+    protected byte processMessage(Socket conn) throws COPSPepException, COPSException, IOException {\r
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
+\r
+        if (msg.getHeader().isAClientClose()) {\r
+            handleClientCloseMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_CC;\r
+        } else if (msg.getHeader().isADecision()) {\r
+            handleDecisionMsg(/*OJO conn, */msg);\r
+            return COPSHeader.COPS_OP_DEC;\r
+        } else if (msg.getHeader().isASyncStateReq()) {\r
+            handleSyncStateReqMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_SSQ;\r
+        } else if (msg.getHeader().isAKeepAlive()) {\r
+            handleKeepAliveMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_KA;\r
+        } else {\r
+            throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Handle Client Close Message, close the passed connection\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     *\r
+     * <Client-Close> ::= <Common Header>\r
+     *                      <Error>\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     */\r
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
+        _error = cMsg.getError();\r
+\r
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
+\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null)\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+\r
+            conn.close();\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Gets the COPS error\r
+     * @return  <tt>COPSError</tt> returned by PDP\r
+     */\r
+    protected COPSError getError() {\r
+        return _error;\r
+    }\r
+\r
+    /**\r
+     * Handle Keep Alive Message\r
+     *\r
+     * <Keep-Alive> ::= <Common Header>\r
+     *                  [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
+        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
+\r
+        // COPSDebug.out(getClass().getName(),"Get KAlive Msg");\r
+\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null)\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+\r
+            // must we do anything else?\r
+\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Method handleDecisionMsg\r
+     *\r
+     * <Decision Message> ::= <Common Header: Flag SOLICITED>\r
+     *                          <Client Handle>\r
+     *                          *(<Decision>) | <Error>\r
+     *                          [<Integrity>]\r
+     * <Decision> ::= <Context>\r
+     *                  <Decision: Flags>\r
+     *                  [<ClientSI Decision Data: Outsourcing>]\r
+     * <Decision: Flags> ::= <Command-Code> NULLFlag\r
+     * <Command-Code> ::= NULLDecision | Install | Remove\r
+     * <ClientSI Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
+     * <Install Decision> ::= *(<PRID> <EPD>)\r
+     * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
+     *\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleDecisionMsg(/*OJO Socket conn, */COPSMsg msg) throws COPSPepException {\r
+        COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;\r
+        COPSHandle handle = dMsg.getClientHandle();\r
+        COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(handle.getId().str());\r
+        manager.processDecision(dMsg);\r
+    }\r
+\r
+    /**\r
+     * Method handleSyncStateReqMsg\r
+     *\r
+     *              <Synchronize State> ::= <Common Header>\r
+     *                                      [<Client Handle>]\r
+     *                                      [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {\r
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
+        // COPSHandle handle = cMsg.getClientHandle();\r
+        // COPSHeader header = cMsg.getHeader();\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null)\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+\r
+        COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+\r
+        if (manager == null)\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        else\r
+            manager.processSyncStateRequest(cMsg);\r
+    }\r
+\r
+    /**\r
+     * Adds a new request state\r
+     * @param clientHandle  Client's handle\r
+     * @param process       Policy data processing object\r
+     * @param clientSIs     Client data from the outsourcing event\r
+     * @return              The newly created request state manager\r
+     * @throws COPSException\r
+     * @throws COPSPepException\r
+     */\r
+    protected COPSPepOSReqStateMan addRequestState(String clientHandle, COPSPepOSDataProcess process, Vector clientSIs) throws COPSException, COPSPepException {\r
+        COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType, clientHandle);\r
+        if (_managerMap.get(clientHandle) != null)\r
+            throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);\r
+\r
+        manager.setDataProcess(process);\r
+        manager.setClientSI(clientSIs);\r
+        _managerMap.put(clientHandle, manager);\r
+        manager.initRequestState(_sock);\r
+        return manager;\r
+    }\r
+\r
+    /**\r
+     * Deletes a request state\r
+     * @param manager   Request state manager\r
+     * @throws COPSException\r
+     * @throws COPSPepException\r
+     */\r
+    protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {\r
+        manager.finalizeRequestState();\r
+    }\r
+\r
+    private void notifyCloseAllReqStateMan() throws COPSPepException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processClosedConnection(_error);\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyNoKAAllReqStateMan() throws COPSPepException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processNoKAConnection();\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyAcctAllReqStateMan() throws COPSPepException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processAcctReport();\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSDataProcess.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSDataProcess.java
new file mode 100644 (file)
index 0000000..1ee476b
--- /dev/null
@@ -0,0 +1,59 @@
+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
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSEventListener.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSEventListener.java
new file mode 100644 (file)
index 0000000..9266440
--- /dev/null
@@ -0,0 +1,30 @@
+package org.umu.cops.ospep;\r
+\r
+/**\r
+ * Abstract class for creating listeners for outsourcing events.\r
+ */\r
+public abstract class COPSPepOSEventListener extends Thread {\r
+    /**\r
+     * COPSPepOSAgent to be waked up upon event detection.\r
+     */\r
+    protected COPSPepOSAgent _agent;\r
+\r
+    /**\r
+     * Sets the COPS agent to be waked up.\r
+     * @param anAgent   A COPSPepOSAgent\r
+     */\r
+    public void setAgent(COPSPepOSAgent anAgent) {\r
+        _agent = anAgent;\r
+    }\r
+\r
+    /**\r
+     * This must implement event detection, and wake up\r
+     * the COPS agent when it occurs. The steps are:\r
+     * <ul>\r
+     * <li>Detect the outsourcing event</li>\r
+     * <li>Build a <tt>Vector clientSIs</tt> from the event</li>\r
+     * <li>Generate a <tt>COPSHandle handle</tt> for the request</li>\r
+     * <li>Invoke <tt>_agent.dispatchEvent(handle, clientSIs)</tt></li></ul>\r
+     */\r
+    public abstract void run();\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSMsgSender.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSMsgSender.java
new file mode 100644 (file)
index 0000000..2f8526e
--- /dev/null
@@ -0,0 +1,261 @@
+package org.umu.cops.ospep;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSClientSI;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSReason;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReportType;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * COPS message transceiver class for outsourcing connections at the PEP side.\r
+ */\r
+public class COPSPepOSMsgSender {\r
+    /**\r
+     * Socket connection to PDP\r
+     */\r
+    protected Socket _sock;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     * COPS client handle used to uniquely identify a particular\r
+     * PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Creates a COPSPepMsgSender\r
+     *\r
+     * @param clientType        Client-type\r
+     * @param clientHandle      Client handle\r
+     * @param sock              Socket connected to the PDP\r
+     */\r
+    public COPSPepOSMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
+        // COPS Handle\r
+        _handle = clientHandle;\r
+        _clientType = clientType;\r
+\r
+        _sock = sock;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return  Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return  Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Sends a request to the PDP.\r
+     * The PEP establishes a request state client handle for which the\r
+     * remote PDP may maintain state.\r
+     * @param    clientSIs              Client data\r
+     * @throws   COPSPepException\r
+     */\r
+    public void sendRequest(Vector clientSIs) throws COPSPepException {\r
+        // Create COPS Message\r
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_REQ, _clientType);\r
+\r
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG , (short) 0);\r
+\r
+        COPSHandle handle = _handle;\r
+\r
+        COPSReqMsg msg = new COPSReqMsg();\r
+        try {\r
+            msg.add(hdr) ;\r
+            msg.add(handle) ;\r
+            msg.add(cntxt) ;\r
+\r
+            Enumeration clientSIEnum = clientSIs.elements();\r
+            while (clientSIEnum.hasMoreElements())\r
+                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
+        } catch (COPSException e) {\r
+            throw new COPSPepException("Error making Request Msg, reason: " + e.getMessage());\r
+        }\r
+\r
+        // Send message\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a failure report to the PDP. This report message notifies the PDP\r
+     * of failure when carrying out the PDP's decision, or when reporting\r
+     *  an accounting related state change.\r
+     * @param clientSIs Report data\r
+     * @throws   COPSPepException\r
+     */\r
+    public void sendFailReport(Vector clientSIs) throws COPSPepException {\r
+        COPSReportMsg msg = new COPSReportMsg();\r
+        // Report FAIL\r
+        try {\r
+            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
+            COPSHandle hnd = _handle;\r
+\r
+            COPSReportType report = new COPSReportType(COPSReportType.FAILURE);\r
+\r
+            msg.add(hdr);\r
+            msg.add(hnd);\r
+            msg.add(report);\r
+\r
+            Enumeration clientSIEnum = clientSIs.elements();\r
+            while (clientSIEnum.hasMoreElements())\r
+                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a success report to the PDP. This report message notifies the PDP\r
+     * of success when carrying out the PDP's decision, or when reporting\r
+     *  an accounting related state change.\r
+     * @param   clientSIs   Report data\r
+     * @throws  COPSPepException\r
+     */\r
+    public void sendSuccessReport(Vector clientSIs) throws COPSPepException {\r
+        COPSReportMsg msg = new COPSReportMsg();\r
+        // Report SUCESS\r
+        try {\r
+            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
+            COPSHandle hnd = _handle;\r
+\r
+            COPSReportType report = new COPSReportType(COPSReportType.SUCCESS);\r
+\r
+            msg.add(hdr);\r
+            msg.add(hnd);\r
+            msg.add(report);\r
+\r
+            Enumeration clientSIEnum = clientSIs.elements();\r
+            while (clientSIEnum.hasMoreElements())\r
+                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends an accounting report to the PDP\r
+     * @param clientSIs Report data\r
+     * @throws COPSPepException\r
+     */\r
+    public void sendAcctReport(Vector clientSIs) throws COPSPepException {\r
+        COPSReportMsg msg = new COPSReportMsg();\r
+        // Report SUCCESS\r
+        try {\r
+            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
+            COPSHandle hnd = _handle;\r
+\r
+            COPSReportType report = new COPSReportType(COPSReportType.ACCT);\r
+\r
+            msg.add(hdr);\r
+            msg.add(hnd);\r
+            msg.add(report);\r
+\r
+            Enumeration clientSIEnum = clientSIs.elements();\r
+            while (clientSIEnum.hasMoreElements())\r
+                msg.add( (COPSClientSI) clientSIEnum.nextElement());\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a sync-complete message to the PDP. This indicates the\r
+     * end of a synchronization requested by the PDP.\r
+     * @throws   COPSPepException\r
+     */\r
+    public void sendSyncComplete() throws COPSPepException {\r
+        // Common Header with the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSC, _clientType);\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = _handle;\r
+\r
+        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
+        try {\r
+            msg.add(hdr);\r
+            msg.add(clienthandle);\r
+        } catch (Exception e) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a delete request to the PDP.\r
+     * When sent from the PEP this message indicates to the remote PDP that\r
+     * the state identified by the client handle is no longer\r
+     * available/relevant.\r
+     * @throws   COPSPepException\r
+     */\r
+    public void sendDeleteRequest() throws COPSPepException {\r
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DRQ, _clientType);\r
+        COPSHandle handle = _handle;\r
+\r
+        // *** TODO: use real reason codes\r
+        COPSReason reason = new COPSReason((short) 234, (short) 345);\r
+\r
+        COPSDeleteMsg msg = new COPSDeleteMsg();\r
+        try {\r
+            msg.add(hdr);\r
+            msg.add(handle);\r
+            msg.add(reason);\r
+            msg.writeData(_sock);\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSReqStateMan.java b/packetcable-driver/src/main/java/org/umu/cops/ospep/COPSPepOSReqStateMan.java
new file mode 100644 (file)
index 0000000..aab3bc1
--- /dev/null
@@ -0,0 +1,308 @@
+package org.umu.cops.ospep;\r
+\r
+import java.net.Socket;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDecisionMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * State manager class for outsourcing requests, at the PEP side.\r
+ */\r
+public class COPSPepOSReqStateMan {\r
+    /**\r
+     * Request State created\r
+     */\r
+    public final static short ST_CREATE = 1;\r
+    /**\r
+     * Request sent\r
+     */\r
+    public final static short ST_INIT = 2;\r
+    /**\r
+     * Decisions received\r
+     */\r
+    public final static short ST_DECS = 3;\r
+    /**\r
+     * Report sent\r
+     */\r
+    public final static short ST_REPORT = 4;\r
+    /**\r
+     * Request State finalized\r
+     */\r
+    public final static short ST_FINAL = 5;\r
+    /**\r
+     * New Request State solicited\r
+     */\r
+    public final static short ST_NEW = 6;\r
+    /**\r
+     * Delete Request State solicited\r
+     */\r
+    public final static short ST_DEL = 7;\r
+    /**\r
+     * SYNC request received\r
+     */\r
+    public final static short ST_SYNC = 8;\r
+    /**\r
+     * Sync completed\r
+     */\r
+    public final static short ST_SYNCALL = 9;\r
+    /**\r
+     * Close connection received\r
+     */\r
+    public final static short ST_CCONN = 10;\r
+    /**\r
+     * Keep-alive timeout\r
+     */\r
+    public final static short ST_NOKA = 11;\r
+    /**\r
+     * Accounting timeout\r
+     */\r
+    public final static short ST_ACCT = 12;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     *  COPS client handle used to uniquely identify a particular\r
+     *  PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+        Object for performing policy data processing\r
+     */\r
+    protected COPSPepOSDataProcess _process;\r
+\r
+    /**\r
+     * ClientSI data from signaling.\r
+     */\r
+    protected Vector _clientSIs;\r
+\r
+    /**\r
+     *  Current state of the request being managed\r
+     */\r
+    protected short _status;\r
+\r
+    /**\r
+        COPS message transceiver used to send COPS messages\r
+     */\r
+    protected COPSPepOSMsgSender _sender;\r
+\r
+    /**\r
+     * Sync state\r
+     */\r
+    protected boolean _syncState;\r
+\r
+    /**\r
+     * Creates a state request manager\r
+     * @param    clientType Client-type\r
+     * @param   clientHandle    Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSPepOSReqStateMan(short clientType, String clientHandle) {\r
+        // COPS Handle\r
+        _handle = new COPSHandle();\r
+        COPSData id = new COPSData(clientHandle);\r
+        _handle.setId(id);\r
+        // client-type\r
+        _clientType = clientType;\r
+        _syncState = true;\r
+        _status = ST_CREATE;\r
+        _clientSIs = null;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return  Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Sets the client SI data.\r
+     * @param someClientSIs Client SI data built by the event listener\r
+     */\r
+    public void setClientSI(Vector someClientSIs) {\r
+        _clientSIs = someClientSIs;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return  Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets the request status\r
+     * @return  Request status value\r
+     */\r
+    public short getStatus() {\r
+        return _status;\r
+    }\r
+\r
+    /**\r
+     * Gets the policy data processing object\r
+     *\r
+     * @return   Policy data processing object\r
+     *\r
+     */\r
+    public COPSPepOSDataProcess getDataProcess() {\r
+        return _process;\r
+    }\r
+\r
+    /**\r
+     * Sets the policy data processing object\r
+     *\r
+     * @param   process   Policy data processing object\r
+     *\r
+     */\r
+    public void setDataProcess(COPSPepOSDataProcess process) {\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Initializes a new request state over a socket\r
+     * @param sock  Socket to the PDP\r
+     * @throws COPSPepException\r
+     */\r
+    protected void initRequestState(Socket sock) throws COPSPepException {\r
+        // Inits an object for sending COPS messages to the PDP\r
+        _sender = new COPSPepOSMsgSender(_clientType, _handle, sock);\r
+\r
+        // If an object exists for retrieving the PEP features,\r
+        // use it for retrieving them.\r
+        /*      Hashtable clientSIs;\r
+                if (_process != null)\r
+                    clientSIs = _process.getClientData(this);\r
+                else\r
+                    clientSIs = null;*/\r
+\r
+        // Semd the request\r
+        _sender.sendRequest(_clientSIs);\r
+\r
+        // Initial state\r
+        _status = ST_INIT;\r
+    }\r
+\r
+    /**\r
+     * Deletes the request state\r
+     * @throws COPSPepException\r
+     */\r
+    protected void finalizeRequestState() throws COPSPepException {\r
+        _sender.sendDeleteRequest();\r
+        _status = ST_FINAL;\r
+    }\r
+\r
+    /**\r
+     * Processes the decision message\r
+     * @param    dMsg Decision message from the PDP\r
+     * @throws   COPSPepException\r
+     */\r
+    protected void processDecision(COPSDecisionMsg dMsg) throws COPSPepException {\r
+        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());\r
+\r
+        //Hashtable decisionsPerContext = dMsg.getDecisions();\r
+\r
+        //** Applies decisions to the configuration\r
+        //_process.setDecisions(this, removeDecs, installDecs, errorDecs);\r
+        // second param changed to dMsg so that the data processor\r
+        // can check the 'solicited' flag\r
+        boolean isFailReport = _process.setDecisions(this, dMsg /*decisionsPerContext*/);\r
+        _status = ST_DECS;\r
+\r
+        if (isFailReport) {\r
+            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");\r
+            _sender.sendFailReport(_process.getReportData(this));\r
+        } else {\r
+            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");\r
+            _sender.sendSuccessReport(_process.getReportData(this));\r
+        }\r
+        _status = ST_REPORT;\r
+\r
+        if (!_syncState) {\r
+            _sender.sendSyncComplete();\r
+            _syncState = true;\r
+            _status = ST_SYNCALL;\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Processes a COPS delete message\r
+     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PDP\r
+     * @throws COPSPepException\r
+     */\r
+    protected void processDeleteRequestState(COPSDecisionMsg dMsg) throws COPSPepException {\r
+        if (_process != null)\r
+            _process.closeRequestState(this);\r
+\r
+        _status = ST_DEL;\r
+    }\r
+\r
+    /**\r
+     * Processes the message SycnStateRequest.\r
+     * The message SycnStateRequest indicates that the remote PDP\r
+     * wishes the client (which appears in the common header)\r
+     * to re-send its state.\r
+     *\r
+     * @param    ssMsg               The sync request from the PDP\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg) throws COPSPepException {\r
+        _syncState = false;\r
+        // If an object exists for retrieving the PEP features,\r
+        // use it for retrieving them.\r
+\r
+        // Send the request\r
+        _sender.sendRequest(_clientSIs);\r
+\r
+        _status = ST_SYNC;\r
+    }\r
+\r
+    /**\r
+     * Called when connection is closed\r
+     * @param error Reason\r
+     * @throws COPSPepException\r
+     */\r
+    protected void processClosedConnection(COPSError error) throws COPSPepException {\r
+        if (_process != null)\r
+            _process.notifyClosedConnection(this, error);\r
+\r
+        _status = ST_CCONN;\r
+    }\r
+\r
+    /**\r
+     * Called when no keep-alive is received\r
+     * @throws COPSPepException\r
+     */\r
+    protected void processNoKAConnection() throws COPSPepException {\r
+        if (_process != null)\r
+            _process.notifyNoKAliveReceived(this);\r
+\r
+        _status = ST_NOKA;\r
+    }\r
+\r
+    /**\r
+     * Processes the accounting report\r
+     * @throws COPSPepException\r
+     */\r
+    protected void processAcctReport() throws COPSPepException {\r
+        Vector report = new Vector();\r
+\r
+        if (_process != null)\r
+            report = _process.getAcctData(this);\r
+\r
+        _sender.sendAcctReport(report);\r
+\r
+        _status = ST_ACCT;\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java
new file mode 100644 (file)
index 0000000..b6043c6
--- /dev/null
@@ -0,0 +1,334 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpdp;\r
+\r
+import java.io.IOException;\r
+import java.net.ServerSocket;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.stack.COPSAcctTimer;\r
+import org.umu.cops.stack.COPSClientAcceptMsg;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSClientOpenMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKATimer;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * Core PDP agent for provisioning\r
+ */\r
+public class COPSPdpAgent extends Thread {\r
+    /** Well-known port for COPS */\r
+    public static final int WELL_KNOWN_PDP_PORT = 3288;\r
+    /** Default keep-alive timer value (secs) */\r
+    public static final short KA_TIMER_VALUE = 30;\r
+    /** Default accounting timer value (secs) */\r
+    public static final short ACCT_TIMER_VALUE = 0;\r
+\r
+    /**\r
+        PDP host IP\r
+     */\r
+    private ServerSocket _serverSocket;\r
+\r
+    /**\r
+        PDP host port\r
+     */\r
+    private int _serverPort;\r
+\r
+    /**\r
+        Client-type of connecting PEP\r
+     */\r
+    private short _clientType;\r
+\r
+    /**\r
+        Accounting timer (secs)\r
+     */\r
+    private short _acctTimer;\r
+\r
+    /**\r
+        Keep-alive timer (secs)\r
+     */\r
+    private short _kaTimer;\r
+\r
+    /**\r
+        Maps a PEP-ID to a connection\r
+     */\r
+    private Hashtable _connectionMap;\r
+    // map < String(PEPID), COPSPdpConnection > ConnectionMap;\r
+\r
+    /**\r
+     *  Policy data processing object\r
+     */\r
+    private COPSPdpDataProcess _process;\r
+\r
+    /**\r
+     * Creates a PDP Agent\r
+     *\r
+     * @param clientType    COPS Client-type\r
+     * @param process       Object to perform policy data processing\r
+     */\r
+    public COPSPdpAgent(short clientType, COPSPdpDataProcess process) {\r
+        _serverPort = WELL_KNOWN_PDP_PORT;\r
+        _kaTimer = KA_TIMER_VALUE;\r
+        _acctTimer = ACCT_TIMER_VALUE;\r
+\r
+        _clientType = clientType;\r
+        _connectionMap = new Hashtable(40);\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Creates a PDP Agent\r
+     *\r
+     * @param port  Port to listen to\r
+     * @param clientType    COPS Client-type\r
+     * @param process   Object to perform policy data processing\r
+     */\r
+    public COPSPdpAgent(int port, short clientType, COPSPdpDataProcess process) {\r
+        _serverPort = port;\r
+\r
+        _kaTimer = KA_TIMER_VALUE;\r
+        _acctTimer = ACCT_TIMER_VALUE;\r
+\r
+        _clientType = clientType;\r
+        _connectionMap = new Hashtable(40);\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Sets the keep-alive timer value\r
+     * @param    kaTimer    Keep alive timer value (secs)\r
+     */\r
+    public void setKaTimer (short kaTimer) {\r
+        _kaTimer = kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Sets the accounting timer value\r
+     * @param    acctTimer  Accounting timer value (secs)\r
+     */\r
+    public void setAcctTimer (short acctTimer) {\r
+        _acctTimer = acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the value of the keep-alive timer\r
+     * @return   Keep-alive timer value (secs)\r
+     */\r
+    public short getKaTimer () {\r
+        return _kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the accounting timer value\r
+     * @return   Accounting timer value (secs)\r
+     */\r
+    public short getAcctTimer () {\r
+        return _acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the PEPs connected to this PDP\r
+     * @return   An <tt>Enumeration</tt> of all connected PEPs\r
+     */\r
+    public Enumeration getConnectedPEPIds() {\r
+        return _connectionMap.keys();\r
+    }\r
+\r
+    /**\r
+     * Gets the connection map\r
+     * @return   A <tt>Hashtable</tt> holding the connection map\r
+     */\r
+    public Hashtable getConnectionMap() {\r
+        return _connectionMap;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   The client-type\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Disconnects a PEP\r
+     * @param pepID PEP-ID of the PEP to be disconnected\r
+     * @param error COPS Error to be reported as a reason\r
+     * @throws COPSException\r
+     * @throws IOException\r
+     */\r
+    public void disconnect (String pepID, COPSError error)\r
+    throws COPSException, IOException {\r
+\r
+        COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);\r
+\r
+        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
+        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+        closeMsg.add(cHdr);\r
+        if (error != null)\r
+            closeMsg.add(error);\r
+\r
+        closeMsg.writeData(pdpConn.getSocket());\r
+        pdpConn.close();\r
+        pdpConn = null;\r
+    }\r
+\r
+    /**\r
+     * Requests a COPS sync for a PEP\r
+     * @param pepID PEP-ID of the PEP to be synced\r
+     * @throws COPSException\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sync (String pepID)\r
+    throws COPSException, COPSPdpException {\r
+\r
+        COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);\r
+        pdpConn.syncAllRequestState();\r
+    }\r
+\r
+    /**\r
+     * Removes a PEP from the connection map\r
+     * @param pepID PEP-ID of the PEP to be removed\r
+     */\r
+    public void delete (String pepID) {\r
+        _connectionMap.remove(pepID);\r
+    }\r
+\r
+\r
+    /**\r
+     * Runs the PDP process\r
+     */\r
+    public void run() {\r
+        try {\r
+            _serverSocket = new ServerSocket (_serverPort);\r
+\r
+            //Loop through for Incoming messages\r
+\r
+            // server infinite loop\r
+            while (true) {\r
+\r
+                // Wait for an incoming connection from a PEP\r
+                Socket socket = _serverSocket.accept();\r
+\r
+                // COPSDebug.out(getClass().getName(),"New connection accepted " +\r
+                //           socket.getInetAddress() +\r
+                //           ":" + socket.getPort());\r
+\r
+                // We're waiting for an OPN message\r
+                try {\r
+                    COPSMsg msg = COPSTransceiver.receiveMsg(socket);\r
+                    if (msg.getHeader().isAClientOpen()) {\r
+                        handleClientOpenMsg(socket, msg);\r
+                    } else {\r
+                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+                        try {\r
+                            socket.close();\r
+                        } catch (Exception ex) {};\r
+                    }\r
+                } catch (Exception e) { // COPSException, IOException\r
+                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,\r
+                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);\r
+                    try {\r
+                        socket.close();\r
+                    } catch (Exception ex) {};\r
+                }\r
+            }\r
+        } catch (IOException e) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+            return;\r
+        }\r
+    }\r
+\r
+    /**\r
+      * Handles a COPS client-open message\r
+      * @param    conn Socket to the PEP\r
+      * @param    msg <tt>COPSMsg</tt> holding the client-open message\r
+      * @throws COPSException\r
+      * @throws IOException\r
+      */\r
+    private void handleClientOpenMsg(Socket conn, COPSMsg msg)\r
+    throws COPSException, IOException {\r
+        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;\r
+        COPSPepId pepId = cMsg.getPepId();\r
+\r
+        // Validate Client Type\r
+        if (msg.getHeader().getClientType() != _clientType) {\r
+            // Unsupported client type\r
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
+            COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);\r
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+            closeMsg.add(cHdr);\r
+            closeMsg.add(err);\r
+            try {\r
+                closeMsg.writeData(conn);\r
+            } catch (IOException unae) {}\r
+\r
+            throw new COPSException("Unsupported client type");\r
+        }\r
+\r
+        // PEPId is mandatory\r
+        if (pepId == null) {\r
+            // Mandatory COPS object missing\r
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
+            COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);\r
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+            closeMsg.add(cHdr);\r
+            closeMsg.add(err);\r
+            try {\r
+                closeMsg.writeData(conn);\r
+            } catch (IOException unae) {}\r
+\r
+            throw new COPSException("Mandatory COPS object missing (PEPId)");\r
+        }\r
+\r
+        // Support\r
+        if ( (cMsg.getClientSI() != null) ||\r
+                (cMsg.getPdpAddress() != null) ||\r
+                (cMsg.getIntegrity() != null)) {\r
+\r
+            // Unsupported objects\r
+            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
+            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);\r
+            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+            closeMsg.add(cHdr);\r
+            closeMsg.add(err);\r
+            try {\r
+                closeMsg.writeData(conn);\r
+            } catch (IOException unae) {}\r
+\r
+            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");\r
+        }\r
+\r
+        // Connection accepted\r
+        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());\r
+        COPSKATimer katimer = new COPSKATimer(_kaTimer);\r
+        COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);\r
+        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();\r
+        acceptMsg.add(ahdr);\r
+        acceptMsg.add(katimer) ;\r
+        if (_acctTimer != 0) acceptMsg.add(acctTimer);\r
+        acceptMsg.writeData(conn);\r
+\r
+        COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);\r
+        pdpConn.setKaTimer(_kaTimer);\r
+        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);\r
+        new Thread(pdpConn).start();\r
+        _connectionMap.put(pepId.getData().str(),pdpConn);\r
+    }\r
+\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpConnection.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpConnection.java
new file mode 100644 (file)
index 0000000..d1c011c
--- /dev/null
@@ -0,0 +1,555 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpdp;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Date;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKAMsg;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * Class for managing an provisioning connection at the PDP side.\r
+ */\r
+public class COPSPdpConnection implements Runnable {\r
+\r
+    /**\r
+        Socket connected to PEP\r
+     */\r
+    private Socket _sock;\r
+\r
+    /**\r
+        PEP identifier\r
+    */\r
+    private COPSPepId _pepId;\r
+\r
+    /**\r
+        Time of the latest keep-alive sent\r
+     */\r
+    private Date _lastKa;\r
+\r
+    /**\r
+        Opcode of the latest message sent\r
+    */\r
+    private byte _lastmessage;\r
+\r
+    /**\r
+     *  Time of the latest keep-alive received\r
+     */\r
+    protected Date _lastRecKa;\r
+\r
+    /**\r
+        Maps a Client Handle to a Handler\r
+     */\r
+    protected Hashtable _managerMap;\r
+    // map < String(COPSHandle), COPSPdpHandler> HandlerMap;\r
+\r
+    /**\r
+     *  PDP policy data processor class\r
+     */\r
+    protected COPSPdpDataProcess _process;\r
+\r
+    /**\r
+        Accounting timer value (secs)\r
+     */\r
+    protected short _acctTimer;\r
+\r
+    /**\r
+        Keep-alive timer value (secs)\r
+     */\r
+    protected short _kaTimer;\r
+\r
+    /**\r
+        COPS error returned by PEP\r
+     */\r
+    protected COPSError _error;\r
+\r
+    /**\r
+     * Creates a new PDP connection\r
+     *\r
+     * @param pepId PEP-ID of the connected PEP\r
+     * @param sock  Socket connected to PEP\r
+     * @param process   Object for processing policy data\r
+     */\r
+    public COPSPdpConnection(COPSPepId pepId, Socket sock, COPSPdpDataProcess process) {\r
+        _sock = sock;\r
+        _pepId = pepId;\r
+\r
+        _lastKa = new Date();\r
+        _lastmessage = COPSHeader.COPS_OP_OPN;\r
+        _managerMap = new Hashtable(20);\r
+\r
+        _kaTimer = 0;\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Gets the time of that latest keep-alive sent\r
+     * @return Time of that latest keep-alive sent\r
+     */\r
+    public Date getLastKAlive() {\r
+        return _lastKa;\r
+    }\r
+\r
+    /**\r
+     * Sets the keep-alive timer value\r
+     * @param kaTimer Keep-alive timer value (secs)\r
+     */\r
+    public void setKaTimer(short kaTimer) {\r
+        _kaTimer = kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the keep-alive timer value\r
+     * @return Keep-alive timer value (secs)\r
+     */\r
+    public short getKaTimer() {\r
+        return _kaTimer;\r
+    }\r
+\r
+    /**\r
+     * Sets the accounting timer value\r
+     * @param acctTimer Accounting timer value (secs)\r
+     */\r
+    public void setAccTimer(short acctTimer) {\r
+        _acctTimer = acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the accounting timer value\r
+     * @return Accounting timer value (secs)\r
+     */\r
+    public short getAcctTimer() {\r
+        return _acctTimer;\r
+    }\r
+\r
+    /**\r
+     * Gets the latest COPS message\r
+     * @return   Code of the latest message sent\r
+     */\r
+    public byte getLastMessage() {\r
+        return _lastmessage;\r
+    }\r
+\r
+    /**\r
+     * Gets active handles\r
+     * @return   An <tt>Enumeration</tt> holding all active handles\r
+     */\r
+    public Enumeration getHandles() {\r
+        return _managerMap.keys();\r
+    }\r
+\r
+    /**\r
+     * Gets the handle map\r
+     * @return   A <tt>Hashtable</tt> holding the handle map\r
+     */\r
+    public Hashtable getReqStateMans() {\r
+        return _managerMap;\r
+    }\r
+\r
+    /**\r
+     * Gets the PEP-ID\r
+     * @return   The ID of the PEP, as a <tt>String</tt>\r
+     */\r
+    public String getPepId() {\r
+        return _pepId.getData().str();\r
+    }\r
+\r
+    /**\r
+     * Checks whether the socket to the PEP is closed or not\r
+     * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise\r
+     */\r
+    public boolean isClosed() {\r
+        return _sock.isClosed();\r
+    }\r
+\r
+    /**\r
+     * Closes the socket to the PEP\r
+     * @throws IOException\r
+     */\r
+    protected void close()\r
+    throws IOException {\r
+        _sock.close();\r
+    }\r
+\r
+    /**\r
+     * Gets the socket to the PEP\r
+     * @return   Socket connected to the PEP\r
+     */\r
+    public Socket getSocket() {\r
+        return _sock;\r
+    }\r
+\r
+    /**\r
+     * Main loop\r
+     */\r
+    public void run () {\r
+        Date _lastSendKa = new Date();\r
+        _lastRecKa = new Date();\r
+        try {\r
+            while (!_sock.isClosed()) {\r
+                if (_sock.getInputStream().available() != 0) {\r
+                    _lastmessage = processMessage(_sock);\r
+                    _lastRecKa = new Date();\r
+                }\r
+\r
+                // Keep Alive\r
+                if (_kaTimer > 0) {\r
+                    // Timeout at PDP\r
+                    int _startTime = (int) (_lastRecKa.getTime());\r
+                    int cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
+                        _sock.close();\r
+                        // Notify all Request State Managers\r
+                        notifyNoKAAllReqStateMan();\r
+                    }\r
+\r
+                    // Send to PEP\r
+                    _startTime = (int) (_lastSendKa.getTime());\r
+                    cTime = (int) (new Date().getTime());\r
+\r
+                    if ((int)(cTime - _startTime) > ((_kaTimer*3/4)*1000)) {\r
+                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
+                        COPSKAMsg msg = new COPSKAMsg();\r
+\r
+                        msg.add(hdr);\r
+\r
+                        COPSTransceiver.sendMsg(msg, _sock);\r
+                        _lastSendKa = new Date();\r
+                    }\r
+                }\r
+\r
+                try {\r
+                    Thread.sleep(500);\r
+                } catch (Exception e) {};\r
+\r
+            }\r
+        } catch (Exception e) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+        }\r
+\r
+        // connection closed by server\r
+        // COPSDebug.out(getClass().getName(),"Connection closed by client");\r
+        try {\r
+            _sock.close();\r
+        } catch (IOException e) {};\r
+\r
+        // Notify all Request State Managers\r
+        try {\r
+            notifyCloseAllReqStateMan();\r
+        } catch (COPSPdpException e) {};\r
+    }\r
+\r
+    /**\r
+     * Gets a COPS message from the socket and processes it\r
+     * @param    conn Socket connected to the PEP\r
+     * @return Type of COPS message\r
+     */\r
+    private byte processMessage(Socket conn)\r
+    throws COPSPdpException, COPSException, IOException {\r
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
+\r
+        if (msg.getHeader().isAClientClose()) {\r
+            handleClientCloseMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_CC;\r
+        } else if (msg.getHeader().isAKeepAlive()) {\r
+            handleKeepAliveMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_KA;\r
+        } else if (msg.getHeader().isARequest()) {\r
+            handleRequestMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_REQ;\r
+        } else if (msg.getHeader().isAReport()) {\r
+            handleReportMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_RPT;\r
+        } else if (msg.getHeader().isADeleteReq()) {\r
+            handleDeleteRequestMsg(conn, msg);\r
+            return COPSHeader.COPS_OP_DRQ;\r
+        } else if (msg.getHeader().isASyncComplete()) {\r
+            handleSyncComplete(conn, msg);\r
+            return COPSHeader.COPS_OP_SSC;\r
+        } else {\r
+            throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Handle Client Close Message, close the passed connection\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     *\r
+     * <Client-Close> ::= <Common Header>\r
+     *                      <Error>\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     */\r
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
+        _error = cMsg.getError();\r
+\r
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
+\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+            }\r
+\r
+            conn.close();\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Gets the occurred COPS Error\r
+     * @return   <tt>COPSError</tt> object\r
+     */\r
+    protected COPSError getError()  {\r
+        return _error;\r
+    }\r
+\r
+    /**\r
+     * Handle Keep Alive Message\r
+     *\r
+     * <Keep-Alive> ::= <Common Header>\r
+     *                  [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
+        COPSKAMsg cMsg = (COPSKAMsg) msg;\r
+\r
+        COPSKAMsg kaMsg = (COPSKAMsg) msg;\r
+        try {\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+            }\r
+\r
+            kaMsg.writeData(conn);\r
+        } catch (Exception unae) { };\r
+    }\r
+\r
+    /**\r
+     * Handle Delete Request Message\r
+     *\r
+     * <Delete Request> ::= <Common Header>\r
+     *                      <Client Handle>\r
+     *                      <Reason>\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;\r
+        // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +\r
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        // Delete clientHandler\r
+        if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {\r
+            // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +\r
+            //  cMsg.getClientHandle().getId().getData());\r
+        }\r
+\r
+        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processDeleteRequestState(cMsg);\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * Handle Request Message\r
+     *\r
+     * <Request> ::= <Common Header>\r
+     *                  <Client Handle>\r
+     *                  <Context>\r
+     *                  *(<Named ClientSI>)\r
+     *                  [<Integrity>]\r
+     * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleRequestMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+\r
+        COPSReqMsg reqMsg = (COPSReqMsg) msg;\r
+        COPSContext cntxt = reqMsg.getContext();\r
+        COPSHeader header = reqMsg.getHeader();\r
+        //short reqType = cntxt.getRequestType();\r
+        short cType   = header.getClientType();\r
+\r
+        // Support\r
+        if (reqMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        COPSPdpReqStateMan man;\r
+        man = (COPSPdpReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+\r
+            man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());\r
+            _managerMap.put(reqMsg.getClientHandle().getId().str(),man);\r
+            man.setDataProcess(_process);\r
+            man.initRequestState(_sock);\r
+\r
+            // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +\r
+            //    header.getClientType() + " msgType=" +\r
+            //    cntxt.getMessageType() + ", connId=" + conn.toString());\r
+        }\r
+\r
+        man.processRequest(reqMsg);\r
+    }\r
+\r
+    /**\r
+     * Handle Report Message\r
+     *\r
+     * <Report State> ::= <Common Header>\r
+     *                      <Client Handle>\r
+     *                      <Report Type>\r
+     *                      *(<Named ClientSI>)\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not support [<Integrity>]\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleReportMsg(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSReportMsg repMsg = (COPSReportMsg) msg;\r
+        // COPSHandle handle = repMsg.getClientHandle();\r
+        // COPSHeader header = repMsg.getHeader();\r
+\r
+        // Support\r
+        if (repMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processReport(repMsg);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Method handleSyncComplete\r
+     *\r
+     * @param    conn                a  Socket\r
+     * @param    msg                 a  COPSMsg\r
+     *\r
+     */\r
+    private void handleSyncComplete(Socket conn, COPSMsg msg)\r
+    throws COPSPdpException {\r
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
+        // COPSHandle handle = cMsg.getClientHandle();\r
+        // COPSHeader header = cMsg.getHeader();\r
+\r
+        // Support\r
+        if (cMsg.getIntegrity() != null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+        }\r
+\r
+        COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+        if (man == null) {\r
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+        } else {\r
+            man.processSyncComplete(cMsg);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Requests a COPS sync from the PEP\r
+     * @throws COPSException\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void syncAllRequestState()\r
+    throws COPSException, COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(handle);\r
+\r
+                man.syncRequestState();\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyCloseAllReqStateMan()\r
+    throws COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processClosedConnection(_error);\r
+            }\r
+        }\r
+    }\r
+\r
+    private void notifyNoKAAllReqStateMan()\r
+    throws COPSPdpException {\r
+        if (_managerMap.size() > 0) {\r
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+                String handle = (String) e.nextElement();\r
+                COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(handle);\r
+\r
+                man.processNoKAConnection();\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpDataProcess.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpDataProcess.java
new file mode 100644 (file)
index 0000000..8491774
--- /dev/null
@@ -0,0 +1,83 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpdp;\r
+\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.stack.COPSError;\r
+\r
+/**\r
+ * Abstract class for implementing policy data processing classes for provisioning PDPs.\r
+ */\r
+abstract public class COPSPdpDataProcess {\r
+    /**\r
+     * Gets the policies to be uninstalled\r
+     * @param man   The associated request state manager\r
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
+     */\r
+    abstract public Hashtable getRemovePolicy(COPSPdpReqStateMan man);\r
+    /**\r
+     * Gets the policies to be installed\r
+     * @param man   The associated request state manager\r
+     * @return A <tt>Vector</tt> holding the policies to be uninstalled\r
+     */\r
+    abstract public Hashtable getInstallPolicy(COPSPdpReqStateMan man);\r
+    /**\r
+     * Makes a decision from the supplied request data\r
+     * @param man   The associated request state manager\r
+     * @param reqSIs    Client specific data suppplied in the COPS request\r
+     */\r
+    abstract public void setClientData(COPSPdpReqStateMan man, Hashtable reqSIs);\r
+    /**\r
+     * Builds a failure report\r
+     * @param man   The associated request state manager\r
+     * @param reportSIs Report data\r
+     */\r
+    abstract public void failReport (COPSPdpReqStateMan man, Hashtable reportSIs);\r
+    /**\r
+     * Builds a success report\r
+     * @param man   The associated request state manager\r
+     * @param reportSIs Report data\r
+     */\r
+    abstract public void successReport (COPSPdpReqStateMan man, Hashtable reportSIs);\r
+    /**\r
+     * Builds an accounting report\r
+     * @param man   The associated request state manager\r
+     * @param reportSIs Report data\r
+     */\r
+    abstract public void acctReport (COPSPdpReqStateMan man, Hashtable reportSIs);\r
+    /**\r
+     * Notifies that no accounting report has been received\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void notifyNoAcctReport (COPSPdpReqStateMan man);\r
+\r
+    /**\r
+     * Notifies a keep-alive timeout\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void notifyNoKAliveReceived (COPSPdpReqStateMan man);\r
+\r
+    /**\r
+      * Notifies that the connection has been closed\r
+      * @param man  The associated request state manager\r
+      * @param error Reason\r
+      */\r
+    public abstract void notifyClosedConnection (COPSPdpReqStateMan man, COPSError error);\r
+\r
+    /**\r
+     * Notifies that a request state has been deleted\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void notifyDeleteRequestState (COPSPdpReqStateMan man);\r
+\r
+    /**\r
+     * Notifies that a request state has been closed\r
+     * @param man   The associated request state manager\r
+     */\r
+    public abstract void closeRequestState(COPSPdpReqStateMan man);\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpException.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpException.java
new file mode 100644 (file)
index 0000000..fc4c74d
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpMsgSender.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpMsgSender.java
new file mode 100644 (file)
index 0000000..a892b7f
--- /dev/null
@@ -0,0 +1,441 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpdp;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDecision;\r
+import org.umu.cops.stack.COPSDecisionMsg;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSPrEPD;\r
+import org.umu.cops.stack.COPSPrID;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * COPS message transceiver class for provisioning connections at the PDP side.\r
+ */\r
+public class COPSPdpMsgSender {\r
+\r
+    /**\r
+     * Socket connected to PEP\r
+     */\r
+    protected Socket _sock;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     * COPS client handle used to uniquely identify a particular\r
+     * PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Creates a COPSPepMsgSender\r
+     *\r
+     * @param clientType        COPS client-type\r
+     * @param clientHandle      Client handle\r
+     * @param sock              Socket to the PEP\r
+     */\r
+    public COPSPdpMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
+        // COPS Handle\r
+        _handle = clientHandle;\r
+        _clientType = clientType;\r
+\r
+        _sock = sock;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return   Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Sends a decision message\r
+     * @param removeDecs    Decisions to be removed\r
+     * @param installDecs   Decisions to be installed\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendDecision(Hashtable removeDecs, Hashtable installDecs)\r
+    throws COPSPdpException {\r
+        /* <Decision Message> ::= <Common Header: Flag SOLICITED>\r
+         *                          <Client Handle>\r
+         *                          *(<Decision>) | <Error>\r
+         *                          [<Integrity>]\r
+         * <Decision> ::= <Context>\r
+         *                  <Decision: Flags>\r
+         *                  [<Named Decision Data: Provisioning>]\r
+         * <Decision: Flags> ::= <Command-Code> NULLFlag\r
+         * <Command-Code> ::= NULLDecision | Install | Remove\r
+         * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
+         * <Install Decision> ::= *(<PRID> <EPD>)\r
+         * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
+         *\r
+         * Very important, this is actually being treated like this:\r
+         * <Install Decision> ::= <PRID> | <EPD>\r
+         * <Remove Decision> ::= <PRID> | <PPRID>\r
+         *\r
+        */\r
+\r
+        // Common Header with the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+        hdr.setFlag(COPSHeader.COPS_FLAG_SOLICITED);\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle handle = new COPSHandle();\r
+        handle.setId(getClientHandle().getId());\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(handle);\r
+\r
+            // Decisions (no flags supplied)\r
+            //  <Context>\r
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+\r
+            // Remove Decisions\r
+            //  <Decision: Flags>\r
+            if (removeDecs.size() > 0) {\r
+                COPSDecision rdec1 = new COPSDecision();\r
+                rdec1.setCmdCode(COPSDecision.DEC_REMOVE);\r
+\r
+                decisionMsg.addDecision(rdec1, cntxt);\r
+\r
+                for (Enumeration e = removeDecs.keys() ; e.hasMoreElements() ;) {\r
+                    String strprid = (String) e.nextElement();\r
+                    String strepd = (String) removeDecs.get(strprid);\r
+\r
+                    //  <Named Decision Data: Provisioning> (PRID)\r
+                    COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                    COPSPrID prid = new COPSPrID();\r
+                    prid.setData(new COPSData(strprid));\r
+                    dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+                    //  <Named Decision Data: Provisioning> (EPD)\r
+                    COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                    COPSPrEPD epd = new COPSPrEPD();\r
+                    epd.setData(new COPSData(strepd));\r
+                    dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                    decisionMsg.addDecision(dec2, cntxt);\r
+                    decisionMsg.addDecision(dec3, cntxt);\r
+                }\r
+            }\r
+\r
+            // Install Decisions\r
+            //  <Decision: Flags>\r
+            if (installDecs.size() > 0) {\r
+                COPSDecision idec1 = new COPSDecision();\r
+                idec1.setCmdCode(COPSDecision.DEC_INSTALL);\r
+\r
+                decisionMsg.addDecision(idec1, cntxt);\r
+\r
+                for (Enumeration e = installDecs.keys() ; e.hasMoreElements() ;) {\r
+                    String strprid = (String) e.nextElement();\r
+                    String strepd = (String) installDecs.get(strprid);\r
+\r
+                    //  <Named Decision Data: Provisioning> (PRID)\r
+                    COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                    COPSPrID prid = new COPSPrID();\r
+                    prid.setData(new COPSData(strprid));\r
+                    dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+                    //  <Named Decision Data: Provisioning> (EPD)\r
+                    COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                    COPSPrEPD epd = new COPSPrEPD();\r
+                    epd.setData(new COPSData(strepd));\r
+                    dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                    decisionMsg.addDecision(dec2, cntxt);\r
+                    decisionMsg.addDecision(dec3, cntxt);\r
+                }\r
+\r
+                /**\r
+                COPSIntegrity intr = new COPSIntegrity();\r
+                intr.setKeyId(19);\r
+                intr.setSeqNum(9);\r
+                intr.setKeyDigest(new COPSData("KEY DIGEST"));\r
+                decisionMsg.add(intr);\r
+                /**/\r
+            }\r
+        } catch (COPSException e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        //** Send the decision\r
+        //**\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a decision message which was not requested by the PEP\r
+     * @param removeDecs    Decisions to be removed\r
+     * @param installDecs   Decisions to be installed\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendUnsolicitedDecision(Hashtable removeDecs, Hashtable installDecs)\r
+    throws COPSPdpException {\r
+        //** Example of an UNSOLICITED decision\r
+        //**\r
+\r
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
+         *                          <Client Handle>\r
+         *                          *(<Decision>) | <Error>\r
+         *                          [<Integrity>]\r
+         * <Decision> ::= <Context>\r
+         *                  <Decision: Flags>\r
+         *                  [<Named Decision Data: Provisioning>]\r
+         * <Decision: Flags> ::= <Command-Code> NULLFlag\r
+         * <Command-Code> ::= NULLDecision | Install | Remove\r
+         * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
+         * <Install Decision> ::= *(<PRID> <EPD>)\r
+         * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
+         *\r
+         * Very important, this is actually being treated like this:\r
+         * <Install Decision> ::= <PRID> | <EPD>\r
+         * <Remove Decision> ::= <PRID> | <PPRID>\r
+         *\r
+        */\r
+\r
+        // Common Header with the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle handle = new COPSHandle();\r
+        handle.setId(getClientHandle().getId());\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(handle);\r
+\r
+            // Decisions (no flags supplied)\r
+            //  <Context>\r
+            COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+\r
+            // Remove Decisions\r
+            //  <Decision: Flags>\r
+            COPSDecision rdec1 = new COPSDecision();\r
+            rdec1.setCmdCode(COPSDecision.DEC_REMOVE);\r
+\r
+            decisionMsg.addDecision(rdec1, cntxt);\r
+\r
+            for (Enumeration e = removeDecs.keys() ; e.hasMoreElements() ;) {\r
+                String strprid = (String) e.nextElement();\r
+                String strepd = (String) removeDecs.get(strprid);\r
+\r
+                //  <Named Decision Data: Provisioning> (PRID)\r
+                COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                COPSPrID prid = new COPSPrID();\r
+                prid.setData(new COPSData(strprid));\r
+                dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+                //  <Named Decision Data: Provisioning> (EPD)\r
+                COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                COPSPrEPD epd = new COPSPrEPD();\r
+                epd.setData(new COPSData(strepd));\r
+                dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                decisionMsg.addDecision(dec2, cntxt);\r
+                decisionMsg.addDecision(dec3, cntxt);\r
+            }\r
+\r
+            // Install Decisions\r
+            //  <Decision: Flags>\r
+            COPSDecision idec1 = new COPSDecision();\r
+            idec1.setCmdCode(COPSDecision.DEC_INSTALL);\r
+\r
+            decisionMsg.addDecision(idec1, cntxt);\r
+\r
+            for (Enumeration e = installDecs.keys() ; e.hasMoreElements() ;) {\r
+                String strprid = (String) e.nextElement();\r
+                String strepd = (String) installDecs.get(strprid);\r
+\r
+                //  <Named Decision Data: Provisioning> (PRID)\r
+                COPSDecision dec2 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                COPSPrID prid = new COPSPrID();\r
+                prid.setData(new COPSData(strprid));\r
+                dec2.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+                //  <Named Decision Data: Provisioning> (EPD)\r
+                COPSDecision dec3 = new COPSDecision(COPSDecision.DEC_NAMED);\r
+                COPSPrEPD epd = new COPSPrEPD();\r
+                epd.setData(new COPSData(strepd));\r
+                dec3.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                decisionMsg.addDecision(dec2, cntxt);\r
+                decisionMsg.addDecision(dec3, cntxt);\r
+            }\r
+\r
+            /**\r
+            COPSIntegrity intr = new COPSIntegrity();\r
+            intr.setKeyId(19);\r
+            intr.setSeqNum(9);\r
+            intr.setKeyDigest(new COPSData("KEY DIGEST"));\r
+            decisionMsg.add(intr);\r
+            /**/\r
+        } catch (COPSException e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        //** Send the decision\r
+        //**\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a message asking that the request state be deleted\r
+     * @throws   COPSPdpException\r
+     */\r
+    public void sendDeleteRequestState()\r
+    throws COPSPdpException {\r
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
+         *                          <Client Handle>\r
+         *                          *(<Decision>)\r
+         *                          [<Integrity>]\r
+         * <Decision> ::= <Context>\r
+         *                  <Decision: Flags>\r
+         * <Decision: Flags> ::= Remove Request-State\r
+         *\r
+        */\r
+\r
+        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = new COPSHandle();\r
+        clienthandle.setId(_handle.getId());\r
+\r
+        // Decisions\r
+        //  <Context>\r
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+        //  <Decision: Flags>\r
+        COPSDecision dec = new COPSDecision();\r
+        dec.setCmdCode(COPSDecision.DEC_REMOVE);\r
+        dec.setFlags(COPSDecision.F_REQSTATE);\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(clienthandle);\r
+            decisionMsg.addDecision(dec, cntxt);\r
+        } catch (COPSException e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a request asking that a new request state be created\r
+     * @throws   COPSPdpException\r
+     */\r
+    public void sendOpenNewRequestState()\r
+    throws COPSPdpException {\r
+        /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>\r
+         *                          <Client Handle>\r
+         *                          *(<Decision>)\r
+         *                          [<Integrity>]\r
+         * <Decision> ::= <Context>\r
+         *                  <Decision: Flags>\r
+         * <Decision: Flags> ::= Install Request-State\r
+         *\r
+        */\r
+\r
+        // Common Header with the same ClientType as the request (default UNSOLICITED)\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_DEC, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = new COPSHandle();\r
+        clienthandle.setId(_handle.getId());\r
+\r
+        // Decisions\r
+        //  <Context>\r
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG, (short) 0);\r
+        //  <Decision: Flags>\r
+        COPSDecision dec = new COPSDecision();\r
+        dec.setCmdCode(COPSDecision.DEC_INSTALL);\r
+        dec.setFlags(COPSDecision.F_REQSTATE);\r
+\r
+        COPSDecisionMsg decisionMsg = new COPSDecisionMsg();\r
+        try {\r
+            decisionMsg.add(hdr);\r
+            decisionMsg.add(clienthandle);\r
+            decisionMsg.addDecision(dec, cntxt);\r
+        } catch (COPSException e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            decisionMsg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Sends a message asking for a COPS sync operation\r
+     * @throws COPSPdpException\r
+     */\r
+    public void sendSyncRequestState()\r
+    throws COPSPdpException {\r
+        /* <Synchronize State Request>  ::= <Common Header>\r
+         *                                  [<Client Handle>]\r
+         *                                  [<Integrity>]\r
+         */\r
+\r
+        // Common Header with the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSQ, getClientType());\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = new COPSHandle();\r
+        clienthandle.setId(_handle.getId());\r
+\r
+        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
+        try {\r
+            msg.add(hdr);\r
+            msg.add(clienthandle);\r
+        } catch (Exception e) {\r
+            throw new COPSPdpException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpReqStateMan.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpReqStateMan.java
new file mode 100644 (file)
index 0000000..0698951
--- /dev/null
@@ -0,0 +1,390 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpdp;\r
+\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSClientSI;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSPrObjBase;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReportType;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * State manager class for provisioning requests, at the PDP side.\r
+ */\r
+public class COPSPdpReqStateMan {\r
+\r
+    /**\r
+     * Request State created\r
+     */\r
+    public final static short ST_CREATE = 1;\r
+    /**\r
+     * Request received\r
+     */\r
+    public final static short ST_INIT = 2;\r
+    /**\r
+     * Decisions sent\r
+     */\r
+    public final static short ST_DECS = 3;\r
+    /**\r
+     * Report received\r
+     */\r
+    public final static short ST_REPORT = 4;\r
+    /**\r
+     * Request State finalized\r
+     */\r
+    public final static short ST_FINAL = 5;\r
+    /**\r
+     * New Request State solicited\r
+     */\r
+    public final static short ST_NEW = 6;\r
+    /**\r
+     * Delete Request State solicited\r
+     */\r
+    public final static short ST_DEL = 7;\r
+    /**\r
+     * SYNC request sent\r
+     */\r
+    public final static short ST_SYNC = 8;\r
+    /**\r
+     * SYNC completed\r
+     */\r
+    public final static short ST_SYNCALL = 9;\r
+    /**\r
+     * Close connection received\r
+     */\r
+    public final static short ST_CCONN = 10;\r
+    /**\r
+     * Keep-alive timeout\r
+     */\r
+    public final static short ST_NOKA = 11;\r
+    /**\r
+     * Accounting timeout\r
+     */\r
+    public final static short ST_ACCT = 12;\r
+\r
+    /**\r
+     * COPS client-type that identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     *  COPS client handle used to uniquely identify a particular\r
+     *  PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Object for performing policy data processing\r
+     */\r
+    protected COPSPdpDataProcess _process;\r
+\r
+    /**\r
+     *  Current state of the request being managed\r
+     */\r
+    protected short _status;\r
+\r
+    /** COPS message transceiver used to send COPS messages */\r
+    protected COPSPdpMsgSender _sender;\r
+\r
+    /**\r
+     * Creates a request state manager\r
+     * @param clientType    Client-type\r
+     * @param clientHandle  Client handle\r
+     */\r
+    public COPSPdpReqStateMan(short clientType, String clientHandle) {\r
+        // COPS Handle\r
+        _handle = new COPSHandle();\r
+        COPSData id = new COPSData(clientHandle);\r
+        _handle.setId(id);\r
+        // client-type\r
+        _clientType = clientType;\r
+\r
+        _status = ST_CREATE;\r
+    }\r
+\r
+    /**\r
+     * Gets the client handle\r
+     * @return   Client's <tt>COPSHandle</tt>\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Gets the client-type\r
+     * @return   Client-type value\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets the status of the request\r
+     * @return      Request state value\r
+     */\r
+    public short getStatus() {\r
+        return _status;\r
+    }\r
+\r
+    /**\r
+     * Gets the policy data processing object\r
+     * @return   Policy data processing object\r
+     */\r
+    public COPSPdpDataProcess getDataProcess() {\r
+        return _process;\r
+    }\r
+\r
+    /**\r
+     * Sets the policy data processing object\r
+     * @param   process Policy data processing object\r
+     */\r
+    public void setDataProcess(COPSPdpDataProcess process) {\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Called when COPS sync is completed\r
+     * @param    repMsg              COPS sync message\r
+     * @throws   COPSPdpException\r
+     */\r
+    protected void processSyncComplete(COPSSyncStateMsg repMsg)\r
+    throws COPSPdpException {\r
+\r
+        _status = ST_SYNCALL;\r
+\r
+        // maybe we should notifySyncComplete ...\r
+    }\r
+\r
+    /**\r
+     * Initializes a new request state over a socket\r
+     * @param sock  Socket to the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void initRequestState(Socket sock)\r
+    throws COPSPdpException {\r
+        // Inits an object for sending COPS messages to the PEP\r
+        _sender = new COPSPdpMsgSender(_clientType, _handle, sock);\r
+\r
+        // Initial state\r
+        _status = ST_INIT;\r
+    }\r
+\r
+    /**\r
+     * Processes a COPS request\r
+     * @param msg   COPS request received from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processRequest(COPSReqMsg msg)\r
+    throws COPSPdpException {\r
+\r
+        COPSHeader hdrmsg = msg.getHeader();\r
+        COPSHandle handlemsg = msg.getClientHandle();\r
+        COPSContext contextmsg = msg.getContext();\r
+\r
+        //** Analyze the request\r
+        //**\r
+\r
+        /* <Request> ::= <Common Header>\r
+        *                   <Client Handle>\r
+        *                   <Context>\r
+        *                   *(<Named ClientSI>)\r
+        *                   [<Integrity>]\r
+        * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
+        *\r
+        * Very important, this is actually being treated like this:\r
+        * <Named ClientSI> ::= <PRID> | <EPD>\r
+        *\r
+\r
+        // Named ClientSI\r
+        Vector clientSIs = msg.getClientSI();\r
+        Hashtable reqSIs = new Hashtable(40);\r
+        String strobjprid = new String();\r
+        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+\r
+            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());\r
+            switch (obj.getSNum())\r
+            {\r
+                case COPSPrObjBase.PR_PRID:\r
+                    strobjprid = obj.getData().str();\r
+                    break;\r
+                case COPSPrObjBase.PR_EPD:\r
+                    reqSIs.put(strobjprid, obj.getData().str());\r
+                    // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);\r
+                    // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());\r
+                    break;\r
+                default:\r
+                    break;\r
+            }\r
+        }\r
+\r
+        //** Here we must retrieve a decision depending on\r
+        //** the supplied ClientSIs\r
+        // reqSIs is a hashtable with the prid and epds\r
+\r
+        // ................\r
+        //\r
+        Hashtable removeDecs = new Hashtable();\r
+        Hashtable installDecs = new Hashtable();\r
+        _process.setClientData(this, reqSIs);\r
+\r
+        removeDecs = _process.getRemovePolicy(this);\r
+        installDecs = _process.getInstallPolicy(this);\r
+\r
+        //** We create the SOLICITED decision\r
+        //**\r
+        _sender.sendDecision(removeDecs, installDecs);\r
+        _status = ST_DECS;\r
+        */\r
+    }\r
+\r
+    /**\r
+     * Processes a report\r
+     * @param msg   Report message from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processReport(COPSReportMsg msg)\r
+    throws COPSPdpException {\r
+\r
+        //** Analyze the report\r
+        //**\r
+\r
+        /*\r
+         * <Report State> ::= <Common Header>\r
+         *                      <Client Handle>\r
+         *                      <Report Type>\r
+         *                      *(<Named ClientSI>)\r
+         *                      [<Integrity>]\r
+         * <Named ClientSI: Report> ::= <[<GPERR>] *(<report>)>\r
+         * <report> ::= <ErrorPRID> <CPERR> *(<PRID><EPD>)\r
+         *\r
+         * Important, <Named ClientSI> is not parsed\r
+        */\r
+\r
+        // COPSHeader hdrmsg = msg.getHeader();\r
+        // COPSHandle handlemsg = msg.getClientHandle();\r
+\r
+        // Report Type\r
+        COPSReportType rtypemsg = msg.getReport();\r
+\r
+        // Named ClientSI\r
+        Vector clientSIs = msg.getClientSI();\r
+        Hashtable repSIs = new Hashtable(40);\r
+        String strobjprid = new String();\r
+        for (Enumeration e = clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+\r
+            COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());\r
+            switch (obj.getSNum()) {\r
+            case COPSPrObjBase.PR_PRID:\r
+                strobjprid = obj.getData().str();\r
+                break;\r
+            case COPSPrObjBase.PR_EPD:\r
+                repSIs.put(strobjprid, obj.getData().str());\r
+                // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);\r
+                // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());\r
+                break;\r
+            default:\r
+                break;\r
+            }\r
+        }\r
+\r
+        //** Here we must act in accordance with\r
+        //** the report received\r
+        if (rtypemsg.isSuccess()) {\r
+            _status = ST_REPORT;\r
+            _process.successReport(this, repSIs);\r
+        } else if (rtypemsg.isFailure()) {\r
+            _status = ST_REPORT;\r
+            _process.failReport(this, repSIs);\r
+        } else if (rtypemsg.isAccounting()) {\r
+            _status = ST_ACCT;\r
+            _process.acctReport(this, repSIs);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Called when connection is closed\r
+     * @param error Reason\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processClosedConnection(COPSError error)\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.notifyClosedConnection(this, error);\r
+\r
+        _status = ST_CCONN;\r
+    }\r
+\r
+    /**\r
+     * Called when no keep-alive is received\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processNoKAConnection()\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.notifyNoKAliveReceived(this);\r
+\r
+        _status = ST_NOKA;\r
+    }\r
+\r
+    /**\r
+     * Deletes the request state\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void finalizeRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendDeleteRequestState();\r
+        _status = ST_FINAL;\r
+    }\r
+\r
+    /**\r
+     * Asks for a COPS sync\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void syncRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendSyncRequestState();\r
+        _status = ST_SYNC;\r
+    }\r
+\r
+    /**\r
+     * Opens a new request state\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void openNewRequestState()\r
+    throws COPSPdpException {\r
+        _sender.sendOpenNewRequestState();\r
+        _status = ST_NEW;\r
+    }\r
+\r
+    /**\r
+     * Processes a COPS delete message\r
+     * @param dMsg  <tt>COPSDeleteMsg</tt> received from the PEP\r
+     * @throws COPSPdpException\r
+     */\r
+    protected void processDeleteRequestState(COPSDeleteMsg dMsg)\r
+    throws COPSPdpException {\r
+        if (_process != null)\r
+            _process.closeRequestState(this);\r
+\r
+        _status = ST_DEL;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepAgent.java b/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepAgent.java
new file mode 100644 (file)
index 0000000..343d40c
--- /dev/null
@@ -0,0 +1,319 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpep;\r
+\r
+import java.io.IOException;\r
+import java.net.InetAddress;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.stack.COPSAcctTimer;\r
+import org.umu.cops.stack.COPSClientAcceptMsg;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSClientOpenMsg;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKATimer;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSPepId;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * This is a provisioning COPS PEP. Responsible for making\r
+ * connection to the PDP and maintaining it\r
+ */\r
+public class COPSPepAgent {\r
+\r
+    /**\r
+        PEP's Identifier\r
+     */\r
+    private String _pepID;\r
+\r
+    /**\r
+        PEP's client-type\r
+     */\r
+    private short _clientType;\r
+\r
+    /**\r
+        PDP host name\r
+     */\r
+    private String _psHost;\r
+\r
+    /**\r
+        PDP port\r
+     */\r
+    private int _psPort;\r
+\r
+    /**\r
+        PEP-PDP connection manager\r
+     */\r
+    private COPSPepConnection _conn;\r
+\r
+    /**\r
+        COPS error returned by PDP\r
+     */\r
+    private COPSError _error;\r
+\r
+    /**\r
+     * Creates a PEP agent\r
+     * @param    pepID              PEP-ID\r
+     * @param    clientType         Client-type\r
+     */\r
+    public COPSPepAgent(String pepID, short clientType) {\r
+        _pepID = pepID;\r
+        _clientType = clientType;\r
+    }\r
+\r
+    /**\r
+     * Creates a PEP agent with a PEP-ID equal to "noname"\r
+     * @param    clientType         Client-type\r
+     */\r
+    public COPSPepAgent(short clientType) {\r
+\r
+        // PEPId\r
+        try {\r
+            _pepID = InetAddress.getLocalHost().getHostName();\r
+        } catch (Exception e) {\r
+            _pepID = "noname";\r
+        }\r
+\r
+        _clientType = clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets the identifier of the PEP\r
+     * @return  PEP-ID\r
+     */\r
+    public String getPepID() {\r
+        return _pepID;\r
+    }\r
+\r
+    /**\r
+     * Gets the COPS client-type\r
+     * @return  PEP's client-type\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Gets PDP host name\r
+     * @return  PDP host name\r
+     */\r
+    public String getPDPName() {\r
+        return _psHost;\r
+    }\r
+\r
+    /**\r
+     * Gets the port of the PDP\r
+     * @return  PDP port\r
+     */\r
+    public int getPDPPort() {\r
+        return _psPort;\r
+    }\r
+\r
+    /**\r
+     * Connects to a PDP\r
+     * @param    psHost              PDP host name\r
+     * @param    psPort              PDP port\r
+     * @return   <tt>true</tt> if PDP accepts the connection; <tt>false</tt> otherwise\r
+     * @throws   java.net.UnknownHostException\r
+     * @throws   java.io.IOException\r
+     * @throws   COPSException\r
+     * @throws   COPSPepException\r
+     */\r
+    public boolean connect(String psHost, int psPort)\r
+    throws UnknownHostException, IOException, COPSException, COPSPepException {\r
+\r
+        // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");\r
+        _psHost = psHost;\r
+        _psPort = psPort;\r
+\r
+        // Check whether it already exists\r
+        if (_conn == null)\r
+            _conn = processConnection(psHost,psPort);\r
+        else {\r
+            // Check if it's closed\r
+            if (_conn.isClosed()) {\r
+                _conn = processConnection(psHost,psPort);\r
+            } else {\r
+                disconnect(null);\r
+                _conn = processConnection(psHost,psPort);\r
+            }\r
+        }\r
+\r
+        return (_conn != null);\r
+    }\r
+\r
+    /**\r
+     * Gets the connection manager\r
+     * @return  PEP-PDP connection manager object\r
+     */\r
+    public COPSPepConnection getConnection () {\r
+        return (_conn);\r
+    }\r
+\r
+    /**\r
+     * Gets the COPS error returned by the PDP\r
+     * @return   <tt>COPSError</tt> returned by PDP\r
+     */\r
+    public COPSError getConnectionError()   {\r
+        return _error;\r
+    }\r
+\r
+    /**\r
+     * Disconnects from the PDP\r
+     * @param error Reason\r
+     * @throws COPSException\r
+     * @throws IOException\r
+     */\r
+    public void disconnect(COPSError error)\r
+    throws COPSException, IOException {\r
+\r
+        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
+        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
+        closeMsg.add(cHdr);\r
+        if (error != null)\r
+            closeMsg.add(error);\r
+\r
+        closeMsg.writeData(_conn.getSocket());\r
+        _conn.close();\r
+        _conn = null;\r
+    }\r
+\r
+    /**\r
+     * Adds a request state to the connection manager.\r
+     * @return  The newly created connection manager\r
+     * @throws COPSPepException\r
+     * @throws COPSException\r
+     */\r
+    public COPSPepReqStateMan addRequestState (String handle, COPSPepDataProcess process)\r
+    throws COPSPepException, COPSException {\r
+        if (_conn != null) {\r
+            return _conn.addRequestState(handle, process);\r
+        }\r
+        return null;\r
+    }\r
+\r
+\r
+    /**\r
+     * Queries the connection manager to delete a request state\r
+     * @param man   Request state manager\r
+     * @throws COPSPepException\r
+     * @throws COPSException\r
+     */\r
+    public void deleteRequestState (COPSPepReqStateMan man)\r
+    throws COPSPepException, COPSException {\r
+        if (_conn != null)\r
+            _conn.deleteRequestState(man);\r
+    }\r
+\r
+    /**\r
+     * Gets all the request state managers\r
+     * @return  A <tt>Hashtable</tt> holding all active request state managers\r
+     */\r
+    public Hashtable getReqStateMans() {\r
+        if (_conn != null)\r
+            return _conn.getReqStateMans();\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Establish connection to PDP's IP address\r
+     *\r
+     * <Client-Open> ::= <Common Header>\r
+     *                  <PEPID>\r
+     *                  [<ClientSI>]\r
+     *                  [<LastPDPAddr>]\r
+     *                  [<Integrity>]\r
+     *\r
+     * Not support [<ClientSI>], [<LastPDPAddr>], [<Integrity>]\r
+     *\r
+     * <Client-Accept> ::= <Common Header>\r
+     *                      <KA Timer>\r
+     *                      [<ACCT Timer>]\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not send [<Integrity>]\r
+     *\r
+     * <Client-Close> ::= <Common Header>\r
+     *                      <Error>\r
+     *                      [<PDPRedirAddr>]\r
+     *                      [<Integrity>]\r
+     *\r
+     * Not send [<PDPRedirAddr>], [<Integrity>]\r
+     *\r
+     * @throws   UnknownHostException\r
+     * @throws   IOException\r
+     * @throws   COPSException\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    private COPSPepConnection processConnection(String psHost, int psPort)\r
+    throws UnknownHostException, IOException, COPSException, COPSPepException {\r
+        // Build OPN\r
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_OPN, _clientType);\r
+\r
+        COPSPepId pepId = new COPSPepId();\r
+        COPSData d = new COPSData(_pepID);\r
+        pepId.setData(d);\r
+\r
+        COPSClientOpenMsg msg = new COPSClientOpenMsg();\r
+        msg.add(hdr);\r
+        msg.add(pepId);\r
+\r
+        // Create Socket and send OPN\r
+        InetAddress addr = InetAddress.getByName(psHost);\r
+        Socket socket = new Socket(addr,psPort);\r
+        msg.writeData(socket);\r
+\r
+        // Receive the response\r
+        COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);\r
+\r
+        if (recvmsg.getHeader().isAClientAccept()) {\r
+            COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;\r
+\r
+            // Support\r
+            if (cMsg.getIntegrity() != null) {\r
+                throw new COPSPepException("Unsupported object (Integrity)");\r
+            }\r
+\r
+            // Mandatory KATimer\r
+            COPSKATimer kt = cMsg.getKATimer();\r
+            if (kt == null)\r
+                throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");\r
+            short _kaTimeVal = kt.getTimerVal();\r
+\r
+            // ACTimer\r
+            COPSAcctTimer at = cMsg.getAcctTimer();\r
+            short _acctTimer = 0;\r
+            if (at != null)\r
+                _acctTimer = at.getTimerVal();\r
+\r
+            // Create the connection manager\r
+            COPSPepConnection conn = new COPSPepConnection(_clientType, socket);\r
+            conn.setKaTimer(_kaTimeVal);\r
+            conn.setAcctTimer(_acctTimer);\r
+            new Thread(conn).start();\r
+\r
+            return conn;\r
+        } else if (recvmsg.getHeader().isAClientClose()) {\r
+            COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;\r
+            _error = cMsg.getError();\r
+            socket.close();\r
+            return null;\r
+        } else { // messages of other types are not expected\r
+            throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepConnection.java b/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepConnection.java
new file mode 100644 (file)
index 0000000..0e888ce
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpep;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.umu.cops.common.COPSDebug;
+import org.umu.cops.stack.COPSClientCloseMsg;
+import org.umu.cops.stack.COPSContext;
+import org.umu.cops.stack.COPSDecision;
+import org.umu.cops.stack.COPSDecisionMsg;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSHeader;
+import org.umu.cops.stack.COPSKAMsg;
+import org.umu.cops.stack.COPSMsg;
+import org.umu.cops.stack.COPSSyncStateMsg;
+import org.umu.cops.stack.COPSTransceiver;
+
+/**
+ * COPSPepConnection represents a PEP-PDP Connection Manager.
+ * Responsible for processing messages received from PDP.
+ */
+public class COPSPepConnection implements Runnable {
+
+    /** Socket connected to PDP */
+    protected Socket _sock;
+
+    /** Time to wait responses (milliseconds), default is 10 seconds */
+    protected int _responseTime;
+
+    /** COPS Client-type */
+    protected short _clientType;
+
+    /**
+        Accounting timer value (secs)
+     */
+    protected short _acctTimer;
+
+    /**
+        Keep-alive timer value (secs)
+     */
+    protected short _kaTimer;
+
+    /**
+     *  Time of the latest keep-alive received
+     */
+    protected Date _lastRecKa;
+
+    /**
+        Opcode of the latest message sent
+    */
+    protected byte _lastmessage;
+
+    /**
+        Maps a COPS Client Handle to a Request State Manager
+     */
+    protected Hashtable _managerMap;
+    // map < String(COPSHandle), COPSPepReqStateMan>;
+
+    /**
+        COPS error returned by PDP
+     */
+    protected COPSError _error;
+
+    /**
+     * Creates a new PEP connection
+     * @param clientType    PEP's client-type
+     * @param sock          Socket connected to PDP
+     */
+    public COPSPepConnection(short clientType, Socket sock) {
+
+        _clientType = clientType;
+        _sock = sock;
+
+        // Timers
+        _acctTimer = 0;
+        _kaTimer = 0;
+        _responseTime = 10000;
+        _lastmessage = COPSHeader.COPS_OP_CAT;
+
+        _managerMap = new Hashtable(20);
+    }
+
+    /**
+     * Gets the response time
+     * @return  Response time value (msecs)
+     */
+    public int getResponseTime() {
+        return _responseTime;
+    }
+
+    /**
+     * Gets the socket connected to the PDP
+     * @return  Socket connected to PDP
+     */
+    public Socket getSocket() {
+        return _sock;
+    }
+
+    /**
+     * Gets keep-alive timer
+     * @return  Keep-alive timer value (secs)
+     */
+    public short getKaTimer () {
+        return _kaTimer;
+    }
+
+    /**
+     * Gets accounting timer
+     * @return  Accounting timer value (secs)
+     */
+    public short getAcctTimer () {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets active COPS handles
+     * @return  An <tt>Enumeration</tt> holding all active handles
+     */
+    protected Enumeration getHandles() {
+        return _managerMap.keys();
+    }
+
+    /**
+     * Gets all request state managers
+     * @return  A <tt>Hashatable</tt> holding all request state managers
+     */
+    protected Hashtable getReqStateMans() {
+        return _managerMap;
+    }
+
+    /**
+     * Checks whether the socket to the PDP is closed or not
+     * @return  <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise
+     */
+    public boolean isClosed() {
+        return _sock.isClosed();
+    }
+
+    /**
+     * Closes the socket
+     *
+     * @throws java.io.IOException
+     */
+    protected void close()
+    throws IOException {
+        _sock.close();
+    }
+
+    /**
+     * Gets the opcode of the lastest message sent
+     * @return  Message opcode
+     */
+    public byte getLastmessage() {
+        return _lastmessage;
+    }
+
+    /**
+     * Sets response time
+     * @param respTime  Response time value (msecs)
+     */
+    public void setResponseTime(int respTime) {
+        _responseTime = respTime;
+    };
+
+    /**
+     * Sets keep-alive timer
+     * @param kaTimer   Keep-alive timer value (secs)
+     */
+    public void setKaTimer (short kaTimer) {
+        _kaTimer = kaTimer;
+    }
+
+    /**
+     * Sets accounting timer
+     * @param acctTimer Accounting timer value (secs)
+     */
+    public void setAcctTimer (short acctTimer) {
+        _acctTimer = acctTimer;
+    }
+
+    /**
+     * Message-processing loop
+     */
+    public void run () {
+        Date _lastSendKa = new Date();
+        Date _lastSendAcc = new Date();
+        _lastRecKa = new Date();
+        try {
+            while (!_sock.isClosed()) {
+                if (_sock.getInputStream().available() != 0) {
+                    _lastmessage = processMessage(_sock);
+                    _lastRecKa = new Date();
+                }
+
+                // Keep Alive
+                if (_kaTimer > 0) {
+                    // Timeout at PDP
+                    int _startTime = (int) (_lastRecKa.getTime());
+                    int cTime = (int) (new Date().getTime());
+
+                    if ((int)(cTime - _startTime) > _kaTimer*1000) {
+                        _sock.close();
+                        // Notify all Request State Managers
+                        notifyNoKAAllReqStateMan();
+                    }
+
+                    // Send to PEP
+                    _startTime = (int) (_lastSendKa.getTime());
+                    cTime = (int) (new Date().getTime());
+
+                    if ((int)(cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {
+                        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);
+                        COPSKAMsg msg = new COPSKAMsg();
+
+                        msg.add(hdr);
+
+                        COPSTransceiver.sendMsg(msg, _sock);
+                        _lastSendKa = new Date();
+                    }
+                }
+
+                // Accounting
+                if (_acctTimer > 0) {
+                    int _startTime = (int) (_lastSendAcc.getTime());
+                    int cTime = (int) (new Date().getTime());
+
+                    if ((int)(cTime - _startTime) > ((_acctTimer*3/4)*1000)) {
+                        // Notify all Request State Managers
+                        notifyAcctAllReqStateMan();
+                        _lastSendAcc = new Date();
+                    }
+                }
+
+                try {
+                    Thread.sleep(500);
+                } catch (Exception e) {};
+            }
+        } catch (Exception e) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);
+        }
+
+        // connection closed by server
+        // COPSDebug.out(getClass().getName(),"Connection closed by server");
+        try {
+            _sock.close();
+        } catch (IOException e) {};
+
+        // Notify all Request State Managers
+        try {
+            notifyCloseAllReqStateMan();
+        } catch (COPSPepException e) {};
+    }
+
+    /**
+     * Gets a COPS message from the socket and processes it
+     * @param conn  Socket connected to the PDP
+     * @return COPS message type
+     * @throws COPSPepException
+     * @throws COPSException
+     * @throws IOException
+     */
+    protected byte processMessage(Socket conn)
+    throws COPSPepException, COPSException, IOException {
+        COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+
+        if (msg.getHeader().isAClientClose()) {
+            handleClientCloseMsg(conn, msg);
+            return COPSHeader.COPS_OP_CC;
+        } else if (msg.getHeader().isADecision()) {
+            handleDecisionMsg(conn, msg);
+            return COPSHeader.COPS_OP_DEC;
+        } else if (msg.getHeader().isASyncStateReq()) {
+            handleSyncStateReqMsg(conn, msg);
+            return COPSHeader.COPS_OP_SSQ;
+        } else if (msg.getHeader().isAKeepAlive()) {
+            handleKeepAliveMsg(conn, msg);
+            return COPSHeader.COPS_OP_KA;
+        } else {
+            throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+        }
+    }
+
+    /**
+     * Handle Client Close Message, close the passed connection
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     *
+     * <Client-Close> ::= <Common Header>
+     *                      <Error>
+     *                      [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     */
+    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
+        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+        _error = cMsg.getError();
+
+        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
+        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
+
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            }
+
+            conn.close();
+        } catch (Exception unae) { };
+    }
+
+    /**
+     * Method getError
+     *
+     * @return   a COPSError
+     *
+     */
+    protected COPSError getError()  {
+        return _error;
+    }
+
+    /**
+     * Handle Keep Alive Message
+     *
+     * <Keep-Alive> ::= <Common Header>
+     *                  [<Integrity>]
+     *
+     * Not support [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
+        COPSKAMsg cMsg = (COPSKAMsg) msg;
+
+        // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
+
+        try {
+            // Support
+            if (cMsg.getIntegrity() != null) {
+                COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,
+                              "Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            }
+
+            // should we do anything else?? ....
+
+        } catch (Exception unae) { };
+    }
+
+    /**
+     * 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
+     *
+     */
+    private void handleDecisionMsg(Socket conn, COPSMsg msg)
+    throws COPSPepException {
+        COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+        COPSHandle handle = dMsg.getClientHandle();
+        Hashtable decisions = dMsg.getDecisions();
+
+        for (Enumeration e = decisions.keys() ; e.hasMoreElements() ;) {
+
+            COPSContext context = (COPSContext) e.nextElement();
+            Vector v = (Vector) decisions.get(context);
+
+            Enumeration ee = v.elements();
+            if (ee.hasMoreElements()) {
+                COPSDecision decision = (COPSDecision) ee.nextElement();
+
+                // Get the associated manager
+                COPSPepReqStateMan manager = (COPSPepReqStateMan) _managerMap.get(handle.getId().str());
+                if (manager == null)
+                    COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+
+                // Check message type
+                if (decision.getFlags() == COPSDecision.F_REQSTATE) {
+                    if (decision.isRemoveDecision())
+                        // Delete Request State
+                        manager.processDeleteRequestState(dMsg);
+                    else
+                        // Open new Request State
+                        handleOpenNewRequestStateMsg(conn, handle);
+                } else
+                    // Decision
+                    manager.processDecision(dMsg);
+            }
+        }
+    }
+
+
+    /**
+     * Method handleOpenNewRequestStateMsg
+     *
+     * @param    conn                a  Socket
+     * @param    handle              a  COPSHandle
+     *
+     */
+    private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle)
+    throws COPSPepException {
+
+        COPSPepReqStateMan manager = (COPSPepReqStateMan) _managerMap.get(handle.getId().str());
+        if (manager == null)
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+
+        manager.processOpenNewRequestState();
+    }
+
+    /**
+     * Method handleSyncStateReqMsg
+     *
+     *              <Synchronize State> ::= <Common Header>
+     *                                      [<Client Handle>]
+     *                                      [<Integrity>]
+     *
+     * @param    conn                a  Socket
+     * @param    msg                 a  COPSMsg
+     *
+     */
+    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg)
+    throws COPSPepException {
+        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
+        // COPSHandle handle = cMsg.getClientHandle();
+        // COPSHeader header = cMsg.getHeader();
+
+        // Support
+        if (cMsg.getIntegrity() != null) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,
+                          "Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+        }
+
+        COPSPepReqStateMan manager = (COPSPepReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+        if (manager == null) {
+            COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+        } 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);
+        if (_managerMap.get(clientHandle) != null)
+            throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
+
+        manager.setDataProcess(process);
+        _managerMap.put(clientHandle,manager);
+        manager.initRequestState(_sock);
+        return manager;
+    }
+
+    /**
+     * Method deleteRequestState
+     *
+     * @param    manager             a  COPSPepReqStateMan
+     *
+     * @throws   COPSException
+     * @throws   COPSPepException
+     *
+     */
+    protected void deleteRequestState(COPSPepReqStateMan manager)
+    throws COPSException, COPSPepException {
+        manager.finalizeRequestState();
+    }
+
+    private void notifyCloseAllReqStateMan()
+    throws COPSPepException {
+        if (_managerMap.size() > 0) {
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
+                String handle = (String) e.nextElement();
+                COPSPepReqStateMan man = (COPSPepReqStateMan) _managerMap.get(handle);
+
+                man.processClosedConnection(_error);
+            }
+        }
+    }
+
+    private void notifyNoKAAllReqStateMan()
+    throws COPSPepException {
+        if (_managerMap.size() > 0) {
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
+                String handle = (String) e.nextElement();
+                COPSPepReqStateMan man = (COPSPepReqStateMan) _managerMap.get(handle);
+
+                man.processNoKAConnection();
+            }
+        }
+    }
+
+    private void notifyAcctAllReqStateMan()
+    throws COPSPepException {
+        if (_managerMap.size() > 0) {
+            for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
+                String handle = (String) e.nextElement();
+                COPSPepReqStateMan man = (COPSPepReqStateMan) _managerMap.get(handle);
+
+                man.processAcctReport();
+            }
+        }
+    }
+
+}
+
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepDataProcess.java b/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepDataProcess.java
new file mode 100644 (file)
index 0000000..45d11dd
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpep;
+
+import java.util.Hashtable;
+
+import org.umu.cops.stack.COPSError;
+
+/**
+ * COPSPepDataProcess process policy data and events.
+ *
+ * @version COPSPepDataProcess.java, v 2.00 2004
+ *
+ */
+public abstract class COPSPepDataProcess {
+
+    /**
+     * Establish PDP decisions
+     *
+     * @param removeDecs
+     * @param installDecs
+     * @param errorDecs
+     */
+
+       public abstract void setDecisions(COPSPepReqStateMan man, Hashtable removeDecs, Hashtable installDecs, Hashtable errorDecs);
+
+    /**
+     *  If the report is fail, return true
+     *
+     * @return
+     */
+    public abstract boolean isFailReport(COPSPepReqStateMan man);
+
+    /**
+     * Return Report Data
+     *
+     * @return
+     */
+    public abstract Hashtable getReportData(COPSPepReqStateMan man);
+
+    /**
+     * Return Client Data
+     *
+     * @return
+     */
+    public abstract Hashtable getClientData(COPSPepReqStateMan man);
+
+    /**
+     * Return Accouting Data
+     *
+     * @return
+     */
+    public abstract Hashtable getAcctData(COPSPepReqStateMan man);
+
+    /**
+     * Notify the connection closed
+     *
+     * @param error
+     */
+    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);
+
+    /**
+     * Process a PDP request to open a new Request State
+     *
+     * @param man
+     */
+    public abstract void newRequestState(COPSPepReqStateMan man);
+}
+
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepException.java b/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepException.java
new file mode 100644 (file)
index 0000000..ccac8ee
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpep;\r
+\r
+/**\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
+    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
+    }\r
+\r
+    /**\r
+     * Return error code\r
+     *\r
+     * @return    error code\r
+     *\r
+     */\r
+    public int returnCode() {\r
+        return rc;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepMsgSender.java b/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepMsgSender.java
new file mode 100644 (file)
index 0000000..010560c
--- /dev/null
@@ -0,0 +1,372 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpep;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+\r
+import org.umu.cops.stack.COPSClientSI;\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDeleteMsg;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSPrEPD;\r
+import org.umu.cops.stack.COPSPrID;\r
+import org.umu.cops.stack.COPSReason;\r
+import org.umu.cops.stack.COPSReportMsg;\r
+import org.umu.cops.stack.COPSReportType;\r
+import org.umu.cops.stack.COPSReqMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * COPSPepMsgSender sends COPS messages to PDP.\r
+ *\r
+ * @version COPSPepMsgSender.java, v 2.00 2004\r
+ *\r
+ */\r
+public class COPSPepMsgSender {\r
+\r
+    /**\r
+     * Socket connection to PDP\r
+     */\r
+    protected Socket _sock;\r
+\r
+    /**\r
+     * The client-type identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     * The client handle is used to uniquely identify a particular\r
+     * PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+     * Create a COPSPepMsgSender\r
+     *\r
+     * @param clientType        client-type\r
+     * @param clientHandle      client handle\r
+     * @param sock              socket of PDP connection\r
+     */\r
+    public COPSPepMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {\r
+        // COPS Handle\r
+        _handle = clientHandle;\r
+        _clientType = clientType;\r
+\r
+        _sock = sock;\r
+    }\r
+\r
+    /**\r
+     * Return client handle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Return client-type\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Send Request to PDP.\r
+     *   The PEP establishes a request state client handle for which the\r
+     *   remote PDP may maintain state.\r
+     *\r
+     * @param    clientSIs              a  Hashtable\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    public void sendRequest(Hashtable clientSIs)\r
+    throws COPSPepException {\r
+        // Create COPS Message\r
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_REQ, _clientType);\r
+        COPSContext cntxt = new COPSContext(COPSContext.CONFIG , (short) 0);\r
+\r
+        COPSHandle handle = _handle;\r
+\r
+        // Add the clientSIs\r
+        COPSReqMsg msg = new COPSReqMsg();\r
+        try {\r
+            msg.add(hdr) ;\r
+            msg.add(handle) ;\r
+            msg.add(cntxt) ;\r
+\r
+            if (clientSIs.size() > 0) {\r
+                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
+                    String strprid = (String) e.nextElement();\r
+                    String strepd = (String) clientSIs.get(strprid);\r
+\r
+                    //  (PRID)\r
+                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrID prid = new COPSPrID();\r
+                    prid.setData(new COPSData(strprid));\r
+                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+\r
+                    //  (EPD)\r
+                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrEPD epd = new COPSPrEPD();\r
+                    epd.setData(new COPSData(strepd));\r
+                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                    msg.add(cSi);\r
+                    msg.add(cSi2);\r
+                }\r
+            }\r
+\r
+        } catch (COPSException e) {\r
+            throw new COPSPepException("Error making Request Msg, reason: " + e.getMessage());\r
+        }\r
+\r
+        // Send message\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Send Fail Report to PDP.\r
+     *    The RPT message is used by the PEP to communicate to the PDP its\r
+     *    success or failure in carrying out the PDP's decision, or to report\r
+     *    an accounting related change in state.\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    public void sendFailReport(Hashtable clientSIs)\r
+    throws COPSPepException {\r
+        COPSReportMsg msg = new COPSReportMsg();\r
+        // Report FAIL\r
+        try {\r
+            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
+            COPSHandle hnd = _handle;\r
+\r
+            COPSReportType report = new COPSReportType(COPSReportType.FAILURE);\r
+\r
+            msg.add(hdr);\r
+            msg.add(hnd);\r
+            msg.add(report);\r
+            if (clientSIs.size() > 0) {\r
+                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
+                    String strprid = (String) e.nextElement();\r
+                    String strepd = (String) clientSIs.get(strprid);\r
+\r
+                    //  (PRID)\r
+                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrID prid = new COPSPrID();\r
+                    prid.setData(new COPSData(strprid));\r
+                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+\r
+                    //  (EPD)\r
+                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrEPD epd = new COPSPrEPD();\r
+                    epd.setData(new COPSData(strepd));\r
+                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                    msg.add(cSi);\r
+                    msg.add(cSi2);\r
+                }\r
+            }\r
+\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Send Succes Report to PDP.\r
+     *    The RPT message is used by the PEP to communicate to the PDP its\r
+     *    success or failure in carrying out the PDP's decision, or to report\r
+     *    an accounting related change in state.\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    public void sendSuccessReport(Hashtable clientSIs)\r
+    throws COPSPepException {\r
+        COPSReportMsg msg = new COPSReportMsg();\r
+        // Report SUCESS\r
+        try {\r
+            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
+            COPSHandle hnd = _handle;\r
+\r
+            COPSReportType report = new COPSReportType(COPSReportType.SUCCESS);\r
+\r
+            msg.add(hdr);\r
+            msg.add(hnd);\r
+            msg.add(report);\r
+\r
+            if (clientSIs.size() > 0) {\r
+                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
+                    String strprid = (String) e.nextElement();\r
+                    String strepd = (String) clientSIs.get(strprid);\r
+\r
+                    //  (PRID)\r
+                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrID prid = new COPSPrID();\r
+                    prid.setData(new COPSData(strprid));\r
+                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+\r
+                    //  (EPD)\r
+                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrEPD epd = new COPSPrEPD();\r
+                    epd.setData(new COPSData(strepd));\r
+                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                    msg.add(cSi);\r
+                    msg.add(cSi2);\r
+                }\r
+            }\r
+\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    public void sendAcctReport(Hashtable clientSIs)\r
+    throws COPSPepException {\r
+        COPSReportMsg msg = new COPSReportMsg();\r
+        // Report SUCESS\r
+        try {\r
+            COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_RPT, _clientType);\r
+            COPSHandle hnd = _handle;\r
+\r
+            COPSReportType report = new COPSReportType(COPSReportType.ACCT);\r
+\r
+            msg.add(hdr);\r
+            msg.add(hnd);\r
+            msg.add(report);\r
+\r
+            if (clientSIs.size() > 0) {\r
+                for (Enumeration e = clientSIs.keys() ; e.hasMoreElements() ;) {\r
+                    String strprid = (String) e.nextElement();\r
+                    String strepd = (String) clientSIs.get(strprid);\r
+\r
+                    //  (PRID)\r
+                    COPSClientSI cSi = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrID prid = new COPSPrID();\r
+                    prid.setData(new COPSData(strprid));\r
+                    cSi.setData(new COPSData(prid.getDataRep(), 0, prid.getDataLength()));\r
+\r
+                    //  (EPD)\r
+                    COPSClientSI cSi2 = new COPSClientSI(COPSClientSI.CSI_NAMED);\r
+                    COPSPrEPD epd = new COPSPrEPD();\r
+                    epd.setData(new COPSData(strepd));\r
+                    cSi2.setData(new COPSData(epd.getDataRep(), 0, epd.getDataLength()));\r
+\r
+                    msg.add(cSi);\r
+                    msg.add(cSi2);\r
+                }\r
+            }\r
+\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the report, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Send Sync State Complete to PDP.\r
+     *   The Synchronize State Complete is sent by the PEP to the PDP after\r
+     *   the PDP sends a synchronize state request to the PEP and the PEP has\r
+     *   finished synchronization.\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    public void sendSyncComplete()\r
+    throws COPSPepException {\r
+        // Common Header with the same ClientType as the request\r
+        COPSHeader hdr = new COPSHeader (COPSHeader.COPS_OP_SSC, _clientType);\r
+\r
+        // Client Handle with the same clientHandle as the request\r
+        COPSHandle clienthandle = _handle;\r
+\r
+        COPSSyncStateMsg msg = new COPSSyncStateMsg();\r
+        try {\r
+            msg.add(hdr);\r
+            msg.add(clienthandle);\r
+        } catch (Exception e) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Send Delete Request to PDP.\r
+     * When sent from the PEP this message indicates to the remote PDP that\r
+     * the state identified by the client handle is no longer\r
+     * available/relevant.\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    public void sendDeleteRequest()\r
+    throws COPSPepException {\r
+        COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_DRQ, _clientType);\r
+        COPSHandle handle = _handle;\r
+\r
+        // *** TODO: send a real reason\r
+        COPSReason reason = new COPSReason((short) 234, (short) 345);\r
+\r
+        COPSDeleteMsg msg = new COPSDeleteMsg();\r
+        try {\r
+            msg.add(hdr);\r
+            msg.add(handle);\r
+            msg.add(reason);\r
+        } catch (COPSException ex) {\r
+            throw new COPSPepException("Error making Msg");\r
+        }\r
+        try {\r
+            msg.writeData(_sock);\r
+        } catch (IOException e) {\r
+            throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepReqStateMan.java b/packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepReqStateMan.java
new file mode 100644 (file)
index 0000000..c004e82
--- /dev/null
@@ -0,0 +1,406 @@
+/*\r
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.prpep;\r
+\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.stack.COPSContext;\r
+import org.umu.cops.stack.COPSData;\r
+import org.umu.cops.stack.COPSDecision;\r
+import org.umu.cops.stack.COPSDecisionMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSPrObjBase;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+\r
+/**\r
+ * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)\r
+ * in PEP.\r
+ *\r
+ *   The client handle is used to identify a unique request state for a\r
+ *   single PEP per client-type. Client handles are chosen by the PEP and\r
+ *   are opaque to the PDP. The PDP simply uses the request handle to\r
+ *   uniquely identify the request state for a particular Client-Type over\r
+ *   a particular TCP connection and generically tie its decisions to a\r
+ *   corresponding request. Client handles are initiated in request\r
+ *   messages and are then used by subsequent request, decision, and\r
+ *   report messages to reference the same request state. When the PEP is\r
+ *   ready to remove a local request state, it will issue a delete message\r
+ *   to the PDP for the corresponding client handle. A handle MUST be\r
+ *   explicitly deleted by the PEP before it can be used by the PEP to\r
+ *   identify a new request state. Handles referring to different request\r
+ *   states MUST be unique within the context of a particular TCP\r
+ *   connection and client-type.\r
+ *\r
+ * @version COPSPepReqStateMan.java, v 2.00 2004\r
+ *\r
+ */\r
+public class COPSPepReqStateMan {\r
+\r
+    /**\r
+     * Request State created\r
+     */\r
+    public final static short ST_CREATE = 1;\r
+    /**\r
+     * Request sent\r
+     */\r
+    public final static short ST_INIT = 2;\r
+    /**\r
+     * Decisions received\r
+     */\r
+    public final static short ST_DECS = 3;\r
+    /**\r
+     * Report sent\r
+     */\r
+    public final static short ST_REPORT = 4;\r
+    /**\r
+     * Request State finalized\r
+     */\r
+    public final static short ST_FINAL = 5;\r
+    /**\r
+     * New Request State solicited\r
+     */\r
+    public final static short ST_NEW = 6;\r
+    /**\r
+     * Delete Request State solicited\r
+     */\r
+    public final static short ST_DEL = 7;\r
+    /**\r
+     * SYNC Request received\r
+     */\r
+    public final static short ST_SYNC = 8;\r
+    /**\r
+     * SYNC Completed\r
+     */\r
+    public final static short ST_SYNCALL = 9;\r
+    /**\r
+     * Close Connection received\r
+     */\r
+    public final static short ST_CCONN = 10;\r
+    /**\r
+     * KAlive Time out\r
+     */\r
+    public final static short ST_NOKA = 11;\r
+    /**\r
+     * ACCT Time out\r
+     */\r
+    public final static short ST_ACCT = 12;\r
+\r
+    /**\r
+     * The client-type identifies the policy client\r
+     */\r
+    protected short _clientType;\r
+\r
+    /**\r
+     *  The client handle is used to uniquely identify a particular\r
+     *  PEP's request for a client-type\r
+     */\r
+    protected COPSHandle _handle;\r
+\r
+    /**\r
+        The PolicyDataProcess is used to process policy data in the PEP\r
+     */\r
+    protected COPSPepDataProcess _process;\r
+\r
+    /**\r
+     *  State Request State\r
+     */\r
+    protected short _status;\r
+\r
+    /**\r
+        The Msg Sender is used to send COPS messages\r
+     */\r
+    protected COPSPepMsgSender _sender;\r
+\r
+    /**\r
+     * Sync State\r
+     */\r
+    protected boolean _syncState;\r
+\r
+    /**\r
+     * Create a State Request Manager\r
+     *\r
+     * @param    clientHandle                a Client Handle\r
+     *\r
+     */\r
+    public COPSPepReqStateMan(short clientType, String clientHandle) {\r
+        // COPS Handle\r
+        _handle = new COPSHandle();\r
+        COPSData id = new COPSData(clientHandle);\r
+        _handle.setId(id);\r
+        // client-type\r
+        _clientType = clientType;\r
+        _syncState = true;\r
+        _status = ST_CREATE;\r
+    }\r
+\r
+    /**\r
+     * Return client handle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _handle;\r
+    }\r
+\r
+    /**\r
+     * Return client-type\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getClientType() {\r
+        return _clientType;\r
+    }\r
+\r
+    /**\r
+     * Return Request State status\r
+     *\r
+     * @return      s short\r
+     */\r
+    public short getStatus() {\r
+        return _status;\r
+    }\r
+\r
+    /**\r
+     * Return the Policy Data Process\r
+     *\r
+     * @return   a PolicyConfigure\r
+     *\r
+     */\r
+    public COPSPepDataProcess getDataProcess() {\r
+        return _process;\r
+    }\r
+\r
+    /**\r
+     * Establish the Policy Data Process\r
+     *\r
+     * @param    process              a  PolicyConfigure\r
+     *\r
+     */\r
+    public void setDataProcess(COPSPepDataProcess process) {\r
+        _process = process;\r
+    }\r
+\r
+    /**\r
+     * Init Request State\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void initRequestState(Socket sock)\r
+    throws COPSPepException {\r
+        // Inits an object for sending COPS messages to the PDP\r
+        _sender = new COPSPepMsgSender(_clientType, _handle, sock);\r
+\r
+        // If an object for retrieving PEP features exists,\r
+        // use it for retrieving them\r
+        Hashtable clientSIs;\r
+        if (_process != null)\r
+            clientSIs = _process.getClientData(this);\r
+        else\r
+            clientSIs = null;\r
+\r
+        // Send the request\r
+        _sender.sendRequest(clientSIs);\r
+\r
+        // Initial state\r
+        _status = ST_INIT;\r
+    }\r
+\r
+    /**\r
+     * Finalize Request State\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void finalizeRequestState()\r
+    throws COPSPepException {\r
+        _sender.sendDeleteRequest();\r
+        _status = ST_FINAL;\r
+    }\r
+\r
+    /**\r
+     * Process the message Decision\r
+     *\r
+     * @param    dMsg                a  COPSDecisionMsg\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void processDecision(COPSDecisionMsg dMsg)\r
+    throws COPSPepException {\r
+        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());\r
+\r
+        // COPSHandle handle = dMsg.getClientHandle();\r
+        Hashtable decisions = dMsg.getDecisions();\r
+\r
+        Hashtable removeDecs = new Hashtable(40);\r
+        Hashtable installDecs = new Hashtable(40);\r
+        Hashtable errorDecs = new Hashtable(40);\r
+        for (Enumeration e = decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) decisions.get(context);\r
+            Enumeration ee = v.elements();\r
+            COPSDecision cmddecision = (COPSDecision) ee.nextElement();\r
+\r
+            // cmddecision --> we must check whether it is an error!\r
+\r
+            if (cmddecision.isInstallDecision()) {\r
+                String prid = new String();\r
+                for (; ee.hasMoreElements() ;) {\r
+                    COPSDecision decision = (COPSDecision) ee.nextElement();\r
+\r
+                    COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());\r
+                    switch (obj.getSNum()) {\r
+                    case COPSPrObjBase.PR_PRID:\r
+                        prid = obj.getData().str();\r
+                        break;\r
+                    case COPSPrObjBase.PR_EPD:\r
+                        installDecs.put(prid, obj.getData().str());\r
+                        break;\r
+                    default:\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+\r
+            if (cmddecision.isRemoveDecision()) {\r
+\r
+                String prid = new String();\r
+                for (; ee.hasMoreElements() ;) {\r
+                    COPSDecision decision = (COPSDecision) ee.nextElement();\r
+\r
+                    COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());\r
+                    switch (obj.getSNum()) {\r
+                    case COPSPrObjBase.PR_PRID:\r
+                        prid = obj.getData().str();\r
+                        break;\r
+                    case COPSPrObjBase.PR_EPD:\r
+                        removeDecs.put(prid, obj.getData().str());\r
+                        break;\r
+                    default:\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        //** Apply decisions to the configuration\r
+        _process.setDecisions(this, removeDecs, installDecs, errorDecs);\r
+        _status = ST_DECS;\r
+\r
+\r
+        if (_process.isFailReport(this)) {\r
+            // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");\r
+            _sender.sendFailReport(_process.getReportData(this));\r
+        } else {\r
+            // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");\r
+            _sender.sendSuccessReport(_process.getReportData(this));\r
+        }\r
+        _status = ST_REPORT;\r
+\r
+        if (!_syncState) {\r
+            _sender.sendSyncComplete();\r
+            _syncState = true;\r
+            _status = ST_SYNCALL;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Process the message NewRequestState\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void processOpenNewRequestState()\r
+    throws COPSPepException {\r
+\r
+        if (_process != null)\r
+            _process.newRequestState(this);\r
+\r
+        _status = ST_NEW;\r
+    }\r
+\r
+    /**\r
+     * Process the message DeleteRequestState\r
+     *\r
+     * @param    dMsg                a  COPSDecisionMsg\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void processDeleteRequestState(COPSDecisionMsg dMsg)\r
+    throws COPSPepException {\r
+        if (_process != null)\r
+            _process.closeRequestState(this);\r
+\r
+        _status = ST_DEL;\r
+    }\r
+\r
+    /**\r
+     * Process the message SycnStateRequest.\r
+     * The message SycnStateRequest indicates that the remote PDP\r
+     * wishes the client (which appears in the common header)\r
+     * to re-send its state.\r
+     *\r
+     * @param    ssMsg               a  COPSSyncStateMsg\r
+     *\r
+     * @throws   COPSPepException\r
+     *\r
+     */\r
+    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)\r
+    throws COPSPepException {\r
+        _syncState = false;\r
+        // If an object for retrieving PEP features exists,\r
+        // use it for retrieving them\r
+        Hashtable clientSIs;\r
+        if (_process != null)\r
+            clientSIs = _process.getClientData(this);\r
+        else\r
+            clientSIs = null;\r
+\r
+        // Send request\r
+        _sender.sendRequest(clientSIs);\r
+\r
+        _status = ST_SYNC;\r
+    }\r
+\r
+    protected void processClosedConnection(COPSError error)\r
+    throws COPSPepException {\r
+        if (_process != null)\r
+            _process.notifyClosedConnection(this, error);\r
+\r
+        _status = ST_CCONN;\r
+    }\r
+\r
+    protected void processNoKAConnection()\r
+    throws COPSPepException {\r
+        if (_process != null)\r
+            _process.notifyNoKAliveReceived(this);\r
+\r
+        _status = ST_NOKA;\r
+    }\r
+\r
+    protected void processAcctReport()\r
+    throws COPSPepException {\r
+\r
+        Hashtable report = new Hashtable();\r
+        if (_process != null)\r
+            report = _process.getAcctData(this);\r
+\r
+        _sender.sendAcctReport(report);\r
+\r
+        _status = ST_ACCT;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSAcctTimer.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSAcctTimer.java
new file mode 100644 (file)
index 0000000..be961c5
--- /dev/null
@@ -0,0 +1,49 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Accounting Timer Object\r
+ *\r
+ * @version COPSAcctTimer.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSAcctTimer extends COPSTimer {\r
+\r
+    public COPSAcctTimer() {\r
+        super ((short) 1);\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ACCT_TIMER);\r
+        _objHdr.setCType((byte) 1);\r
+    }\r
+\r
+    ///\r
+    public COPSAcctTimer(short timeVal) {\r
+        super(timeVal);\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ACCT_TIMER);\r
+        _objHdr.setCType((byte) 1);\r
+    }\r
+\r
+    ///\r
+    /**\r
+     * Method isAcctTimer\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAcctTimer() {\r
+        return true;\r
+    }\r
+\r
+    ///\r
+    protected COPSAcctTimer(byte[] dataPtr) {\r
+        super (dataPtr);\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientAcceptMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientAcceptMsg.java
new file mode 100644 (file)
index 0000000..af72a1a
--- /dev/null
@@ -0,0 +1,256 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ *     COPS Client Accept Message\r
+ *\r
+ * @version COPSClientAcceptMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSClientAcceptMsg extends COPSMsg {\r
+\r
+    /* COPSHeader coming from base class */\r
+    private COPSKATimer _kaTimer;\r
+    private COPSAcctTimer _acctTimer;\r
+    private COPSIntegrity _integrity;\r
+\r
+    ///Constructor\r
+    public COPSClientAcceptMsg() {\r
+        _kaTimer = null;\r
+        _acctTimer = null;\r
+        _integrity = null;\r
+    }\r
+\r
+    ///Create object from data\r
+    protected COPSClientAcceptMsg(byte[] data) throws COPSException {\r
+        parse(data);\r
+    }\r
+\r
+    /** Checks the sanity of COPS message and throw an\r
+      * COPSBadDataException when data is bad.\r
+      */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_kaTimer == null))\r
+            throw new COPSException("Bad message format");\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_CAT)\r
+            throw new COPSException ("Error Header (no COPS_OP_CAT)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Timer object to the message\r
+     *\r
+     * @param    timer               a  COPSTimer\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSTimer timer) throws COPSException {\r
+        if (timer.isKATimer()) {\r
+            _kaTimer = (COPSKATimer) timer;\r
+        } else {\r
+            _acctTimer = (COPSAcctTimer) timer;\r
+        }\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Integrity objects\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Method getKATimer\r
+     *\r
+     * @return   a COPSKATimer\r
+     *\r
+     */\r
+    public COPSKATimer getKATimer() {\r
+        return _kaTimer;\r
+    };\r
+\r
+    /**\r
+     * Returns true if has a account timer object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasAcctTimer() {\r
+        return (_acctTimer != null);\r
+    };\r
+\r
+    /**\r
+     * Should check hasAcctTimer() before calling\r
+     *\r
+     * @return   a COPSAcctTimer\r
+     *\r
+     */\r
+    public COPSAcctTimer getAcctTimer() {\r
+        return (_acctTimer);\r
+    }\r
+\r
+    /**\r
+     * Returns true if has a Integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    };\r
+\r
+    /**\r
+     * Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return (_integrity);\r
+    }\r
+\r
+    /**\r
+     * Writes data to a given socket id\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_kaTimer != null) _kaTimer.writeData(id);\r
+        if (_acctTimer != null) _acctTimer.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_KA: {\r
+                _kaTimer = new COPSKATimer(buf);\r
+                _dataStart += _kaTimer.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_ACCT_TIMER: {\r
+                _acctTimer = new COPSAcctTimer(buf);\r
+                _dataStart += _acctTimer.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_CAT)\r
+            throw new COPSException("Error Header");\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength() throws COPSException {\r
+        short len = 0;\r
+        if (_kaTimer != null) len += _kaTimer.getDataLength();\r
+        if (_acctTimer != null) len += _acctTimer.getDataLength();\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_kaTimer != null)\r
+            _kaTimer.dump(os);\r
+\r
+        if (_acctTimer != null)\r
+            _acctTimer.dump(os);\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientCloseMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientCloseMsg.java
new file mode 100644 (file)
index 0000000..5fb91e4
--- /dev/null
@@ -0,0 +1,224 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Client Close Message\r
+ *\r
+ * @version COPSClientCloseMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSClientCloseMsg extends COPSMsg {\r
+\r
+    /* COPSHeader coming from base class */\r
+    private COPSError _error;\r
+    private COPSIntegrity _integrity;\r
+\r
+\r
+    public COPSClientCloseMsg() {\r
+        _error = null;\r
+        _integrity = null;\r
+    }\r
+\r
+    protected COPSClientCloseMsg(byte[] data) throws COPSException {\r
+        parse (data);\r
+    }\r
+\r
+    /** Checks the sanity of COPS message and throw an\r
+      * COPSBadDataException when data is bad.\r
+      */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_error == null))\r
+            throw new COPSException("Bad message format");\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_CC)\r
+            throw new COPSException ("Error Header (no COPS_OP_CC)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Error object\r
+     *\r
+     * @param    error               a  COPSError\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSError error) throws COPSException {\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_error != null)\r
+            throw new COPSException ("No null Error");\r
+        _error = error;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Integrity objects\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Method getError\r
+     *\r
+     * @return   a COPSError\r
+     *\r
+     */\r
+    public COPSError getError() {\r
+        return (_error);\r
+    }\r
+\r
+    /**\r
+     * Returns true If it has integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    };\r
+\r
+    /**\r
+     * Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return (_integrity);\r
+    }\r
+\r
+    /**\r
+     * Write object data to given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_error != null) _error.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_ERROR: {\r
+                _error = new COPSError(buf);\r
+                _dataStart += _error.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_CC)\r
+            throw new COPSException("Error Header");\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength() throws COPSException {\r
+        int len = 0;\r
+        if (_error != null) len += _error.getDataLength();\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_error != null)\r
+            _error.dump(os);\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientOpenMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientOpenMsg.java
new file mode 100644 (file)
index 0000000..7574757
--- /dev/null
@@ -0,0 +1,330 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Client Open Message\r
+ *\r
+ * @version COPSClientOpenMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSClientOpenMsg extends COPSMsg {\r
+\r
+    private COPSPepId _pepId;\r
+    private COPSClientSI _clientSI;\r
+    private COPSPdpAddress _pdpAddress;\r
+    private COPSIntegrity _integrity;\r
+\r
+    public COPSClientOpenMsg() {\r
+        _pepId = null;\r
+        _clientSI = null;\r
+        _pdpAddress = null;\r
+        _integrity = null;\r
+        _hdr = null;\r
+    }\r
+\r
+    protected COPSClientOpenMsg(byte[] data) throws COPSException {\r
+        _pepId = null;\r
+        _clientSI = null;\r
+        _pdpAddress = null;\r
+        _integrity = null;\r
+        _hdr = null;\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Method writeData\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null)_hdr.writeData(id);\r
+        if (_pepId != null) _pepId.writeData(id);\r
+        if (_clientSI != null) _clientSI.writeData(id);\r
+        if (_pdpAddress != null) _pdpAddress.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_OPN)\r
+            throw new COPSException ("Error Header (no COPS_OP_OPN)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add PEP Identification Object\r
+     *\r
+     * @param    pepid               a  COPSPepId\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSPepId pepid) throws COPSException {\r
+        if (pepid == null)\r
+            throw new COPSException ("Null COPSPepId");\r
+        if (!pepid.isPepId())\r
+            throw new COPSException ("Error COPSPepId");\r
+        _pepId = pepid;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Client Specific Information Object\r
+     *\r
+     * @param    clientSI            a  COPSClientSI\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSClientSI clientSI) throws COPSException {\r
+        if (clientSI == null)\r
+            throw new COPSException ("Null COPSClientSI");\r
+        if (!clientSI.isClientSI())\r
+            throw new COPSException ("Error COPSClientSI");\r
+        _clientSI = clientSI;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add PDP Address\r
+     *\r
+     * @param    pdpAddr             a  COPSPdpAddress\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSPdpAddress pdpAddr) throws COPSException {\r
+        if (pdpAddr == null)\r
+            throw new COPSException ("Null COPSPdpAddress");\r
+        if (!pdpAddr.isLastPdpAddress())\r
+            throw new COPSException ("Error COPSPdpAddress");\r
+        _pdpAddress = pdpAddr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Integrity object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /** Checks the sanity of COPS message and throw an\r
+          * COPSBadDataException when data is bad.\r
+    */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_pepId == null))\r
+            throw new COPSException("Bad message format");\r
+    }\r
+\r
+    /**\r
+     * Method getPepId\r
+     *\r
+     * @return   a COPSPepId\r
+     *\r
+     */\r
+    public COPSPepId getPepId() {\r
+        return _pepId;\r
+    }\r
+\r
+    /**\r
+     * Method hasClientSI\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasClientSI() {\r
+        return (_clientSI != null);\r
+    }\r
+\r
+    /**\r
+     * Method getClientSI\r
+     *\r
+     * @return   a COPSClientSI\r
+     *\r
+     */\r
+    public COPSClientSI getClientSI() {\r
+        return (_clientSI);\r
+    }\r
+\r
+    /**\r
+     * Method hasPdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasPdpAddress() {\r
+        return (_pdpAddress != null);\r
+    }\r
+\r
+    /**\r
+     * Method getPdpAddress\r
+     *\r
+     * @return   a COPSPdpAddress\r
+     *\r
+     */\r
+    public COPSPdpAddress getPdpAddress() {\r
+        return _pdpAddress;\r
+    }\r
+\r
+    /**\r
+     * Method hasIntegrity\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    }\r
+\r
+    /**\r
+     * Method getIntegrity\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return _integrity;\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    private void setMsgLength() throws COPSException {\r
+        short len = 0;\r
+        if (_pepId != null) len += _pepId.getDataLength();\r
+        if (_clientSI != null) len += _clientSI.getDataLength();\r
+        if (_pdpAddress != null) len += _pdpAddress.getDataLength();\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        parseHeader(data);\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_PEPID: {\r
+                _pepId = new COPSPepId(buf);\r
+                _dataStart += _pepId.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_LAST_PDP_ADDR: {\r
+                if (objHdr.getCType() == 1) {\r
+                    _pdpAddress = new COPSIpv4LastPdpAddr(buf);\r
+                } else if (objHdr.getCType() == 2) {\r
+                    _pdpAddress = new COPSIpv6LastPdpAddr(buf);\r
+                }\r
+                _dataStart += _pdpAddress.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_CSI: {\r
+                _clientSI = new COPSClientSI(buf);\r
+                _dataStart += _clientSI.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_OPN)\r
+            throw new COPSException("Error Header");\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_pepId != null)\r
+            _pepId.dump(os);\r
+\r
+        if (_clientSI != null)\r
+            _clientSI.dump(os);\r
+\r
+        if (_pdpAddress != null)\r
+            _pdpAddress.dump(os);\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientSI.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSClientSI.java
new file mode 100644 (file)
index 0000000..69b5fdd
--- /dev/null
@@ -0,0 +1,131 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Client Specific Information Object\r
+ *\r
+ * @version COPSClientSI.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSClientSI extends COPSObjBase {\r
+    public final static byte CSI_SIGNALED = 1;\r
+    public final static byte CSI_NAMED = 2;\r
+\r
+    private COPSObjHeader _objHdr;\r
+    private COPSData _data;\r
+    private COPSData _padding;\r
+\r
+    ///\r
+    public COPSClientSI(byte type) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_CSI);\r
+        _objHdr.setCType(type);\r
+    }\r
+\r
+    public COPSClientSI(byte cnum, byte ctype) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(cnum);\r
+        _objHdr.setCType(ctype);\r
+    }\r
+\r
+    /**\r
+     Parse the data and create a ClientSI object\r
+     */\r
+    protected COPSClientSI(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        //Get the length of data following the obj header\r
+        short dLen = (short) (_objHdr.getDataLength() - 4);\r
+        COPSData d = new COPSData(dataPtr, 4, dLen);\r
+        setData(d);\r
+    }\r
+\r
+    /**\r
+     * Method setData\r
+     *\r
+     * @param    data                a  COPSData\r
+     *\r
+     */\r
+    public void setData(COPSData data) {\r
+        _data = data;\r
+        if (_data.length() % 4 != 0) {\r
+            int padLen = 4 - _data.length() % 4;\r
+            _padding = getPadding(padLen);\r
+        }\r
+        _objHdr.setDataLength((short) _data.length());\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        int lpadding = 0;\r
+        if (_padding != null) lpadding = _padding.length();\r
+        return (short) (_objHdr.getDataLength() + lpadding);\r
+    }\r
+\r
+    /**\r
+     * Method getData\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getData() {\r
+        return _data;\r
+    };\r
+\r
+    /**\r
+     * Method isClientSI\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isClientSI() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+        COPSUtil.writeData(id, _data.getData(), _data.length());\r
+        if (_padding != null) {\r
+            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("client-SI: " + _data.str() + "\n").getBytes());\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSContext.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSContext.java
new file mode 100644 (file)
index 0000000..5ff6eb3
--- /dev/null
@@ -0,0 +1,211 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Context Object\r
+ *\r
+ * @version COPSContext.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSContext extends COPSObjBase {\r
+\r
+    public final static byte IN_ADMIN = 0x01;\r
+    public final static byte RES_ALLOC = 0x02;\r
+    public final static byte OUT = 0x04;\r
+    public final static byte CONFIG = 0x08;\r
+\r
+    private COPSObjHeader _objHdr;\r
+    private short _rType;\r
+    private short _mType;\r
+\r
+    ///\r
+    public COPSContext(short rType, short mType ) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_CONTEXT);\r
+        _objHdr.setCType((byte) 1);\r
+        _rType = rType;\r
+        _mType = mType;\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a Context object\r
+     */\r
+    protected COPSContext(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _rType |= ((short) dataPtr[4]) << 8;\r
+        _rType |= ((short) dataPtr[5]) & 0xFF;\r
+\r
+        _mType |= ((short) dataPtr[6]) << 8;\r
+        _mType |= ((short) dataPtr[7]) & 0xFF;\r
+\r
+        _objHdr.setDataLength( (short) 4);\r
+    }\r
+\r
+    /**\r
+     * Write object in network byte order to a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+\r
+        buf[0] = (byte) (_rType >> 8);\r
+        buf[1] = (byte) _rType;\r
+\r
+        buf[2] = (byte) (_mType >> 8);\r
+        buf[3] = (byte) _mType;\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    /**\r
+     * Returns the detail description of the request type\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String getDescription() {\r
+        String retStr = new String();\r
+        if ((_rType & 0x01) != 0) {\r
+            retStr += (retStr.length() != 0) ? "," : "";\r
+            retStr += "Incoming Message/Admission Control";\r
+        }\r
+        if ((_rType & 0x02) != 0) {\r
+            retStr += (retStr.length() != 0) ? "," : "";\r
+            retStr += "Resource allocation";\r
+        }\r
+        if ((_rType & 0x04) != 0) {\r
+            retStr += (retStr.length() != 0) ? "," : "";\r
+            retStr += "Outgoing message";\r
+        }\r
+        if ((_rType & 0x08) != 0) {\r
+            retStr += (retStr.length() != 0) ? "," : "";\r
+            retStr += "Configuration";\r
+        }\r
+        return retStr;\r
+    }\r
+\r
+    /**\r
+     * Method isIncomingMessage\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIncomingMessage() {\r
+        return (_rType & IN_ADMIN) != 0;\r
+    };\r
+\r
+    /**\r
+     * Method isAdminControl\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAdminControl() {\r
+        return (_rType & IN_ADMIN) != 0;\r
+    };\r
+\r
+    /**\r
+     * Method isResourceAllocationReq\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isResourceAllocationReq() {\r
+        return (_rType & RES_ALLOC) != 0;\r
+    };\r
+\r
+    /**\r
+     * Method isOutgoingMessage\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isOutgoingMessage() {\r
+        return (_rType & OUT) != 0;\r
+    };\r
+\r
+    /**\r
+     * Method isConfigRequest\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isConfigRequest() {\r
+        return (_rType & CONFIG) != 0;\r
+    };\r
+\r
+    /**\r
+     * Method getMessageType\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getMessageType() {\r
+        return (_mType) ;\r
+    };\r
+\r
+    /**\r
+     * Method getRequestType\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getRequestType() {\r
+        return (_rType);\r
+    };\r
+\r
+    /**\r
+     * Method isContext\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isContext() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("context: " + getDescription() + "," + _mType + "\n").getBytes());\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSData.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSData.java
new file mode 100644 (file)
index 0000000..7b7ab12
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Data\r
+ *\r
+ * @version COPSData.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSData {\r
+\r
+    private byte[] _dataBuf;\r
+    private int _dLen;\r
+\r
+    public COPSData() {\r
+        _dataBuf = null;\r
+        _dLen = 0;\r
+    }\r
+\r
+    public COPSData(byte[] dPtr, int offset, int dLen) {\r
+        _dataBuf = new byte[dLen];\r
+        System.arraycopy(dPtr,offset,_dataBuf,0,dLen);\r
+        _dLen = dLen;\r
+    }\r
+\r
+    public COPSData(String data) {\r
+        _dLen = data.getBytes().length;\r
+        _dataBuf = new byte[_dLen];\r
+        System.arraycopy(data.getBytes(),0,_dataBuf,0,_dLen);\r
+    }\r
+\r
+    /**\r
+     * Method getData\r
+     *\r
+     * @return   a byte[]\r
+     *\r
+     */\r
+    public byte[] getData() {\r
+        return _dataBuf;\r
+    }\r
+\r
+    /**\r
+     * Method length\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int length() {\r
+        return _dLen;\r
+    }\r
+\r
+    /**\r
+     * Method str\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String str() {\r
+        return new String (_dataBuf);\r
+    }\r
+\r
+    public String toString() {\r
+        return str();\r
+    }\r
+\r
+    public boolean equals(Object obj) {\r
+        return (((COPSData) obj).toString().equals(str()));\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecision.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecision.java
new file mode 100644 (file)
index 0000000..095e3f7
--- /dev/null
@@ -0,0 +1,297 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Decision\r
+ *\r
+ * @version COPSDecision.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSDecision extends COPSObjBase {\r
+\r
+    // CType\r
+    public final static byte DEC_DEF = 1;\r
+    public final static byte DEC_STATELESS = 2;\r
+    public final static byte DEC_REPL = 3;\r
+    public final static byte DEC_CSI = 4;\r
+    public final static byte DEC_NAMED = 5;\r
+\r
+    // Command\r
+    public final static byte DEC_NULL = 0;\r
+    public final static byte DEC_INSTALL = 1;\r
+    public final static byte DEC_REMOVE = 2;\r
+\r
+    // Flags\r
+    public final static byte F_REQERROR = 0x1;\r
+    public final static byte F_REQSTATE = 0x2;\r
+\r
+    protected COPSObjHeader _objHdr;\r
+    private COPSData _data;\r
+    private short _cmdCode;\r
+    private short _flags;\r
+    private COPSData _padding;\r
+\r
+    /**\r
+      Constructor to create a Decision object. By default creates\r
+      a decision object which is of fixed length.\r
+     */\r
+    public COPSDecision(byte cType) {\r
+        _objHdr = new COPSObjHeader();\r
+        _cmdCode = 0;\r
+        _flags = 0;\r
+        _objHdr.setCNum(COPSObjHeader.COPS_DEC);\r
+        _objHdr.setCType(cType);\r
+        if (cType == DEC_DEF) _objHdr.setDataLength( (short) 4);\r
+    }\r
+\r
+    public COPSDecision() {\r
+        _objHdr = new COPSObjHeader();\r
+        _cmdCode = 0;\r
+        _flags = 0;\r
+        _objHdr.setCNum(COPSObjHeader.COPS_DEC);\r
+        _objHdr.setCType(DEC_DEF);\r
+        _objHdr.setDataLength( (short) 4);\r
+    }\r
+\r
+    /**\r
+          Initialize the decision object with values from COPSObj header\r
+     */\r
+    protected COPSDecision(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _cmdCode = 0;\r
+        _flags = 0;\r
+        if (_objHdr.getCType() == DEC_DEF) {\r
+            _cmdCode |= ((short) dataPtr[4]) << 8;\r
+            _cmdCode |= ((short) dataPtr[5]) & 0xFF;\r
+            _flags |= ((short) dataPtr[6]) << 8;\r
+            _flags |= ((short) dataPtr[7]) & 0xFF;\r
+\r
+            _objHdr.setDataLength((short) 4);\r
+        } else {\r
+            int dLen = _objHdr.getDataLength() - 4;\r
+            COPSData d = new COPSData(dataPtr, 4, dLen);\r
+            setData(d);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Method getDataLength\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        int lpadding = 0;\r
+        if (_padding != null) lpadding = _padding.length();\r
+        return ((short) (_objHdr.getDataLength() + lpadding));\r
+    }\r
+\r
+\r
+\r
+    /**\r
+     * Get the associated data if decision object is of cType 2 or higher\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getData() {\r
+        return (_data);\r
+    }\r
+\r
+    /**\r
+     * Set the decision data if decision object is of cType 2 or higher\r
+     *\r
+     * @param    data                a  COPSData\r
+     *\r
+     */\r
+    public void setData(COPSData data) {\r
+        if (data.length() % 4 != 0) {\r
+            int padLen = 4 - data.length() % 4;\r
+            _padding = getPadding(padLen);\r
+        }\r
+        _data = data;\r
+        _objHdr.setDataLength((short) data.length());\r
+    }\r
+\r
+    /**\r
+     * Retruns true if cType = 1\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isFlagSet() {\r
+        return ( _objHdr.getCType() == 1);\r
+    };\r
+\r
+    /**\r
+     * If cType == 1 , get the flags associated\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getFlags() {\r
+        return (_flags);\r
+    };\r
+\r
+    /**\r
+     * If cType == 1 ,set the cmd code\r
+     *\r
+     * @param    cCode               a  byte\r
+     *\r
+     */\r
+    public void setCmdCode(byte cCode) {\r
+        _cmdCode = (short) cCode;\r
+    }\r
+\r
+    /**\r
+     * If cType == 1 ,set the cmd flags\r
+     *\r
+     * @param    flags               a  short\r
+     *\r
+     */\r
+    public void setFlags(short flags) {\r
+        _flags = flags;\r
+    }\r
+\r
+    /**\r
+     * Method isNullDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isNullDecision() {\r
+        return ( _cmdCode == 0);\r
+    };\r
+\r
+    /**\r
+     * Method isInstallDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isInstallDecision() {\r
+        return ( _cmdCode == 1);\r
+    };\r
+\r
+    /**\r
+     * Method isRemoveDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isRemoveDecision() {\r
+        return ( _cmdCode == 2);\r
+    };\r
+\r
+    /**\r
+     * Method getTypeStr\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String getTypeStr() {\r
+        switch (_objHdr.getCType()) {\r
+        case DEC_DEF:\r
+            return "Default";\r
+        case DEC_STATELESS:\r
+            return "Stateless data";\r
+        case DEC_REPL:\r
+            return "Replacement data";\r
+        case DEC_CSI:\r
+            return "Client specific decision data";\r
+        case DEC_NAMED:\r
+            return "Named decision data";\r
+        default:\r
+            return "Unknown";\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Method isDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isDecision() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Method isLocalDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isLocalDecision() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Writes data to a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        if (_objHdr.getCType() >= 2) {\r
+            COPSUtil.writeData(id, _data.getData(), _data.length());\r
+            if (_padding != null) {\r
+                COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
+            }\r
+        } else {\r
+            byte[] buf = new byte[4];\r
+            buf[0] = (byte) (_cmdCode >> 8);\r
+            buf[1] = (byte) _cmdCode;\r
+            buf[2] = (byte) (_flags >> 8);\r
+            buf[3] = (byte) _flags;\r
+            COPSUtil.writeData(id, buf, 4);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+\r
+        if (_objHdr.getCType() == 1) {\r
+            os.write(new String("Decision (" + getTypeStr() + ")\n").getBytes());\r
+            os.write(new String("Command code: " + _cmdCode + "\n").getBytes());\r
+            os.write(new String("Command flags: " + _flags + "\n").getBytes());\r
+        } else {\r
+            os.write(new String("Decision (" + getTypeStr() + ")\n").getBytes());\r
+            os.write(new String("Data: " + _data.str() + "\n").getBytes());\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecisionMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSDecisionMsg.java
new file mode 100644 (file)
index 0000000..3539d23
--- /dev/null
@@ -0,0 +1,438 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * COPS Decision Message\r
+ *\r
+ * @version COPSDecisionMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSDecisionMsg extends COPSMsg {\r
+\r
+    /* COPSHeader coming from base class */\r
+    private COPSHandle _clientHandle;\r
+    private COPSError _error;\r
+    private Hashtable _decisions;\r
+    private COPSIntegrity _integrity;\r
+    private COPSContext _decContext;\r
+    private COPSClientSI _decSI;\r
+\r
+    ///\r
+    public COPSDecisionMsg() {\r
+        _clientHandle = null;\r
+        _error = null;\r
+        _decisions = new Hashtable(20);\r
+        _integrity = null;\r
+        _decContext = null;\r
+        _decSI = null;\r
+    }\r
+\r
+    /** Checks the sanity of COPS message and throw an\r
+      * COPSBadDataException when data is bad.\r
+      */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_clientHandle == null) || ( (_error == null) && (_decisions.size() == 0))) {\r
+            throw new COPSException("Bad message format");\r
+        }\r
+    }\r
+\r
+    ///\r
+    protected COPSDecisionMsg(byte[] data) throws COPSException  {\r
+        _decisions = new Hashtable(20);\r
+        _clientHandle = null;\r
+        _error = null;\r
+        _integrity = null;\r
+        _decContext = null;\r
+        _decSI = null;\r
+\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Parses the data and fills COPSDecisionMsg with its constituents\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        super.parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_HANDLE: {\r
+                _clientHandle = new COPSHandle(buf);\r
+                _dataStart += _clientHandle.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_CONTEXT: {\r
+                //dec context\r
+                _decContext = new COPSContext(buf);\r
+                _dataStart += _decContext.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_ERROR: {\r
+                _error = new COPSError(buf);\r
+                _dataStart += _error.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_DEC: {\r
+                COPSDecision decs = new COPSDecision(buf);\r
+                _dataStart += decs.getDataLength();\r
+                addDecision(decs, _decContext);\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format, unknown object type");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Parses the data and fills that follows the header hdr and fills COPSDecisionMsg\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_DEC)\r
+            throw new COPSException ("Error Header (no COPS_OP_DEC)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add client handle to the message\r
+     *\r
+     * @param    handle              a  COPSHandle\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHandle handle) throws COPSException {\r
+        if (handle == null)\r
+            throw new COPSException ("Null Handle");\r
+        _clientHandle = handle;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add an Error object\r
+     *\r
+     * @param    error               a  COPSError\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSError error) throws COPSException {\r
+        if (_decisions.size() != 0)\r
+            throw new COPSException ("No null decisions");\r
+        if (_error != null)\r
+            throw new COPSException ("No null error");\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_integrity != null)\r
+            throw new COPSException ("No null integrity");\r
+        _error = error;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add one or more local decision object for a given decision context\r
+     * the context is optional, if null all decision object are tided to\r
+     * message context\r
+     *\r
+     * @param    decision            a  COPSDecision\r
+     * @param    context             a  COPSContext\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void addDecision(COPSDecision decision, COPSContext context)  throws COPSException {\r
+        //Either error or decision can be added\r
+        //If error is aleady there assert\r
+        if (_error != null)\r
+            throw new COPSException ("No null error");\r
+\r
+        if (decision.isLocalDecision())\r
+            throw new COPSException ("Is local decision");\r
+\r
+        Vector v = (Vector) _decisions.get(context);\r
+        if (v == null) v = new Vector();\r
+\r
+        if (decision.isFlagSet()) {//Commented out as advised by Felix\r
+            //if (v.size() != 0)\r
+            //{\r
+            //Only one set of decision flags is allowed\r
+            //for each context\r
+            //     throw new COPSException ("Bad Message format, only one set of decision flags is allowed.");\r
+            //}\r
+        } else {\r
+            if (v.size() == 0) {\r
+                //The flags decision must precede any other\r
+                //decision message, since the decision is not\r
+                //flags throw exception\r
+                throw new COPSException ("Bad Message format, flags decision must precede any other decision object.");\r
+            }\r
+        }\r
+        v.add(decision);\r
+        _decisions.put(context,v);\r
+\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add integrity object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity)  throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+    /**\r
+     * Add clientSI object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSClientSI clientSI)  throws COPSException {\r
+        if (clientSI == null)\r
+            throw new COPSException ("Null clientSI");\r
+        /*\r
+                  if (!integrity.isMessageIntegrity())\r
+                       throw new COPSException ("Error Integrity");\r
+        */\r
+        _decSI = clientSI;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_clientHandle != null) _clientHandle.writeData(id);\r
+        if (_error != null) _error.writeData(id);\r
+\r
+        //Display decisions\r
+        //Display any local decisions\r
+        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) _decisions.get(context);\r
+            context.writeData(id);\r
+\r
+            for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {\r
+                COPSDecision decision = (COPSDecision) ee.nextElement();\r
+                decision.writeData(id);\r
+            }\r
+        }\r
+\r
+        if (_decSI != null) _decSI.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Method getHeader\r
+     *\r
+     * @return   a COPSHeader\r
+     *\r
+     */\r
+    public COPSHeader getHeader() {\r
+        return _hdr;\r
+    }\r
+\r
+    /**\r
+     * Method getClientHandle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _clientHandle;\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has error object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasError() {\r
+        return (_error != null);\r
+    };\r
+\r
+    /**\r
+     * Should check hasError() before calling\r
+     *\r
+     * @return   a COPSError\r
+     *\r
+     */\r
+    public COPSError getError() {\r
+        return _error;\r
+    };\r
+\r
+    /**\r
+     * Returns a map of decision for which is an arry of context and vector\r
+     * of associated decision object.\r
+     *\r
+     * @return   a Hashtable\r
+     *\r
+     */\r
+    public Hashtable getDecisions() {\r
+        return _decisions;\r
+    };\r
+\r
+    /**\r
+     * Returns true if it has integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    };\r
+\r
+    /**\r
+     * Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return _integrity;\r
+    };\r
+\r
+    /**\r
+     * Method setMsgLength\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength()  throws COPSException {\r
+        short len = 0;\r
+        if (_clientHandle != null)\r
+            len += _clientHandle.getDataLength();\r
+        if (_error != null)\r
+            len += _error.getDataLength();\r
+\r
+        //Display any local decisions\r
+        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) _decisions.get(context);\r
+            len += context.getDataLength();\r
+\r
+            for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {\r
+                COPSDecision decision = (COPSDecision) ee.nextElement();\r
+                len += decision.getDataLength();\r
+            }\r
+        }\r
+        if (_decSI != null) {\r
+            len += _decSI.getDataLength();\r
+        }\r
+        if (_integrity != null) {\r
+            len += _integrity.getDataLength();\r
+        }\r
+\r
+        _hdr.setMsgLength((int) len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_clientHandle != null)\r
+            _clientHandle.dump(os);\r
+        if (_error != null)\r
+            _error.dump(os);\r
+\r
+        //Display any local decisions\r
+        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) _decisions.get(context);\r
+            context.dump(os);\r
+\r
+            for (Enumeration ee = v.elements() ; ee.hasMoreElements() ;) {\r
+                COPSDecision decision = (COPSDecision) ee.nextElement();\r
+                decision.dump(os);\r
+            }\r
+        }\r
+        if (_decSI != null) {\r
+            _decSI.dump(os);\r
+        }\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSDeleteMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSDeleteMsg.java
new file mode 100644 (file)
index 0000000..9499713
--- /dev/null
@@ -0,0 +1,287 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Delete Message (RFC 2748 pag. 24)\r
+ *\r
+ *    When sent from the PEP this message indicates to the remote PDP that\r
+ *    the state identified by the client handle is no longer\r
+ *    available/relevant. This information will then be used by the remote\r
+ *    PDP to initiate the appropriate housekeeping actions. The reason code\r
+ *    object is interpreted with respect to the client-type and signifies\r
+ *    the reason for the removal.\r
+ *\r
+ *    The format of the Delete Request State message is as follows:\r
+ *\r
+ *               <Delete Request>  ::= <Common Header>\r
+ *                                     <Client Handle>\r
+ *                                     <Reason>\r
+ *                                     [<Integrity>]\r
+ *\r
+ *\r
+ * @version COPSDeleteMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSDeleteMsg extends COPSMsg {\r
+    /* COPSHeader coming from base class */\r
+    private COPSHandle  _clientHandle;\r
+    private COPSReason _reason;\r
+    private COPSIntegrity _integrity;\r
+\r
+    public COPSDeleteMsg() {\r
+        _clientHandle = null;\r
+        _reason = null;\r
+        _integrity = null;\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSDeleteMsg object\r
+     */\r
+    protected COPSDeleteMsg(byte[] data) throws COPSException {\r
+        _clientHandle = null;\r
+        _reason = null;\r
+        _integrity = null;\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Checks the sanity of COPS message and throw an\r
+     * COPSException when data is bad.\r
+     *\r
+     */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_clientHandle == null) || (_reason == null))\r
+            throw new COPSException("Bad message format");\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_DRQ)\r
+            throw new COPSException ("Error Header (no COPS_OP_DRQ)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Reason object to the message\r
+     *\r
+     * @param    reason              a  COPSReason\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSReason reason) throws COPSException {\r
+        if (_reason != null)\r
+            throw new COPSException ("No null Reason");\r
+\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_integrity != null)\r
+            throw new COPSException ("No null Integrity");\r
+        _reason = reason;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Handle object\r
+     *\r
+     * @param    handle              a  COPSHandle\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHandle handle) throws COPSException {\r
+        if (handle == null)\r
+            throw new COPSException ("Null Handle");\r
+        _clientHandle = handle;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Integrity object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Get Client Handle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _clientHandle;\r
+    };\r
+\r
+    /**\r
+     * Get Reason\r
+     *\r
+     * @return   a COPSReason\r
+     *\r
+     */\r
+    public COPSReason getReason() {\r
+        return _reason;\r
+    };\r
+\r
+    /**\r
+     * Returns true if it has integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    };\r
+\r
+    /**\r
+     * Get Integrity. Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return (_integrity);\r
+    }\r
+\r
+    /**\r
+     * Writes data to given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_clientHandle != null) _clientHandle.writeData(id);\r
+        if (_reason != null) _reason.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Parse data\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        super.parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_HANDLE: {\r
+                _clientHandle = new COPSHandle(buf);\r
+                _dataStart += _clientHandle.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_REASON_CODE: {\r
+                _reason = new COPSReason(buf);\r
+                _dataStart += _reason.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format, unknown object type");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Parse data\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_DRQ)\r
+            throw new COPSException("Error Header");\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength()  throws COPSException  {\r
+        short len = 0;\r
+        if (_clientHandle != null) len += _clientHandle.getDataLength();\r
+        if (_reason != null) len += _reason.getDataLength();\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_clientHandle != null)\r
+            _clientHandle.dump(os);\r
+\r
+        if (_reason != null)\r
+            _reason.dump(os);\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSError.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSError.java
new file mode 100644 (file)
index 0000000..3bd184b
--- /dev/null
@@ -0,0 +1,163 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Error\r
+ *\r
+ * @version COPSError.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSError extends COPSObjBase {\r
+\r
+    public final static byte COPS_ERR_BAD_HANDLE = 1;\r
+    public final static byte COPS_ERR_BAD_HANDLE_REF = 2;\r
+    public final static byte COPS_ERR_BAD_MSG_FORMAT = 3;\r
+    public final static byte COPS_ERR_FAIL_PROCESS = 4;\r
+    public final static byte COPS_ERR_MISSING_INFO = 5;\r
+    public final static byte COPS_ERR_UNSUPPORTED_CLIENT_TYPE = 6;\r
+    public final static byte COPS_ERR_MANDATORY_OBJECT_MISSING = 7;\r
+    public final static byte COPS_ERR_CLIENT_FAILURE = 8;\r
+    public final static byte COPS_ERR_COMM_FAILURE = 9;\r
+    public final static byte COPS_ERR_UNKNOWN = 10;\r
+    public final static byte COPS_ERR_SHUTTING_DOWN = 11;\r
+    public final static byte COPS_ERR_PDP_REDIRECT = 12;\r
+    public final static byte COPS_ERR_UNKNOWN_OBJECT = 13;\r
+    public final static byte COPS_ERR_AUTH_FAILURE = 14;\r
+    public final static byte COPS_ERR_AUTH_REQUIRED = 15;\r
+    public final static byte COPS_ERR_MA = 16;\r
+\r
+    private final static String G_errmsgArray[] = {\r
+        "Unknown.",\r
+        "Bad handle.",\r
+        "Invalid handle reference.",\r
+        "Bad message format (Malformed message).",\r
+        "Unable to process.",\r
+        "Mandatory client-specific info missing.",\r
+        "Unsupported client-type",\r
+        "Mandatory COPS object missing.",\r
+        "Client failure.",\r
+        "Communication failure.",\r
+        "Unknown.",\r
+        "Shutting down.",\r
+        "Redirect to preferred server.",\r
+        "Unknown COPS object",\r
+        "Authentication failure.",\r
+        "Authentication required.",\r
+    };\r
+\r
+    private COPSObjHeader _objHdr;\r
+    private short _errCode;\r
+    private short _errSubCode;\r
+\r
+    public COPSError(short errCode, short subCode) {\r
+        _objHdr = new COPSObjHeader();\r
+        _errCode = errCode;\r
+        _errSubCode = subCode;\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ERROR);\r
+        _objHdr.setCType((byte) 1);\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    protected COPSError(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _errCode |= ((short) dataPtr[4]) << 8;\r
+        _errCode |= ((short) dataPtr[5]) & 0xFF;\r
+        _errSubCode |= ((short) dataPtr[6]) << 8;\r
+        _errSubCode |= ((short) dataPtr[7]) & 0xFF;\r
+\r
+        // _objHdr.setDataLength(sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    public short getErrCode() {\r
+               return _errCode;\r
+       }\r
+    \r
+    public short getErrSubCode() {\r
+               return _errSubCode;\r
+       }\r
+    /**\r
+     * Returns size in number of octects\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        return (_objHdr.getDataLength());\r
+    };\r
+\r
+    /**\r
+     * Method getDescription\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String getDescription() {\r
+        String errStr1;\r
+        String errStr2;\r
+\r
+        ///Get the details from the error code\r
+        errStr1 = G_errmsgArray[_errCode];\r
+        //TODO - define error sub-codes\r
+        errStr2 = "";\r
+        return (errStr1 + ":" + errStr2);\r
+    }\r
+\r
+    /**\r
+     * Method isError\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isError() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Writes object to given network socket in network byte order\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+\r
+        buf[0] = (byte) (_errCode >> 8);\r
+        buf[1] = (byte) _errCode;\r
+        buf[2] = (byte) (_errSubCode >> 8);\r
+        buf[3] = (byte) _errSubCode;\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Error Code: " + _errCode + "\n").getBytes());\r
+        os.write(new String("Error Sub Code: " + _errSubCode + "\n").getBytes());\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSException.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSException.java
new file mode 100644 (file)
index 0000000..127ce61
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+/**\r
+ * COPS Exception\r
+ *\r
+ * @version COPSException.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSException extends Exception {\r
+\r
+    private int rc;\r
+    final static int GENERAL_ERROR = 0x00000001;\r
+\r
+    public COPSException(String s) {\r
+        super(s);\r
+        rc=0;\r
+    }\r
+\r
+    public COPSException(String msg, int retCode) {\r
+        super(msg);\r
+        rc = retCode;\r
+    }\r
+\r
+    /**\r
+     * Method returnCode\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int returnCode() {\r
+        return rc;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSHandle.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSHandle.java
new file mode 100644 (file)
index 0000000..dc652e3
--- /dev/null
@@ -0,0 +1,146 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Handle Object (RFC 2748 pag. 9)\r
+ *\r
+ *   The Handle Object encapsulates a unique value that identifies an\r
+ *   installed state. This identification is used by most COPS operations.\r
+ *\r
+ *           C-Num = 1\r
+ *\r
+ *           C-Type = 1, Client Handle.\r
+ *\r
+ *   Variable-length field, no implied format other than it is unique from\r
+ *   other client handles from the same PEP (a.k.a. COPS TCP connection)\r
+ *   for a particular client-type. It is always initially chosen by the\r
+ *   PEP and then deleted by the PEP when no longer applicable. The client\r
+ *   handle is used to refer to a request state initiated by a particular\r
+ *   PEP and installed at the PDP for a client-type. A PEP will specify a\r
+ *   client handle in its Request messages, Report messages and Delete\r
+ *   messages sent to the PDP. In all cases, <b>the client handle is used to\r
+ *   uniquely identify a particular PEP's request for a client-type</b>.\r
+ *\r
+ *   The client handle value is set by the PEP and is opaque to the PDP.\r
+ *   The PDP simply performs a byte-wise comparison on the value in this\r
+ *   object with respect to the handle object values of other currently\r
+ *   installed requests.\r
+ *\r
+ * @version COPSHandle.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSHandle extends COPSObjBase {\r
+\r
+    private COPSObjHeader _objHdr;\r
+    private COPSData _id;\r
+    private COPSData _padding;\r
+\r
+    public COPSHandle() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_HANDLE);\r
+        _objHdr.setCType((byte) 1);\r
+        _padding = new COPSData();\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSHandle object\r
+     */\r
+    protected COPSHandle(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        //Get the length of data following the obj header\r
+        int dLen = _objHdr.getDataLength() - 4;\r
+        COPSData d = new COPSData (dataPtr, 4, dLen);\r
+        setId(d);\r
+    }\r
+\r
+    /**\r
+     * Set handle value\r
+     *\r
+     * @param    id                  a  COPSData\r
+     *\r
+     */\r
+    public void setId(COPSData id) {\r
+        _id = id;\r
+        if ((id.length() % 4) != 0) {\r
+            int padLen = 4 - (_id.length() % 4);\r
+            _padding = getPadding(padLen);\r
+        }\r
+        _objHdr.setDataLength((short) _id.length());\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        int lpadding = 0;\r
+        if (_padding != null) lpadding = _padding.length();\r
+        return ((short) (_objHdr.getDataLength() + lpadding));\r
+    }\r
+\r
+    /**\r
+     * Get handle value\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getId() {\r
+        return _id;\r
+    }\r
+\r
+    /**\r
+     * Always return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isClientHandle() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write data in network byte order on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        COPSUtil.writeData(id, _id.getData(), _id.length());\r
+        if (_padding != null) {\r
+            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("client-handle: " + _id.str() + "\n").getBytes());\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeader.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSHeader.java
new file mode 100644 (file)
index 0000000..90a0a63
--- /dev/null
@@ -0,0 +1,371 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Header (RFC 2748 pag. 6)\r
+ *\r
+ *   Each COPS message consists of the COPS header followed by a number of\r
+ *   typed objects.\r
+ *\r
+ *             0              1              2              3\r
+ *     +--------------+--------------+--------------+--------------+\r
+ *     |Version| Flags|    Op Code   |       Client-type           |\r
+ *     +--------------+--------------+--------------+--------------+\r
+ *     |                      Message Length                       |\r
+ *     +--------------+--------------+--------------+--------------+\r
+ *\r
+ *     Global note: //// implies field is reserved, set to 0.\r
+ *\r
+ *       The fields in the header are:\r
+ *         Version: 4 bits\r
+ *             COPS version number. Current version is 1.\r
+ *\r
+ *         Flags: 4 bits\r
+ *             Defined flag values (all other flags MUST be set to 0):\r
+ *               0x1 Solicited Message Flag Bit\r
+ *                This flag is set when the message is solicited by\r
+ *                another COPS message. This flag is NOT to be set\r
+ *                (value=0) unless otherwise specified.\r
+ *\r
+ *         Op Code: 8 bits\r
+ *            The COPS operations:\r
+ *              1 = Request                 (REQ)\r
+ *              2 = Decision                (DEC)\r
+ *              3 = Report State            (RPT)\r
+ *              4 = Delete Request State    (DRQ)\r
+ *              5 = Synchronize State Req   (SSQ)\r
+ *              6 = Client-Open             (OPN)\r
+ *              7 = Client-Accept           (CAT)\r
+ *              8 = Client-Close            (CC)\r
+ *              9 = Keep-Alive              (KA)\r
+ *              10= Synchronize Complete    (SSC)\r
+ *\r
+ *       Client-type: 16 bits\r
+ *\r
+ *\r
+ * @version COPSHeader.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSHeader {\r
+\r
+    public final static byte COPS_OP_REQ = 1;\r
+    public final static byte COPS_OP_DEC = 2;\r
+    public final static byte COPS_OP_RPT = 3;\r
+    public final static byte COPS_OP_DRQ = 4;\r
+    public final static byte COPS_OP_SSQ = 5;\r
+    public final static byte COPS_OP_OPN = 6;\r
+    public final static byte COPS_OP_CAT = 7;\r
+    public final static byte COPS_OP_CC = 8;\r
+    public final static byte COPS_OP_KA = 9;\r
+    public final static byte COPS_OP_SSC = 10;\r
+\r
+    public final static byte COPS_FLAG_NULL = 0;\r
+    public final static byte COPS_FLAG_SOLICITED = 1;\r
+\r
+    private byte _versionNflg;\r
+    private byte _opCode;\r
+    private short _cType;\r
+    private int _msgLength;\r
+\r
+    public COPSHeader() {\r
+        _versionNflg = 0x10;\r
+        _opCode = 0;\r
+        _cType = 0;\r
+        _msgLength = 0;\r
+    }\r
+\r
+    public COPSHeader(byte opCode, short clientType) {\r
+        _versionNflg = 0x10;\r
+        _opCode = opCode;\r
+        _cType = clientType;\r
+        _msgLength = 0;\r
+        if (isAKeepAlive()) _cType = 0;\r
+    }\r
+\r
+    public COPSHeader(byte opCode) {\r
+        _versionNflg = 0x10;\r
+        _opCode = opCode;\r
+        _cType = 0;\r
+        _msgLength = 0;\r
+        if (isAKeepAlive()) _cType = 0;\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSHeader object\r
+     */\r
+    public COPSHeader(byte[] buf) {\r
+        _versionNflg = (byte) buf[0];\r
+        _opCode = (byte) buf[1];\r
+        _cType |= ((short) buf[2]) << 8;\r
+        _cType |= ((short) buf[3]) & 0xFF;\r
+        _msgLength |= ((short) buf[4]) << 24;\r
+        _msgLength |= ((short) buf[5]) << 16;\r
+        _msgLength |= ((short) buf[6]) << 8;\r
+        _msgLength |= ((short) buf[7]) & 0xFF;\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message Request, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isARequest() {\r
+        return (_opCode == COPS_OP_REQ);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message Decision, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isADecision() {\r
+        return (_opCode == COPS_OP_DEC);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message Report, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAReport() {\r
+        return (_opCode == COPS_OP_RPT);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message DeleteRequest, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isADeleteReq() {\r
+        return (_opCode == COPS_OP_DRQ);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message SyncStateReq, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isASyncStateReq() {\r
+        return (_opCode == COPS_OP_SSQ);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message ClientOpen, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAClientOpen() {\r
+        return (_opCode == COPS_OP_OPN);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message ClientAccept, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAClientAccept() {\r
+        return (_opCode == COPS_OP_CAT);\r
+    }\r
+\r
+    /**\r
+     * If operation code corresponds with a message ClientClose, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAClientClose() {\r
+        return (_opCode == COPS_OP_CC);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message KeepAlive, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAKeepAlive() {\r
+        return (_opCode == COPS_OP_KA);\r
+    }\r
+\r
+    /**\r
+     * If the operation code corresponds with a message SSC, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isASyncComplete() {\r
+        return (_opCode == COPS_OP_SSC);\r
+    }\r
+\r
+    /**\r
+     * Get message length\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getMsgLength() {\r
+        return _msgLength;\r
+    }\r
+\r
+    /**\r
+     * Get header length\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getHdrLength() {\r
+        // return (sizeof(u_int32_t) * 2);\r
+        return ( 8 );\r
+    }\r
+\r
+    /**\r
+     * Get Operation Code\r
+     *\r
+     * @return   a byte\r
+     *\r
+     */\r
+    public byte getOpCode() {\r
+        return _opCode;\r
+    }\r
+\r
+    /**\r
+     * Set the solicitation flag\r
+     *\r
+     * @param    flg                 a  byte\r
+     *\r
+     */\r
+    public void setFlag(byte flg) {\r
+        _versionNflg &= 0x10;\r
+        _versionNflg |= flg;\r
+    }\r
+\r
+    /**\r
+     * Returns the flags field\r
+     * @return aByte     Flags field in header\r
+     */\r
+    public byte getFlags() { //OJO\r
+        return (byte) (_versionNflg & 0x0f);\r
+    }\r
+\r
+    /**\r
+     * Set the client-type\r
+     *\r
+     * @param    cType               a  short\r
+     *\r
+     */\r
+    public void setClientType(short cType) {\r
+        _cType = cType;\r
+    };\r
+\r
+    /**\r
+     * Set the message length\r
+     *\r
+     * @param    len                 an int\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void setMsgLength(int len) throws COPSException {\r
+        if ((len % 4) != 0)\r
+            throw new COPSException ("Message is not aligned on 32 bit intervals");\r
+        _msgLength = len + 8;\r
+    }\r
+\r
+    /**\r
+     * Get client-type\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getClientType() {\r
+        return (_cType);\r
+    };\r
+\r
+    /**\r
+     * Always return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isCOPSHeader() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Writes object to given network socket in network byte order\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        byte buf[] = new byte[8];\r
+\r
+        buf[0] = (byte) _versionNflg;\r
+        buf[1] = (byte) _opCode;\r
+        buf[2] = (byte) (_cType >> 8);\r
+        buf[3] = (byte) _cType;\r
+        buf[4] = (byte) (_msgLength >> 24);\r
+        buf[5] = (byte) (_msgLength >> 16);\r
+        buf[6] = (byte) (_msgLength >> 8);\r
+        buf[7] = (byte) _msgLength;\r
+\r
+        COPSUtil.writeData(id, buf, 8);\r
+    }\r
+\r
+    /**\r
+     * Get an object textual description\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String toString() {\r
+        String str = new String();\r
+\r
+        str += "**MSG HEADER** \n";\r
+        str += "Version: " + (_versionNflg >> 4) + "\n";\r
+        str += "Flags: " + (_versionNflg & 0x01) + "\n";\r
+        str += "OpCode: " + _opCode + "\n";\r
+        str += "Client-type: " + _cType + "\n";\r
+        str += "Message-length(bytes): " + _msgLength + "\n";\r
+        return str;\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        os.write(new String("**MSG HEADER**" + "\n").getBytes());\r
+        os.write(new String("Version: " + (_versionNflg >> 4) + "\n").getBytes());\r
+        os.write(new String("Flags: " + (_versionNflg & 0x01) + "\n").getBytes());\r
+        os.write(new String("OpCode: " + _opCode + "\n").getBytes());\r
+        os.write(new String("Client-type: " + _cType + "\n").getBytes());\r
+        os.write(new String("Message-length(bytes): " + _msgLength + "\n").getBytes());\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIntegrity.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIntegrity.java
new file mode 100644 (file)
index 0000000..84ff09b
--- /dev/null
@@ -0,0 +1,187 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Integrity Object\r
+ *\r
+ * @version COPSIntegrity.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIntegrity extends COPSObjBase {\r
+    private COPSObjHeader _objHdr;\r
+    private int _keyId;\r
+    private int _seqNum;\r
+    private COPSData _keyDigest;\r
+    private COPSData _padding;\r
+\r
+    public COPSIntegrity() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_MSG_INTEGRITY);\r
+        _objHdr.setCType((byte) 1);\r
+        _keyId = 0;\r
+        _seqNum = 0;\r
+    }\r
+\r
+    public COPSIntegrity(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _keyId |= ((short) dataPtr[4]) << 24;\r
+        _keyId |= ((short) dataPtr[5]) << 16;\r
+        _keyId |= ((short) dataPtr[6]) << 8;\r
+        _keyId |= ((short) dataPtr[7]) & 0xFF;\r
+        _seqNum |= ((short) dataPtr[8]) << 24;\r
+        _seqNum |= ((short) dataPtr[9]) << 16;\r
+        _seqNum |= ((short) dataPtr[10]) << 8;\r
+        _seqNum |= ((short) dataPtr[11]) & 0xFF;\r
+\r
+        int dLen = _objHdr.getDataLength() - 12;\r
+        COPSData d = new COPSData(dataPtr, 12, dLen);\r
+        setKeyDigest(d);\r
+    }\r
+\r
+    /**\r
+     * Method setKeyId\r
+     *\r
+     * @param    keyId               an int\r
+     *\r
+     */\r
+    public void setKeyId(int keyId) {\r
+        _keyId = keyId;\r
+    };\r
+\r
+    /**\r
+     * Method setSeqNum\r
+     *\r
+     * @param    seqNum              an int\r
+     *\r
+     */\r
+    public void setSeqNum(int seqNum) {\r
+        _seqNum = seqNum;\r
+    };\r
+\r
+    /**\r
+     * Method setKeyDigest\r
+     *\r
+     * @param    keyDigest           a  COPSData\r
+     *\r
+     */\r
+    public void setKeyDigest(COPSData keyDigest) {\r
+        _keyDigest = keyDigest;\r
+        if (_keyDigest.length() % 4 != 0) {\r
+            int padLen = 4 - _keyDigest.length() % 4;\r
+            _padding = getPadding(padLen);\r
+        }\r
+        // _objHdr.setDataLength(sizeof(u_int32_t)\r
+        //                           + sizeof(u_int32_t) + _keyDigest.length());\r
+        _objHdr.setDataLength((short) (8 + _keyDigest.length()));\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        int lpadding = 0;\r
+        if (_padding != null) lpadding = _padding.length();\r
+        return ((short) (_objHdr.getDataLength() + lpadding));\r
+    }\r
+\r
+    /**\r
+     * Method getKeyId\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getKeyId() {\r
+        return _keyId;\r
+    };\r
+\r
+    /**\r
+     * Method getSeqNum\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getSeqNum() {\r
+        return _seqNum;\r
+    };\r
+\r
+    /**\r
+     * Method getKeyDigest\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getKeyDigest() {\r
+        return _keyDigest;\r
+    };\r
+\r
+    /**\r
+     * Method isMessageIntegrity\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isMessageIntegrity() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        byte[] buf = new byte[8];\r
+        buf[0] = (byte) (_keyId >> 24);\r
+        buf[1] = (byte) (_keyId >> 16);\r
+        buf[2] = (byte) (_keyId >> 8);\r
+        buf[3] = (byte) _keyId;\r
+        buf[4] = (byte) (_seqNum >> 24);\r
+        buf[5] = (byte) (_seqNum >> 16);\r
+        buf[6] = (byte) (_seqNum >> 8);\r
+        buf[7] = (byte) _seqNum;\r
+        COPSUtil.writeData(id, buf, 8);\r
+\r
+        COPSUtil.writeData(id, _keyDigest.getData(), _keyDigest.length());\r
+        if (_padding != null) {\r
+            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Key Id: " + _keyId + "\n").getBytes());\r
+        os.write(new String("Sequence: " + _seqNum + "\n").getBytes());\r
+        os.write(new String("Key digest: " + _keyDigest.str() + "\n").getBytes());\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSInterface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSInterface.java
new file mode 100644 (file)
index 0000000..7d6b746
--- /dev/null
@@ -0,0 +1,67 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Interface\r
+ *\r
+ * @version COPSInterface.java, v 1.00 2003\r
+ *\r
+ */\r
+abstract class COPSInterface extends COPSObjBase {\r
+    /**\r
+     * Method isIpv4Address\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    protected boolean isIpv4Address() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isIpv6Address\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    protected boolean isIpv6Address() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isInInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    protected boolean isInInterface() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isOutInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    protected boolean isOutInterface() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    protected boolean isInterface() {\r
+        return true;\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Address.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Address.java
new file mode 100644 (file)
index 0000000..2bb7d87
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+import java.net.InetAddress;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * COPS IPv4 Address\r
+ *\r
+ * @version COPSIpv4Address.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv4Address {\r
+\r
+    private byte[] _addr;\r
+\r
+    public COPSIpv4Address() {\r
+        _addr = new byte[4];\r
+    }\r
+\r
+    public COPSIpv4Address(String hostName) throws UnknownHostException {\r
+        setIpAddress(hostName);\r
+    }\r
+\r
+    /**\r
+     * Method setIpAddress\r
+     *\r
+     * @param    hostName            a  String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public void setIpAddress(String hostName) throws UnknownHostException {\r
+        _addr = InetAddress.getByName(hostName).getAddress();\r
+    }\r
+\r
+    /**\r
+     * Method getIpName\r
+     *\r
+     * @return   a String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public String getIpName() throws UnknownHostException {\r
+        return InetAddress.getByAddress(_addr).getHostName();\r
+    }\r
+\r
+    /**\r
+     * Method getIpAddress\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getIpAddress() {\r
+        int ipaddr = 0;\r
+\r
+        ipaddr |= ((int) _addr[0]) << 24;\r
+        ipaddr |= ((int) _addr[1]) << 16;\r
+        ipaddr |= ((int) _addr[2]) << 8;\r
+        ipaddr |= ((int) _addr[3]) & 0xFF;\r
+\r
+        return ipaddr;\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    dataPtr             a  byte[]\r
+     *\r
+     */\r
+    public void parse(byte[] dataPtr) {\r
+        new ByteArrayInputStream(dataPtr).read(_addr,0,4);\r
+    }\r
+\r
+    /**\r
+     * Method getDataLength\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        return (4);\r
+    }\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        COPSUtil.writeData(id, _addr, 4);\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4InInterface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4InInterface.java
new file mode 100644 (file)
index 0000000..d3a2c02
--- /dev/null
@@ -0,0 +1,57 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS IPv4 Input Address\r
+ *\r
+ * @version COPSIpv4InInterface.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv4InInterface extends COPSIpv4Interface {\r
+    public COPSIpv4InInterface() {\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ININTF);\r
+    }\r
+\r
+    public COPSIpv4InInterface(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method className\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String className() {\r
+        return "COPSIpv4InInterface";\r
+    }\r
+\r
+    /**\r
+     * Method isInInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isInInterface() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Interface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4Interface.java
new file mode 100644 (file)
index 0000000..d22d788
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * COPS IPv4 Interface\r
+ *\r
+ * @version COPSIpv4Interface.java, v 1.00 2003\r
+ *\r
+ */\r
+public abstract class COPSIpv4Interface extends COPSInterface {\r
+\r
+    protected COPSObjHeader _objHdr;\r
+    private COPSIpv4Address _addr;\r
+    private int _ifindex;\r
+\r
+\r
+    /**\r
+     * Method isIpv4Address\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIpv4Address() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Method setIpAddress\r
+     *\r
+     * @param    hostName            a  String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public void setIpAddress(String hostName) throws UnknownHostException {\r
+        _addr.setIpAddress(hostName);\r
+    }\r
+\r
+    /**\r
+     * Method getIpName\r
+     *\r
+     * @return   a String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public String getIpName() throws UnknownHostException {\r
+        return (_addr.getIpName());\r
+    }\r
+\r
+    /**\r
+     * Method getIpAddress\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getIpAddress() {\r
+        return (_addr.getIpAddress());\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    protected COPSIpv4Interface() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCType((byte) 1);\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    protected COPSIpv4Interface(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        byte[] buf = new byte[4];\r
+        System.arraycopy(dataPtr,4,buf,0,4);\r
+\r
+        _addr.parse(buf);\r
+\r
+        _ifindex |= ((int) dataPtr[8]) << 24;\r
+        _ifindex |= ((int) dataPtr[9]) << 16;\r
+        _ifindex |= ((int) dataPtr[10]) << 8;\r
+        _ifindex |= ((int) dataPtr[11]) & 0xFF;\r
+\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4LastPdpAddr.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4LastPdpAddr.java
new file mode 100644 (file)
index 0000000..a392b19
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+/**\r
+ * COPS IPv4 Last PDP Address\r
+ *\r
+ * @version COPSIpv4LastPdpAddr.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv4LastPdpAddr extends COPSIpv4PdpAddress {\r
+\r
+    public COPSIpv4LastPdpAddr() {\r
+        super();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_LAST_PDP_ADDR);\r
+    }\r
+\r
+    public COPSIpv4LastPdpAddr(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method isLastPdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isLastPdpAddress() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Ipv4PdpAddress" + "\n").getBytes());\r
+        os.write(new String("Address: " + _addr.getIpName() + "\n").getBytes());\r
+        os.write(new String("Port: " + _tcpPort + "\n").getBytes());\r
+    }\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4OutInterface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4OutInterface.java
new file mode 100644 (file)
index 0000000..3178a93
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS IPv4 Output Interface\r
+ *\r
+ * @version COPSIpv4OutInterface.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv4OutInterface extends COPSIpv4Interface {\r
+    public COPSIpv4OutInterface() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ININTF);\r
+    }\r
+\r
+    public COPSIpv4OutInterface(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method className\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String className() {\r
+        return "COPSIpv4OutInterface";\r
+    }\r
+\r
+    /**\r
+     * Method isInInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isInInterface() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+    }\r
+\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpAddress.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv4PdpAddress.java
new file mode 100644 (file)
index 0000000..5c8d1df
--- /dev/null
@@ -0,0 +1,141 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * COPS IPv4 PDP Address\r
+ *\r
+ * @version COPSIpv4PdpAddress.java, v 1.00 2003\r
+ *\r
+ */\r
+abstract public class COPSIpv4PdpAddress extends COPSPdpAddress {\r
+\r
+    protected COPSObjHeader _objHdr;\r
+    protected COPSIpv4Address _addr;\r
+    private short _reserved;\r
+    protected short _tcpPort;\r
+\r
+    protected COPSIpv4PdpAddress() {\r
+        _addr = new COPSIpv4Address();\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCType((byte) 1);\r
+        // _objHdr.setDataLength((short) _addr.getDataLength() + sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    protected COPSIpv4PdpAddress(byte[] dataPtr) {\r
+        _addr = new COPSIpv4Address();\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        byte[] buf = new byte[4];\r
+        System.arraycopy(dataPtr,2,buf,0,4);\r
+        _addr.parse(buf);\r
+\r
+        _reserved |= ((short) dataPtr[8]) << 8;\r
+        _reserved |= ((short) dataPtr[9]) & 0xFF;\r
+        _tcpPort |= ((short) dataPtr[10]) << 8;\r
+        _tcpPort |= ((short) dataPtr[11]) & 0xFF;\r
+\r
+        // _objHdr.setDataLength(_addr.getDataLength() + sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    /**\r
+     * Method setIpAddress\r
+     *\r
+     * @param    hostName            a  String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public void setIpAddress(String hostName) throws UnknownHostException  {\r
+        _addr.setIpAddress(hostName);\r
+    }\r
+\r
+    /**\r
+     * Method setTcpPort\r
+     *\r
+     * @param    port                a  short\r
+     *\r
+     */\r
+    public void setTcpPort(short port) {\r
+        _tcpPort = port;\r
+    }\r
+\r
+    /**\r
+     * Method getIpName\r
+     *\r
+     * @return   a String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public String getIpName() throws UnknownHostException {\r
+        return (_addr.getIpName());\r
+    }\r
+\r
+    /**\r
+     * Method getTcpPort\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    short getTcpPort() {\r
+        return _tcpPort;\r
+    };\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    /**\r
+     * Method isIpv6PdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIpv6PdpAddress() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        //\r
+        _objHdr.writeData(id);\r
+        _addr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+        buf[0] = (byte) (_reserved & 0xFF);\r
+        buf[1] = (byte) (_reserved << 8);\r
+        buf[2] = (byte) (_tcpPort & 0xFF);\r
+        buf[3] = (byte) (_tcpPort << 8);\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Address.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Address.java
new file mode 100644 (file)
index 0000000..0364359
--- /dev/null
@@ -0,0 +1,90 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+import java.net.InetAddress;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * COPS IPv6 Address\r
+ *\r
+ * @version COPSIpv6Address.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv6Address {\r
+\r
+    private byte[] _addr;\r
+\r
+    public COPSIpv6Address() {\r
+        _addr = new byte[16];\r
+    }\r
+\r
+    public COPSIpv6Address(String hostName) throws UnknownHostException {\r
+        setIpAddress(hostName);\r
+    }\r
+\r
+    /**\r
+     * Method setIpAddress\r
+     *\r
+     * @param    hostName            a  String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public void setIpAddress(String hostName) throws UnknownHostException {\r
+        _addr = InetAddress.getByName(hostName).getAddress();\r
+    }\r
+\r
+    /**\r
+     * Method getIpName\r
+     *\r
+     * @return   a String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public String getIpName() throws UnknownHostException {\r
+        return InetAddress.getByAddress(_addr).getHostName();\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    dataPtr             a  byte[]\r
+     *\r
+     */\r
+    public void parse(byte[] dataPtr) {\r
+        new ByteArrayInputStream(dataPtr).read(_addr,0,16);\r
+    }\r
+\r
+    /**\r
+     * Method getDataLength\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        return (16);\r
+    }\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        COPSUtil.writeData(id, _addr, 16);\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6InInterface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6InInterface.java
new file mode 100644 (file)
index 0000000..068c897
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS IPv6 Input Interface\r
+ *\r
+ * @version COPSIpv6InInterface.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv6InInterface extends COPSIpv6Interface {\r
+    public COPSIpv6InInterface() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ININTF);\r
+    }\r
+\r
+    public COPSIpv6InInterface(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method className\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String className() {\r
+        return "COPSIpv6InInterface";\r
+    }\r
+\r
+    /**\r
+     * Method isInInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isInInterface() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Interface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6Interface.java
new file mode 100644 (file)
index 0000000..d1214a0
--- /dev/null
@@ -0,0 +1,95 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * COPS IPv6 Interface\r
+ *\r
+ * @version COPSIpv6Interface.java, v 1.00 2003\r
+ *\r
+ */\r
+public abstract class COPSIpv6Interface extends COPSInterface {\r
+\r
+    /**\r
+     * Method isIpv6Address\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIpv6Address() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Method setIpAddress\r
+     *\r
+     * @param    hostName            a  String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public void setIpAddress(String hostName) throws UnknownHostException {\r
+        _addr.setIpAddress(hostName);\r
+    }\r
+\r
+    /**\r
+     * Method getIpName\r
+     *\r
+     * @return   a String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public String getIpName() throws UnknownHostException {\r
+        return (_addr.getIpName());\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    protected COPSIpv6Interface() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCType((byte) 2);\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    protected COPSIpv6Interface(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        byte[] buf = new byte[4];\r
+        System.arraycopy(dataPtr,4,buf,0,16);\r
+\r
+        _addr.parse(buf);\r
+\r
+        _ifindex |= ((int) dataPtr[20]) << 24;\r
+        _ifindex |= ((int) dataPtr[21]) << 16;\r
+        _ifindex |= ((int) dataPtr[22]) << 8;\r
+        _ifindex |= ((int) dataPtr[23]) & 0xFF;\r
+\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    protected COPSObjHeader _objHdr;\r
+    private COPSIpv6Address _addr;\r
+    private int _ifindex;\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6LastPdpAddr.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6LastPdpAddr.java
new file mode 100644 (file)
index 0000000..f0d52bb
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+/**\r
+ * COPS IPv6 Last PDP Address\r
+ *\r
+ * @version COPSIpv6LastPdpAddr.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv6LastPdpAddr extends COPSIpv6PdpAddress {\r
+\r
+    public COPSIpv6LastPdpAddr() {\r
+        super();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_LAST_PDP_ADDR);\r
+    }\r
+\r
+    public COPSIpv6LastPdpAddr(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method isLastPdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isLastPdpAddress() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Ipv6PdpAddress" + "\n").getBytes());\r
+        os.write(new String("Address: " + _addr.getIpName() + "\n").getBytes());\r
+        os.write(new String("Port: " + _tcpPort + "\n").getBytes());\r
+    }\r
+};\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6OutInterface.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6OutInterface.java
new file mode 100644 (file)
index 0000000..bb1f641
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS IPv6 Output Interface\r
+ *\r
+ * @version COPSIpv6OutInterface.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSIpv6OutInterface extends COPSIpv6Interface {\r
+    public COPSIpv6OutInterface() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_ININTF);\r
+    }\r
+\r
+    public COPSIpv6OutInterface(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method className\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String className() {\r
+        return "COPSIpv6OutInterface";\r
+    }\r
+\r
+    /**\r
+     * Method isInInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isInInterface() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpAddress.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSIpv6PdpAddress.java
new file mode 100644 (file)
index 0000000..f46ff04
--- /dev/null
@@ -0,0 +1,140 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * COPS IPv6 PDP Address\r
+ *\r
+ * @version COPSIpv6PdpAddress.java, v 1.00 2003\r
+ *\r
+ */\r
+abstract public class COPSIpv6PdpAddress extends COPSPdpAddress {\r
+\r
+    protected COPSObjHeader _objHdr;\r
+    protected COPSIpv6Address _addr;\r
+    private short _reserved;\r
+    protected short _tcpPort;\r
+\r
+    protected COPSIpv6PdpAddress() {\r
+        _addr = new COPSIpv6Address();\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCType((byte) 2);\r
+        // _objHdr.setDataLength((short) _addr.getDataLength() + sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    protected COPSIpv6PdpAddress(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        byte[] buf = new byte[16];\r
+        System.arraycopy(dataPtr,2,buf,0,16);\r
+        _addr.parse(buf);\r
+\r
+        _reserved |= ((short) dataPtr[20]) << 8;\r
+        _reserved |= ((short) dataPtr[21]) & 0xFF;\r
+        _tcpPort |= ((short) dataPtr[22]) << 8;\r
+        _tcpPort |= ((short) dataPtr[23]) & 0xFF;\r
+\r
+        // _objHdr.setDataLength(_addr.getDataLength() + sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) (_addr.getDataLength() + 4));\r
+    }\r
+\r
+    /**\r
+     * Method setIpAddress\r
+     *\r
+     * @param    hostName            a  String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public void setIpAddress(String hostName) throws UnknownHostException  {\r
+        _addr.setIpAddress(hostName);\r
+    }\r
+\r
+    /**\r
+     * Method setTcpPort\r
+     *\r
+     * @param    port                a  short\r
+     *\r
+     */\r
+    public void setTcpPort(short port) {\r
+        _tcpPort = port;\r
+    }\r
+\r
+    /**\r
+     * Method getIpName\r
+     *\r
+     * @return   a String\r
+     *\r
+     * @throws   UnknownHostException\r
+     *\r
+     */\r
+    public String getIpName() throws UnknownHostException {\r
+        return (_addr.getIpName());\r
+    }\r
+\r
+    /**\r
+     * Method getTcpPort\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    short getTcpPort() {\r
+        return _tcpPort;\r
+    };\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    /**\r
+     * Method isIpv6PdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIpv6PdpAddress() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        //\r
+        _objHdr.writeData(id);\r
+        _addr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+        buf[0] = (byte) (_reserved >> 8);\r
+        buf[1] = (byte) _reserved;\r
+        buf[2] = (byte) (_tcpPort >> 8);\r
+        buf[3] = (byte) _tcpPort ;\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSKAMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSKAMsg.java
new file mode 100644 (file)
index 0000000..17abb33
--- /dev/null
@@ -0,0 +1,191 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Keep Alive Message\r
+ *\r
+ * @version COPSKAMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSKAMsg extends COPSMsg {\r
+\r
+    /* COPSHeader coming from base class */\r
+    private COPSIntegrity  _integrity;\r
+\r
+    public COPSKAMsg() {\r
+        _integrity = null;\r
+    }\r
+\r
+    protected COPSKAMsg(byte[] data) throws COPSException {\r
+        _integrity = null;\r
+        parse(data);\r
+    }\r
+\r
+    /** Checks the sanity of COPS message and throw an\r
+      * COPSBadDataException when data is bad.\r
+      */\r
+    public void checkSanity() throws COPSException {\r
+        //The client type in the header MUST always be set to 0\r
+        //as KA is used for connection verification.RFC 2748\r
+        if ((_hdr == null) && (_hdr.getClientType() != 0))\r
+            throw new COPSException("Bad message format");\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_KA)\r
+            throw new COPSException ("Error Header (no COPS_OP_KA)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Integrity objects\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has Integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    };\r
+\r
+    /**\r
+     * Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return (_integrity);\r
+    }\r
+\r
+    /**\r
+     * Writes data to given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        super.parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format, unknown object type");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data)     throws COPSException {\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_KA)\r
+            throw new COPSException("Error Header");\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    private void setMsgLength() throws COPSException {\r
+        short len = 0;\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSKATimer.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSKATimer.java
new file mode 100644 (file)
index 0000000..63c4eab
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Keep Alive Timer\r
+ *\r
+ * @version COPSKATimer.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSKATimer extends COPSTimer {\r
+\r
+    public COPSKATimer() {\r
+        super ((short) 1);\r
+        _objHdr.setCNum(COPSObjHeader.COPS_KA);\r
+        _objHdr.setCType((byte) 1);\r
+    }\r
+\r
+    ///\r
+    public COPSKATimer(short timeVal) {\r
+        super(timeVal);\r
+        _objHdr.setCNum(COPSObjHeader.COPS_KA);\r
+        _objHdr.setCType((byte) 1);\r
+    }\r
+\r
+    /**\r
+     * Method isKATimer\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isKATimer() {\r
+        return true;\r
+    }\r
+\r
+    protected COPSKATimer(byte[] dataPtr) {\r
+        super (dataPtr);\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSLPDPDecision.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSLPDPDecision.java
new file mode 100644 (file)
index 0000000..cd4a7ff
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS LPDP Decision Object\r
+ *\r
+ * @version COPSLPDPDecision.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSLPDPDecision extends COPSDecision {\r
+\r
+    /**\r
+      Constructor to create a Local Decision object.\r
+     */\r
+    public COPSLPDPDecision(byte cType) {\r
+        super (cType);\r
+        _objHdr.setCNum(COPSObjHeader.COPS_LPDP_DEC);\r
+    }\r
+\r
+    public COPSLPDPDecision() {\r
+        super ();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_LPDP_DEC);\r
+    }\r
+\r
+    /**\r
+     * Method isLocalDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isLocalDecision() {\r
+        return true;\r
+    }\r
+\r
+    protected COPSLPDPDecision(byte[] data) {\r
+        super (data);\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsg.java
new file mode 100644 (file)
index 0000000..2c492f3
--- /dev/null
@@ -0,0 +1,121 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Message\r
+ *\r
+ * @version COPSMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+abstract public class COPSMsg {\r
+\r
+    protected COPSHeader _hdr;\r
+    protected int _dataLength;\r
+    protected int _dataStart;\r
+\r
+    /**\r
+     * Method getHeader\r
+     *\r
+     * @return   a COPSHeader\r
+     *\r
+     */\r
+    public COPSHeader getHeader() {\r
+        return _hdr;\r
+    }\r
+\r
+    /**\r
+     * Method writeData\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public abstract void writeData(Socket id) throws IOException;\r
+\r
+    /**\r
+     * Method getMsgLength\r
+     *\r
+     * @return   an int\r
+     *\r
+     */\r
+    public int getMsgLength() {\r
+        return _hdr.getMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected abstract void parse(COPSHeader hdr, byte[] data) throws COPSException;\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected abstract void parse(byte[] data) throws COPSException;\r
+\r
+    /**\r
+     * Method parseHeader\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parseHeader(byte[] data) throws COPSException {\r
+        _dataLength = 0;\r
+        _dataStart = 0;\r
+        if (_hdr == null) {\r
+            // _hdr = new COPSHeader(COPSHeader.COPS_OP_CAT);\r
+            _hdr = new COPSHeader(data);\r
+            _dataStart += 8;\r
+            _dataLength = _hdr.getMsgLength();\r
+        } else {\r
+            //header is already read\r
+            _dataLength = _hdr.getMsgLength() - 8;\r
+        }\r
+\r
+        //validate the message length\r
+        //Should fill on the 32bit boundary\r
+        if ((_hdr.getMsgLength() % 4 != 0)) {\r
+            throw new COPSException("Bad message format: COPS message is not on 32 bit bounday");\r
+        }\r
+    }\r
+\r
+    /** Checks the sanity of COPS message and throw an\r
+         COPSBadDataException when data is bad.\r
+    */\r
+    public abstract void checkSanity()throws COPSException;\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        os.write(new String("COPS Message").getBytes());\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsgParser.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSMsgParser.java
new file mode 100644 (file)
index 0000000..04a4aff
--- /dev/null
@@ -0,0 +1,133 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+/**\r
+ * COPS Message Parser\r
+ *\r
+ * @version COPSMsgParser.java, v 1.00 2003\r
+ *\r
+ */\r
+\r
+// import org.umu.cops.common.COPSDebug;\r
+\r
+public class COPSMsgParser {\r
+    ///\r
+    public COPSMsgParser() {\r
+\r
+    }\r
+\r
+    /** Parses the given COPS data and returns a COPSMsg object\r
+     *     with COPS object filed in.The COPSMsg object is allocated in the\r
+     *     call and it is the responsibility of the caller to free the memory\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @return   a COPSMsg\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public COPSMsg parse(byte[] data) throws COPSException {\r
+        COPSHeader hdr = new COPSHeader(data);\r
+\r
+        byte[] buf = new byte[data.length - 8];\r
+        System.arraycopy(data,8,buf,0,data.length - 8);\r
+\r
+        return (parse(hdr, buf));\r
+    }\r
+\r
+    /**\r
+     * Parse the message with given header , the data is pointing\r
+     * to the data following the header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @return   a COPSMsg\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public COPSMsg parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        COPSMsg copsMsg = null;\r
+        short cCode = hdr.getOpCode();\r
+        switch (cCode) {\r
+        case COPSHeader.COPS_OP_REQ: {\r
+            // COPSDebug.out(getClass().getName(), "Creating REQ msg");\r
+            copsMsg = new COPSReqMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_DEC: {\r
+            // COPSDebug.out(getClass().getName(), "Creating DEC msg");\r
+            copsMsg = new COPSDecisionMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_RPT: {\r
+            // COPSDebug.out(getClass().getName(), "Creating RPT msg");\r
+            copsMsg = new COPSReportMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_DRQ: {\r
+            // COPSDebug.out(getClass().getName(), "Creating DRQ msg");\r
+            copsMsg = new COPSDeleteMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_OPN: {\r
+            // COPSDebug.out(getClass().getName(), "Creating Client-Open msg");\r
+            copsMsg = new COPSClientOpenMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_CAT: {\r
+            // COPSDebug.out(getClass().getName(), "Creating Client-Accept msg");\r
+            copsMsg = new COPSClientAcceptMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_CC: {\r
+            // COPSDebug.out(getClass().getName(), "Creating Client-Close msg");\r
+            copsMsg = new COPSClientCloseMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_KA: {\r
+            // COPSDebug.out(getClass().getName(), "Creating KA msg");\r
+            copsMsg = new COPSKAMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_SSQ: {\r
+            // COPSDebug.out(getClass().getName(), "Creating Sync-State Request msg");\r
+            copsMsg = new COPSSyncStateMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        case COPSHeader.COPS_OP_SSC: {\r
+            // COPSDebug.out(getClass().getName(), "Creating Sync-State Complete msg");\r
+            copsMsg = new COPSSyncStateMsg();\r
+            copsMsg.parse(hdr, data);\r
+        }\r
+        break;\r
+        default:\r
+            // COPSDebug.out(getClass().getName(), "Unknown message type");\r
+            break;\r
+        }\r
+\r
+\r
+        // if(copsMsg != null)\r
+        //     try { copsMsg.dump(COPSDebug.out); } catch (Exception e) {};\r
+\r
+        return copsMsg;\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjBase.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjBase.java
new file mode 100644 (file)
index 0000000..bd05be2
--- /dev/null
@@ -0,0 +1,196 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Arrays;\r
+\r
+/**\r
+ * COPS Object\r
+ *\r
+ * @version COPSObjBase.java, v 1.00 2003\r
+ *\r
+ */\r
+public abstract class COPSObjBase {\r
+    /**\r
+     * Add padding in the data, if the data does not fall on 32-bit boundary\r
+     *\r
+     * @param    len                 an int\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    static COPSData getPadding(int len) {\r
+        byte[] padBuf = new byte[len];\r
+        Arrays.fill(padBuf, (byte) 0);\r
+        COPSData d = new COPSData(padBuf, 0, len);\r
+        return d;\r
+    }\r
+\r
+    /**\r
+     * Writes data to a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public abstract void writeData(Socket id) throws IOException;\r
+\r
+    /**\r
+     * Method getDataLength\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    short getDataLength() {\r
+        return 0;\r
+    }\r
+\r
+    /**\r
+     * Method isCOPSHeader\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isCOPSHeader() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isClientHandle\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isClientHandle() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isContext\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isContext() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isInterface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isInterface() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isDecision() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isLocalDecision\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isLocalDecision() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isReport\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isReport() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isError\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isError() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isTimer\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isTimer() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isPepId\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isPepId() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isReason\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isReason() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isPdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isPdpAddress() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isClientSI\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isClientSI() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Method isMessageIntegrity\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    boolean isMessageIntegrity() {\r
+        return false;\r
+    }\r
+\r
+};\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeader.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSObjHeader.java
new file mode 100644 (file)
index 0000000..ae24233
--- /dev/null
@@ -0,0 +1,225 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Object Header\r
+ *\r
+ * @version COPSObjHeader.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSObjHeader extends COPSObjBase {\r
+\r
+    public final static byte COPS_HANDLE = 1;\r
+    public final static byte COPS_CONTEXT = 2;\r
+    public final static byte COPS_ININTF = 3;\r
+    public final static byte COPS_OUTINTF = 4;\r
+    public final static byte COPS_REASON_CODE = 5;\r
+    public final static byte COPS_DEC = 6;\r
+    public final static byte COPS_LPDP_DEC = 7;\r
+    public final static byte COPS_ERROR = 8;\r
+    public final static byte COPS_CSI = 9;\r
+    public final static byte COPS_KA = 10;\r
+    public final static byte COPS_PEPID = 11;\r
+    public final static byte COPS_RPT = 12;\r
+    public final static byte COPS_PDP_REDIR = 13;\r
+    public final static byte COPS_LAST_PDP_ADDR = 14;\r
+    public final static byte COPS_ACCT_TIMER = 15;\r
+    public final static byte COPS_MSG_INTEGRITY = 16;\r
+\r
+    private short _len;\r
+    private byte _cNum;\r
+    private byte _cType;\r
+\r
+    public COPSObjHeader(byte cNum, byte cType) {\r
+        _len = 4;\r
+        _cNum = cNum;\r
+        _cType = cType;\r
+    }\r
+\r
+    public COPSObjHeader() {\r
+        _len = 4;\r
+        _cNum = 0;\r
+        _cType = 0;\r
+    }\r
+\r
+    protected COPSObjHeader(byte[] data) {\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Get the data length in number of octets\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        return _len;\r
+    };\r
+\r
+    /**\r
+     * Get the class information identifier cNum\r
+     *\r
+     * @return   a byte\r
+     *\r
+     */\r
+    public byte getCNum() {\r
+        return _cNum;\r
+    };\r
+\r
+    /**\r
+     * Get the type per cNum\r
+     *\r
+     * @return   a byte\r
+     *\r
+     */\r
+    public byte getCType() {\r
+        return _cType;\r
+    };\r
+\r
+    /**\r
+     * Get stringified CNum\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String getStrCNum() {\r
+        switch (getCNum()) {\r
+        case COPS_HANDLE:\r
+            return ("Client-handle");\r
+        case COPS_CONTEXT:\r
+            return ("Context");\r
+        case COPS_ININTF:\r
+            return ("In-Interface");\r
+        case COPS_OUTINTF:\r
+            return ("Out-Interface");\r
+        case COPS_REASON_CODE:\r
+            return ("Reason");\r
+        case COPS_DEC:\r
+            return ("Decision");\r
+        case COPS_LPDP_DEC:\r
+            return ("Local-Decision");\r
+        case COPS_ERROR:\r
+            return ("Error");\r
+        case COPS_CSI:\r
+            return ("Client-SI");\r
+        case COPS_KA:\r
+            return ("KA-timer");\r
+        case COPS_PEPID:\r
+            return ("PEP-id");\r
+        case COPS_RPT:\r
+            return ("Report");\r
+        case COPS_PDP_REDIR:\r
+            return ("Redirect PDP addr");\r
+        case COPS_LAST_PDP_ADDR:\r
+            return ("Last PDP addr");\r
+        case COPS_ACCT_TIMER:\r
+            return ("Account-Timer");\r
+        case COPS_MSG_INTEGRITY:\r
+            return ("Message-Integrity");\r
+        default:\r
+            return ("Unknown");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Set the obj length, the length is the length of the data following\r
+     * the object header.The length of the object header (4 bytes) is added\r
+     * to the length passed.\r
+     *\r
+     * @param    len                 a  short\r
+     *\r
+     */\r
+    public void setDataLength(short len) {\r
+        //Add the length of the header also\r
+        _len = (short) (len + 4);\r
+    }\r
+\r
+    /**\r
+     * Set the class of information cNum\r
+     *\r
+     * @param    cNum                a  byte\r
+     *\r
+     */\r
+    public void setCNum(byte cNum) {\r
+        _cNum = cNum;\r
+    } ;\r
+\r
+    /**\r
+     * Set the  type defined per cNum\r
+     *\r
+     * @param    cType               a  byte\r
+     *\r
+     */\r
+    public void setCType(byte cType) {\r
+        _cType = cType;\r
+    } ;\r
+\r
+    /**\r
+     * Method checkDataLength\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void checkDataLength() throws COPSException {\r
+\r
+    }\r
+\r
+    /**\r
+     * Writes data to a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        byte[] buf = new byte[4];\r
+\r
+        buf[0] = (byte) (_len >> 8);\r
+        buf[1] = (byte) _len;\r
+        buf[2] = (byte) _cNum;\r
+        buf[3] = (byte) _cType;\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+    /**\r
+     * Method parse\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     */\r
+    public void parse(byte[] data) {\r
+        _len = 0;\r
+        _len |= ((short) data[0]) << 8;\r
+        _len |= ((short) data[1]) & 0xFF;\r
+        _cNum |= data[2];\r
+        _cType |= data[3];\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        os.write(new String("**" + getStrCNum() + "**" + "\n").getBytes());\r
+        os.write(new String("Length: " + _len + "\n").getBytes());\r
+        os.write(new String("C-num: " + _cNum + "\n").getBytes());\r
+        os.write(new String("C-type: " + _cType + "\n").getBytes());\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPdpAddress.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPdpAddress.java
new file mode 100644 (file)
index 0000000..f202364
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+/**\r
+ * COPS PDP Address\r
+ *\r
+ * @version COPSPdpAddress.java, v 1.00 2003\r
+ *\r
+ */\r
+abstract public class COPSPdpAddress extends COPSObjBase {\r
+\r
+    /**\r
+     * Method isPdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPdpAddress() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Method isIpv4PdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIpv4PdpAddress() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isIpv6PdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isIpv6PdpAddress() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isLastPdpAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isLastPdpAddress() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isPdpredirectAddress\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPdpredirectAddress() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    abstract public void dump(OutputStream os) throws IOException;\r
+};\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPepId.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPepId.java
new file mode 100644 (file)
index 0000000..df02586
--- /dev/null
@@ -0,0 +1,121 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS PEP Identification Object\r
+ *\r
+ * @version COPSPepId.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPepId extends COPSObjBase {\r
+\r
+    COPSObjHeader _objHdr;\r
+    COPSData _data;\r
+    COPSData _padding;\r
+\r
+    public COPSPepId() {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_PEPID);\r
+        _objHdr.setCType((byte) 1);\r
+    }\r
+\r
+    protected COPSPepId(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        //Get the length of data following the obj header\r
+        short dLen = (short) (_objHdr.getDataLength() - 4);\r
+        COPSData d = new COPSData (dataPtr, 4, dLen);\r
+        setData(d);\r
+    }\r
+\r
+    /**\r
+     * Method setData\r
+     *\r
+     * @param    data                a  COPSData\r
+     *\r
+     */\r
+    public void setData(COPSData data) {\r
+        _data = data;\r
+        if (_data.length() % 4 != 0) {\r
+            int padLen = 4 - _data.length() % 4;\r
+            _padding = getPadding(padLen);\r
+        }\r
+        _objHdr.setDataLength((short)_data.length());\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        int lpadding = 0;\r
+        if (_padding != null) lpadding = _padding.length();\r
+        return ((short) (_objHdr.getDataLength() + lpadding));\r
+    }\r
+\r
+    /**\r
+     * Method getData\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getData() {\r
+        return _data;\r
+    };\r
+\r
+    /**\r
+     * Method isPepId\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPepId() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Write data to given netwrok socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+        COPSUtil.writeData(id, _data.getData(), _data.length());\r
+        if (_padding != null) {\r
+            COPSUtil.writeData(id, _padding.getData(), _padding.length());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("PEPID: " + _data.str() + "\n").getBytes());\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrClassError.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrClassError.java
new file mode 100644 (file)
index 0000000..c86a99e
--- /dev/null
@@ -0,0 +1,84 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Provisioning Class Error\r
+ *\r
+ * @version COPSPrClassError.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrClassError extends COPSPrError {\r
+\r
+    public final static byte C_spaceExhausted = 1;\r
+    public final static byte C_instanceInvalid = 2;\r
+    public final static byte C_attrValueInvalid = 3;\r
+    public final static byte C_attrValueSupLimited = 4;\r
+    public final static byte C_attrEnumSupLimited = 5;\r
+    public final static byte C_attrMaxLengthExceeded = 6;\r
+    public final static byte C_attrRefUnknown = 7;\r
+    public final static byte C_notifyOnly = 8;\r
+    public final static byte C_unknownPrc = 9;\r
+    public final static byte C_tooFewAttrs = 10;\r
+    public final static byte C_invalidAttrType = 11;\r
+    public final static byte C_deletedInRef = 12;\r
+    public final static byte C_specificError = 13;\r
+    public final static byte C_errmax = 14;\r
+\r
+    private final static String CerrTable[] = {\r
+        "Reserved",\r
+        "No more instances may currently be installed in the given class",\r
+        "Invalid class instance",\r
+        "Invalid attribute value",\r
+        "The value for attribute not currently supported by the device",\r
+        "The enumeration for attribute not currently supported by the device",\r
+        "Attribute length exceeds device limitations",\r
+        "Unknown attribute reference",\r
+        "Only supported for use by request or report",\r
+        "Class not supported by PEP",\r
+        "Too few attributes",\r
+        "Invalid attribute type",\r
+        "Reference to deleted instance",\r
+        "PRC specific error, check subcode for more details"\r
+    };\r
+\r
+    public COPSPrClassError(short eCode, short eSubCode) {\r
+        super (eCode, eSubCode);\r
+        _sNum = COPSPrObjBase.PR_CPERR;\r
+        _sType = COPSPrObjBase.PR_BER;\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a PrClassError object\r
+     */\r
+    protected COPSPrClassError(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method isPRCClassError\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPRCClassError() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Method strError\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String strError() {\r
+        return CerrTable[_errCode];\r
+    };\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrEPD.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrEPD.java
new file mode 100644 (file)
index 0000000..74f5dd0
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Provisioning EPD\r
+ *\r
+ * @version COPSPrEPD.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrEPD extends COPSPrObjBase {\r
+\r
+    public COPSPrEPD() {\r
+        _sNum = COPSPrObjBase.PR_EPD;\r
+        _sType = COPSPrObjBase.PR_XML;\r
+    }\r
+\r
+    /**\r
+     * Method isEncodedInstanceData\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isEncodedInstanceData() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a PrEPD object\r
+     */\r
+    protected COPSPrEPD(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+\r
+};\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrError.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrError.java
new file mode 100644 (file)
index 0000000..467f9bf
--- /dev/null
@@ -0,0 +1,111 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Provisioning Error\r
+ *\r
+ * @version COPSPrError.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrError extends COPSPrObjBase {\r
+\r
+    protected short _errCode;\r
+    protected short _errSubCode;\r
+\r
+    public COPSPrError(short eCode, short eSubCode) {\r
+        _errCode = eCode;\r
+        _errSubCode = eSubCode;\r
+        _len = 8;\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a PrGlobalError object\r
+     */\r
+    protected COPSPrError(byte[] dataPtr) {\r
+        _dataRep = null;\r
+\r
+        _len |= ((short) dataPtr[0]) << 8;\r
+        _len |= ((short) dataPtr[1]) & 0xFF;\r
+\r
+        _sNum |= ((short) dataPtr[2]) << 8;\r
+        _sNum |= ((short) dataPtr[3]) & 0xFF;\r
+\r
+        _errCode |= ((short) dataPtr[4]) << 8;\r
+        _errCode |= ((short) dataPtr[5]) & 0xFF;\r
+\r
+        _errSubCode |= ((short) dataPtr[6]) << 8;\r
+        _errSubCode |= ((short) dataPtr[7]) & 0xFF;\r
+    }\r
+\r
+    /**\r
+     * Method strError\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String strError() {\r
+        return "Error";\r
+    }\r
+\r
+    /**\r
+     * Method setData\r
+     *\r
+     * @param    data                a  COPSData\r
+     *\r
+     */\r
+    public void setData(COPSData data) { }     ;\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        byte[] dataRep = getDataRep();\r
+        COPSUtil.writeData(id, dataRep, dataRep.length);\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        return 8;\r
+    }\r
+\r
+    /**\r
+     * Method getDataRep\r
+     *\r
+     * @return   a byte[]\r
+     *\r
+     */\r
+    public byte[] getDataRep() {\r
+        _dataRep = new byte[getDataLength()];\r
+\r
+        _dataRep[0] = (byte) (_len >> 8);\r
+        _dataRep[1] = (byte) _len;\r
+        _dataRep[2] = (byte) (_sNum >> 8);\r
+        _dataRep[3] = (byte) _sNum;\r
+        _dataRep[4] = (byte) (_errCode >> 8);\r
+        _dataRep[5] = (byte) _errCode;\r
+        _dataRep[6] = (byte) (_errSubCode >> 8);\r
+        _dataRep[7] = (byte) _errSubCode;\r
+\r
+        return _dataRep;\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrErrorPRID.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrErrorPRID.java
new file mode 100644 (file)
index 0000000..132c587
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Provisioning Error PRID\r
+ *\r
+ * @version COPSPrErrorPRID.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrErrorPRID extends COPSPrObjBase {\r
+\r
+    public COPSPrErrorPRID() {\r
+        _sNum = COPSPrObjBase.PR_IDERR;\r
+        _sType = COPSPrObjBase.PR_BER;\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a PrErrorPRID object\r
+     */\r
+    protected COPSPrErrorPRID(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method isErrorPRID\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isErrorPRID() {\r
+        return true;\r
+    }\r
+\r
+}\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrGlobalError.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrGlobalError.java
new file mode 100644 (file)
index 0000000..d44848e
--- /dev/null
@@ -0,0 +1,84 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Provisioning Global Error\r
+ *\r
+ * @version COPSPrGlobalError.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrGlobalError extends COPSPrError {\r
+\r
+    public final static byte G_availMemoryLow = 1;\r
+    public final static byte G_availMemoryExhausted = 2;\r
+    public final static byte G_unknownASN1Tag = 3;\r
+    public final static byte G_maxMsgSizeExceeded = 4;\r
+    public final static byte G_unknownError = 5;\r
+    public final static byte G_maxReqStateOpen = 6;\r
+    public final static byte G_invalidASN1Length = 7;\r
+    public final static byte G_invalidObjPad = 8;\r
+    public final static byte G_unknownPIBData = 9;\r
+    public final static byte G_unknownCOPSPrObj = 10;\r
+    public final static byte G_malformedDec = 11;\r
+    public final static byte G_errmax = 12;\r
+\r
+\r
+    private final static String GerrTable[] = {\r
+        "Reserved",\r
+        "Available memory low",\r
+        "Available memory exhausted",\r
+        "Unknown ASN.1 tag",\r
+        "Max. message size exceeded",\r
+        "Unknown error",\r
+        "No more Request-states can be created by the PEP",\r
+        "ASN.1 object length was incorrect",\r
+        "Object was not properly padded",\r
+        "Unknown PIB data",\r
+        "Unknown COPS-PR object",\r
+        "Melformed decision"\r
+    };\r
+\r
+    ///\r
+    COPSPrGlobalError(short eCode, short eSubCode) {\r
+        super(eCode, eSubCode);\r
+        _sNum = COPSPrObjBase.PR_GPERR;\r
+        _sType = COPSPrObjBase.PR_BER;\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a PrGlobalError object\r
+     */\r
+    protected COPSPrGlobalError(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+\r
+    /**\r
+     * Method isGlobalPrError\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isGlobalPrError() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Method strError\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String strError() {\r
+        return GerrTable[_errCode];\r
+    };\r
+\r
+};\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrID.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrID.java
new file mode 100644 (file)
index 0000000..8332d60
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Provisioning ID\r
+ *\r
+ * @version COPSPrID.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrID extends COPSPrObjBase {\r
+\r
+    public COPSPrID() {\r
+        _sNum = COPSPrObjBase.PR_PRID;\r
+        _sType = COPSPrObjBase.PR_XML;\r
+    }\r
+\r
+    ///Parse the data and create a PrID object\r
+    protected COPSPrID(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+\r
+    /**\r
+     * Method isPRID\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPRID() {\r
+        return true;\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrObjBase.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrObjBase.java
new file mode 100644 (file)
index 0000000..7915272
--- /dev/null
@@ -0,0 +1,255 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Arrays;\r
+\r
+/**\r
+ * COPS Provisioning Object Base\r
+ *\r
+ * @version COPSPrObjBase.java, v 1.01 2003\r
+ *\r
+ */\r
+public class COPSPrObjBase {\r
+    public final static byte PR_PRID = 1;\r
+    public final static byte PR_PPRID = 2;\r
+    public final static byte PR_EPD = 3;\r
+    public final static byte PR_GPERR = 4;\r
+    public final static byte PR_CPERR = 5;\r
+    public final static byte PR_IDERR = 6;\r
+\r
+    public final static byte PR_BER = 1;\r
+    public final static byte PR_XML = 2;\r
+\r
+    protected short _len;\r
+    protected byte _sNum;\r
+    protected byte _sType;\r
+    protected COPSData _data;\r
+    protected COPSData _padding;\r
+\r
+    protected byte[] _dataRep;\r
+    ///\r
+    protected COPSPrObjBase() {\r
+        _dataRep = null;\r
+    }\r
+\r
+    public COPSPrObjBase(byte[] dataPtr) {\r
+        _dataRep = null;\r
+\r
+        _len |= ((short) dataPtr[0]) << 8;\r
+        _len |= ((short) dataPtr[1]) & 0xFF;\r
+\r
+        _sNum |= ((short) dataPtr[2]) << 8;\r
+        _sNum |= ((short) dataPtr[3]) & 0xFF;\r
+\r
+        //Get the length of data following the obj header\r
+        short dLen = (short) (_len - 4);\r
+        COPSData d = new COPSData(dataPtr, 4, dLen);\r
+        setData(d);\r
+    }\r
+\r
+    /**\r
+     * Add padding in the data, if the Provisioning data does\r
+     * not fall on 32-bit boundary\r
+     *\r
+     * @param    len                 an int\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getPadding(int len) {\r
+        byte[] padBuf = new byte[len];\r
+        Arrays.fill(padBuf, (byte) 0);\r
+        COPSData d = new COPSData(padBuf, 0, len);\r
+        return d;\r
+    }\r
+\r
+    /**\r
+     * Method isPRID\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPRID() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isPRIDPrefix\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPRIDPrefix() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isEncodedInstanceData\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isEncodedInstanceData() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isGlobalPrError\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isGlobalPrError() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isPRCClassError\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPRCClassError() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isErrorPRID\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isErrorPRID() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method setData\r
+     *\r
+     * @param    data                a  COPSData\r
+     *\r
+     */\r
+    public void setData(COPSData data) {\r
+        _data = data;\r
+        if (_data.length() % 4 != 0) {\r
+            int padLen = 4 - (_data.length() % 4);\r
+            _padding = getPadding(padLen);\r
+        }\r
+        _len = (short) (_data.length() + 4);\r
+    }\r
+\r
+    /**\r
+     * Get the class information identifier cNum\r
+     *\r
+     * @return   a byte\r
+     *\r
+     */\r
+    public byte getSNum() {\r
+        return _sNum;\r
+    };\r
+\r
+    /**\r
+     * Get the type per sNum\r
+     *\r
+     * @return   a byte\r
+     *\r
+     */\r
+    public byte getSType() {\r
+        return _sType;\r
+    };\r
+\r
+    /**\r
+     * Get stringified CNum\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String getStrSNum() {\r
+        switch (getSNum()) {\r
+        case PR_PRID:\r
+            return ("PRID");\r
+        case PR_PPRID:\r
+            return ("PRID Prefix");\r
+        case PR_EPD:\r
+            return ("EPD");\r
+        case PR_GPERR:\r
+            return ("GPERR");\r
+        case PR_CPERR:\r
+            return ("CPERR");\r
+        case PR_IDERR:\r
+            return ("IDERR");\r
+        default:\r
+            return ("Unknown");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        //Header length contains the header+data length\r
+        int lpadding = 0;\r
+        if (_padding != null) lpadding = _padding.length();\r
+        return ( (short) (_len + lpadding));\r
+    }\r
+\r
+    /**\r
+     * Method getData\r
+     *\r
+     * @return   a COPSData\r
+     *\r
+     */\r
+    public COPSData getData() {\r
+        return _data;\r
+    };\r
+\r
+    /**\r
+     * Write data on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        byte[] dataRep = getDataRep();\r
+        COPSUtil.writeData(id, dataRep, dataRep.length);\r
+    }\r
+\r
+    /**\r
+     * Get the binary data contained in the object\r
+     *\r
+     * @return   a byte[]\r
+     *\r
+     */\r
+    public byte[] getDataRep() {\r
+        _dataRep = new byte[getDataLength()];\r
+\r
+        _dataRep[0] = (byte) (_len >> 8);\r
+        _dataRep[1] = (byte) _len;\r
+        _dataRep[2] = (byte) (_sNum >> 8);\r
+        _dataRep[3] = (byte) _sNum;\r
+\r
+        System.arraycopy(_data.getData(), 0, _dataRep, 4, _data.length());\r
+\r
+        if (_padding != null) {\r
+            System.arraycopy(_padding.getData(), 0, _dataRep, 4 + _data.length(), _padding.length());\r
+        }\r
+\r
+        return _dataRep;\r
+    }\r
+\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrefixPrID.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSPrefixPrID.java
new file mode 100644 (file)
index 0000000..781d8f5
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+\r
+\r
+/**\r
+ * COPS Prefix Provisioning ID\r
+ *\r
+ * @version COPSPrefixPrID.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSPrefixPrID extends COPSPrObjBase {\r
+\r
+    ///\r
+    public COPSPrefixPrID() {\r
+        _sNum = COPSPrObjBase.PR_PPRID;\r
+        _sType = COPSPrObjBase.PR_XML;\r
+    }\r
+\r
+    /**\r
+     * Method isPRIDPrefix\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isPRIDPrefix() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+          Parse the data and create a PrefixPrID object\r
+     */\r
+    protected COPSPrefixPrID(byte[] dataPtr) {\r
+        super(dataPtr);\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReason.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReason.java
new file mode 100644 (file)
index 0000000..25c4a46
--- /dev/null
@@ -0,0 +1,172 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Reason Object (RFC 2748 pag. 12)\r
+ *\r
+ *   This object specifies the reason why the request state was deleted.\r
+ *   It appears in the delete request (DRQ) message. The Reason Sub-code\r
+ *   field is reserved for more detailed client-specific reason codes\r
+ *   defined in the corresponding documents.\r
+ *\r
+ *           C-Num = 5, C-Type = 1\r
+ *\r
+ *               0             1              2             3\r
+ *       +--------------+--------------+--------------+--------------+\r
+ *       |         Reason-Code         |       Reason Sub-code       |\r
+ *       +--------------+--------------+--------------+--------------+\r
+ *\r
+ *           Reason Code:\r
+ *               1 = Unspecified\r
+ *               2 = Management\r
+ *               3 = Preempted (Another request state takes precedence)\r
+ *               4 = Tear (Used to communicate a signaled state removal)\r
+ *               5 = Timeout (Local state has timed-out)\r
+ *               6 = Route Change (Change invalidates request state)\r
+ *               7 = Insufficient Resources (No local resource available)\r
+ *               8 = PDP's Directive (PDP decision caused the delete)\r
+ *                9 = Unsupported decision (PDP decision not supported)\r
+ *               10= Synchronize Handle Unknown\r
+ *               11= Transient Handle (stateless event)\r
+ *               12= Malformed Decision (could not recover)\r
+ *               13= Unknown COPS Object from PDP:\r
+ *                   Sub-code (octet 2) contains unknown object's C-Num\r
+ *                   and (octet 3) contains unknown object's C-Type.\r
+ *\r
+ * @version COPSReason.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSReason extends COPSPrObjBase {\r
+\r
+    public final static String[] G_msgArray = {\r
+        "Unknown.",\r
+        "Unspecified.",\r
+        "Management.",\r
+        "Preempted (Another request state takes precedence).",\r
+        "Tear (Used to communicate a signaled state removal).",\r
+        "Timeout ( Local state has timed-out).",\r
+        "Route change (Change invalidates request state).",\r
+        "Insufficient Resources.",\r
+        "PDP's Directive.",\r
+        "Unsupported decision.",\r
+        "Synchronize handle unknown.",\r
+        "Transient handle.",\r
+        "Malformed decision.",\r
+        "Unknown COPS object from PDP.",\r
+    };\r
+\r
+    private COPSObjHeader _objHdr;\r
+    private short _reasonCode;\r
+    private short _reasonSubCode;\r
+\r
+    ///\r
+    public COPSReason(short reasonCode, short subCode) {\r
+        _objHdr = new COPSObjHeader();\r
+        _reasonCode = reasonCode;\r
+        _reasonSubCode = subCode;\r
+        _objHdr.setCNum(COPSObjHeader.COPS_REASON_CODE);\r
+        _objHdr.setCType((byte) 1);\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSReason object\r
+     */\r
+    protected COPSReason(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _reasonCode |= ((short) dataPtr[4]) << 8;\r
+        _reasonCode |= ((short) dataPtr[5]) & 0xFF;\r
+        _reasonSubCode |= ((short) dataPtr[6]) << 8;\r
+        _reasonSubCode |= ((short) dataPtr[7]) & 0xFF;\r
+\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    /**\r
+     * Get Reason description\r
+     *\r
+     * @return   a String\r
+     *\r
+     */\r
+    public String getDescription() {\r
+        String reasonStr1;\r
+        String reasonStr2;\r
+\r
+        ///Get the details from the error code\r
+        reasonStr1 = G_msgArray[_reasonCode];\r
+        //TODO - defind reason sub-codes\r
+        reasonStr2 = "";\r
+        return (reasonStr1 + ":" + reasonStr2);\r
+    }\r
+\r
+    /**\r
+     * Always return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isReason() {\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Write object in network byte order to a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+\r
+        _objHdr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+\r
+        buf[0] = (byte) (_reasonCode >> 8);\r
+        buf[1] = (byte) _reasonCode;\r
+        buf[2] = (byte) (_reasonSubCode >> 8);\r
+        buf[3] = (byte) _reasonSubCode;\r
+\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Reason Code: " + _reasonCode + "\n").getBytes());\r
+        os.write(new String("Reason Sub Code: " + _reasonSubCode + "\n").getBytes());\r
+    }\r
+}\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportMsg.java
new file mode 100644 (file)
index 0000000..6b1540a
--- /dev/null
@@ -0,0 +1,362 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * COPS Report Message (RFC 2748 pag. 25)\r
+ *\r
+ *    The RPT message is used by the PEP to communicate to the PDP its\r
+ *   success or failure in carrying out the PDP's decision, or to report\r
+ *   an accounting related change in state. The Report-Type specifies the\r
+ *   kind of report and the optional ClientSI can carry additional\r
+ *   information per Client-Type.\r
+ *\r
+ *   For every DEC message containing a configuration context that is\r
+ *   received by a PEP, the PEP MUST generate a corresponding Report State\r
+ *   message with the Solicited Message flag set describing its success or\r
+ *   failure in applying the configuration decision. In addition,\r
+ *   outsourcing decisions from the PDP MAY result in a corresponding\r
+ *   solicited Report State from the PEP depending on the context and the\r
+ *   type of client. RPT messages solicited by decisions for a given\r
+ *   Client Handle MUST set the Solicited Message flag and MUST be sent in\r
+ *   the same order as their corresponding Decision messages were\r
+ *   received. There MUST never be more than one Report State message\r
+ *   generated with the Solicited Message flag set per Decision.\r
+ *\r
+ *   The Report State may also be used to provide periodic updates of\r
+ *   client specific information for accounting and state monitoring\r
+ *   purposes depending on the type of the client. In such cases the\r
+ *   accounting report type should be specified utilizing the appropriate\r
+ *   client specific information object.\r
+ *\r
+ *              <Report State> ::== <Common Header>\r
+ *                                  <Client Handle>\r
+ *                                  <Report-Type>\r
+ *                                  [<ClientSI>]\r
+ *                                  [<Integrity>]\r
+ *\r
+ * @version COPSReportMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSReportMsg extends COPSMsg {\r
+    /* COPSHeader coming from base class */\r
+    private COPSHandle _clientHandle;\r
+    private COPSReportType _report;\r
+    private Vector _clientSI;\r
+    private COPSIntegrity _integrity;\r
+\r
+    public COPSReportMsg() {\r
+        _clientHandle = null;\r
+        _report = null;\r
+        _integrity = null;\r
+        _clientSI = new Vector(20);\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSReportMsg object\r
+     */\r
+    protected COPSReportMsg (byte[] data) throws COPSException {\r
+        _clientHandle = null;\r
+        _report = null;\r
+        _integrity = null;\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Checks the sanity of COPS message and throw an\r
+     * COPSException when data is bad.\r
+     */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_clientHandle == null) || (_report == null))\r
+            throw new COPSException("Bad message format");\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_RPT)\r
+            throw new COPSException ("Error Header (no COPS_OP_REQ)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Report object to the message\r
+     *\r
+     * @param    report              a  COPSReportType\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSReportType report) throws COPSException {\r
+        if (report == null)\r
+            throw new COPSException ("Null Handle");\r
+\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_integrity != null)\r
+            throw new COPSException ("No null Handle");\r
+\r
+        _report = report;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add client handle to the message\r
+     *\r
+     * @param    handle              a  COPSHandle\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHandle handle) throws COPSException {\r
+        if (handle == null)\r
+            throw new COPSException ("Null Handle");\r
+\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_integrity != null)\r
+            throw new COPSException ("No null Handle");\r
+\r
+        _clientHandle = handle;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add one or more clientSI objects\r
+     *\r
+     * @param    clientSI            a  COPSClientSI\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSClientSI clientSI) throws COPSException {\r
+        if (clientSI == null)\r
+            throw new COPSException ("Null ClientSI");\r
+        _clientSI.add(clientSI);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add integrity object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Get client Handle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _clientHandle;\r
+    }\r
+\r
+    /**\r
+     * Get report type\r
+     *\r
+     * @return   a COPSReportType\r
+     *\r
+     */\r
+    public COPSReportType getReport() {\r
+        return _report;\r
+    }\r
+\r
+    /**\r
+     * Get clientSI\r
+     *\r
+     * @return   a Vector\r
+     *\r
+     */\r
+    public Vector getClientSI() {\r
+        return _clientSI;\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has Integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    }\r
+\r
+\r
+    /**\r
+     * Get Integrity. Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return (_integrity);\r
+    }\r
+\r
+    /**\r
+     * Writes data to given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        //checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_clientHandle != null) _clientHandle.writeData(id);\r
+        if (_report != null) _report.writeData(id);\r
+\r
+        for (Enumeration e = _clientSI.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+            clientSI.writeData(id);\r
+        }\r
+\r
+        if (_integrity != null) _integrity.writeData(id);\r
+    }\r
+\r
+    /**\r
+     * Parse data\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        super.parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_HANDLE: {\r
+                _clientHandle = new COPSHandle(buf);\r
+                _dataStart += _clientHandle.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_RPT: {\r
+                _report = new COPSReportType(buf);\r
+                _dataStart += _report.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_CSI: {\r
+                COPSClientSI csi = new COPSClientSI(buf);\r
+                _dataStart += csi.getDataLength();\r
+                _clientSI.add(csi);\r
+            }\r
+            break;\r
+\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+\r
+            default: {\r
+                throw new COPSException("Bad Message format, unknown object type");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Parse data\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_RPT)\r
+            throw new COPSException ("Null Header");\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength() throws COPSException {\r
+        short len = 0;\r
+        if (_clientHandle != null) len += _clientHandle.getDataLength();\r
+        if (_report != null) len += _report.getDataLength();\r
+\r
+        for (Enumeration e = _clientSI.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+            len += clientSI.getDataLength();\r
+        }\r
+\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_clientHandle != null)\r
+            _clientHandle.dump(os);\r
+\r
+        if (_report != null)\r
+            _report.dump(os);\r
+\r
+        for (Enumeration e = _clientSI.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+            clientSI.dump(os);\r
+        }\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportType.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReportType.java
new file mode 100644 (file)
index 0000000..41703e7
--- /dev/null
@@ -0,0 +1,164 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Report Type (RFC 2748 pag. 16\r
+ *\r
+ *   The Type of Report on the request state associated with a handle:\r
+ *\r
+ *           C-Num = 12, C-Type = 1\r
+ *\r
+ *               0             1              2             3\r
+ *       +--------------+--------------+--------------+--------------+\r
+ *       |         Report-Type         |        /////////////        |\r
+ *       +--------------+--------------+--------------+--------------+\r
+ *\r
+ *           Report-Type:\r
+ *               1 = Success   : Decision was successful at the PEP\r
+ *               2 = Failure   : Decision could not be completed by PEP\r
+ *               3 = Accounting: Accounting update for an installed state\r
+ *\r
+ *\r
+ * @version COPSReportType.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSReportType extends COPSPrObjBase {\r
+\r
+    public final static String[] msgMap = {\r
+        "Unknown",\r
+        "Success",\r
+        "Failure",\r
+        "Accounting",\r
+    };\r
+\r
+    private COPSObjHeader _objHdr;\r
+    private short _rType;\r
+    private short _reserved;\r
+\r
+    public final static short SUCCESS = 1;\r
+    public final static short FAILURE = 2;\r
+    public final static short ACCT = 3;\r
+\r
+    public COPSReportType(short rType) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.setCNum(COPSObjHeader.COPS_RPT);\r
+        _objHdr.setCType((byte) 1);\r
+        _rType = rType;\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSReportType object\r
+     */\r
+    protected COPSReportType(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _rType |= ((short) dataPtr[4]) << 8;\r
+        _rType |= ((short) dataPtr[5]) & 0xFF;\r
+        _reserved |= ((short) dataPtr[6]) << 8;\r
+        _reserved |= ((short) dataPtr[7]) & 0xFF;\r
+\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    /**\r
+     * If it is Success, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isSuccess() {\r
+        return (_rType == SUCCESS );\r
+    };\r
+\r
+    /**\r
+     * If it is Failure, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isFailure() {\r
+        return (_rType == FAILURE);\r
+    };\r
+\r
+    /**\r
+     * If it is Accounting, return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAccounting() {\r
+        return (_rType == ACCT);\r
+    };\r
+\r
+    /**\r
+     * Always return true\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isReport() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Write data in network byte order on a given network socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+\r
+        buf[0] = (byte) (_rType >> 8);\r
+        buf[1] = (byte) _rType;\r
+        buf[2] = (byte) (_reserved >> 8);\r
+        buf[3] = (byte) _reserved;\r
+\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Report: " + msgMap[_rType] + "\n").getBytes());\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReqMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSReqMsg.java
new file mode 100644 (file)
index 0000000..3f3a803
--- /dev/null
@@ -0,0 +1,598 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * COPS Request Message (RFC 2748 pag. 22)\r
+ *\r
+ *   The PEP establishes a request state client handle for which the\r
+ *   remote PDP may maintain state. The remote PDP then uses this handle\r
+ *   to refer to the exchanged information and decisions communicated over\r
+ *   the TCP connection to a particular PEP for a given client-type.\r
+ *\r
+ *   Once a stateful handle is established for a new request, any\r
+ *   subsequent modifications of the request can be made using the REQ\r
+ *   message specifying the previously installed handle. The PEP is\r
+ *   responsible for notifying the PDP whenever its local state changes so\r
+ *   the PDP's state will be able to accurately mirror the PEP's state.\r
+ *\r
+ *   The format of the Request message is as follows:\r
+ *\r
+ *               <Request Message> ::=  <Common Header>\r
+ *                                      <Client Handle>\r
+ *                                      <Context>\r
+ *                                      [<IN-Int>]\r
+ *                                      [<OUT-Int>]\r
+ *                                      [<ClientSI(s)>]\r
+ *                                      [<LPDPDecision(s)>]\r
+ *                                      [<Integrity>]\r
+ *\r
+ *               <ClientSI(s)> ::= <ClientSI> | <ClientSI(s)> <ClientSI>\r
+ *\r
+ *               <LPDPDecision(s)> ::= <LPDPDecision> |\r
+ *                                     <LPDPDecision(s)> <LPDPDecision>\r
+ *\r
+ *               <LPDPDecision> ::= [<Context>]\r
+ *                                  <LPDPDecision: Flags>\r
+ *                                  [<LPDPDecision: Stateless Data>]\r
+ *                                  [<LPDPDecision: Replacement Data>]\r
+ *                                  [<LPDPDecision: ClientSI Data>]\r
+ *                                  [<LPDPDecision: Named Data>]\r
+ *\r
+ *   The context object is used to determine the context within which all\r
+ *   the other objects are to be interpreted. It also is used to determine\r
+ *   the kind of decision to be returned from the policy server. This\r
+ *   decision might be related to admission control, resource allocation,\r
+ *   object forwarding and substitution, or configuration.\r
+ *\r
+ *   The interface objects are used to determine the corresponding\r
+ *   interface on which a signaling protocol message was received or is\r
+ *   about to be sent. They are typically used if the client is\r
+ *   participating along the path of a signaling protocol or if the client\r
+ *   is requesting configuration data for a particular interface.\r
+ *\r
+ *   ClientSI, the client specific information object, holds the client-\r
+ *   type specific data for which a policy decision needs to be made. In\r
+ *   the case of configuration, the Named ClientSI may include named\r
+ *   information about the module, interface, or functionality to be\r
+ *   configured. The ordering of multiple ClientSIs is not important.\r
+ *\r
+ *   Finally, LPDPDecision object holds information regarding the local\r
+ *   decision made by the LPDP.\r
+ *\r
+ *   Malformed Request messages MUST result in the PDP specifying a\r
+ *   Decision message with the appropriate error code.\r
+ *\r
+ * @version COPSReqMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSReqMsg extends COPSMsg {\r
+\r
+    /* COPSHeader coming from base class */\r
+    private COPSHandle _clientHandle;\r
+    private COPSContext _context;\r
+    private COPSInterface _inInterface;\r
+    private COPSInterface _outInterface;\r
+    private Vector _clientSIs;\r
+    private Hashtable _decisions;\r
+    private COPSIntegrity _integrity;\r
+    private COPSContext _lpdpContext;\r
+\r
+    public COPSReqMsg() {\r
+        _clientHandle = null;\r
+        _context = null;\r
+        _inInterface = null;\r
+        _outInterface = null;\r
+        _clientSIs = new Vector(20);\r
+        _decisions = new Hashtable();\r
+        _integrity = null;\r
+        _lpdpContext = null;\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSReqMsg object\r
+     */\r
+    protected COPSReqMsg(byte[] data) throws COPSException {\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Checks the sanity of COPS message and throw an\r
+     * COPSBadDataException when data is bad.\r
+     */\r
+    public void checkSanity() throws COPSException {\r
+        if ((_hdr == null) || (_clientHandle == null) || (_context == null)) {\r
+            throw new COPSException("Bad message format");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Add an IN or OUT interface object\r
+     *\r
+     * @param    inter               a  COPSInterface\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSInterface inter) throws COPSException {\r
+        if (!(inter.isInInterface() || inter.isOutInterface()))\r
+            throw new COPSException ("No Interface");\r
+\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_integrity != null)\r
+            throw new COPSException ("Integrity should be the last one");\r
+\r
+        if (inter.isInInterface()) {\r
+            if (_inInterface != null)\r
+                throw new COPSException ("Object inInterface exits");\r
+\r
+            if (inter.isIpv4Address()) {\r
+                COPSIpv4InInterface inInter = (COPSIpv4InInterface) inter;\r
+                _inInterface = inInter;\r
+            } else {\r
+                COPSIpv6InInterface inInter = (COPSIpv6InInterface) inter;\r
+                _inInterface = inInter;\r
+            }\r
+        } else {\r
+            if (_outInterface != null)\r
+                throw new COPSException ("Object outInterface exits");\r
+\r
+            if (inter.isIpv4Address()) {\r
+                COPSIpv4OutInterface outInter = (COPSIpv4OutInterface) inter;\r
+                _outInterface = outInter;\r
+            } else {\r
+                COPSIpv6OutInterface outInter = (COPSIpv6OutInterface) inter;\r
+                _outInterface = outInter;\r
+            }\r
+        }\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add header to the message\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if (hdr.getOpCode() != COPSHeader.COPS_OP_REQ)\r
+            throw new COPSException ("Error Header (no COPS_OP_REQ)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add Context object to the message\r
+     *\r
+     * @param    context             a  COPSContext\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSContext context) throws COPSException {\r
+        if (context == null)\r
+            throw new COPSException ("Null Context");\r
+        _context = context;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add client handle to the message\r
+     *\r
+     * @param    handle              a  COPSHandle\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHandle handle) throws COPSException {\r
+        if (handle == null)\r
+            throw new COPSException ("Null Handle");\r
+        _clientHandle = handle;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add one or more clientSI objects\r
+     *\r
+     * @param    clientSI            a  COPSClientSI\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSClientSI clientSI) throws COPSException {\r
+        if (clientSI == null)\r
+            throw new COPSException ("Null ClientSI");\r
+        _clientSIs.add(clientSI);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add one or more local decision object for a given decision context\r
+     * the context is optional, if null all decision object are tided to\r
+     * message context\r
+     *\r
+     * @param    decision            a  COPSLPDPDecision\r
+     * @param    context             a  COPSContext\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void addLocalDecision(COPSLPDPDecision decision, COPSContext context) throws COPSException {\r
+        if (!decision.isLocalDecision())\r
+            throw new COPSException ("Local Decision");\r
+\r
+        Vector v = (Vector) _decisions.get(context);\r
+        if (decision.isFlagSet()) {\r
+            if (v.size() != 0) {\r
+                //Only one set of decision flags is allowed\r
+                //for each context\r
+                throw new COPSException ("Bad Message format, only one set of decision flags is allowed.");\r
+            }\r
+        } else {\r
+            if (v.size() == 0) {\r
+                //The flags decision must precede any other\r
+                //decision message, since the decision is not\r
+                //flags throw exception\r
+                throw new COPSException ("Bad Message format, flags decision must precede any other decision object.");\r
+            }\r
+        }\r
+        v.add(decision);\r
+        _decisions.put(context,v);\r
+\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add integrity object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_clientHandle != null) _clientHandle.writeData(id);\r
+        if (_context != null) _context.writeData(id);\r
+\r
+        for (Enumeration e = _clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+            clientSI.writeData(id);\r
+        }\r
+\r
+        //Display any local decisions\r
+        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) _decisions.get(context);\r
+            context.writeData(id);\r
+\r
+            for (Enumeration ee = v.elements() ; e.hasMoreElements() ;) {\r
+                COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();\r
+                decision.writeData(id);\r
+            }\r
+        }\r
+\r
+        if (_integrity != null) _integrity.writeData(id);\r
+\r
+    }\r
+\r
+    /**\r
+     * Return Header\r
+     *\r
+     * @return   a COPSHeader\r
+     *\r
+     */\r
+    public COPSHeader getHeader() {\r
+        return _hdr;\r
+    }\r
+\r
+    /**\r
+     * Return client Handle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _clientHandle;\r
+    }\r
+\r
+    /**\r
+     * Return Context\r
+     *\r
+     * @return   a COPSContext\r
+     *\r
+     */\r
+    public COPSContext getContext() {\r
+        return _context;\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has In Interface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasInInterface() {\r
+        return (_inInterface == null);\r
+    }\r
+\r
+    /**\r
+     * Should check hasInInterface() before calling\r
+     *\r
+     * @return   a COPSInterface\r
+     *\r
+     */\r
+    public COPSInterface getInInterface() {\r
+        return _inInterface;\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has Out interface\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasOutInterface() {\r
+        return (_outInterface == null);\r
+    }\r
+\r
+    /**\r
+     * Should check hasOutInterface() before calling\r
+     *\r
+     * @return   a COPSInterface\r
+     *\r
+     */\r
+    public COPSInterface getOutInterface() {\r
+        return _outInterface;\r
+    }\r
+\r
+    /**\r
+     * Returns a vector if ClientSI objects\r
+     *\r
+     * @return   a Vector\r
+     *\r
+     */\r
+    public Vector getClientSI() {\r
+        return _clientSIs;\r
+    }\r
+\r
+    /**\r
+     * Returns a HashTable of any local decisions\r
+     *\r
+     * @return   a Hashtable\r
+     *\r
+     */\r
+    public Hashtable getLpdpDecisions() {\r
+        return _decisions;\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has Integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity == null);\r
+    }\r
+\r
+    /**\r
+     * Get Integrity. Should check hasIntegrity() becfore calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return _integrity;\r
+    }\r
+\r
+    /**\r
+     * Parses the data and fills COPSReqMsg with its constituents\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        super.parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_HANDLE: {\r
+                _clientHandle = new COPSHandle(buf);\r
+                _dataStart += _clientHandle.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_CONTEXT: {\r
+                if (_context == null) {\r
+                    //Message context\r
+                    _context = new COPSContext(buf);\r
+                    _dataStart += _context.getDataLength();\r
+                } else {\r
+                    //lpdp context\r
+                    _lpdpContext = new COPSContext(buf);\r
+                    _dataStart += _lpdpContext.getDataLength();\r
+                }\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_ININTF: {\r
+                if (objHdr.getCType() == 1) {\r
+                    _inInterface = new COPSIpv4InInterface(buf);\r
+                } else {\r
+                    _inInterface = new COPSIpv6InInterface(buf);\r
+                }\r
+                _dataStart += _inInterface.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_OUTINTF: {\r
+                if (objHdr.getCType() == 1) {\r
+                    _outInterface = new COPSIpv4OutInterface(buf);\r
+                } else {\r
+                    _outInterface = new COPSIpv6OutInterface(buf);\r
+                }\r
+                _dataStart += _outInterface.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_LPDP_DEC: {\r
+                COPSLPDPDecision lpdp = new COPSLPDPDecision(buf);\r
+                _dataStart += lpdp.getDataLength();\r
+                addLocalDecision(lpdp, _lpdpContext);\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_CSI: {\r
+                COPSClientSI csi = new COPSClientSI (buf);\r
+                _dataStart += csi.getDataLength();\r
+                _clientSIs.add(csi);\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format, unknown object type");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+\r
+    }\r
+\r
+    /**\r
+     * Parses the data and fills that follows the header hdr and fills COPSReqMsg\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength() throws COPSException {\r
+        short len = 0;\r
+\r
+        if (_clientHandle != null)\r
+            len += _clientHandle.getDataLength();\r
+\r
+        if (_context != null)\r
+            len += _context.getDataLength();\r
+\r
+        for (Enumeration e = _clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+            len += clientSI.getDataLength();\r
+        }\r
+\r
+        //Display any local decisions\r
+        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) _decisions.get(context);\r
+            len += context.getDataLength();\r
+\r
+            for (Enumeration ee = v.elements() ; e.hasMoreElements() ;) {\r
+                COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();\r
+                len += decision.getDataLength();\r
+            }\r
+        }\r
+\r
+        if (_integrity != null) {\r
+            len += _integrity.getDataLength();\r
+        }\r
+\r
+        _hdr.setMsgLength((int) len);\r
+\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_clientHandle != null)\r
+            _clientHandle.dump(os);\r
+\r
+        if (_context != null)\r
+            _context.dump(os);\r
+\r
+        for (Enumeration e = _clientSIs.elements() ; e.hasMoreElements() ;) {\r
+            COPSClientSI clientSI = (COPSClientSI) e.nextElement();\r
+            clientSI.dump(os);\r
+        }\r
+\r
+        //Display any local decisions\r
+        for (Enumeration e = _decisions.keys() ; e.hasMoreElements() ;) {\r
+\r
+            COPSContext context = (COPSContext) e.nextElement();\r
+            Vector v = (Vector) _decisions.get(context);\r
+            context.dump(os);\r
+\r
+            for (Enumeration ee = v.elements() ; e.hasMoreElements() ;) {\r
+                COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();\r
+                decision.dump(os);\r
+            }\r
+        }\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSSyncStateMsg.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSSyncStateMsg.java
new file mode 100644 (file)
index 0000000..628e413
--- /dev/null
@@ -0,0 +1,280 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Sync State Message (RFC 2748 pag. 26 and pag. 29\r
+ *\r
+ *   The format of the Synchronize State Query message is as follows:\r
+ *\r
+ *              <Synchronize State> ::= <Common Header>\r
+ *                                      [<Client Handle>]\r
+ *                                      [<Integrity>]\r
+ *\r
+ *   This message indicates that the remote PDP wishes the client (which\r
+ *   appears in the common header) to re-send its state. If the optional\r
+ *   Client Handle is present, only the state associated with this handle\r
+ *   is synchronized. If the PEP does not recognize the requested handle,\r
+ *   it MUST immediately send a DRQ message to the PDP for the handle that\r
+ *   was specified in the SSQ message. If no handle is specified in the\r
+ *    SSQ message, all the active client state MUST be synchronized with\r
+ *   the PDP.\r
+ *\r
+ *   The client performs state synchronization by re-issuing request\r
+ *   queries of the specified client-type for the existing state in the\r
+ *   PEP. When synchronization is complete, the PEP MUST issue a\r
+ *   synchronize state complete message to the PDP.\r
+ *\r
+ *         <Synchronize State Complete>  ::= <Common Header>\r
+ *                                           [<Client Handle>]\r
+ *                                           [<Integrity>]\r
+ *\r
+ *   The Client Handle object only needs to be included if the corresponding\r
+ *   Synchronize State Message originally referenced a specific handle.\r
+ *\r
+ * @version COPSSyncStateMsg.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSSyncStateMsg extends COPSMsg {\r
+\r
+    /* COPSHeader coming from base class */\r
+    private COPSHandle  _clientHandle;\r
+    private COPSIntegrity  _integrity;\r
+\r
+    public COPSSyncStateMsg() {\r
+        _clientHandle = null;\r
+        _integrity = null;\r
+    }\r
+\r
+    /**\r
+          Parse data and create COPSSyncStateMsg object\r
+     */\r
+    protected COPSSyncStateMsg(byte[] data) throws COPSException  {\r
+        _clientHandle = null;\r
+        _integrity = null;\r
+        parse(data);\r
+    }\r
+\r
+    /**\r
+     * Checks the sanity of COPS message and throw an\r
+     * COPSException when data is bad.\r
+     */\r
+    public void checkSanity() throws COPSException {\r
+        if (_hdr == null) {\r
+            throw new COPSException("Bad message format");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Add message header\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHeader hdr) throws COPSException {\r
+        if (hdr == null)\r
+            throw new COPSException ("Null Header");\r
+        if ((hdr.getOpCode() != COPSHeader.COPS_OP_SSC) &&\r
+                (hdr.getOpCode() != COPSHeader.COPS_OP_SSQ))\r
+            throw new COPSException ("Error Header (no COPS_OP_SSX)");\r
+        _hdr = hdr;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add client handle to the message\r
+     *\r
+     * @param    handle              a  COPSHandle\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSHandle handle) throws COPSException {\r
+        if (handle == null)\r
+            throw new COPSException ("Null Handle");\r
+\r
+        //Message integrity object should be the very last one\r
+        //If it is already added\r
+        if (_integrity != null)\r
+            throw new COPSException ("No null Handle");\r
+\r
+        _clientHandle = handle;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Add integrity object\r
+     *\r
+     * @param    integrity           a  COPSIntegrity\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    public void add (COPSIntegrity integrity) throws COPSException {\r
+        if (integrity == null)\r
+            throw new COPSException ("Null Integrity");\r
+        if (!integrity.isMessageIntegrity())\r
+            throw new COPSException ("Error Integrity");\r
+        _integrity = integrity;\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * If the optional Client Handle is present, only the state associated\r
+      * with this handle is synchronized. If no handle is specified in the\r
+      * SSQ message, all the active client state MUST be synchronized with\r
+      * the PDP.\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasClientHandle() {\r
+        return (_clientHandle != null);\r
+    }\r
+\r
+    /**\r
+     * Get client Handle\r
+     *\r
+     * @return   a COPSHandle\r
+     *\r
+     */\r
+    public COPSHandle getClientHandle() {\r
+        return _clientHandle;\r
+    }\r
+\r
+    /**\r
+     * Returns true if it has integrity object\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean hasIntegrity() {\r
+        return (_integrity != null);\r
+    }\r
+\r
+    /**\r
+     * Get Integrity. Should check hasIntegrity() before calling\r
+     *\r
+     * @return   a COPSIntegrity\r
+     *\r
+     */\r
+    public COPSIntegrity getIntegrity() {\r
+        return (_integrity);\r
+    }\r
+\r
+    /**\r
+     * Writes data to given socket\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        // checkSanity();\r
+        if (_hdr != null) _hdr.writeData(id);\r
+        if (_clientHandle != null) _clientHandle.writeData(id);\r
+        if (_integrity != null) _integrity.writeData(id);\r
+\r
+    }\r
+\r
+    /**\r
+     * Parse data\r
+     *\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(byte[] data) throws COPSException {\r
+        super.parseHeader(data);\r
+\r
+        while (_dataStart < _dataLength) {\r
+            byte[] buf = new byte[data.length - _dataStart];\r
+            System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);\r
+\r
+            COPSObjHeader objHdr = new COPSObjHeader (buf);\r
+            switch (objHdr.getCNum()) {\r
+            case COPSObjHeader.COPS_HANDLE: {\r
+                _clientHandle = new COPSHandle(buf);\r
+                _dataStart += _clientHandle.getDataLength();\r
+            }\r
+            break;\r
+            case COPSObjHeader.COPS_MSG_INTEGRITY: {\r
+                _integrity = new COPSIntegrity(buf);\r
+                _dataStart += _integrity.getDataLength();\r
+            }\r
+            break;\r
+            default: {\r
+                throw new COPSException("Bad Message format, unknown object type");\r
+            }\r
+            }\r
+        }\r
+        checkSanity();\r
+    }\r
+\r
+    /**\r
+     * Parse data\r
+     *\r
+     * @param    hdr                 a  COPSHeader\r
+     * @param    data                a  byte[]\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void parse(COPSHeader hdr, byte[] data) throws COPSException {\r
+\r
+        if ((hdr.getOpCode() != COPSHeader.COPS_OP_SSC) &&\r
+                (hdr.getOpCode() != COPSHeader.COPS_OP_SSQ))\r
+            throw new COPSException ("Error Header (no COPS_OP_SSX)");\r
+\r
+        _hdr = hdr;\r
+        parse(data);\r
+        setMsgLength();\r
+    }\r
+\r
+    /**\r
+     * Set the message length, base on the set of objects it contains\r
+     *\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    protected void setMsgLength() throws COPSException {\r
+        short len = 0;\r
+        if (_clientHandle != null) len += _clientHandle.getDataLength();\r
+        if (_integrity != null) len += _integrity.getDataLength();\r
+        _hdr.setMsgLength(len);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _hdr.dump(os);\r
+\r
+        if (_clientHandle != null)\r
+            _clientHandle.dump(os);\r
+\r
+        if (_integrity != null) {\r
+            _integrity.dump(os);\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSTimer.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSTimer.java
new file mode 100644 (file)
index 0000000..5fe1a4f
--- /dev/null
@@ -0,0 +1,135 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+\r
+/**\r
+ * COPS Timer Object\r
+ *\r
+ * @version COPSTimer.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSTimer extends COPSObjBase {\r
+\r
+    protected COPSObjHeader _objHdr;\r
+    private short _reserved;\r
+    private short _timerValue;\r
+\r
+    /**\r
+     * Returns size in number of octects, including header\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getDataLength() {\r
+        //Add the size of the header also\r
+        return (_objHdr.getDataLength());\r
+    }\r
+\r
+    /**\r
+     * Method getTimerVal\r
+     *\r
+     * @return   a short\r
+     *\r
+     */\r
+    public short getTimerVal() {\r
+        return _timerValue;\r
+    };\r
+\r
+    /**\r
+     * Method isTimer\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isTimer() {\r
+        return true;\r
+    };\r
+\r
+    /**\r
+     * Method isKATimer\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isKATimer() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Method isAcctTimer\r
+     *\r
+     * @return   a boolean\r
+     *\r
+     */\r
+    public boolean isAcctTimer() {\r
+        return false;\r
+    };\r
+\r
+    /**\r
+     * Write data to given socket in Network byte order\r
+     *\r
+     * @param    id                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void writeData(Socket id) throws IOException {\r
+        _objHdr.writeData(id);\r
+\r
+        byte[] buf = new byte[4];\r
+\r
+        buf[0] = (byte) (_reserved >> 8);\r
+        buf[1] = (byte) _reserved;\r
+        buf[2] = (byte) (_timerValue >> 8);\r
+        buf[3] = (byte) _timerValue;\r
+        COPSUtil.writeData(id, buf, 4);\r
+    }\r
+\r
+    protected COPSTimer(short timeVal) {\r
+        _objHdr = new COPSObjHeader();\r
+        //Time range is 1 - 65535 seconds\r
+        _timerValue = timeVal;\r
+        // _objHdr.setDataLength(sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+     * Receive data that is in netwrok byte order and fill in the obj.\r
+     */\r
+    protected COPSTimer(byte[] dataPtr) {\r
+        _objHdr = new COPSObjHeader();\r
+        _objHdr.parse(dataPtr);\r
+        // _objHdr.checkDataLength();\r
+\r
+        _reserved |= ((short) dataPtr[4]) << 8;\r
+        _reserved |= ((short) dataPtr[5]) & 0xFF;\r
+        _timerValue |= ((short) dataPtr[6]) << 8;\r
+        _timerValue |= ((short) dataPtr[7]) & 0xFF;\r
+\r
+        // _objHdr.setDataLength(sizeof(u_int32_t));\r
+        _objHdr.setDataLength((short) 4);\r
+    }\r
+\r
+    /**\r
+     * Write an object textual description in the output stream\r
+     *\r
+     * @param    os                  an OutputStream\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    public void dump(OutputStream os) throws IOException {\r
+        _objHdr.dump(os);\r
+        os.write(new String("Timer val: " + _timerValue + "\n").getBytes());\r
+    }\r
+\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSTransceiver.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSTransceiver.java
new file mode 100644 (file)
index 0000000..56471de
--- /dev/null
@@ -0,0 +1,91 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+\r
+// import org.umu.cops.common.COPSDebug;\r
+\r
+/**\r
+ * COPS Transceiver\r
+ *\r
+ * @version COPSTransceiver.java, v 1.00 2003\r
+ *\r
+ */\r
+public class COPSTransceiver {\r
+\r
+    /**\r
+     * Method sendMsg\r
+     *\r
+     * @param    msg                 a  COPSMsg\r
+     * @param    fd                  a  Socket\r
+     *\r
+     * @throws   IOException\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    static public void sendMsg(COPSMsg msg, Socket fd) throws IOException, COPSException {\r
+        // COPSDebug.out("COPSTransceiver", "sendMsg ******************************** START" );\r
+\r
+        msg.checkSanity();\r
+        msg.writeData(fd);\r
+\r
+        // COPSDebug.out("COPSTransceiver", "sendMsg ******************************** END" );\r
+    }\r
+\r
+    /**\r
+     * Method receiveMsg\r
+     *\r
+     * @param    fd                  a  Socket\r
+     *\r
+     * @return   a COPSMsg\r
+     *\r
+     * @throws   IOException\r
+     * @throws   COPSException\r
+     *\r
+     */\r
+    static public COPSMsg receiveMsg (Socket fd)  throws IOException, COPSException {\r
+        int nread = 0;\r
+        byte[] hBuf = new byte[8];\r
+\r
+        // COPSDebug.out("COPSTransceiver", "receiveMsg ******************************** START" );\r
+\r
+        nread = COPSUtil.readData(fd, hBuf, 8);\r
+\r
+        if (nread == 0) {\r
+            throw new COPSException("Error reading connection");\r
+        }\r
+\r
+        if (nread != 8) {\r
+            throw new COPSException("Bad COPS message");\r
+        }\r
+\r
+        COPSHeader hdr = new COPSHeader(hBuf);\r
+        int dataLen = hdr.getMsgLength() - hdr.getHdrLength();\r
+        // COPSDebug.out("COPSTransceiver", "COPS Msg length :[" + dataLen + "]\n" );\r
+        byte[] buf = new byte[dataLen + 1];\r
+        nread = 0;\r
+\r
+        nread = COPSUtil.readData(fd, buf, dataLen);\r
+        buf[dataLen] = (byte) '\0';\r
+        // COPSDebug.out("COPSTransceiver", "Data read length:[" + nread + "]\n");\r
+\r
+        if (nread != dataLen) {\r
+            throw new COPSException("Bad COPS message");\r
+        }\r
+\r
+        COPSMsgParser prser = new COPSMsgParser();\r
+        COPSMsg msg = prser.parse(hdr, buf);\r
+\r
+        // COPSDebug.out("COPSTransceiver", "Message received");\r
+\r
+        // COPSDebug.out("COPSTransceiver", "receiveMsg ******************************** END" );\r
+        return msg;\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/java/org/umu/cops/stack/COPSUtil.java b/packetcable-driver/src/main/java/org/umu/cops/stack/COPSUtil.java
new file mode 100644 (file)
index 0000000..072da7b
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright (c) 2003 University of Murcia.  All rights reserved.\r
+ * --------------------------------------------------------------\r
+ * For more information, please see <http://www.umu.euro6ix.org/>.\r
+ */\r
+\r
+package org.umu.cops.stack;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.net.Socket;\r
+import java.util.Date;\r
+\r
+/**\r
+ * COPS Utils\r
+ *\r
+ * @version COPSUtil.java, v 2.00 2004\r
+ *\r
+ */\r
+public class COPSUtil {\r
+\r
+    /**\r
+     * Method writeData\r
+     *\r
+     * @param    id                  a  Socket\r
+     * @param    data                a  byte[]\r
+     * @param    len                 an int\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    static void writeData(Socket id, byte[] data, int len) throws IOException {\r
+        OutputStream output;\r
+        output = id.getOutputStream();\r
+\r
+        output.write(data,0,len);\r
+    }\r
+\r
+    /**\r
+     * Reads nchar from a given sockets, blocks on read untill nchar are read of conenction has error\r
+     * bRead returns the bytes read\r
+     *\r
+     * @param    connId              a  Socket\r
+     * @param    dataRead            a  byte[]\r
+     * @param    nchar               an int\r
+     *\r
+     * @return   an int\r
+     *\r
+     * @throws   IOException\r
+     *\r
+     */\r
+    static int readData(Socket connId, byte[] dataRead, int nchar)  throws IOException {\r
+        InputStream input;\r
+        input = connId.getInputStream();\r
+\r
+        int nread = 0;\r
+        int startTime = (int) (new Date().getTime());\r
+        do {\r
+            if (input.available() != 0) {\r
+                nread += input.read(dataRead,nread,nchar-nread);\r
+                startTime = (int) (new Date().getTime());\r
+            } else {\r
+                int nowTime = (int) (new Date().getTime());\r
+                if ((int)(nowTime - startTime) > 2000)\r
+                    break;\r
+            }\r
+        } while (nread != nchar);\r
+\r
+        return nread;\r
+    }\r
+}\r
+\r
diff --git a/packetcable-driver/src/main/resources/pcmm.properties b/packetcable-driver/src/main/resources/pcmm.properties
new file mode 100644 (file)
index 0000000..5f696df
--- /dev/null
@@ -0,0 +1,15 @@
+#----------------------------------------------------------------------------------
+# This file contains the common properties of the PCMM 
+#----------------------------------------------------------------------------------
+#Port used by the PCMM 
+pcmm.port=3918
+#Pool size, determining the number of connections that could be established with CMTSs
+pcmm.ps.pool.size=32
+#Default keep-alive timer value (secs)
+pcmm.keep.alive.timer = 30
+#Default accounting timer value (secs) 
+pcmm.accounting.timer = 0;
+#default mask
+pcmm.default.mask=0.0.0.0
+#timeout for the connection in ms
+pcmm.default.timeout=-1
\ No newline at end of file
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/BestEffortServiceTest.java b/packetcable-driver/src/test/java/org/pcmm/test/BestEffortServiceTest.java
new file mode 100644 (file)
index 0000000..defde2e
--- /dev/null
@@ -0,0 +1,42 @@
+package org.pcmm.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.gates.impl.BestEffortService;
+
+public class BestEffortServiceTest {
+
+    private BestEffortService be;
+
+    @Before
+    public void init() {
+        be = new BestEffortService((byte) 7);
+        be.getAuthorizedEnvelop().setMinimumReservedTrafficRate(192);
+        be.getCommittedEnvelop().setRequiredAttributeMask(938);
+        be.getReservedEnvelop().setTrafficPriority((byte) 5);
+    }
+
+    @Test
+    public void testGetAsBinaryArray() {
+        assertTrue(be.getAsBinaryArray().length == 116);
+    }
+
+    @Test
+    public void testBestEffortServiceByteArray() {
+        assertTrue(new BestEffortService(be.getAsBinaryArray())
+                   .getAuthorizedEnvelop().getMinimumReservedTrafficRate() == 192);
+        assertTrue(new BestEffortService(be.getAsBinaryArray())
+                   .getReservedEnvelop().getTrafficPriority() == 5);
+        assertTrue(new BestEffortService(be.getAsBinaryArray())
+                   .getCommittedEnvelop().getRequiredAttributeMask() == 938);
+
+    }
+
+    @Test
+    public void testGetEnvelop() {
+        assertTrue(be.getEnvelop() == 7);
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/Main.java b/packetcable-driver/src/test/java/org/pcmm/test/Main.java
new file mode 100644 (file)
index 0000000..ad1ea5e
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ *
+ */
+package org.pcmm.test;
+
+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;
+
+/**
+ *
+ */
+public class Main {
+
+       /**
+        * @param args
+        */
+       public static void main(String[] args) {
+               ICMTS icmts = new CMTS();
+               icmts.startServer();
+               IPCMMPolicyServer ps = new PCMMPolicyServer();
+               IPSCMTSClient client = ps.requestCMTSConnection("localhost");
+               client.gateSet();
+               // IWorkerPool pool = new WorkerPool(2);
+               // IWorker worker = new Worker(new Callable<String>() {
+               // @Override
+               // public String call() throws Exception {
+               // System.out
+               // .println("Main.main(...).new Callable() {...}.call()");
+               // return null;
+               // }
+               // });
+               // IWorker worker2 = new Worker(new Callable<String>() {
+               // @Override
+               // public String call() throws Exception {
+               // System.out
+               // .println("|||||||Main.main(...).new Callable() {...}.call()||||||||||||");
+               // return null;
+               // }
+               // });
+               // pool.schedule(worker2, 2000);
+               // pool.schedule(worker, 500);
+               // pool.recycle();
+
+
+       }
+}
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/PCErrorTest.java b/packetcable-driver/src/test/java/org/pcmm/test/PCErrorTest.java
new file mode 100644 (file)
index 0000000..d6f129a
--- /dev/null
@@ -0,0 +1,29 @@
+package org.pcmm.test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.pcmm.gates.IPCMMError;
+import org.pcmm.gates.impl.PCMMError;
+
+public class PCErrorTest {
+
+       IPCMMError error;
+
+       @Before
+       public void init() {
+               error = new PCMMError();
+               error.setErrorCode((short) 1);
+       }
+
+       @Test
+       public void testGetDescription() {
+               for (IPCMMError.Description d : IPCMMError.Description.values()) {
+                       error.setErrorCode(d.getCode());
+                       Assert.assertNotNull(error.getDescription());
+                       System.out.println(error.getDescription());
+               }
+
+       }
+
+}
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/PCMMGateReqTest.java b/packetcable-driver/src/test/java/org/pcmm/test/PCMMGateReqTest.java
new file mode 100644 (file)
index 0000000..bfd622c
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ *
+ */
+package org.pcmm.test;
+
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.pcmm.utils.PCMMUtils;
+
+/**
+ * @author RH030971
+ *
+ */
+public class PCMMGateReqTest {
+
+    /**
+     * Test method for
+     * {@link org.pcmm.gates.impl.PCMMGateReq#PCMMGateReq(byte[])}.
+     */
+    @Test
+    public void testPCMMGateReqByteArray() {
+/*
+        new PCMMGateReq(
+            PCMMUtils
+            .ReadBinaryDump("traces/COPSReportClientSI09871088-5329-44ff-b1db-0ea3a544de1e.bin"));
+
+*/
+    }
+
+    /**
+     * Test method for {@link org.pcmm.gates.impl.PCMMGateReq#getData()}.
+     */
+    @Test
+    public void testGetData() {
+        // fail("Not yet implemented");
+    }
+
+}
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/PCMMResourceSetTest.java b/packetcable-driver/src/test/java/org/pcmm/test/PCMMResourceSetTest.java
new file mode 100644 (file)
index 0000000..5f17e59
--- /dev/null
@@ -0,0 +1,39 @@
+package org.pcmm.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.pcmm.objects.PCMMIDHolder;
+import org.pcmm.objects.PCMMResourceSet;
+import org.pcmm.objects.PCMMResourcesMapper;
+
+public class PCMMResourceSetTest {
+
+       
+       @Test
+       public void testGetMappedResources() {
+
+       int flowID=100;
+       short trId=(short)123;
+       //typical use of PCMMresourceSet to add a new mapping
+       PCMMResourceSet.getInstance().mapResources(     /* flow ID */flowID, 
+                                               new PCMMResourcesMapper<Short, PCMMIDHolder>(/* transactionID */(short)trId,
+                                                                               /* PCMMIDHolder */new PCMMIDHolder(/* flowID */flowID, /* gateID */0, /* transactionID */trId)));
+
+       // if we want to retrieve or update mapped data  
+       PCMMIDHolder holder = (PCMMIDHolder) PCMMResourceSet.getInstance().getMappedResources(/* flow ID */flowID).getValue();
+       short transID=(short) PCMMResourceSet.getInstance().getMappedResources(/* flow ID */flowID).getKey();
+       
+       assertTrue(holder.getFlowID()==flowID);
+       assertTrue(holder.getTransactionID()==trId);
+       assertTrue(transID==trId);
+       //update gate ID
+       holder.setGateID(/*gate ID*/ 1234568);
+
+       assertTrue(((PCMMIDHolder) PCMMResourceSet.getInstance().getMappedResources(/* flow ID */flowID).getValue()).getGateID()==1234568);
+                               
+       
+
+       }
+
+}
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/PCMMWorkflowTest.java b/packetcable-driver/src/test/java/org/pcmm/test/PCMMWorkflowTest.java
new file mode 100644 (file)
index 0000000..52d77d2
--- /dev/null
@@ -0,0 +1,99 @@
+package org.pcmm.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+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;
+
+public class PCMMWorkflowTest {
+
+       /**
+        * CMTS emulator, when testing with a real CMTS this should be set to null
+        * and shoudln't be started
+        */
+       private static ICMTS cmts;
+       /**
+        * CMTS host address, when testing with a real CMTS this should be CMTS
+        * address
+        */
+       private static InetAddress host;
+
+       private static IPCMMPolicyServer server;
+       private static IPSCMTSClient client;
+
+       @BeforeClass
+       public static void setUpBeforeClass() throws Exception {
+               // comment this when using real CMTS
+               // ###################################
+               cmts = new CMTS();
+               cmts.startServer();
+               // ###################################
+
+               server = new PCMMPolicyServer();
+               try {
+                       // this should be set to the cmts host ex :
+                       // InetAddress.getByName("10.10.10.10") or
+                       // InetAddress.getByName("my-cmts-host-name")
+                       host = InetAddress.getLocalHost();
+                       assertNotNull(host);
+               } catch (UnknownHostException uhe) {
+                       fail("could not get host address ");
+               }
+               setupConnection();
+       }
+
+       @AfterClass
+       public static void tearDownAfterClass() throws Exception {
+               tearDown();
+               if (cmts != null)
+                       cmts.stopServer();
+       }
+
+       public static void setupConnection() {
+               client = server.requestCMTSConnection(host);
+               assertNotNull(client);
+       }
+
+       public static void tearDown() throws Exception {
+               assertNotNull(client);
+               assertTrue("Client disconnection failed", client.disconnect());
+       }
+
+       
+       //@Test
+       public void testGateSet() {
+               assertNotNull(client);
+               assertTrue("Gate-Set failed", client.gateSet());
+       }
+
+       //@Test
+       public void testGateDelete() {
+               assertNotNull(client);
+               assertTrue("Gate-Delete failed", client.gateDelete());
+
+       }
+
+       //@Test
+       public void testGateInfo() {
+               assertNotNull(client);
+               assertTrue("Gate-Info failed", client.gateInfo());
+       }
+
+       //@Test
+       public void testGateSynchronize() {
+               assertNotNull(client);
+               assertTrue("Gate-Synchronize failed", client.gateSynchronize());
+       }
+
+}
diff --git a/packetcable-driver/src/test/java/org/pcmm/test/README.md b/packetcable-driver/src/test/java/org/pcmm/test/README.md
new file mode 100644 (file)
index 0000000..f32f06a
--- /dev/null
@@ -0,0 +1,2 @@
+This package contains the test set for the PCMM driver, 
+To test the whole workflow  use the junit based test : PCMMWorkflowTest.java 
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 18b56b5dd4aa32600c9280b4fcbf3cd8b5c70062..8e989ac1dbd7f08b89233bef8080c794a22d6de2 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -12,6 +12,7 @@
        <packaging>pom</packaging>
 
        <modules>
+               <module>packetcable-driver</module>
                <module>packetcable-model</module>
                <module>packetcable-consumer</module>
                <module>packetcable-provider</module>