From 96f5c7c441315f91cd9768e5a51effe7392f7ae2 Mon Sep 17 00:00:00 2001 From: samhendley Date: Wed, 16 Jun 2010 16:24:11 -0400 Subject: [PATCH] normalize all CRLFs to LFs in repo and removed trailing whitespace --- .gitignore | 20 +- APL/APL.vcproj | 1732 ++++---- APL/ASIOIncludes.h | 8 +- APL/ASIOSerialHelpers.h | 44 +- APL/AsyncLayerInterfaces.h | 18 +- APL/AsyncPhysLayerMonitor.cpp | 224 +- APL/AsyncPhysLayerMonitor.h | 14 +- APL/AsyncTaskBase.h | 16 +- APL/AsyncTaskContinuous.h | 16 +- APL/AsyncTaskGroup.cpp | 330 +- APL/AsyncTaskGroup.h | 8 +- APL/AsyncTaskInterfaces.h | 10 +- APL/AsyncTaskNonPeriodic.cpp | 64 +- APL/AsyncTaskNonPeriodic.h | 14 +- APL/AsyncTaskPeriodic.cpp | 64 +- APL/AsyncTaskPeriodic.h | 18 +- APL/AsyncTaskScheduler.cpp | 104 +- APL/AsyncTaskScheduler.h | 10 +- APL/BoundNotifier.h | 8 +- APL/CRC.cpp | 74 +- APL/CRC.h | 8 +- APL/ChangeBuffer.h | 44 +- APL/CommandInterfaces.h | 10 +- APL/CommandManager.h | 16 +- APL/CommandQueue.h | 16 +- APL/CommandResponseQueue.h | 16 +- APL/CommandTypes.h | 36 +- APL/Configure.h | 12 +- APL/CopyableBuffer.cpp | 128 +- APL/CopyableBuffer.h | 100 +- APL/DataInterfaces.h | 8 +- APL/DataTypes.cpp | 142 +- APL/DataTypes.h | 82 +- APL/EventLock.h | 10 +- APL/EventLockBase.h | 150 +- APL/EventSet.h | 18 +- APL/Exception.h | 20 +- APL/FlexibleDataObserver.cpp | 174 +- APL/FlexibleDataObserver.h | 40 +- APL/IEventLock.h | 42 +- APL/IHandlerAsync.cpp | 30 +- APL/IHandlerAsync.h | 60 +- APL/INotifier.h | 16 +- APL/IOService.cpp | 32 +- APL/IOService.h | 60 +- APL/IOServiceThread.cpp | 120 +- APL/IOServiceThread.h | 90 +- APL/IPhysMonitor.h | 62 +- APL/IPhysicalLayerAsync.h | 10 +- APL/IPhysicalLayerSource.h | 16 +- APL/ISubject.h | 46 +- APL/ITimeSource.h | 66 +- APL/Lock.h | 8 +- APL/LockBase.cpp | 34 +- APL/LockBase.h | 8 +- APL/LockBoost.h | 10 +- APL/Log.cpp | 176 +- APL/Log.h | 18 +- APL/LogBase.h | 12 +- APL/LogEntry.h | 12 +- APL/LogEntryCircularBuffer.cpp | 158 +- APL/LogEntryCircularBuffer.h | 18 +- APL/LogToFile.h | 10 +- APL/LogToStdio.cpp | 34 +- APL/LogToStdio.h | 54 +- APL/LogTypes.cpp | 24 +- APL/LogTypes.h | 54 +- APL/LogVar.h | 10 +- APL/Loggable.h | 10 +- APL/Logger.h | 22 +- APL/LowerLayerToPhysAdapter.h | 14 +- APL/MetricBuffer.h | 12 +- APL/MultiplexingDataObserver.h | 10 +- APL/Notifier.h | 10 +- APL/PackingTemplates.h | 8 +- APL/PackingUnpacking.h | 64 +- APL/Parsing.cpp | 46 +- APL/Parsing.h | 70 +- APL/PhysLayerSettings.h | 58 +- APL/PhysicalLayerAsyncASIO.h | 8 +- APL/PhysicalLayerAsyncBase.h | 22 +- APL/PhysicalLayerAsyncBaseTCP.cpp | 120 +- APL/PhysicalLayerAsyncBaseTCP.h | 8 +- APL/PhysicalLayerAsyncSerial.cpp | 144 +- APL/PhysicalLayerAsyncSerial.h | 10 +- APL/PhysicalLayerAsyncTCPClient.cpp | 92 +- APL/PhysicalLayerAsyncTCPClient.h | 8 +- APL/PhysicalLayerAsyncTCPServer.cpp | 104 +- APL/PhysicalLayerAsyncTCPServer.h | 12 +- APL/PhysicalLayerFactory.h | 14 +- APL/PhysicalLayerFunctors.h | 50 +- APL/PhysicalLayerInstance.h | 26 +- APL/PhysicalLayerManager.h | 14 +- APL/PhysicalLayerMap.h | 16 +- APL/PostingNotifier.cpp | 34 +- APL/PostingNotifier.h | 60 +- APL/PostingNotifierSource.cpp | 42 +- APL/PostingNotifierSource.h | 60 +- APL/ProtocolUtil.cpp | 40 +- APL/ProtocolUtil.h | 12 +- APL/QualityMasks.h | 14 +- APL/SerialTypes.h | 10 +- APL/ShiftableBuffer.cpp | 172 +- APL/ShiftableBuffer.h | 8 +- APL/Singleton.h | 12 +- APL/SubjectBase.h | 16 +- APL/SyncVar.h | 28 +- APL/Thread.h | 8 +- APL/ThreadBase.h | 12 +- APL/ThreadBoost.h | 10 +- APL/Threadable.h | 18 +- APL/TimeBase.h | 16 +- APL/TimeBoost.h | 14 +- APL/TimeSource.cpp | 134 +- APL/TimeSource.h | 140 +- APL/TimeTypes.h | 8 +- APL/Timeout.cpp | 96 +- APL/Timeout.h | 14 +- APL/TimerASIO.cpp | 54 +- APL/TimerASIO.h | 8 +- APL/TimerInterfaces.h | 10 +- APL/TimerSourceASIO.cpp | 140 +- APL/TimerSourceASIO.h | 100 +- APL/TimingTools.h | 12 +- APL/ToHex.cpp | 42 +- APL/ToHex.h | 74 +- APL/Types.h | 14 +- APL/Uncopyable.h | 8 +- APL/Util.cpp | 204 +- APL/Util.h | 86 +- APL/rake.project.rb | 10 +- APLTestTools/APLTestTools.vcproj | 588 +-- APLTestTools/AsyncTestObject.h | 14 +- APLTestTools/AsyncTestObjectASIO.h | 12 +- APLTestTools/BufferHelpers.cpp | 172 +- APLTestTools/BufferHelpers.h | 88 +- APLTestTools/BufferTestObject.cpp | 150 +- APLTestTools/BufferTestObject.h | 16 +- APLTestTools/LogTester.cpp | 92 +- APLTestTools/LogTester.h | 10 +- APLTestTools/LoopbackPhysicalLayerAsync.cpp | 170 +- APLTestTools/LoopbackPhysicalLayerAsync.h | 90 +- APLTestTools/MockCommandAcceptor.h | 120 +- APLTestTools/MockCommandHandler.h | 52 +- APLTestTools/MockLowerLayer.cpp | 126 +- APLTestTools/MockLowerLayer.h | 10 +- APLTestTools/MockNodeSaver.h | 10 +- APLTestTools/MockNotifier.h | 8 +- APLTestTools/MockPhysicalLayerAsync.cpp | 128 +- APLTestTools/MockPhysicalLayerAsync.h | 114 +- APLTestTools/MockPhysicalLayerAsyncTS.cpp | 194 +- APLTestTools/MockPhysicalLayerAsyncTS.h | 106 +- APLTestTools/MockResponseAcceptor.cpp | 56 +- APLTestTools/MockResponseAcceptor.h | 12 +- APLTestTools/MockTimerSource.h | 10 +- APLTestTools/MockUpperLayer.cpp | 114 +- APLTestTools/MockUpperLayer.h | 22 +- APLTestTools/TestHelpers.h | 8 +- APLTestTools/TestTypedefs.h | 8 +- APLTestTools/rake.project.rb | 10 +- APLXML/APLXML.vcproj | 398 +- APLXML/INodeSaver.h | 10 +- APLXML/PhysicalLayerManagerXML.cpp | 110 +- APLXML/PhysicalLayerManagerXML.h | 82 +- APLXML/PhysicalLayerXMLFactory.h | 68 +- APLXML/SingleNodeSaver.h | 10 +- APLXML/XMLConversion.cpp | 44 +- APLXML/XMLConversion.h | 32 +- APLXML/XML_APL.h | 12 +- APLXML/rake.project.rb | 10 +- APLXML/tinybinding.cpp | 182 +- APLXML/tinybinding.h | 14 +- CSToCppXMLBinder/Bind.cs | 68 +- CSToCppXMLBinder/CSToCppXMLBinder.csproj | 98 +- CSToCppXMLBinder/CppBinder.cs | 2 +- .../ReBuildCSharpFromSchema.bat | 34 +- DNP.sln | 388 +- DNP3/APDU.h | 46 +- DNP3/APDUConstants.h | 14 +- DNP3/AppChannelStates.cpp | 484 +-- DNP3/AppChannelStates.h | 42 +- DNP3/AppConfig.h | 78 +- DNP3/AppHeader.cpp | 294 +- DNP3/AppHeader.h | 22 +- DNP3/AppLayerChannel.cpp | 252 +- DNP3/AppLayerChannel.h | 200 +- DNP3/AsyncAppInterfaces.h | 34 +- DNP3/AsyncAppLayer.h | 30 +- DNP3/AsyncDatabase.h | 26 +- DNP3/AsyncDatabaseInterfaces.h | 16 +- DNP3/AsyncEventBufferBase.h | 58 +- DNP3/AsyncEventBuffers.h | 28 +- DNP3/AsyncLinkLayer.h | 22 +- DNP3/AsyncLinkLayerRouter.h | 14 +- DNP3/AsyncMaster.h | 26 +- DNP3/AsyncMasterStack.cpp | 42 +- DNP3/AsyncMasterStack.h | 62 +- DNP3/AsyncMasterStates.h | 18 +- DNP3/AsyncPort.cpp | 158 +- DNP3/AsyncPort.h | 28 +- DNP3/AsyncResponseContext.cpp | 790 ++-- DNP3/AsyncResponseContext.h | 78 +- DNP3/AsyncSlave.h | 38 +- DNP3/AsyncSlaveEventBuffer.h | 18 +- DNP3/AsyncSlaveStack.h | 84 +- DNP3/AsyncSlaveStates.h | 34 +- DNP3/AsyncStack.cpp | 34 +- DNP3/AsyncStack.h | 64 +- DNP3/AsyncStackManager.cpp | 446 +- DNP3/AsyncStackManager.h | 44 +- DNP3/AsyncTransportLayer.h | 18 +- DNP3/BufferSetTypes.h | 24 +- DNP3/CTOHistory.h | 18 +- DNP3/ClassCounter.h | 10 +- DNP3/ClassMask.h | 88 +- DNP3/DNP3.vcproj | 1382 +++--- DNP3/DNPCommandMaster.h | 28 +- DNP3/DNPConstants.h | 18 +- DNP3/DNPCrc.h | 8 +- DNP3/DNPDatabaseTypes.h | 28 +- DNP3/DNPExceptions.h | 12 +- DNP3/DNPFromStream.h | 12 +- DNP3/DNPToStream.h | 36 +- DNP3/DeviceTemplate.cpp | 54 +- DNP3/DeviceTemplate.h | 124 +- DNP3/DeviceTemplateTypes.h | 138 +- DNP3/EventTypes.h | 22 +- DNP3/HeaderReadIterator.h | 34 +- DNP3/IFrameSink.h | 80 +- DNP3/ILinkContext.h | 52 +- DNP3/ILinkRouter.h | 50 +- DNP3/IndexedWriteIterator.h | 14 +- DNP3/LinkConfig.h | 140 +- DNP3/LinkFrame.cpp | 382 +- DNP3/LinkFrame.h | 24 +- DNP3/LinkHeader.cpp | 194 +- DNP3/LinkHeader.h | 10 +- DNP3/LinkLayerConstants.h | 22 +- DNP3/LinkLayerReceiver.cpp | 508 +-- DNP3/LinkLayerReceiver.h | 10 +- DNP3/LinkReceiverStates.cpp | 148 +- DNP3/LinkReceiverStates.h | 10 +- DNP3/MasterConfig.h | 140 +- DNP3/MasterConfigTypes.h | 42 +- DNP3/MasterStackConfig.h | 62 +- DNP3/ObjectHeader.cpp | 114 +- DNP3/ObjectHeader.h | 26 +- DNP3/ObjectInterfaces.h | 18 +- DNP3/ObjectReadIterator.h | 32 +- DNP3/ObjectWriteIterator.h | 18 +- DNP3/Objects.cpp | 724 ++-- DNP3/Objects.h | 52 +- DNP3/PointClass.h | 8 +- DNP3/PriLinkLayerStates.h | 12 +- DNP3/ResponseLoader.cpp | 186 +- DNP3/ResponseLoader.h | 22 +- DNP3/SecLinkLayerStates.h | 26 +- DNP3/SlaveConfig.h | 206 +- DNP3/SlaveResponseTypes.cpp | 284 +- DNP3/SlaveResponseTypes.h | 96 +- DNP3/SlaveStackConfig.h | 66 +- DNP3/SolicitedChannel.cpp | 114 +- DNP3/SolicitedChannel.h | 78 +- DNP3/StackManager.cpp | 98 +- DNP3/StackManager.h | 152 +- DNP3/TLS_Base.h | 12 +- DNP3/TransportConstants.h | 8 +- DNP3/TransportRx.h | 10 +- DNP3/TransportStates.h | 12 +- DNP3/TransportTx.h | 14 +- DNP3/UnsolicitedChannel.cpp | 80 +- DNP3/UnsolicitedChannel.h | 62 +- DNP3/rake.project.rb | 10 +- DNP3Java/DNP3Java.vcproj | 394 +- DNP3Java/JNI_INCLUDES.vsprops | 22 +- DNP3Java/JavaDNP3.i | 164 +- DNP3Java/TestBinding.java | 20 +- DNP3Java/rake.project.rb | 26 +- DNP3Test/AppLayerTest.h | 16 +- DNP3Test/AsyncDatabaseTestObject.h | 120 +- DNP3Test/AsyncIntegrationTest.cpp | 244 +- DNP3Test/AsyncIntegrationTest.h | 178 +- DNP3Test/AsyncLinkLayerRouterTest.cpp | 32 +- DNP3Test/AsyncLinkLayerRouterTest.h | 8 +- DNP3Test/AsyncLinkLayerTest.cpp | 58 +- DNP3Test/AsyncLinkLayerTest.h | 8 +- DNP3Test/AsyncMasterTestObject.cpp | 80 +- DNP3Test/AsyncMasterTestObject.h | 10 +- DNP3Test/AsyncSlaveTestObject.h | 10 +- DNP3Test/AsyncStartupTeardownTest.cpp | 74 +- DNP3Test/AsyncStartupTeardownTest.h | 86 +- DNP3Test/DNP3Test.vcproj | 932 ++-- DNP3Test/DNPHelpers.h | 8 +- DNP3Test/LinkReceiverTest.h | 92 +- DNP3Test/MockAppUser.cpp | 204 +- DNP3Test/MockAppUser.h | 16 +- DNP3Test/MockAsyncAppLayer.cpp | 166 +- DNP3Test/MockAsyncAppLayer.h | 14 +- DNP3Test/MockFrameSink.cpp | 212 +- DNP3Test/MockFrameSink.h | 126 +- DNP3Test/ResponseLoaderTestObject.cpp | 160 +- DNP3Test/ResponseLoaderTestObject.h | 76 +- DNP3Test/TestAPDU.cpp | 816 ++-- DNP3Test/TestAPDUWriting.cpp | 654 +-- DNP3Test/TestAsyncAppLayer.cpp | 954 ++-- DNP3Test/TestAsyncDatabase.cpp | 356 +- DNP3Test/TestAsyncEventBufferBase.cpp | 258 +- DNP3Test/TestAsyncEventBuffers.cpp | 206 +- DNP3Test/TestAsyncIntegration.cpp | 128 +- DNP3Test/TestAsyncLinkLayer.cpp | 796 ++-- DNP3Test/TestAsyncLinkLayerRouter.cpp | 260 +- DNP3Test/TestAsyncMaster.cpp | 1092 ++--- DNP3Test/TestAsyncSlave.cpp | 2558 +++++------ DNP3Test/TestAsyncSlaveEventBuffer.cpp | 214 +- DNP3Test/TestAsyncTransportLayer.cpp | 506 +-- DNP3Test/TestAsyncTransportLoopback.cpp | 162 +- DNP3Test/TestAsyncTransportScalability.cpp | 124 +- DNP3Test/TestCRC.cpp | 54 +- DNP3Test/TestLinkFrameDNP.cpp | 262 +- DNP3Test/TestLinkReceiver.cpp | 504 +-- DNP3Test/TestObjects.cpp | 120 +- DNP3Test/TestResponseLoader.cpp | 238 +- DNP3Test/TestStartupTeardown.cpp | 86 +- DNP3Test/TransportIntegrationStack.h | 8 +- DNP3Test/TransportLoopbackTestObject.cpp | 124 +- DNP3Test/TransportLoopbackTestObject.h | 12 +- DNP3Test/TransportScalabilityTestObject.cpp | 170 +- DNP3Test/TransportScalabilityTestObject.h | 12 +- DNP3Test/TransportStackPair.cpp | 76 +- DNP3Test/TransportStackPair.h | 10 +- DNP3Test/TransportTestObject.cpp | 112 +- DNP3Test/TransportTestObject.h | 14 +- DNP3Test/rake.project.rb | 14 +- DNP3XML/DNP3XML.vcproj | 350 +- DNP3XML/XML_DNP3.cpp | 362 +- DNP3XML/XML_DNP3.h | 14 +- DNP3XML/XML_TestSet.cpp | 92 +- DNP3XML/XML_TestSet.h | 54 +- DNP3XML/XmlToConfig.cpp | 376 +- DNP3XML/XmlToConfig.h | 228 +- DNP3XML/rake.project.rb | 10 +- NOTICE | 46 +- README.markdown | 310 +- Terminal/ControlResponseTE.cpp | 348 +- Terminal/ControlResponseTE.h | 8 +- Terminal/ControlTerminalExtension.h | 10 +- Terminal/DOTerminalExtension.h | 18 +- Terminal/FlexibleObserverTerminalExtension.h | 6 +- Terminal/LineReader.h | 6 +- Terminal/LogTerminalExtension.h | 152 +- Terminal/PhysicalLayerIOStreamAsync.cpp | 54 +- Terminal/PhysicalLayerIOStreamAsync.h | 68 +- Terminal/PhysicalLayerSyncProxy.cpp | 190 +- Terminal/PhysicalLayerSyncProxy.h | 136 +- Terminal/Terminal.h | 30 +- Terminal/Terminal.vcproj | 494 +-- Terminal/TerminalInterfaces.h | 24 +- Terminal/TokenNode.h | 16 +- Terminal/rake.project.rb | 10 +- TerminalTest/TerminalTest.vcproj | 406 +- TerminalTest/TestPhysicalLayerSyncProxy.cpp | 194 +- TerminalTest/TestTerminal.cpp | 348 +- TerminalTest/rake.project.rb | 14 +- TestAPL/AsyncPhysBaseTest.cpp | 38 +- TestAPL/AsyncPhysBaseTest.h | 56 +- TestAPL/AsyncPhysTestObject.cpp | 102 +- TestAPL/AsyncPhysTestObject.h | 122 +- TestAPL/AsyncSerialTestObject.h | 10 +- TestAPL/TestAPL.vcproj | 744 ++-- TestAPL/TestASIO.cpp | 96 +- TestAPL/TestAsyncTask.cpp | 494 +-- TestAPL/TestCastLongLongDouble.cpp | 182 +- TestAPL/TestCommandQueue.cpp | 212 +- TestAPL/TestCommandTypes.cpp | 202 +- TestAPL/TestLocks.cpp | 400 +- TestAPL/TestLog.cpp | 268 +- TestAPL/TestMisc.cpp | 82 +- TestAPL/TestPackingUnpacking.cpp | 292 +- TestAPL/TestParsing.cpp | 74 +- TestAPL/TestPhysicalLayerAsyncBase.cpp | 268 +- TestAPL/TestPhysicalLayerAsyncSerial.cpp | 92 +- TestAPL/TestPhysicalLayerAsyncTCP.cpp | 352 +- TestAPL/TestQualityMasks.cpp | 38 +- TestAPL/TestShiftableBuffer.cpp | 270 +- TestAPL/TestSyncVar.cpp | 132 +- TestAPL/TestThreading.cpp | 530 +-- TestAPL/TestTime.cpp | 624 +-- TestAPL/TestTimers.cpp | 262 +- TestAPL/TestTypes.cpp | 98 +- TestAPL/TestUtil.cpp | 124 +- TestAPL/TestXmlBinding.cpp | 228 +- TestAPL/rake.project.rb | 14 +- TestSet/StackHelpers.cpp | 144 +- TestSet/StackHelpers.h | 176 +- TestSet/TestSet.vcproj | 452 +- TestSet/rake.project.rb | 14 +- TestSet/tmw_test.rb | 108 +- TestSetInstaller/TestSetInstaller.vdproj | 1922 ++++----- XMLBindings/APLXML_Base.cpp | 32 +- XMLBindings/APLXML_Base.h | 288 +- XMLBindings/APLXML_DNP.cpp | 76 +- XMLBindings/APLXML_DNP.h | 80 +- XMLBindings/APLXML_MTS.cpp | 10 +- XMLBindings/APLXML_MTS.h | 18 +- XMLBindings/APLXML_STS.cpp | 10 +- XMLBindings/APLXML_STS.h | 18 +- XMLBindings/XMLBindings.vcproj | 374 +- XMLBindings/rake.project.rb | 10 +- config/boost_includes.vsprops | 22 +- config/boost_lib.vsprops | 22 +- config/local_dir.vsprops | 22 +- config/output_dirs.vsprops | 18 +- rakefile.rb | 162 +- tinyxml/rake.project.rb | 10 +- tinyxml/tinystr.h | 2 +- tinyxml/tinyxml.cpp | 3840 ++++++++--------- tinyxml/tinyxml.h | 3628 ++++++++-------- tinyxml/tinyxml.vcproj | 358 +- tools/rake_build_system/plugins/rake.boost.rb | 92 +- .../plugins/rake.cpp.enviroment.rb | 176 +- .../plugins/rake.crosstest.rb | 68 +- .../plugins/rake.swigjava.rb | 170 +- 422 files changed, 29782 insertions(+), 29782 deletions(-) diff --git a/.gitignore b/.gitignore index a9e055ea..76418f15 100755 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,11 @@ - -/DNP.ncb -/DNP.suo -/*/Debug -/*/Release -*.user -/*/pc_cygwin -/*/pc_linux_arm -/tools/install_scripts/boost/*/temp -/CSToCppXMLBinder/bin + +/DNP.ncb +/DNP.suo +/*/Debug +/*/Release +*.user +/*/pc_cygwin +/*/pc_linux_arm +/tools/install_scripts/boost/*/temp +/CSToCppXMLBinder/bin /CSToCppXMLBinder/obj \ No newline at end of file diff --git a/APL/APL.vcproj b/APL/APL.vcproj index 3e71b2be..cda355c5 100755 --- a/APL/APL.vcproj +++ b/APL/APL.vcproj @@ -1,866 +1,866 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/APL/ASIOIncludes.h b/APL/ASIOIncludes.h index 758f6e01..e5767e09 100644 --- a/APL/ASIOIncludes.h +++ b/APL/ASIOIncludes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASIO_INCLUDES_H_ #define __ASIO_INCLUDES_H_ diff --git a/APL/ASIOSerialHelpers.h b/APL/ASIOSerialHelpers.h index 29ab5edc..c08d9cdd 100644 --- a/APL/ASIOSerialHelpers.h +++ b/APL/ASIOSerialHelpers.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,31 +6,31 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef _ASIO_SERIAL_HELPERS_H_ -#define _ASIO_SERIAL_HELPERS_H_ - -#include "SerialTypes.h" - -namespace boost { namespace asio { - typedef basic_serial_port<> serial_port; -}} - -namespace apl { namespace asio_serial { - - // Serial port configuration functions "free" to keep the classes simple. - void Configure(SerialSettings& arSettings, boost::asio::serial_port& arPort, boost::system::error_code& ec); - void Configure(SerialSettings& arSettings, boost::asio::serial_port& arPort); - -}} - -#endif +// +#ifndef _ASIO_SERIAL_HELPERS_H_ +#define _ASIO_SERIAL_HELPERS_H_ + +#include "SerialTypes.h" + +namespace boost { namespace asio { + typedef basic_serial_port<> serial_port; +}} + +namespace apl { namespace asio_serial { + + // Serial port configuration functions "free" to keep the classes simple. + void Configure(SerialSettings& arSettings, boost::asio::serial_port& arPort, boost::system::error_code& ec); + void Configure(SerialSettings& arSettings, boost::asio::serial_port& arPort); + +}} + +#endif diff --git a/APL/AsyncLayerInterfaces.h b/APL/AsyncLayerInterfaces.h index a1371a19..98e254f9 100644 --- a/APL/AsyncLayerInterfaces.h +++ b/APL/AsyncLayerInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_LAYER_INTERFACES_H_ #define __ASYNC_LAYER_INTERFACES_H_ @@ -74,10 +74,10 @@ class IUpperLayer : public IUpDown, protected virtual Loggable /// Called by 'layer down' when a previously requested send operation fails void OnSendFailure(); - + void SetLowerLayer(ILowerLayer*); - - + + protected: ILowerLayer* mpLowerLayer; @@ -87,8 +87,8 @@ class IUpperLayer : public IUpDown, protected virtual Loggable virtual void _OnSendSuccess() = 0; virtual void _OnSendFailure() = 0; virtual bool LogReceive() { return true; } - - + + // override this descriptor, it's use in the Hex log messages virtual std::string RecvString() const { return "<-"; } }; diff --git a/APL/AsyncPhysLayerMonitor.cpp b/APL/AsyncPhysLayerMonitor.cpp index efd1d3c5..f9f9fc0b 100644 --- a/APL/AsyncPhysLayerMonitor.cpp +++ b/APL/AsyncPhysLayerMonitor.cpp @@ -16,115 +16,115 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncPhysLayerMonitor.h" - -#include "IPhysicalLayerAsync.h" - -#include -#include -#include -#include "Logger.h" - -namespace apl { - -AsyncPhysLayerMonitor::AsyncPhysLayerMonitor(Logger* apLogger, IPhysicalLayerAsync* apPhys, ITimerSource* apTimerSrc, millis_t aOpenRetry) : -Loggable(apLogger), -IHandlerAsync(apLogger), -mpPhys(apPhys), -mpTimerSrc(apTimerSrc), -mpOpenTimer(NULL), -mPortState(apLogger, "port_state"), -mOpening(false), -mOpen(false), -mStopOpenRetry(false), -M_OPEN_RETRY(aOpenRetry), -mpMonitor(NULL) -{ - mpPhys->SetHandler(this); -} - -AsyncPhysLayerMonitor::~AsyncPhysLayerMonitor() -{} - -bool AsyncPhysLayerMonitor::IsRunning() -{ - return mOpen || mOpening || (mpOpenTimer != NULL); -} - -bool AsyncPhysLayerMonitor::IsOpen() -{ - return mOpen; -} - -void AsyncPhysLayerMonitor::SetMonitor(IPhysMonitor* apMonitor) -{ - mpMonitor = apMonitor; -} - -void AsyncPhysLayerMonitor::Notify(IPhysMonitor::State aState) -{ - mPortState.Set(aState); - if(mpMonitor) mpMonitor->OnStateChange(aState); -} - -void AsyncPhysLayerMonitor::Start() -{ - assert(!mOpening); - if(mpOpenTimer) mpOpenTimer = NULL; - mOpening = true; - mStopOpenRetry = false; - mpPhys->AsyncOpen(); - this->Notify(IPhysMonitor::Opening); -} - -void AsyncPhysLayerMonitor::Stop() -{ - mStopOpenRetry = true; - - if(!this->IsRunning()) { - this->Notify(IPhysMonitor::Stopped); - } - else { - if(mOpen || mOpening) { - mpPhys->AsyncClose(); - } - if(mpOpenTimer) { - mpOpenTimer->Cancel(); - mpOpenTimer = NULL; - } - } -} - -void AsyncPhysLayerMonitor::_OnOpenFailure() -{ - mOpening = false; - if(mStopOpenRetry) { - this->Notify(IPhysMonitor::Stopped); //we're done! - } - else { - this->Notify(IPhysMonitor::Waiting); - mpOpenTimer = mpTimerSrc->Start(M_OPEN_RETRY, boost::bind(&AsyncPhysLayerMonitor::Start, this)); - } -} - -void AsyncPhysLayerMonitor::_OnLowerLayerUp() -{ - assert(mOpening); mOpening = false; mOpen = true; - this->Up(); - this->Notify(IPhysMonitor::Open); -} - -void AsyncPhysLayerMonitor::_OnLowerLayerDown() -{ - mOpen = false; - - this->Down(); - this->Notify(IPhysMonitor::Closed); - - if(mStopOpenRetry) { - this->Notify(IPhysMonitor::Stopped); - } - else this->Start(); -} - -} +#include "AsyncPhysLayerMonitor.h" + +#include "IPhysicalLayerAsync.h" + +#include +#include +#include +#include "Logger.h" + +namespace apl { + +AsyncPhysLayerMonitor::AsyncPhysLayerMonitor(Logger* apLogger, IPhysicalLayerAsync* apPhys, ITimerSource* apTimerSrc, millis_t aOpenRetry) : +Loggable(apLogger), +IHandlerAsync(apLogger), +mpPhys(apPhys), +mpTimerSrc(apTimerSrc), +mpOpenTimer(NULL), +mPortState(apLogger, "port_state"), +mOpening(false), +mOpen(false), +mStopOpenRetry(false), +M_OPEN_RETRY(aOpenRetry), +mpMonitor(NULL) +{ + mpPhys->SetHandler(this); +} + +AsyncPhysLayerMonitor::~AsyncPhysLayerMonitor() +{} + +bool AsyncPhysLayerMonitor::IsRunning() +{ + return mOpen || mOpening || (mpOpenTimer != NULL); +} + +bool AsyncPhysLayerMonitor::IsOpen() +{ + return mOpen; +} + +void AsyncPhysLayerMonitor::SetMonitor(IPhysMonitor* apMonitor) +{ + mpMonitor = apMonitor; +} + +void AsyncPhysLayerMonitor::Notify(IPhysMonitor::State aState) +{ + mPortState.Set(aState); + if(mpMonitor) mpMonitor->OnStateChange(aState); +} + +void AsyncPhysLayerMonitor::Start() +{ + assert(!mOpening); + if(mpOpenTimer) mpOpenTimer = NULL; + mOpening = true; + mStopOpenRetry = false; + mpPhys->AsyncOpen(); + this->Notify(IPhysMonitor::Opening); +} + +void AsyncPhysLayerMonitor::Stop() +{ + mStopOpenRetry = true; + + if(!this->IsRunning()) { + this->Notify(IPhysMonitor::Stopped); + } + else { + if(mOpen || mOpening) { + mpPhys->AsyncClose(); + } + if(mpOpenTimer) { + mpOpenTimer->Cancel(); + mpOpenTimer = NULL; + } + } +} + +void AsyncPhysLayerMonitor::_OnOpenFailure() +{ + mOpening = false; + if(mStopOpenRetry) { + this->Notify(IPhysMonitor::Stopped); //we're done! + } + else { + this->Notify(IPhysMonitor::Waiting); + mpOpenTimer = mpTimerSrc->Start(M_OPEN_RETRY, boost::bind(&AsyncPhysLayerMonitor::Start, this)); + } +} + +void AsyncPhysLayerMonitor::_OnLowerLayerUp() +{ + assert(mOpening); mOpening = false; mOpen = true; + this->Up(); + this->Notify(IPhysMonitor::Open); +} + +void AsyncPhysLayerMonitor::_OnLowerLayerDown() +{ + mOpen = false; + + this->Down(); + this->Notify(IPhysMonitor::Closed); + + if(mStopOpenRetry) { + this->Notify(IPhysMonitor::Stopped); + } + else this->Start(); +} + +} diff --git a/APL/AsyncPhysLayerMonitor.h b/APL/AsyncPhysLayerMonitor.h index ebc44e85..8eecc9d9 100644 --- a/APL/AsyncPhysLayerMonitor.h +++ b/APL/AsyncPhysLayerMonitor.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_PHYS_LAYER_MONITOR_H_ #define __ASYNC_PHYS_LAYER_MONITOR_H_ @@ -41,12 +41,12 @@ namespace apl { void Stop(); bool IsRunning(); - bool IsOpen(); + bool IsOpen(); void SetMonitor(IPhysMonitor* apMonitor); protected: - + bool Opening() const { return mOpening; } IPhysicalLayerAsync* mpPhys; @@ -60,7 +60,7 @@ namespace apl { private: void Notify(IPhysMonitor::State); - + bool mOpening; bool mOpen; bool mStopOpenRetry; diff --git a/APL/AsyncTaskBase.h b/APL/AsyncTaskBase.h index ad53b9c5..7fb047ae 100644 --- a/APL/AsyncTaskBase.h +++ b/APL/AsyncTaskBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_BASE_H_ #define __ASYNC_TASK_BASE_H_ @@ -62,14 +62,14 @@ class AsyncTaskBase : public ITaskCompletion, private Uncopyable void SilentDisable(); std::string Name() const { return mName; } - + static bool LessThan(const AsyncTaskBase* l, const AsyncTaskBase* r); static bool LessThanGroupLevel(const AsyncTaskBase* l, const AsyncTaskBase* r); static bool LessThanGroupLevelNoString(const AsyncTaskBase* l, const AsyncTaskBase* r); - + protected: - + AsyncTaskBase( int aPriority, @@ -77,7 +77,7 @@ class AsyncTaskBase : public ITaskCompletion, private Uncopyable AsyncTaskGroup* apGroup, const boost::posix_time::ptime& arInitialTime, const std::string& arName); - + /// optional NVII function for special bookkeeping virtual void _OnComplete(bool aSuccess) {} virtual void _Reset() {} diff --git a/APL/AsyncTaskContinuous.h b/APL/AsyncTaskContinuous.h index ef83e85c..d5e4a137 100644 --- a/APL/AsyncTaskContinuous.h +++ b/APL/AsyncTaskContinuous.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_CONTINUOUS_H_ #define __ASYNC_TASK_CONTINUOUS_H_ @@ -32,22 +32,22 @@ class AsyncTaskGroup; class AsyncTaskContinuous : public AsyncTaskBase { friend class AsyncTaskGroup; - + public: virtual ~AsyncTaskContinuous(){} private: - /** + /** @param aPriority Tie break between non-dependent tasks. Lower is higher priority. @param arCallback Bound function used for starting the asynchronous task. @param apGroup Associated task group @param arName Name associated with the tasak */ AsyncTaskContinuous(int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName); - - + + }; } diff --git a/APL/AsyncTaskGroup.cpp b/APL/AsyncTaskGroup.cpp index e34426fd..3bf74517 100644 --- a/APL/AsyncTaskGroup.cpp +++ b/APL/AsyncTaskGroup.cpp @@ -16,168 +16,168 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncTaskGroup.h" - -#include "AsyncTaskBase.h" -#include "AsyncTaskPeriodic.h" -#include "AsyncTaskNonPeriodic.h" -#include "AsyncTaskContinuous.h" -#include "AsyncTaskScheduler.h" -#include "Exception.h" - -#include "TimerInterfaces.h" - -#include -#include - -using namespace boost::posix_time; - -namespace apl { - -AsyncTaskGroup::AsyncTaskGroup(ITimerSource* apTimerSrc, ITimeSource* apTimeSrc) : -mIsRunning(false), -mpTimerSrc(apTimerSrc), -mpTimeSrc(apTimeSrc), -mpTimer(NULL) -{ - -} - -AsyncTaskGroup::~AsyncTaskGroup() -{ - - if(mpTimer) { - mpTimer->Cancel(); - mpTimer = NULL; - } - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { delete p; } -} - -AsyncTaskBase* AsyncTaskGroup::Add(millis_t aPeriod, millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, const std::string& arName) -{ - AsyncTaskBase* pTask; - if(aPeriod >= 0) - pTask = new AsyncTaskPeriodic(aPeriod, aRetryDelay, aPriority, arCallback, this, arName); - else - pTask = new AsyncTaskNonPeriodic(aRetryDelay, aPriority, arCallback, this, arName); - - mTaskVec.push_back(pTask); - return pTask; -} - -void AsyncTaskGroup::ResetTasks(int aMask) -{ - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) - { - if(!p->IsRunning() && (p->GetFlags() & aMask)) p->Reset(); - } -} - -AsyncTaskContinuous* AsyncTaskGroup::AddContinuous(int aPriority, const TaskHandler& arCallback, const std::string& arName) -{ - AsyncTaskContinuous* pTask = new AsyncTaskContinuous(aPriority, arCallback, this, arName); - mTaskVec.push_back(pTask); - return pTask; -} - -void AsyncTaskGroup::Enable() -{ - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { p->SilentEnable(); } - this->CheckState(); -} - -void AsyncTaskGroup::Disable() -{ - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { p->SilentDisable(); } - this->CheckState(); -} - -void AsyncTaskGroup::Enable(int aMask) -{ - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) - { - if((p->GetFlags() & aMask) != 0) p->SilentEnable(); - } - this->CheckState(); -} - -void AsyncTaskGroup::Disable(int aMask) -{ - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) - { - if((p->GetFlags() & aMask) != 0) p->SilentDisable(); - } - this->CheckState(); -} - -AsyncTaskBase* AsyncTaskGroup::GetNext(const boost::posix_time::ptime& arTime) -{ - this->Update(arTime); - TaskVec::iterator max = max_element(mTaskVec.begin(), mTaskVec.end(), AsyncTaskBase::LessThanGroupLevel); - - AsyncTaskBase* pRet = NULL; - if(max != mTaskVec.end()) { - AsyncTaskBase* p = *max; - if(!p->IsRunning() && p->IsEnabled()) pRet = p; - } - - return pRet; -} - -void AsyncTaskGroup::CheckState() -{ - ptime now = GetUTC(); - AsyncTaskBase* pTask = GetNext(now); - - - if(pTask == NULL) return; - if(pTask->NextRunTime() == max_date_time) return; - - if(pTask->NextRunTime() <= now) - { - mIsRunning = true; - pTask->Dispatch(); - } - else - { - this->RestartTimer(pTask->NextRunTime()); - } -} - -void AsyncTaskGroup::OnCompletion() -{ - if(!mIsRunning) throw InvalidStateException(LOCATION, "Not running"); - mIsRunning = false; - this->CheckState(); -} - -boost::posix_time::ptime AsyncTaskGroup::GetUTC() const -{ - return mpTimeSrc->GetUTC(); -} - -void AsyncTaskGroup::Update(const boost::posix_time::ptime& arTime) -{ - BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { p->UpdateTime(arTime); } -} - -void AsyncTaskGroup::RestartTimer(const ptime& arTime) -{ - if(mpTimer != NULL) { - if(mpTimer->ExpiresAt() != arTime) { - mpTimer->Cancel(); - mpTimer = NULL; - } - } - - if(mpTimer == NULL) - mpTimer = mpTimerSrc->Start(arTime, boost::bind(&AsyncTaskGroup::OnTimerExpiration, this)); -} - -void AsyncTaskGroup::OnTimerExpiration() -{ - mpTimer = NULL; - this->CheckState(); -} - -} // end ns +#include "AsyncTaskGroup.h" + +#include "AsyncTaskBase.h" +#include "AsyncTaskPeriodic.h" +#include "AsyncTaskNonPeriodic.h" +#include "AsyncTaskContinuous.h" +#include "AsyncTaskScheduler.h" +#include "Exception.h" + +#include "TimerInterfaces.h" + +#include +#include + +using namespace boost::posix_time; + +namespace apl { + +AsyncTaskGroup::AsyncTaskGroup(ITimerSource* apTimerSrc, ITimeSource* apTimeSrc) : +mIsRunning(false), +mpTimerSrc(apTimerSrc), +mpTimeSrc(apTimeSrc), +mpTimer(NULL) +{ + +} + +AsyncTaskGroup::~AsyncTaskGroup() +{ + + if(mpTimer) { + mpTimer->Cancel(); + mpTimer = NULL; + } + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { delete p; } +} + +AsyncTaskBase* AsyncTaskGroup::Add(millis_t aPeriod, millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, const std::string& arName) +{ + AsyncTaskBase* pTask; + if(aPeriod >= 0) + pTask = new AsyncTaskPeriodic(aPeriod, aRetryDelay, aPriority, arCallback, this, arName); + else + pTask = new AsyncTaskNonPeriodic(aRetryDelay, aPriority, arCallback, this, arName); + + mTaskVec.push_back(pTask); + return pTask; +} + +void AsyncTaskGroup::ResetTasks(int aMask) +{ + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) + { + if(!p->IsRunning() && (p->GetFlags() & aMask)) p->Reset(); + } +} + +AsyncTaskContinuous* AsyncTaskGroup::AddContinuous(int aPriority, const TaskHandler& arCallback, const std::string& arName) +{ + AsyncTaskContinuous* pTask = new AsyncTaskContinuous(aPriority, arCallback, this, arName); + mTaskVec.push_back(pTask); + return pTask; +} + +void AsyncTaskGroup::Enable() +{ + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { p->SilentEnable(); } + this->CheckState(); +} + +void AsyncTaskGroup::Disable() +{ + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { p->SilentDisable(); } + this->CheckState(); +} + +void AsyncTaskGroup::Enable(int aMask) +{ + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) + { + if((p->GetFlags() & aMask) != 0) p->SilentEnable(); + } + this->CheckState(); +} + +void AsyncTaskGroup::Disable(int aMask) +{ + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) + { + if((p->GetFlags() & aMask) != 0) p->SilentDisable(); + } + this->CheckState(); +} + +AsyncTaskBase* AsyncTaskGroup::GetNext(const boost::posix_time::ptime& arTime) +{ + this->Update(arTime); + TaskVec::iterator max = max_element(mTaskVec.begin(), mTaskVec.end(), AsyncTaskBase::LessThanGroupLevel); + + AsyncTaskBase* pRet = NULL; + if(max != mTaskVec.end()) { + AsyncTaskBase* p = *max; + if(!p->IsRunning() && p->IsEnabled()) pRet = p; + } + + return pRet; +} + +void AsyncTaskGroup::CheckState() +{ + ptime now = GetUTC(); + AsyncTaskBase* pTask = GetNext(now); + + + if(pTask == NULL) return; + if(pTask->NextRunTime() == max_date_time) return; + + if(pTask->NextRunTime() <= now) + { + mIsRunning = true; + pTask->Dispatch(); + } + else + { + this->RestartTimer(pTask->NextRunTime()); + } +} + +void AsyncTaskGroup::OnCompletion() +{ + if(!mIsRunning) throw InvalidStateException(LOCATION, "Not running"); + mIsRunning = false; + this->CheckState(); +} + +boost::posix_time::ptime AsyncTaskGroup::GetUTC() const +{ + return mpTimeSrc->GetUTC(); +} + +void AsyncTaskGroup::Update(const boost::posix_time::ptime& arTime) +{ + BOOST_FOREACH(AsyncTaskBase* p, mTaskVec) { p->UpdateTime(arTime); } +} + +void AsyncTaskGroup::RestartTimer(const ptime& arTime) +{ + if(mpTimer != NULL) { + if(mpTimer->ExpiresAt() != arTime) { + mpTimer->Cancel(); + mpTimer = NULL; + } + } + + if(mpTimer == NULL) + mpTimer = mpTimerSrc->Start(arTime, boost::bind(&AsyncTaskGroup::OnTimerExpiration, this)); +} + +void AsyncTaskGroup::OnTimerExpiration() +{ + mpTimer = NULL; + this->CheckState(); +} + +} // end ns diff --git a/APL/AsyncTaskGroup.h b/APL/AsyncTaskGroup.h index 8b45bb1c..caf4acc4 100644 --- a/APL/AsyncTaskGroup.h +++ b/APL/AsyncTaskGroup.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_GROUP_H_ #define __ASYNC_TASK_GROUP_H_ diff --git a/APL/AsyncTaskInterfaces.h b/APL/AsyncTaskInterfaces.h index c7229633..beb50d82 100644 --- a/APL/AsyncTaskInterfaces.h +++ b/APL/AsyncTaskInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_INTERFACES_H_ #define __ASYNC_TASK_INTERFACES_H_ @@ -24,7 +24,7 @@ namespace apl { class ITaskCompletion -{ +{ public: virtual void OnComplete(bool aSuccess) = 0; diff --git a/APL/AsyncTaskNonPeriodic.cpp b/APL/AsyncTaskNonPeriodic.cpp index a615792c..dd158974 100644 --- a/APL/AsyncTaskNonPeriodic.cpp +++ b/APL/AsyncTaskNonPeriodic.cpp @@ -16,35 +16,35 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncTaskNonPeriodic.h" - -#include "AsyncTaskGroup.h" - -using namespace boost::posix_time; - -namespace apl { - - -AsyncTaskNonPeriodic::AsyncTaskNonPeriodic(millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName) : -AsyncTaskBase(aPriority, arCallback, apGroup, min_date_time, arName), -mRetryDelay(aRetryDelay) -{ - -} - -void AsyncTaskNonPeriodic::_OnComplete(bool aSuccess) -{ - ptime now = mpGroup->GetUTC(); - if(aSuccess) - { - mIsComplete = true; - mNextRunTime = max_date_time; - } - else - { - mNextRunTime = now + milliseconds(mRetryDelay); - } -} - -} //end ns - +#include "AsyncTaskNonPeriodic.h" + +#include "AsyncTaskGroup.h" + +using namespace boost::posix_time; + +namespace apl { + + +AsyncTaskNonPeriodic::AsyncTaskNonPeriodic(millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName) : +AsyncTaskBase(aPriority, arCallback, apGroup, min_date_time, arName), +mRetryDelay(aRetryDelay) +{ + +} + +void AsyncTaskNonPeriodic::_OnComplete(bool aSuccess) +{ + ptime now = mpGroup->GetUTC(); + if(aSuccess) + { + mIsComplete = true; + mNextRunTime = max_date_time; + } + else + { + mNextRunTime = now + milliseconds(mRetryDelay); + } +} + +} //end ns + diff --git a/APL/AsyncTaskNonPeriodic.h b/APL/AsyncTaskNonPeriodic.h index d70534d1..4949e1fc 100644 --- a/APL/AsyncTaskNonPeriodic.h +++ b/APL/AsyncTaskNonPeriodic.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_NON_PERIODIC_H_ #define __ASYNC_TASK_NON_PERIODIC_H_ @@ -39,11 +39,11 @@ class AsyncTaskGroup; class AsyncTaskNonPeriodic : public AsyncTaskBase { friend class AsyncTaskGroup; - + public: virtual ~AsyncTaskNonPeriodic(){} - + private: /// Implements ITaskCompletion @@ -58,7 +58,7 @@ class AsyncTaskNonPeriodic : public AsyncTaskBase @param arName Name associated with the task */ AsyncTaskNonPeriodic(millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName); - + millis_t mRetryDelay; }; diff --git a/APL/AsyncTaskPeriodic.cpp b/APL/AsyncTaskPeriodic.cpp index 078b2390..42faa160 100644 --- a/APL/AsyncTaskPeriodic.cpp +++ b/APL/AsyncTaskPeriodic.cpp @@ -16,35 +16,35 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncTaskPeriodic.h" - -#include "AsyncTaskGroup.h" - -using namespace boost::posix_time; - -namespace apl { - -AsyncTaskPeriodic::AsyncTaskPeriodic(millis_t aPeriod, millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName) : -AsyncTaskBase(aPriority, arCallback, apGroup, min_date_time, arName), -mPeriod(aPeriod), -mRetryDelay(aRetryDelay) -{ - -} - -void AsyncTaskPeriodic::_OnComplete(bool aSuccess) -{ - ptime now = mpGroup->GetUTC(); - if(aSuccess) - { - mIsComplete = true; - mNextRunTime = now + milliseconds(mPeriod); - } - else - { - mNextRunTime = now + milliseconds(mRetryDelay); - } -} - -} //end ns - +#include "AsyncTaskPeriodic.h" + +#include "AsyncTaskGroup.h" + +using namespace boost::posix_time; + +namespace apl { + +AsyncTaskPeriodic::AsyncTaskPeriodic(millis_t aPeriod, millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName) : +AsyncTaskBase(aPriority, arCallback, apGroup, min_date_time, arName), +mPeriod(aPeriod), +mRetryDelay(aRetryDelay) +{ + +} + +void AsyncTaskPeriodic::_OnComplete(bool aSuccess) +{ + ptime now = mpGroup->GetUTC(); + if(aSuccess) + { + mIsComplete = true; + mNextRunTime = now + milliseconds(mPeriod); + } + else + { + mNextRunTime = now + milliseconds(mRetryDelay); + } +} + +} //end ns + diff --git a/APL/AsyncTaskPeriodic.h b/APL/AsyncTaskPeriodic.h index 00bdb9e3..1c7564c8 100644 --- a/APL/AsyncTaskPeriodic.h +++ b/APL/AsyncTaskPeriodic.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_PERIODIC_H_ #define __ASYNC_TASK_PERIODIC_H_ @@ -40,11 +40,11 @@ class AsyncTaskGroup; class AsyncTaskPeriodic : public AsyncTaskBase { friend class AsyncTaskGroup; - + public: virtual ~AsyncTaskPeriodic(){} - + private: /// Implements ITaskCompletion @@ -57,12 +57,12 @@ class AsyncTaskPeriodic : public AsyncTaskBase @param aPriority Tie break between non-dependent tasks. Lower is higher priority. @param arCallback - Bound function used for starting the asynchronous task. @param apGroup Associated task group - @param arName Name associated with the task + @param arName Name associated with the task */ AsyncTaskPeriodic(millis_t aPeriod, millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, AsyncTaskGroup* apGroup, const std::string& arName); - - millis_t mPeriod; + + millis_t mPeriod; millis_t mRetryDelay; }; diff --git a/APL/AsyncTaskScheduler.cpp b/APL/AsyncTaskScheduler.cpp index 883c9e35..7b383da0 100644 --- a/APL/AsyncTaskScheduler.cpp +++ b/APL/AsyncTaskScheduler.cpp @@ -16,55 +16,55 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncTaskScheduler.h" - -#include "AsyncTaskGroup.h" -#include "AsyncTaskBase.h" - -#include -#include - -#include - -using namespace std; -using namespace boost; -using namespace boost::posix_time; - -namespace apl { - -AsyncTaskScheduler::AsyncTaskScheduler(ITimerSource* apTimerSrc, ITimeSource* apTimeSrc) : -mpTimerSrc(apTimerSrc), -mpTimeSrc(apTimeSrc) -{ - -} - -AsyncTaskScheduler::~AsyncTaskScheduler() -{ - BOOST_FOREACH(AsyncTaskGroup* p, mGroupSet) { delete p; } -} - -AsyncTaskGroup* AsyncTaskScheduler::NewGroup() -{ - AsyncTaskGroup* pGroup = new AsyncTaskGroup(mpTimerSrc, mpTimeSrc); - mGroupSet.insert(pGroup); - return pGroup; -} - -AsyncTaskGroup* AsyncTaskScheduler::Sever(AsyncTaskGroup* apGroup) -{ - GroupSet::iterator i = mGroupSet.find(apGroup); - if( i != mGroupSet.end() ) { - AsyncTaskGroup* pGroup = *i; - mGroupSet.erase(i); - return pGroup; - } - else return NULL; -} - -void AsyncTaskScheduler::Release(AsyncTaskGroup* apGroup) -{ - delete Sever(apGroup); -} - -} //end ns +#include "AsyncTaskScheduler.h" + +#include "AsyncTaskGroup.h" +#include "AsyncTaskBase.h" + +#include +#include + +#include + +using namespace std; +using namespace boost; +using namespace boost::posix_time; + +namespace apl { + +AsyncTaskScheduler::AsyncTaskScheduler(ITimerSource* apTimerSrc, ITimeSource* apTimeSrc) : +mpTimerSrc(apTimerSrc), +mpTimeSrc(apTimeSrc) +{ + +} + +AsyncTaskScheduler::~AsyncTaskScheduler() +{ + BOOST_FOREACH(AsyncTaskGroup* p, mGroupSet) { delete p; } +} + +AsyncTaskGroup* AsyncTaskScheduler::NewGroup() +{ + AsyncTaskGroup* pGroup = new AsyncTaskGroup(mpTimerSrc, mpTimeSrc); + mGroupSet.insert(pGroup); + return pGroup; +} + +AsyncTaskGroup* AsyncTaskScheduler::Sever(AsyncTaskGroup* apGroup) +{ + GroupSet::iterator i = mGroupSet.find(apGroup); + if( i != mGroupSet.end() ) { + AsyncTaskGroup* pGroup = *i; + mGroupSet.erase(i); + return pGroup; + } + else return NULL; +} + +void AsyncTaskScheduler::Release(AsyncTaskGroup* apGroup) +{ + delete Sever(apGroup); +} + +} //end ns diff --git a/APL/AsyncTaskScheduler.h b/APL/AsyncTaskScheduler.h index a8536b7b..f2646665 100644 --- a/APL/AsyncTaskScheduler.h +++ b/APL/AsyncTaskScheduler.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TASK_SCHEDULER_H_ #define __ASYNC_TASK_SCHEDULER_H_ @@ -38,7 +38,7 @@ class AsyncTaskScheduler { friend class AsyncTaskGroup; - public: + public: AsyncTaskScheduler(ITimerSource* apTimerSrc, ITimeSource* apTimeSrc = TimeSource::Inst()); ~AsyncTaskScheduler(); diff --git a/APL/BoundNotifier.h b/APL/BoundNotifier.h index 27b5c531..04227be3 100644 --- a/APL/BoundNotifier.h +++ b/APL/BoundNotifier.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __BOUND_NOTIFIER_H_ #define __BOUND_NOTIFIER_H_ diff --git a/APL/CRC.cpp b/APL/CRC.cpp index b10091b6..ad5ccc21 100644 --- a/APL/CRC.cpp +++ b/APL/CRC.cpp @@ -16,40 +16,40 @@ // specific language governing permissions and limitations // under the License. // -#include "CRC.h" - -namespace apl -{ - unsigned int CRC::CalcCRC(const apl::byte_t* aInput, size_t aLength, const unsigned int* apTable, unsigned int aStart, bool aInvert) - { - unsigned int CRC, index; - - CRC = aStart; - - for(size_t i=0; i> 8); - } - - if(aInvert) CRC = (~CRC) & 0xFFFF; - - return CRC; - } - - void CRC::PrecomputeCRC(unsigned int* apTable, unsigned int aPolynomial) - { - unsigned int i, j, CRC; - - for(i = 0; i < 256; i++) - { - CRC = i; - for (j = 0; j < 8; ++j) - { - if(CRC & 0x0001) CRC = (CRC >> 1) ^ aPolynomial; - else CRC >>= 1; - } - apTable[i] = CRC; - } - } -} +#include "CRC.h" + +namespace apl +{ + unsigned int CRC::CalcCRC(const apl::byte_t* aInput, size_t aLength, const unsigned int* apTable, unsigned int aStart, bool aInvert) + { + unsigned int CRC, index; + + CRC = aStart; + + for(size_t i=0; i> 8); + } + + if(aInvert) CRC = (~CRC) & 0xFFFF; + + return CRC; + } + + void CRC::PrecomputeCRC(unsigned int* apTable, unsigned int aPolynomial) + { + unsigned int i, j, CRC; + + for(i = 0; i < 256; i++) + { + CRC = i; + for (j = 0; j < 8; ++j) + { + if(CRC & 0x0001) CRC = (CRC >> 1) ^ aPolynomial; + else CRC >>= 1; + } + apTable[i] = CRC; + } + } +} diff --git a/APL/CRC.h b/APL/CRC.h index 11ecd856..676cccf0 100644 --- a/APL/CRC.h +++ b/APL/CRC.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __CRC_H_ #define __CRC_H_ diff --git a/APL/ChangeBuffer.h b/APL/ChangeBuffer.h index 4cc0f0a4..64410a50 100644 --- a/APL/ChangeBuffer.h +++ b/APL/ChangeBuffer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __CHANGE_BUFFER_H_ #define __CHANGE_BUFFER_H_ @@ -27,9 +27,9 @@ #include -namespace apl { +namespace apl { - /** Moves measurement data across thread boundaries. + /** Moves measurement data across thread boundaries. */ template class ChangeBuffer : public IDataObserver, public SubjectBase @@ -59,29 +59,29 @@ namespace apl { if(notify) this->NotifyAll(); } - void _Update(const Binary& arPoint, size_t aIndex) + void _Update(const Binary& arPoint, size_t aIndex) { mBinaryQueue.push_back(Change(arPoint, aIndex)); } - void _Update(const Analog& arPoint, size_t aIndex) + void _Update(const Analog& arPoint, size_t aIndex) { mAnalogQueue.push_back(Change(arPoint, aIndex)); } void _Update(const Counter& arPoint, size_t aIndex) { mCounterQueue.push_back(Change(arPoint, aIndex)); } - void _Update(const ControlStatus& arPoint, size_t aIndex) + void _Update(const ControlStatus& arPoint, size_t aIndex) { mControlStatusQueue.push_back(Change(arPoint, aIndex)); } void _Update(const SetpointStatus& arPoint, size_t aIndex) { mSetpointStatusQueue.push_back(Change(arPoint, aIndex)); } size_t FlushUpdates(apl::IDataObserver* apObserver, bool aClear = true); - + void Clear() { assert(this->InProgress()); _Clear(); } - - private: - void _Clear() + private: + + void _Clear() { mBinaryQueue.clear(); mAnalogQueue.clear(); @@ -90,13 +90,13 @@ namespace apl { mSetpointStatusQueue.clear(); } - bool HasChanges() + bool HasChanges() { - return mBinaryQueue.size() > 0 || - mAnalogQueue.size() > 0 || - mCounterQueue.size() > 0 || - mControlStatusQueue.size() > 0 || - mSetpointStatusQueue.size() > 0; + return mBinaryQueue.size() > 0 || + mAnalogQueue.size() > 0 || + mCounterQueue.size() > 0 || + mControlStatusQueue.size() > 0 || + mSetpointStatusQueue.size() > 0; } template @@ -111,14 +111,14 @@ namespace apl { LockType mLock; }; - + template size_t ChangeBuffer::FlushUpdates(apl::IDataObserver* apObserver, bool aClear) { Transaction tr(this); size_t count = 0; if(!this->HasChanges()) return count; - + { Transaction t(apObserver); mMidFlush = true; // Will clear on transaction end if an observer call blows up @@ -131,7 +131,7 @@ namespace apl { } if(aClear) this->Clear(); - + return count; } diff --git a/APL/CommandInterfaces.h b/APL/CommandInterfaces.h index 1a40ead6..57078fd1 100644 --- a/APL/CommandInterfaces.h +++ b/APL/CommandInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __COMMAND_INTERFACES_H_ #define __COMMAND_INTERFACES_H_ @@ -66,7 +66,7 @@ namespace apl will call Notify() on the passed in notifier. When Notify() is called (or on a schedule) the application should call bool moreCommands = ExecuteCommand(&handler); until moreCommands is false, which means that all of the commands available have been handled. - + */ class ICommandSource { diff --git a/APL/CommandManager.h b/APL/CommandManager.h index 266cc320..80132f3f 100644 --- a/APL/CommandManager.h +++ b/APL/CommandManager.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __COMMAND_MANAGER_H_ #define __COMMAND_MANAGER_H_ @@ -42,16 +42,16 @@ namespace apl typedef std::map CmdMap; public: - + void DefineCommand(const std::string& arName, CommandTypes aType, size_t aIndex, ICommandAcceptor* apCmdAcceptor); CommandInfo GetCommandInfo(const std::string& arName) { return GetMapping(arName); } - + private: CommandInfo GetMapping(const std::string& arName); - + CmdMap mCmdMap; - + }; } diff --git a/APL/CommandQueue.h b/APL/CommandQueue.h index 5e0ea6e4..706def80 100644 --- a/APL/CommandQueue.h +++ b/APL/CommandQueue.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __COMMAND_QUEUE_H_ #define __COMMAND_QUEUE_H_ @@ -28,13 +28,13 @@ namespace apl { struct CommandData - { - CommandData(apl::CommandTypes aType, size_t aIndex, int aSequence, IResponseAcceptor* apRspAcceptor) : + { + CommandData(apl::CommandTypes aType, size_t aIndex, int aSequence, IResponseAcceptor* apRspAcceptor) : mType(aType), mIndex(aIndex), mSequence(aSequence), mpRspAcceptor(apRspAcceptor) {} CommandData(){} - apl::CommandTypes mType; + apl::CommandTypes mType; size_t mIndex; int mSequence; IResponseAcceptor* mpRspAcceptor; @@ -57,7 +57,7 @@ namespace apl void Read(apl::BinaryOutput& arType, CommandData& arData); void Read(apl::Setpoint& arType, CommandData& arData); - + bool ExecuteCommand(ICommandHandler* apHandler); protected: diff --git a/APL/CommandResponseQueue.h b/APL/CommandResponseQueue.h index 60ab6d19..dc42c852 100644 --- a/APL/CommandResponseQueue.h +++ b/APL/CommandResponseQueue.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __COMMAND_RESPONSE_QUEUE_H_ #define __COMMAND_RESPONSE_QUEUE_H_ @@ -35,19 +35,19 @@ namespace apl void AcceptResponse(const CommandResponse&, int aSequence); bool WaitForResponse(CommandResponse&, int, millis_t aTimeout = -1); - + private: bool FindResponse(int aSeq, CommandResponse& arRsp); - + CommandResponse cr; int mSequence; SigLock mLock; struct RspInfo - { + { RspInfo(const CommandResponse& arRsp, int aSequence) : mResponse(arRsp), mSequence(aSequence) {} - CommandResponse mResponse; int mSequence; + CommandResponse mResponse; int mSequence; }; std::deque mResponseQueue; diff --git a/APL/CommandTypes.h b/APL/CommandTypes.h index 43960f70..fc6c27e8 100644 --- a/APL/CommandTypes.h +++ b/APL/CommandTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __CONTROL_TYPES_H_ #define __CONTROL_TYPES_H_ @@ -25,7 +25,7 @@ namespace apl { - + enum CommandModes { CM_SBO_ONLY, // Point must be selected before operation @@ -41,7 +41,7 @@ namespace apl }; /** - When a command is recieved from a master the application sends a code to + When a command is recieved from a master the application sends a code to indicate if it was successfull or if not what class of error was encountered. Each code has a description that indicates its customary meaning. */ @@ -62,14 +62,14 @@ namespace apl CommandStatus ByteToCommandStatus(byte_t aField); std::string ToString(CommandStatus aType); - + /** There are a number of types of controls. The best way to understand this difference is to think about the hardware controls the communication protocols are emulating. The most common to use are CC_PULSE, CC_LATCH_ON and CC_LATCH_OFF NOTE: Current implementation doesn't support queue/clear - */ + */ enum ControlCode { CC_NULL = 0, //!< illegal command code (used internally) @@ -90,7 +90,7 @@ namespace apl public: CommandTypes GetType() const { return mType; } CommandStatus mStatus; - + protected: //only invokable from super class CommandRequest(CommandTypes); @@ -100,10 +100,10 @@ namespace apl CommandRequest(); CommandTypes mType; }; - + /** - Describes an incoming control request from the master. It is the applications responsibility to handle - the request and return an approiate status code.The PULSE_CLOSE and PULSE_TRIP ControlCodes require + Describes an incoming control request from the master. It is the applications responsibility to handle + the request and return an approiate status code.The PULSE_CLOSE and PULSE_TRIP ControlCodes require setting the mOnTimeMS,mOffTimeMS and mCount variables, otherwise just use the defaults. */ class BinaryOutput : public CommandRequest @@ -122,9 +122,9 @@ namespace apl uint_32_t mOffTimeMS; std::string ToString() const; - + bool operator==(const BinaryOutput& arRHS) const - { + { return (mRawCode == arRHS.mRawCode) && (mCount == arRHS.mCount) && (mOnTimeMS == arRHS.mOnTimeMS) && (mOffTimeMS == arRHS.mOffTimeMS); } @@ -146,20 +146,20 @@ namespace apl }; /** - The object to represent a setpoint request from the master. Think of this like turning a - dial on the front of a machine to desired setting. A setpoint is natively repersented as + The object to represent a setpoint request from the master. Think of this like turning a + dial on the front of a machine to desired setting. A setpoint is natively repersented as a double but can be used to send both floating point and integer values. The key field is mEncodingType which informs the protocol buffers how to treat and format the values. There are smart defaults and behaviors to automatically determine the correct type of encoding to use in most cases (by default uses smallest type that can handle the number). This can be - overridden with the SetEncodingType() function. + overridden with the SetEncodingType() function. */ class Setpoint : public CommandRequest { public: Setpoint(int_16_t aValue); // this constructor is necessary to stop the compiler from having to guess which upcast to use Setpoint(int_32_t aValue); - + Setpoint(double aValue); // blank constructor, care must be used, an exception will be thrown if someone tries to access diff --git a/APL/Configure.h b/APL/Configure.h index 4effa270..4a902b8f 100644 --- a/APL/Configure.h +++ b/APL/Configure.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,23 +6,23 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __CONFIGURE_H_ #define __CONFIGURE_H_ //////////////////////////////////////////////////////// -// Set the target platform +// Set the target platform // -// OS specific .h includes use these APL_PLATFORM_X tags to +// OS specific .h includes use these APL_PLATFORM_X tags to // include the correct file. //////////////////////////////////////////////////////// diff --git a/APL/CopyableBuffer.cpp b/APL/CopyableBuffer.cpp index 0b89be28..db65fbee 100644 --- a/APL/CopyableBuffer.cpp +++ b/APL/CopyableBuffer.cpp @@ -16,67 +16,67 @@ // specific language governing permissions and limitations // under the License. // -#include "CopyableBuffer.h" - -#include - -namespace apl { - -CopyableBuffer::CopyableBuffer(size_t aSize) : -mpBuff(new byte_t[aSize]), -mSize(aSize) -{ - this->Zero(); -} - -CopyableBuffer::CopyableBuffer(const byte_t* apData, size_t aSize) : -mpBuff(new byte_t[aSize]), -mSize(aSize) -{ - memcpy(mpBuff, apData, mSize); -} - -CopyableBuffer::CopyableBuffer(const CopyableBuffer& arBuffer) : -mpBuff(new byte_t[arBuffer.Size()]), -mSize(arBuffer.Size()) -{ - memcpy(mpBuff, arBuffer, mSize); -} - -void CopyableBuffer::Zero() -{ - std::memset(mpBuff, 0, mSize); -} - -CopyableBuffer& CopyableBuffer::operator=(const CopyableBuffer& arRHS) -{ - //check for assignment to self - if(this == &arRHS) return *this; - - if(arRHS.Size() != mSize) { - mSize = arRHS.Size(); - delete mpBuff; mpBuff = new byte_t[mSize]; - } - - memcpy(mpBuff, arRHS, mSize); - - return *this; -} - -CopyableBuffer::~CopyableBuffer() -{ delete [] mpBuff; } - -bool CopyableBuffer::operator==( const CopyableBuffer& other) const -{ - if(other.Size() != this->Size()) return false; - else - { - for(size_t i=0; iSize(); ++i) { - if(this->mpBuff[i] != other.mpBuff[i]) return false; - } - - return true; - } -} - -} +#include "CopyableBuffer.h" + +#include + +namespace apl { + +CopyableBuffer::CopyableBuffer(size_t aSize) : +mpBuff(new byte_t[aSize]), +mSize(aSize) +{ + this->Zero(); +} + +CopyableBuffer::CopyableBuffer(const byte_t* apData, size_t aSize) : +mpBuff(new byte_t[aSize]), +mSize(aSize) +{ + memcpy(mpBuff, apData, mSize); +} + +CopyableBuffer::CopyableBuffer(const CopyableBuffer& arBuffer) : +mpBuff(new byte_t[arBuffer.Size()]), +mSize(arBuffer.Size()) +{ + memcpy(mpBuff, arBuffer, mSize); +} + +void CopyableBuffer::Zero() +{ + std::memset(mpBuff, 0, mSize); +} + +CopyableBuffer& CopyableBuffer::operator=(const CopyableBuffer& arRHS) +{ + //check for assignment to self + if(this == &arRHS) return *this; + + if(arRHS.Size() != mSize) { + mSize = arRHS.Size(); + delete mpBuff; mpBuff = new byte_t[mSize]; + } + + memcpy(mpBuff, arRHS, mSize); + + return *this; +} + +CopyableBuffer::~CopyableBuffer() +{ delete [] mpBuff; } + +bool CopyableBuffer::operator==( const CopyableBuffer& other) const +{ + if(other.Size() != this->Size()) return false; + else + { + for(size_t i=0; iSize(); ++i) { + if(this->mpBuff[i] != other.mpBuff[i]) return false; + } + + return true; + } +} + +} diff --git a/APL/CopyableBuffer.h b/APL/CopyableBuffer.h index fc00866f..761bf2e6 100644 --- a/APL/CopyableBuffer.h +++ b/APL/CopyableBuffer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,59 +6,59 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __COPYABLE_BUFFER_H_ -#define __COPYABLE_BUFFER_H_ - -#include "Types.h" -#include -#include - -namespace apl { - -/** Implements a dynamic buffer with a safe - copy constructor. This makes it easier to compose with - classes without requiring an explicit copy constructor -*/ -class CopyableBuffer -{ - public: - /// Construct based on starting size of buffer - CopyableBuffer(size_t aSize); - CopyableBuffer(const byte_t*, size_t aSize); - CopyableBuffer(const CopyableBuffer&); - CopyableBuffer& operator=(const CopyableBuffer&); - ~CopyableBuffer(); - - bool operator==( const CopyableBuffer& other) const; - bool operator!=( const CopyableBuffer& other) const { return ! (*this == other); } - - const byte_t* Buffer() const { return mpBuff; } - byte_t* WriteBuffer() const { return mpBuff; } - operator const byte_t* () const { return mpBuff; } - operator byte_t* () { return mpBuff; } - - size_t Size() const { return mSize; } - void Zero(); - - protected: - byte_t* mpBuff; - - private: - size_t mSize; -}; - -} - -#endif - - +// +#ifndef __COPYABLE_BUFFER_H_ +#define __COPYABLE_BUFFER_H_ + +#include "Types.h" +#include +#include + +namespace apl { + +/** Implements a dynamic buffer with a safe + copy constructor. This makes it easier to compose with + classes without requiring an explicit copy constructor +*/ +class CopyableBuffer +{ + public: + /// Construct based on starting size of buffer + CopyableBuffer(size_t aSize); + CopyableBuffer(const byte_t*, size_t aSize); + CopyableBuffer(const CopyableBuffer&); + CopyableBuffer& operator=(const CopyableBuffer&); + ~CopyableBuffer(); + + bool operator==( const CopyableBuffer& other) const; + bool operator!=( const CopyableBuffer& other) const { return ! (*this == other); } + + const byte_t* Buffer() const { return mpBuff; } + byte_t* WriteBuffer() const { return mpBuff; } + operator const byte_t* () const { return mpBuff; } + operator byte_t* () { return mpBuff; } + + size_t Size() const { return mSize; } + void Zero(); + + protected: + byte_t* mpBuff; + + private: + size_t mSize; +}; + +} + +#endif + + diff --git a/APL/DataInterfaces.h b/APL/DataInterfaces.h index f2483a78..ce724389 100644 --- a/APL/DataInterfaces.h +++ b/APL/DataInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DATA_INTERFACES_H_ #define __DATA_INTERFACES_H_ diff --git a/APL/DataTypes.cpp b/APL/DataTypes.cpp index aa953d66..bb09d023 100644 --- a/APL/DataTypes.cpp +++ b/APL/DataTypes.cpp @@ -16,74 +16,74 @@ // specific language governing permissions and limitations // under the License. // -#include "DataTypes.h" - -#include "TimingTools.h" - - - -using namespace std; - -namespace apl -{ - std::string GetDataTypeName(DataTypes aType) - { - switch(aType) - { - case(DT_BINARY): - return "Binary"; - case(DT_ANALOG): - return "Analog"; - case(DT_COUNTER): - return "Counter"; - case(DT_CONTROL_STATUS): - return "ControlStatus"; - case(DT_SETPOINT_STATUS): - return "SetpointStatus"; - default: - return "Unknown"; - } - } - - - - // DataPoint - - - DataPoint::DataPoint(byte_t aQuality, DataTypes aType) : - mQuality(aQuality), mTime(0), - mType(aType) - {} - - void DataPoint :: SetToNow() { mTime = TimeStamp::GetTimeStamp(); } - - - // BoolDataPoint - - - BoolDataPoint::BoolDataPoint(byte_t aQuality, DataTypes aType, byte_t aValueMask) : - DataPoint(aQuality, aType), - mValueMask(aValueMask) - {} - - std::string BoolDataPoint::ToString() const - { - std::ostringstream oss; - oss << "Value: " << (GetValue() ? "true" : "false") << " Quality: " << static_cast(GetQuality()); - return oss.str(); - } - - template<> - bool ExceedsDeadband(const double& val1, const double& val2, double aDeadband) - { - double val = fabs(val1-val2); - - if(val == std::numeric_limits::infinity()) return true; - else - { - return fabs(val) > aDeadband; - } - - } -} - +#include "DataTypes.h" + +#include "TimingTools.h" + + + +using namespace std; + +namespace apl +{ + std::string GetDataTypeName(DataTypes aType) + { + switch(aType) + { + case(DT_BINARY): + return "Binary"; + case(DT_ANALOG): + return "Analog"; + case(DT_COUNTER): + return "Counter"; + case(DT_CONTROL_STATUS): + return "ControlStatus"; + case(DT_SETPOINT_STATUS): + return "SetpointStatus"; + default: + return "Unknown"; + } + } + + + + // DataPoint + + + DataPoint::DataPoint(byte_t aQuality, DataTypes aType) : + mQuality(aQuality), mTime(0), + mType(aType) + {} + + void DataPoint :: SetToNow() { mTime = TimeStamp::GetTimeStamp(); } + + + // BoolDataPoint + + + BoolDataPoint::BoolDataPoint(byte_t aQuality, DataTypes aType, byte_t aValueMask) : + DataPoint(aQuality, aType), + mValueMask(aValueMask) + {} + + std::string BoolDataPoint::ToString() const + { + std::ostringstream oss; + oss << "Value: " << (GetValue() ? "true" : "false") << " Quality: " << static_cast(GetQuality()); + return oss.str(); + } + + template<> + bool ExceedsDeadband(const double& val1, const double& val2, double aDeadband) + { + double val = fabs(val1-val2); + + if(val == std::numeric_limits::infinity()) return true; + else + { + return fabs(val) > aDeadband; + } + + } +} + diff --git a/APL/DataTypes.h b/APL/DataTypes.h index e933d1c3..0408e1e1 100644 --- a/APL/DataTypes.h +++ b/APL/DataTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DATA_TYPES_H_ #define __DATA_TYPES_H_ @@ -55,14 +55,14 @@ namespace apl // useful template for pairing a value with an index template struct Change - { + { Change(){} Change(const T& arVal, size_t aIndex) : mValue(arVal), mIndex(aIndex) {} - T mValue; + T mValue; size_t mIndex; }; @@ -72,16 +72,16 @@ namespace apl DT_ANALOG, DT_COUNTER, DT_CONTROL_STATUS, - DT_SETPOINT_STATUS + DT_SETPOINT_STATUS }; std::string GetDataTypeName(DataTypes aType); /** Base class shared by all of the DataPoint types. There are 5 major data types and they all have - a value, timestamp and a quality field. The timestamp should reflect when the value was measured - or calculated. The quality field should be set approriately depending on the data type. Each datatype - has a its own defintion of the quality field that indicate specific conditions but all of the + a value, timestamp and a quality field. The timestamp should reflect when the value was measured + or calculated. The quality field should be set approriately depending on the data type. Each datatype + has a its own defintion of the quality field that indicate specific conditions but all of the datatypes define an XX_ONLINE bit, that is the default "nominal" value. This quality field is not for applying alarming information, that needs to be done with Binaries or in other channels. */ @@ -89,13 +89,13 @@ namespace apl { public: virtual ~DataPoint(){} - + DataTypes GetType() const; TimeStamp_t GetTime() const; - + virtual byte_t GetQuality() const; bool CheckQualityBit(byte_t aQualMask) const; - + virtual void SetQuality(byte_t aQuality); void SetTime(const TimeStamp_t arTime); void SetToNow(); @@ -103,10 +103,10 @@ namespace apl virtual std::string ToString() const = 0; protected: - + //These constructors can only be invoked by super classes DataPoint(byte_t aQuality, DataTypes aType); - + byte_t mQuality; // bitfield that stores type specific quality information TimeStamp_t mTime; // the time that the measurement was made @@ -132,7 +132,7 @@ namespace apl bool GetValue() const; void SetValue(bool aValue); - + byte_t GetQuality() const; void SetQuality(byte_t aQuality); @@ -148,15 +148,15 @@ namespace apl protected: //BoolDataPoint(const BoolDataPoint& arRHS); BoolDataPoint(byte_t aQuality, DataTypes aType, byte_t aValueMask); - + private: BoolDataPoint(); // bool data points store their value as a bit in the quality field byte_t mValueMask; }; - + inline void BoolDataPoint::SetValue(bool aValue) - { + { mQuality = (aValue) ? (mQuality|mValueMask) : (mQuality&(~mValueMask)); } inline bool BoolDataPoint::GetValue() const { return (mQuality&mValueMask) != 0; } @@ -169,8 +169,8 @@ namespace apl } inline void BoolDataPoint::SetQuality(byte_t aQuality) - { - mQuality = (mQuality & (mValueMask)); + { + mQuality = (mQuality & (mValueMask)); mQuality |= aQuality; } @@ -179,11 +179,11 @@ namespace apl template bool ExceedsDeadband(const T& val1, const T& val2, double aDeadband) - { + { //T can be unsigned data type so std::abs won't work since it only directly supports signed data types //If one uses std::abs and T is unsigned one will get an ambiguous override error. uint_32_t diff; - + if (val1 < val2){ diff = val2 - val1; }else{ @@ -195,7 +195,7 @@ namespace apl template <> bool ExceedsDeadband(const double& val1, const double& val2, double aDeadband); - + //Common subclass to analogs and counters template class TypedDataPoint : public DataPoint @@ -205,7 +205,7 @@ namespace apl T GetValue() const { return mValue; } void SetValue(T aValue) { mValue = aValue; } - bool ShouldGenerateEvent(const TypedDataPoint& arRHS, double aDeadband, T aLastReportedVal) const; + bool ShouldGenerateEvent(const TypedDataPoint& arRHS, double aDeadband, T aLastReportedVal) const; typedef T Type; @@ -213,17 +213,17 @@ namespace apl static const T MIN_VALUE; std::string ToString() const; - + bool operator==(const TypedDataPoint& rhs) { return GetValue() == rhs.GetValue() && GetQuality() == rhs.GetQuality(); } - + protected: // IntDataPoints have seperate fields for quality and value //IntDataPoint(const IntDataPoint& arRHS); TypedDataPoint(byte_t aQuality, DataTypes aType); T mValue; - private: + private: TypedDataPoint(); }; @@ -234,11 +234,11 @@ namespace apl const T TypedDataPoint::MIN_VALUE = MaxMinWrapper::Min(); template - TypedDataPoint::TypedDataPoint(byte_t aQuality, DataTypes aType) : - DataPoint(aQuality, aType), - mValue(0) + TypedDataPoint::TypedDataPoint(byte_t aQuality, DataTypes aType) : + DataPoint(aQuality, aType), + mValue(0) { - + } template @@ -246,7 +246,7 @@ namespace apl { if (mQuality != arRHS.mQuality) return true; - return ExceedsDeadband(arRHS.GetValue(), aLastReportedVal, aDeadband); + return ExceedsDeadband(arRHS.GetValue(), aLastReportedVal, aDeadband); } template @@ -255,7 +255,7 @@ namespace apl std::ostringstream oss; oss << "Value: " << GetValue() << " Quality: " << static_cast(GetQuality()); return oss.str(); - } + } #ifdef SWIG %template(DoublePoint) apl::TypedDataPoint; @@ -274,7 +274,7 @@ namespace apl class Binary : public BoolDataPoint { public: - Binary(bool aValue, byte_t aQuality = BQ_RESTART) : BoolDataPoint(BQ_RESTART, DT_BINARY, BQ_STATE) + Binary(bool aValue, byte_t aQuality = BQ_RESTART) : BoolDataPoint(BQ_RESTART, DT_BINARY, BQ_STATE) { SetValue(aValue); SetQuality(aQuality); @@ -285,7 +285,7 @@ namespace apl /// Describes the static data type of the measurement as an enum static const DataTypes MeasEnum = DT_BINARY; - + static const int ONLINE = BQ_ONLINE; operator ValueType() const { return this->GetValue(); } @@ -300,7 +300,7 @@ namespace apl class ControlStatus : public BoolDataPoint { public: - + ControlStatus(bool aValue, byte_t aQuality = TQ_RESTART) : BoolDataPoint(TQ_RESTART, DT_CONTROL_STATUS, TQ_STATE) { SetValue(aValue); @@ -328,14 +328,14 @@ namespace apl { public: Analog() : TypedDataPoint(AQ_RESTART, DT_ANALOG) {} - + Analog(double aVal, byte_t aQuality = AQ_RESTART) : TypedDataPoint(AQ_RESTART, DT_ANALOG) { SetValue(aVal); SetQuality(aQuality); } - + typedef double ValueType; static const DataTypes MeasEnum = DT_ANALOG; @@ -345,7 +345,7 @@ namespace apl operator ValueType() const { return this->GetValue(); } ValueType operator=(ValueType aValue) { this->SetValue(aValue); return GetValue(); } - + }; /** @@ -395,7 +395,7 @@ namespace apl operator ValueType() const { return this->GetValue(); } ValueType operator=(ValueType aValue) { this->SetValue(aValue); return GetValue(); } }; - + } #endif diff --git a/APL/EventLock.h b/APL/EventLock.h index 30a1d15a..490a98d2 100644 --- a/APL/EventLock.h +++ b/APL/EventLock.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __EVENT_LOCK_H_ #define __EVENT_LOCK_H_ @@ -32,7 +32,7 @@ namespace apl class EventLock : public EventLockBase { public: - EventLock(); + EventLock(); //needs to be used only when we are allready locked on the object int_64_t GetEvents(bool aClearSentEvents = true); diff --git a/APL/EventLockBase.h b/APL/EventLockBase.h index dd065e89..09e67140 100644 --- a/APL/EventLockBase.h +++ b/APL/EventLockBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,84 +6,84 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __EVENT_LOCK_BASE_H_ -#define __EVENT_LOCK_BASE_H_ - -#include - -#include "Notifier.h" -#include "Lock.h" -#include "IEventLock.h" - -namespace apl -{ - -/** Inherited classes are free to define how the event code/mask gets recorded and presented - to thread receiving the event alert. -*/ - -template -class EventLockBase : public IEventLock, public SigLock -{ - public: - - EventLockBase(); - virtual ~EventLockBase(); - - // Implement the IEventLock interface - void SignalEvent(const T& arEvent); - void BroadcastEvent(const T& arEvent); - - INotifier* GetNotifier(const T& arEvent); - - protected: - - // Inherited classes must implement the following - virtual void RecordEventCode(const T& arEvent) = 0; - - private: - std::vector< Notifier* > mNotifiers; -}; - -template -EventLockBase::EventLockBase() : -SigLock() -{} - -template -EventLockBase::~EventLockBase() -{ for(size_t i=0; i -void EventLockBase::SignalEvent(const T& arEvent) -{ CriticalSection cs(this); this->RecordEventCode(arEvent); SigLock::Signal(); } - -template -void EventLockBase::BroadcastEvent(const T& arEvent) -{ CriticalSection cs(this); this->RecordEventCode(arEvent); SigLock::Broadcast(); } - -template -INotifier* EventLockBase::GetNotifier(const T& arEvent) -{ - Notifier* pNotifier = new Notifier(arEvent, this); - mNotifiers.push_back(pNotifier); - return pNotifier; -} - - - - - -} - -#endif +// +#ifndef __EVENT_LOCK_BASE_H_ +#define __EVENT_LOCK_BASE_H_ + +#include + +#include "Notifier.h" +#include "Lock.h" +#include "IEventLock.h" + +namespace apl +{ + +/** Inherited classes are free to define how the event code/mask gets recorded and presented + to thread receiving the event alert. +*/ + +template +class EventLockBase : public IEventLock, public SigLock +{ + public: + + EventLockBase(); + virtual ~EventLockBase(); + + // Implement the IEventLock interface + void SignalEvent(const T& arEvent); + void BroadcastEvent(const T& arEvent); + + INotifier* GetNotifier(const T& arEvent); + + protected: + + // Inherited classes must implement the following + virtual void RecordEventCode(const T& arEvent) = 0; + + private: + std::vector< Notifier* > mNotifiers; +}; + +template +EventLockBase::EventLockBase() : +SigLock() +{} + +template +EventLockBase::~EventLockBase() +{ for(size_t i=0; i +void EventLockBase::SignalEvent(const T& arEvent) +{ CriticalSection cs(this); this->RecordEventCode(arEvent); SigLock::Signal(); } + +template +void EventLockBase::BroadcastEvent(const T& arEvent) +{ CriticalSection cs(this); this->RecordEventCode(arEvent); SigLock::Broadcast(); } + +template +INotifier* EventLockBase::GetNotifier(const T& arEvent) +{ + Notifier* pNotifier = new Notifier(arEvent, this); + mNotifiers.push_back(pNotifier); + return pNotifier; +} + + + + + +} + +#endif diff --git a/APL/EventSet.h b/APL/EventSet.h index 15251b31..3c4e13b0 100644 --- a/APL/EventSet.h +++ b/APL/EventSet.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __EVENT_SET_H_ #define __EVENT_SET_H_ @@ -29,7 +29,7 @@ namespace apl class EventSet { public: - + EventSet(apl::int_64_t aEventFlags) { const int_64_t ONE = static_cast(1); @@ -39,9 +39,9 @@ namespace apl if( (aEventFlags & (ONE << i)) != 0) mEvents.push(i); } } - + inline bool HasEvents(){ return mEvents.size() != 0; } - + inline size_t GetNextEvent() { assert(HasEvents()); @@ -50,11 +50,11 @@ namespace apl mEvents.pop(); return ret; } - + private: std::queue mEvents; - + }; } diff --git a/APL/Exception.h b/APL/Exception.h index 4e1b09c4..99a88454 100644 --- a/APL/Exception.h +++ b/APL/Exception.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __EXCEPTION_H_ #define __EXCEPTION_H_ @@ -64,7 +64,7 @@ namespace apl { class ObjectException : public Exception { public: - ObjectException(const std::string& aSource, const std::string& aMessage) throw() : + ObjectException(const std::string& aSource, const std::string& aMessage) throw() : Exception(aSource, aMessage) {} }; @@ -72,7 +72,7 @@ namespace apl { class ReadTimeoutException : public Exception { public: - ReadTimeoutException(const std::string& aSource, const std::string& aMessage) throw() : + ReadTimeoutException(const std::string& aSource, const std::string& aMessage) throw() : Exception(aSource, aMessage) {} }; @@ -80,7 +80,7 @@ namespace apl { class InvalidStateException : public Exception { public: - InvalidStateException(const std::string& aSource, const std::string& aState) throw() : + InvalidStateException(const std::string& aSource, const std::string& aState) throw() : Exception(aSource, "Invalid operation for state: " + aState) {} }; @@ -88,7 +88,7 @@ namespace apl { class ArgumentException : public Exception { public: - ArgumentException(const std::string& aSource, const std::string& aMessage = "") throw() : + ArgumentException(const std::string& aSource, const std::string& aMessage = "") throw() : Exception(aSource, aMessage) {} }; @@ -96,7 +96,7 @@ namespace apl { class NotImplementedException : public Exception { public: - NotImplementedException(const std::string& aSource) throw() : + NotImplementedException(const std::string& aSource) throw() : Exception(aSource, "Function not implemented.") {} }; @@ -104,7 +104,7 @@ namespace apl { class IndexOutOfBoundsException : public Exception { public: - IndexOutOfBoundsException(const std::string& aSource) throw() : + IndexOutOfBoundsException(const std::string& aSource) throw() : Exception(aSource, "Index out of bounds.") {} }; diff --git a/APL/FlexibleDataObserver.cpp b/APL/FlexibleDataObserver.cpp index 37ddff6c..92f0384b 100644 --- a/APL/FlexibleDataObserver.cpp +++ b/APL/FlexibleDataObserver.cpp @@ -16,90 +16,90 @@ // specific language governing permissions and limitations // under the License. // -#include "FlexibleDataObserver.h" -#include "TimingTools.h" - -namespace apl -{ - FlexibleDataObserver::FlexibleDataObserver() : - mCommsLostCount(0), - mLastCommsLostCheck(0), - mNewData(false) - {} - - void FlexibleDataObserver::Clear() - { - Transaction t(this); - mBinaryMap.clear(); - mAnalogMap.clear(); - mCounterMap.clear(); - mControlStatusMap.clear(); - mSetpointStatusMap.clear(); - } - - /// The RHS is a strict subset of the LHS... i.e. everything in the RHS can be found in the LHS - bool FlexibleDataObserver::StrictEquality(const FlexibleDataObserver& arLHS, const FlexibleDataObserver& arRHS) - { - if(! StrictEquality(arLHS.mBinaryMap, arRHS.mBinaryMap) ) return false; - if(! StrictEquality(arLHS.mAnalogMap, arRHS.mAnalogMap) ) return false; - if(! StrictEquality(arLHS.mCounterMap, arRHS.mCounterMap) ) return false; - if(! StrictEquality(arLHS.mControlStatusMap, arRHS.mControlStatusMap) ) return false; - if(! StrictEquality(arLHS.mSetpointStatusMap, arRHS.mSetpointStatusMap) ) return false; - - return true; - } - - /// The RHS is a strict subset of the LHS... i.e. everything in the RHS can be found in the LHS - bool FlexibleDataObserver::IsSubsetOf(const FlexibleDataObserver& arLHS, const FlexibleDataObserver& arRHS) - { - if(! IsSubsetOf(arLHS.mBinaryMap, arRHS.mBinaryMap) ) return false; - if(! IsSubsetOf(arLHS.mAnalogMap, arRHS.mAnalogMap) ) return false; - if(! IsSubsetOf(arLHS.mCounterMap, arRHS.mCounterMap) ) return false; - if(! IsSubsetOf(arLHS.mControlStatusMap, arRHS.mControlStatusMap) ) return false; - if(! IsSubsetOf(arLHS.mSetpointStatusMap, arRHS.mSetpointStatusMap) ) return false; - - return true; - } - - void FlexibleDataObserver::Print() - { - Transaction tr(this); - - std::cout << "--- Binary ---" << std::endl; - this->Print(mBinaryMap); - - std::cout << "--- Analog ---" << std::endl; - this->Print(mAnalogMap); - - std::cout << "--- Counter ---" << std::endl; - this->Print(mCounterMap); - - std::cout << "--- Control Status ---" << std::endl; - this->Print(mControlStatusMap); - - std::cout << "--- Setpoint Status ---" << std::endl; - this->Print(mSetpointStatusMap); - } - - template - bool FlexibleDataObserver::StrictEquality(const T& arMap1, const T& arMap2) - { - if(arMap1.size() != arMap2.size()) return false; - return IsSubsetOf(arMap1, arMap2); - } - - template - bool FlexibleDataObserver::IsSubsetOf(const T& arMap1, const T& arMap2) - { - for(typename T::const_iterator i = arMap1.begin(); i != arMap1.end(); ++i) - { - typename T::const_iterator j = arMap2.find(i->first); - if(j == arMap2.end()) return false; - if(j->second != i->second) return false; - } - - return true; - } - -} - +#include "FlexibleDataObserver.h" +#include "TimingTools.h" + +namespace apl +{ + FlexibleDataObserver::FlexibleDataObserver() : + mCommsLostCount(0), + mLastCommsLostCheck(0), + mNewData(false) + {} + + void FlexibleDataObserver::Clear() + { + Transaction t(this); + mBinaryMap.clear(); + mAnalogMap.clear(); + mCounterMap.clear(); + mControlStatusMap.clear(); + mSetpointStatusMap.clear(); + } + + /// The RHS is a strict subset of the LHS... i.e. everything in the RHS can be found in the LHS + bool FlexibleDataObserver::StrictEquality(const FlexibleDataObserver& arLHS, const FlexibleDataObserver& arRHS) + { + if(! StrictEquality(arLHS.mBinaryMap, arRHS.mBinaryMap) ) return false; + if(! StrictEquality(arLHS.mAnalogMap, arRHS.mAnalogMap) ) return false; + if(! StrictEquality(arLHS.mCounterMap, arRHS.mCounterMap) ) return false; + if(! StrictEquality(arLHS.mControlStatusMap, arRHS.mControlStatusMap) ) return false; + if(! StrictEquality(arLHS.mSetpointStatusMap, arRHS.mSetpointStatusMap) ) return false; + + return true; + } + + /// The RHS is a strict subset of the LHS... i.e. everything in the RHS can be found in the LHS + bool FlexibleDataObserver::IsSubsetOf(const FlexibleDataObserver& arLHS, const FlexibleDataObserver& arRHS) + { + if(! IsSubsetOf(arLHS.mBinaryMap, arRHS.mBinaryMap) ) return false; + if(! IsSubsetOf(arLHS.mAnalogMap, arRHS.mAnalogMap) ) return false; + if(! IsSubsetOf(arLHS.mCounterMap, arRHS.mCounterMap) ) return false; + if(! IsSubsetOf(arLHS.mControlStatusMap, arRHS.mControlStatusMap) ) return false; + if(! IsSubsetOf(arLHS.mSetpointStatusMap, arRHS.mSetpointStatusMap) ) return false; + + return true; + } + + void FlexibleDataObserver::Print() + { + Transaction tr(this); + + std::cout << "--- Binary ---" << std::endl; + this->Print(mBinaryMap); + + std::cout << "--- Analog ---" << std::endl; + this->Print(mAnalogMap); + + std::cout << "--- Counter ---" << std::endl; + this->Print(mCounterMap); + + std::cout << "--- Control Status ---" << std::endl; + this->Print(mControlStatusMap); + + std::cout << "--- Setpoint Status ---" << std::endl; + this->Print(mSetpointStatusMap); + } + + template + bool FlexibleDataObserver::StrictEquality(const T& arMap1, const T& arMap2) + { + if(arMap1.size() != arMap2.size()) return false; + return IsSubsetOf(arMap1, arMap2); + } + + template + bool FlexibleDataObserver::IsSubsetOf(const T& arMap1, const T& arMap2) + { + for(typename T::const_iterator i = arMap1.begin(); i != arMap1.end(); ++i) + { + typename T::const_iterator j = arMap2.find(i->first); + if(j == arMap2.end()) return false; + if(j->second != i->second) return false; + } + + return true; + } + +} + diff --git a/APL/FlexibleDataObserver.h b/APL/FlexibleDataObserver.h index 19d5f417..8df21958 100644 --- a/APL/FlexibleDataObserver.h +++ b/APL/FlexibleDataObserver.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __FLEXIBLE_DATA_OBSERVER_H_ #define __FLEXIBLE_DATA_OBSERVER_H_ @@ -44,7 +44,7 @@ namespace apl template struct PointMap { typedef std::map Type; }; - + // allow direct access to the maps PointMap::Type mBinaryMap; PointMap::Type mAnalogMap; @@ -52,8 +52,8 @@ namespace apl PointMap::Type mControlStatusMap; PointMap::Type mSetpointStatusMap; - bool Check(bool aValue, BinaryQuality aQuality, size_t aIndex) - { + bool Check(bool aValue, BinaryQuality aQuality, size_t aIndex) + { byte_t qual = aQuality; if(aValue) qual |= BQ_STATE; return Check(mBinaryMap, aValue, qual, aIndex); @@ -66,23 +66,23 @@ namespace apl PointMap::Type::iterator i = mAnalogMap.find(aIndex); if(i == mAnalogMap.end()) return false; if(i->second.GetQuality() != aQuality) return false; - return apl::FloatEqual(aValue, i->second.GetValue()); + return apl::FloatEqual(aValue, i->second.GetValue()); } bool Check(uint_32_t aValue, CounterQuality aQuality, size_t aIndex) { return Check(mCounterMap, aValue, aQuality, aIndex); } bool Check(bool aValue, ControlQuality aQuality, size_t aIndex) - { + { byte_t qual = aQuality; if(aValue) qual |= TQ_STATE; - return Check(mControlStatusMap, aValue, qual, aIndex); + return Check(mControlStatusMap, aValue, qual, aIndex); } bool Check(int_32_t aValue, SetpointQuality aQuality, size_t aIndex) { return Check(mSetpointStatusMap, aValue, aQuality, aIndex); } - bool Check(bool aValue, BinaryQuality aQuality, size_t aIndex, TimeStamp_t aTime) - { + bool Check(bool aValue, BinaryQuality aQuality, size_t aIndex, TimeStamp_t aTime) + { byte_t qual = aQuality; if(aValue) qual |= BQ_STATE; return Check(mBinaryMap, aValue, qual, aTime, aIndex); @@ -92,10 +92,10 @@ namespace apl bool Check(uint_32_t aValue, CounterQuality aQuality, size_t aIndex, TimeStamp_t aTime) { return Check(mCounterMap, aValue, aQuality, aTime, aIndex); } bool Check(bool aValue, ControlQuality aQuality, size_t aIndex, TimeStamp_t aTime) - { + { byte_t qual = aQuality; if(aValue) qual |= TQ_STATE; - return Check(mControlStatusMap, aValue, qual, aTime, aIndex); + return Check(mControlStatusMap, aValue, qual, aTime, aIndex); } bool Check(int_32_t aValue, SetpointQuality aQuality, size_t aIndex, TimeStamp_t aTime) { return Check(mSetpointStatusMap, aValue, aQuality, aTime, aIndex); } @@ -126,12 +126,12 @@ namespace apl SigLock mLock; void _Start() { mLock.Lock(); } - void _End() + void _End() { bool notify = mNewData; mNewData = false; - mLock.Unlock(); - if(notify) this->NotifyAll(); + mLock.Unlock(); + if(notify) this->NotifyAll(); } void _Update(const Binary& arPoint, size_t aIndex) { Load(arPoint, mBinaryMap, aIndex); } @@ -139,8 +139,8 @@ namespace apl void _Update(const Counter& arPoint, size_t aIndex) { Load(arPoint, mCounterMap, aIndex); } void _Update(const ControlStatus& arPoint, size_t aIndex) { Load(arPoint, mControlStatusMap, aIndex); } void _Update(const SetpointStatus& arPoint, size_t aIndex) { Load(arPoint, mSetpointStatusMap, aIndex); } - - + + template bool Check(typename PointMap::Type& arMap, U aValue, byte_t aQual, size_t aIndex); @@ -214,7 +214,7 @@ namespace apl { std::cout << j << ", " << i->second.GetValue() << ", " << static_cast(i->second.GetQuality()) << std::endl; ++j; } } - + } diff --git a/APL/IEventLock.h b/APL/IEventLock.h index a31ac0d1..7e19d277 100644 --- a/APL/IEventLock.h +++ b/APL/IEventLock.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,30 +6,30 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_EVENT_LOCK_H_ -#define __I_EVENT_LOCK_H_ - -namespace apl -{ - template - class IEventLock - { - public: - virtual ~IEventLock(){} - - virtual void SignalEvent(const T& arEvent) = 0; - virtual void BroadcastEvent(const T& arEvent) = 0; - }; -} - -#endif +// +#ifndef __I_EVENT_LOCK_H_ +#define __I_EVENT_LOCK_H_ + +namespace apl +{ + template + class IEventLock + { + public: + virtual ~IEventLock(){} + + virtual void SignalEvent(const T& arEvent) = 0; + virtual void BroadcastEvent(const T& arEvent) = 0; + }; +} + +#endif diff --git a/APL/IHandlerAsync.cpp b/APL/IHandlerAsync.cpp index fb007892..69269ebd 100644 --- a/APL/IHandlerAsync.cpp +++ b/APL/IHandlerAsync.cpp @@ -16,18 +16,18 @@ // specific language governing permissions and limitations // under the License. // -#include "IHandlerAsync.h" - -namespace apl { - -IHandlerAsync::IHandlerAsync(Logger* apLogger) : -Loggable(apLogger), -IUpperLayer(apLogger) -{ - -} - -/// For consistency sake, use NVII pattern in case we want pre/post conditions in the future -void IHandlerAsync::OnOpenFailure() { this->_OnOpenFailure(); } - -} +#include "IHandlerAsync.h" + +namespace apl { + +IHandlerAsync::IHandlerAsync(Logger* apLogger) : +Loggable(apLogger), +IUpperLayer(apLogger) +{ + +} + +/// For consistency sake, use NVII pattern in case we want pre/post conditions in the future +void IHandlerAsync::OnOpenFailure() { this->_OnOpenFailure(); } + +} diff --git a/APL/IHandlerAsync.h b/APL/IHandlerAsync.h index 081ff946..ef0a2b60 100644 --- a/APL/IHandlerAsync.h +++ b/APL/IHandlerAsync.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,39 +6,39 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_HANDLER_ASYNC_H_ -#define __I_HANDLER_ASYNC_H_ - -#include "AsyncLayerInterfaces.h" - -namespace apl { - -class IHandlerAsync : public IUpperLayer -{ - public: - IHandlerAsync(Logger*); - virtual ~IHandlerAsync() {} - - /// In addition to all of the IUpperLayer functions, provide a mechanism to receive open failures - /// For consistency sake, use NVII pattern in case we want pre/post conditions in the future - void OnOpenFailure(); - - private: - - /// called when the layer didn't make a connection and has given up trying, safe to delete. - virtual void _OnOpenFailure() = 0; -}; - -} - -#endif +// +#ifndef __I_HANDLER_ASYNC_H_ +#define __I_HANDLER_ASYNC_H_ + +#include "AsyncLayerInterfaces.h" + +namespace apl { + +class IHandlerAsync : public IUpperLayer +{ + public: + IHandlerAsync(Logger*); + virtual ~IHandlerAsync() {} + + /// In addition to all of the IUpperLayer functions, provide a mechanism to receive open failures + /// For consistency sake, use NVII pattern in case we want pre/post conditions in the future + void OnOpenFailure(); + + private: + + /// called when the layer didn't make a connection and has given up trying, safe to delete. + virtual void _OnOpenFailure() = 0; +}; + +} + +#endif diff --git a/APL/INotifier.h b/APL/INotifier.h index 98011fa7..01096acb 100644 --- a/APL/INotifier.h +++ b/APL/INotifier.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __I_NOTIFIER_H_ #define __I_NOTIFIER_H_ @@ -23,18 +23,18 @@ namespace apl { /** A generic interface that defines a notification function. Modeled loosly on a lock - type interaction. Generally used for the multi-threaded observer pattern to indicate + type interaction. Generally used for the multi-threaded observer pattern to indicate that a shared _thread_safe_ object has had a change occur. The application then knows that it needs to look at that shared object which it can do immediatley or at some point - in the future (ie. when the "application" thread is ready). - + in the future (ie. when the "application" thread is ready). + It is critical to remember that the calls to Notify() can potentially come from any thread! */ class INotifier { public: virtual ~INotifier(){} - virtual void Notify() = 0; + virtual void Notify() = 0; }; } diff --git a/APL/IOService.cpp b/APL/IOService.cpp index 00f4ff3e..530795c4 100644 --- a/APL/IOService.cpp +++ b/APL/IOService.cpp @@ -16,19 +16,19 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" -#include "IOService.h" - -namespace apl { - -IOService::IOService() : mpService(new boost::asio::io_service()) -{ - -} - -IOService::~IOService() -{ - -} - -} +#include "ASIOIncludes.h" +#include "IOService.h" + +namespace apl { + +IOService::IOService() : mpService(new boost::asio::io_service()) +{ + +} + +IOService::~IOService() +{ + +} + +} diff --git a/APL/IOService.h b/APL/IOService.h index 9f1140cb..8cae4d3c 100644 --- a/APL/IOService.h +++ b/APL/IOService.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,39 +6,39 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __IO_SERVICE_H_ -#define __IO_SERVICE_H_ - -#include - -namespace boost { namespace asio { - class io_service; -}} - - -namespace apl { - -class IOService { - - public: - IOService(); - ~IOService(); - boost::asio::io_service* Get() { return mpService.get(); } - - private: - std::auto_ptr mpService; -}; - -} - -#endif +// +#ifndef __IO_SERVICE_H_ +#define __IO_SERVICE_H_ + +#include + +namespace boost { namespace asio { + class io_service; +}} + + +namespace apl { + +class IOService { + + public: + IOService(); + ~IOService(); + boost::asio::io_service* Get() { return mpService.get(); } + + private: + std::auto_ptr mpService; +}; + +} + +#endif diff --git a/APL/IOServiceThread.cpp b/APL/IOServiceThread.cpp index c32bd63f..25ec09f1 100644 --- a/APL/IOServiceThread.cpp +++ b/APL/IOServiceThread.cpp @@ -16,63 +16,63 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" -#include "IOServiceThread.h" - -#include "Exception.h" -#include "Logger.h" - -#include - -using namespace boost::asio; - -namespace apl { - -class IOServiceExitException : public Exception -{ - public: - IOServiceExitException(const std::string& aSource) throw() : - Exception(aSource, "") - {} -}; - -IOServiceThread::IOServiceThread(boost::asio::io_service* apService) : -mpService(apService), -mThread(this) -{ - -} - -void IOServiceThread::Stop() -{ - mThread.RequestStop(); - mThread.WaitForStop(); -} - -void IOServiceThread::Throw() -{ - throw IOServiceExitException(LOCATION); -} - -void IOServiceThread::Run() -{ - size_t num = 0; - - try { - num = mpService->run(); - } - catch(IOServiceExitException&) { - //clean exit - } - catch(const std::exception& ex) { - std::cout << ex.what() << std::endl; - } - -} - -void IOServiceThread::SignalStop() -{ - mpService->post(boost::bind(&IOServiceThread::Throw, this)); -} - -} +#include "ASIOIncludes.h" +#include "IOServiceThread.h" + +#include "Exception.h" +#include "Logger.h" + +#include + +using namespace boost::asio; + +namespace apl { + +class IOServiceExitException : public Exception +{ + public: + IOServiceExitException(const std::string& aSource) throw() : + Exception(aSource, "") + {} +}; + +IOServiceThread::IOServiceThread(boost::asio::io_service* apService) : +mpService(apService), +mThread(this) +{ + +} + +void IOServiceThread::Stop() +{ + mThread.RequestStop(); + mThread.WaitForStop(); +} + +void IOServiceThread::Throw() +{ + throw IOServiceExitException(LOCATION); +} + +void IOServiceThread::Run() +{ + size_t num = 0; + + try { + num = mpService->run(); + } + catch(IOServiceExitException&) { + //clean exit + } + catch(const std::exception& ex) { + std::cout << ex.what() << std::endl; + } + +} + +void IOServiceThread::SignalStop() +{ + mpService->post(boost::bind(&IOServiceThread::Throw, this)); +} + +} diff --git a/APL/IOServiceThread.h b/APL/IOServiceThread.h index 31133ce5..8061d57d 100644 --- a/APL/IOServiceThread.h +++ b/APL/IOServiceThread.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,54 +6,54 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __IO_SERVICE_THREAD_H_ -#define __IO_SERVICE_THREAD_H_ - -#include "Thread.h" -#include "TimerSourceASIO.h" - -namespace boost { namespace asio { - class io_service; -}} - -namespace apl { - -class Logger; -class Timer; - -class IOServiceThread : public Threadable -{ - public: - IOServiceThread(boost::asio::io_service* apService); - - void Start() { mThread.Start(); } - void Stop(); - - boost::asio::io_service* GetService() { return mpService; } - - void Run(); - void SignalStop(); - - protected: - - boost::asio::io_service* mpService; - void Throw(); //need something to bind the hold timer to - - private: - - Thread mThread; -}; - -} - -#endif +// +#ifndef __IO_SERVICE_THREAD_H_ +#define __IO_SERVICE_THREAD_H_ + +#include "Thread.h" +#include "TimerSourceASIO.h" + +namespace boost { namespace asio { + class io_service; +}} + +namespace apl { + +class Logger; +class Timer; + +class IOServiceThread : public Threadable +{ + public: + IOServiceThread(boost::asio::io_service* apService); + + void Start() { mThread.Start(); } + void Stop(); + + boost::asio::io_service* GetService() { return mpService; } + + void Run(); + void SignalStop(); + + protected: + + boost::asio::io_service* mpService; + void Throw(); //need something to bind the hold timer to + + private: + + Thread mThread; +}; + +} + +#endif diff --git a/APL/IPhysMonitor.h b/APL/IPhysMonitor.h index 9c2bbf70..9b20aac2 100644 --- a/APL/IPhysMonitor.h +++ b/APL/IPhysMonitor.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,40 +6,40 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_PHYS_MONITOR_H_ -#define __I_PHYS_MONITOR_H_ - -namespace apl { - -class IPhysMonitor -{ - public: - - enum State - { - Closed, // layer is offline and idle - Opening, // layer is trying to open - Waiting, - Open, // layer is open - Stopped // stopped and will no longer dispatch events - }; - - virtual ~IPhysMonitor(){} - - virtual void OnStateChange(State) = 0; - -}; - -} - -#endif +// +#ifndef __I_PHYS_MONITOR_H_ +#define __I_PHYS_MONITOR_H_ + +namespace apl { + +class IPhysMonitor +{ + public: + + enum State + { + Closed, // layer is offline and idle + Opening, // layer is trying to open + Waiting, + Open, // layer is open + Stopped // stopped and will no longer dispatch events + }; + + virtual ~IPhysMonitor(){} + + virtual void OnStateChange(State) = 0; + +}; + +} + +#endif diff --git a/APL/IPhysicalLayerAsync.h b/APL/IPhysicalLayerAsync.h index 9ace3e3f..1f792979 100644 --- a/APL/IPhysicalLayerAsync.h +++ b/APL/IPhysicalLayerAsync.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _I_PHYSICAL_LAYER_ASYNC_H_ #define _I_PHYSICAL_LAYER_ASYNC_H_ @@ -32,7 +32,7 @@ namespace apl{ { public: virtual ~IPhysicalLayerAsync() {} - + /** @return True if the layer is performing an async read */ virtual bool IsReading() = 0; /** @return True if the layer is performing an async write */ diff --git a/APL/IPhysicalLayerSource.h b/APL/IPhysicalLayerSource.h index 6956c69f..35bf0ab7 100644 --- a/APL/IPhysicalLayerSource.h +++ b/APL/IPhysicalLayerSource.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __I_PHYSICAL_LAYER_SOURCE_H_ #define __I_PHYSICAL_LAYER_SOURCE_H_ @@ -32,11 +32,11 @@ namespace boost { namespace asio { class io_service; }} -namespace apl +namespace apl { class Logger; - class IPhysicalLayerAsync; - + class IPhysicalLayerAsync; + struct PhysLayerSettings; class IPhysicalLayerSource @@ -45,7 +45,7 @@ namespace apl virtual ~IPhysicalLayerSource(){} virtual PhysLayerSettings GetSettings(const std::string& arName) = 0; - virtual IPhysicalLayerAsync* GetLayer(const std::string& arName, boost::asio::io_service*) = 0; + virtual IPhysicalLayerAsync* GetLayer(const std::string& arName, boost::asio::io_service*) = 0; }; diff --git a/APL/ISubject.h b/APL/ISubject.h index 2e679da4..953ac4d0 100644 --- a/APL/ISubject.h +++ b/APL/ISubject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,32 +6,32 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_SUBJECT_H_ -#define __I_SUBJECT_H_ - -namespace apl -{ - class INotifier; - - class ISubject - { - public: - virtual ~ISubject(){} - - virtual void AddObserver(INotifier* apNotifier) = 0; - virtual void RemoveObserver(INotifier* apNotifer) = 0; - }; -} - -#endif - +// +#ifndef __I_SUBJECT_H_ +#define __I_SUBJECT_H_ + +namespace apl +{ + class INotifier; + + class ISubject + { + public: + virtual ~ISubject(){} + + virtual void AddObserver(INotifier* apNotifier) = 0; + virtual void RemoveObserver(INotifier* apNotifer) = 0; + }; +} + +#endif + diff --git a/APL/ITimeSource.h b/APL/ITimeSource.h index 6fec1fb1..5582a8dd 100644 --- a/APL/ITimeSource.h +++ b/APL/ITimeSource.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,42 +6,42 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_TIME_SOURCE_H_ -#define __I_TIME_SOURCE_H_ - -#include "Types.h" - -namespace boost { namespace posix_time { - - class ptime; - -}} - -namespace apl -{ - class ITimeManager - { - public: - virtual millis_t GetTime() = 0; - virtual void SetTime(millis_t aTime) = 0; - }; - class ITimeSource - { - public: - virtual boost::posix_time::ptime GetUTC() = 0; - virtual TimeStamp_t GetTimeStampUTC() = 0; - }; -} - -#endif - +// +#ifndef __I_TIME_SOURCE_H_ +#define __I_TIME_SOURCE_H_ + +#include "Types.h" + +namespace boost { namespace posix_time { + + class ptime; + +}} + +namespace apl +{ + class ITimeManager + { + public: + virtual millis_t GetTime() = 0; + virtual void SetTime(millis_t aTime) = 0; + }; + class ITimeSource + { + public: + virtual boost::posix_time::ptime GetUTC() = 0; + virtual TimeStamp_t GetTimeStampUTC() = 0; + }; +} + +#endif + diff --git a/APL/Lock.h b/APL/Lock.h index e990d369..6f5cfbae 100644 --- a/APL/Lock.h +++ b/APL/Lock.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOCK_H_ #define __LOCK_H_ diff --git a/APL/LockBase.cpp b/APL/LockBase.cpp index e85e5628..3530ad2a 100644 --- a/APL/LockBase.cpp +++ b/APL/LockBase.cpp @@ -16,20 +16,20 @@ // specific language governing permissions and limitations // under the License. // -#include "LockBase.h" - -namespace apl -{ - - CriticalSection::CriticalSection(ILockBase* apLock) : mIsLocked(true), mpLock(apLock) - { - mpLock->Lock(); - } - - CriticalSection::~CriticalSection() - { - if(mIsLocked) mpLock->Unlock(); - } - -} - +#include "LockBase.h" + +namespace apl +{ + + CriticalSection::CriticalSection(ILockBase* apLock) : mIsLocked(true), mpLock(apLock) + { + mpLock->Lock(); + } + + CriticalSection::~CriticalSection() + { + if(mIsLocked) mpLock->Unlock(); + } + +} + diff --git a/APL/LockBase.h b/APL/LockBase.h index 44f92221..71bd99c5 100644 --- a/APL/LockBase.h +++ b/APL/LockBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __I_LOCK_BASE_H_ #define __I_LOCK_BASE_H_ diff --git a/APL/LockBoost.h b/APL/LockBoost.h index 95f62f0b..8d4b358d 100644 --- a/APL/LockBoost.h +++ b/APL/LockBoost.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _LOCK_BOOST_H_ @@ -61,7 +61,7 @@ namespace apl{ void Broadcast(); private: - + int mLockCount; boost::condition_variable_any mCondition; boost::shared_mutex mMutex; diff --git a/APL/Log.cpp b/APL/Log.cpp index 61319497..3e758815 100644 --- a/APL/Log.cpp +++ b/APL/Log.cpp @@ -16,91 +16,91 @@ // specific language governing permissions and limitations // under the License. // - -#include -#include -#include -#include "Log.h" -#include "Thread.h" -#include "Exception.h" - -using namespace std; - -namespace apl -{ - - EventLog::~EventLog() - { - for(LoggerMap::iterator i = mLogMap.begin(); i != mLogMap.end(); i++) { - delete (i->second); - } - } - - void EventLog::Log( FilterLevel aFilterLevel, const std::string& aDeviceName, const std::string& aLocation, const std::string& aMessage, int aErrorCode) - { - std::set::iterator i = mSubscribers.begin(); - for(; i != mSubscribers.end(); ++i){ - (*i)->Log(aFilterLevel, aDeviceName, aLocation, aMessage, aErrorCode); - } - } - - void EventLog::SetVar(const std::string& aSource, const std::string& aVarName, int aValue) - { - std::set::iterator i = mSubscribers.begin(); - for(; i != mSubscribers.end(); ++i){ - (*i)->SetVar(aSource, aVarName, aValue); - } - } - - - Logger* EventLog::GetLogger(FilterLevel aFilter, const std::string& arName) - { - Logger* pLogger = GetExistingLogger(arName); - - if(pLogger != NULL) return pLogger; - - { - CriticalSection cs(&mLock); - assert(mLogMap.find(arName) == mLogMap.end()); - - pLogger = new Logger(this, aFilter, arName); - mLogMap[arName] = pLogger; - } - - return pLogger; - } - - Logger* EventLog::GetExistingLogger( const std::string& arLoggerName ) - { - CriticalSection cs(&mLock); - Logger* pLogger = NULL; - LoggerMap::iterator i = mLogMap.find(arLoggerName); - if(i != mLogMap.end()) pLogger = i->second; - return pLogger; - } - - void EventLog::GetAllLoggers( std::vector& apLoggers) - { - apLoggers.empty(); - CriticalSection cs(&mLock); - for(LoggerMap::iterator i = mLogMap.begin(); i != mLogMap.end(); i++) - { - apLoggers.push_back(i->second); - } - } - - void EventLog :: AddLogSubscriber(ILogBase* apBase) - { - mSubscribers.insert(apBase); - } - - void EventLog :: RemoveLogSubscriber(ILogBase* apBase) - { - std::set::iterator i = mSubscribers.find(apBase); - if(i != mSubscribers.end()) mSubscribers.erase(i); - } - -} - - - + +#include +#include +#include +#include "Log.h" +#include "Thread.h" +#include "Exception.h" + +using namespace std; + +namespace apl +{ + + EventLog::~EventLog() + { + for(LoggerMap::iterator i = mLogMap.begin(); i != mLogMap.end(); i++) { + delete (i->second); + } + } + + void EventLog::Log( FilterLevel aFilterLevel, const std::string& aDeviceName, const std::string& aLocation, const std::string& aMessage, int aErrorCode) + { + std::set::iterator i = mSubscribers.begin(); + for(; i != mSubscribers.end(); ++i){ + (*i)->Log(aFilterLevel, aDeviceName, aLocation, aMessage, aErrorCode); + } + } + + void EventLog::SetVar(const std::string& aSource, const std::string& aVarName, int aValue) + { + std::set::iterator i = mSubscribers.begin(); + for(; i != mSubscribers.end(); ++i){ + (*i)->SetVar(aSource, aVarName, aValue); + } + } + + + Logger* EventLog::GetLogger(FilterLevel aFilter, const std::string& arName) + { + Logger* pLogger = GetExistingLogger(arName); + + if(pLogger != NULL) return pLogger; + + { + CriticalSection cs(&mLock); + assert(mLogMap.find(arName) == mLogMap.end()); + + pLogger = new Logger(this, aFilter, arName); + mLogMap[arName] = pLogger; + } + + return pLogger; + } + + Logger* EventLog::GetExistingLogger( const std::string& arLoggerName ) + { + CriticalSection cs(&mLock); + Logger* pLogger = NULL; + LoggerMap::iterator i = mLogMap.find(arLoggerName); + if(i != mLogMap.end()) pLogger = i->second; + return pLogger; + } + + void EventLog::GetAllLoggers( std::vector& apLoggers) + { + apLoggers.empty(); + CriticalSection cs(&mLock); + for(LoggerMap::iterator i = mLogMap.begin(); i != mLogMap.end(); i++) + { + apLoggers.push_back(i->second); + } + } + + void EventLog :: AddLogSubscriber(ILogBase* apBase) + { + mSubscribers.insert(apBase); + } + + void EventLog :: RemoveLogSubscriber(ILogBase* apBase) + { + std::set::iterator i = mSubscribers.find(apBase); + if(i != mSubscribers.end()) mSubscribers.erase(i); + } + +} + + + diff --git a/APL/Log.h b/APL/Log.h index efaaa021..4eb3d5d5 100644 --- a/APL/Log.h +++ b/APL/Log.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __EVENT_LOG_H_ #define __EVENT_LOG_H_ @@ -53,18 +53,18 @@ namespace apl //implement the log function from ILogBase void Log( FilterLevel aFilterLevel, const std::string& aDeviceName, const std::string& aLocation, const std::string& aMessage, int aErrorCode); void SetVar(const std::string& aSource, const std::string& aVarName, int aValue); - + private: SigLock mLock; - + //holds pointers to the loggers that have been distributed typedef std::map LoggerMap; LoggerMap mLogMap; std::set mSubscribers; - + }; - - + + } #endif diff --git a/APL/LogBase.h b/APL/LogBase.h index 528bb97e..93aa8f71 100644 --- a/APL/LogBase.h +++ b/APL/LogBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOG_BASE_H_ #define __LOG_BASE_H_ @@ -28,10 +28,10 @@ namespace apl { public: virtual ~ILogBase(){} - + /// logging error messages, etc virtual void Log( FilterLevel aFilter, const std::string& aDevice, const std::string& aLocation, const std::string& aMessage, int aErrorCode) {} - + /// updating a variable/metric in the system virtual void SetVar(const std::string& aSource, const std::string& aVarName, int aValue) {} }; diff --git a/APL/LogEntry.h b/APL/LogEntry.h index d8f8d822..1e60f173 100644 --- a/APL/LogEntry.h +++ b/APL/LogEntry.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOG_ENTRY_H_ #define __LOG_ENTRY_H_ @@ -24,7 +24,7 @@ namespace apl { - + std::string GetFilterString( FilterLevel aLevel ); std::string GetLevelCode(int aLevel); @@ -61,7 +61,7 @@ namespace apl int mErrorCode; }; - + } diff --git a/APL/LogEntryCircularBuffer.cpp b/APL/LogEntryCircularBuffer.cpp index 29fb3ea5..359997b2 100644 --- a/APL/LogEntryCircularBuffer.cpp +++ b/APL/LogEntryCircularBuffer.cpp @@ -16,82 +16,82 @@ // specific language governing permissions and limitations // under the License. // -#include "LogEntryCircularBuffer.h" -#include - -namespace apl{ - - LogEntryCircularBuffer :: LogEntryCircularBuffer(size_t aMaxEntries) : - mMaxEntries(aMaxEntries) - { - - } - - size_t LogEntryCircularBuffer :: Count() - { - CriticalSection cs(&mLock); - return mItemQueue.size(); - } - - bool LogEntryCircularBuffer :: ReadLog(LogEntry& mEntry, int aTimeout) - { - CriticalSection cs(&mLock); - - if(CheckRead(mEntry)) return true; - else { - if(aTimeout < 0) cs.Wait(); - else if(aTimeout > 0) cs.TimedWait(aTimeout); - if(CheckRead(mEntry)) return true; - } - - return false; - } - - void LogEntryCircularBuffer :: BlockUntilEntry() - { - CriticalSection cs(&mLock); - if(mItemQueue.size() == 0) cs.Wait(); - } - - bool LogEntryCircularBuffer :: CheckRead(LogEntry& aEntry) - { - if(mItemQueue.size() > 0) { - aEntry = mItemQueue.front(); //make a copy of the front of the queue - mItemQueue.pop_front(); - return true; - } - else return false; - } - - void LogEntryCircularBuffer :: AddIgnoreCode(int aCode) - { - mIgnoreCodes.insert(aCode); - } - - void LogEntryCircularBuffer :: Log( FilterLevel aFilterLevel, const std::string& aDeviceName, const std::string& aLocation, const std::string& aMessage, int aErrorCode) - { - if(mIgnoreCodes.find(aErrorCode) == mIgnoreCodes.end()) { //only log messages that aren't ignored - - LogEntry item( aFilterLevel, aDeviceName, aLocation, aMessage, aErrorCode ); - size_t num = 0; - { - CriticalSection cs(&mLock); - num = mItemQueue.size(); - mItemQueue.push_back(item); - if(mItemQueue.size() > mMaxEntries) - { mItemQueue.pop_front(); } - cs.Signal(); - } - - // only notify if the queue was empty - if(num == 0) this->NotifyAll(); - } - } - - void LogEntryCircularBuffer :: SetMaxEntries(size_t aMax) - { - CriticalSection cs(&mLock); - mMaxEntries = aMax; - while(mItemQueue.size() > aMax) mItemQueue.pop_front(); - } -} +#include "LogEntryCircularBuffer.h" +#include + +namespace apl{ + + LogEntryCircularBuffer :: LogEntryCircularBuffer(size_t aMaxEntries) : + mMaxEntries(aMaxEntries) + { + + } + + size_t LogEntryCircularBuffer :: Count() + { + CriticalSection cs(&mLock); + return mItemQueue.size(); + } + + bool LogEntryCircularBuffer :: ReadLog(LogEntry& mEntry, int aTimeout) + { + CriticalSection cs(&mLock); + + if(CheckRead(mEntry)) return true; + else { + if(aTimeout < 0) cs.Wait(); + else if(aTimeout > 0) cs.TimedWait(aTimeout); + if(CheckRead(mEntry)) return true; + } + + return false; + } + + void LogEntryCircularBuffer :: BlockUntilEntry() + { + CriticalSection cs(&mLock); + if(mItemQueue.size() == 0) cs.Wait(); + } + + bool LogEntryCircularBuffer :: CheckRead(LogEntry& aEntry) + { + if(mItemQueue.size() > 0) { + aEntry = mItemQueue.front(); //make a copy of the front of the queue + mItemQueue.pop_front(); + return true; + } + else return false; + } + + void LogEntryCircularBuffer :: AddIgnoreCode(int aCode) + { + mIgnoreCodes.insert(aCode); + } + + void LogEntryCircularBuffer :: Log( FilterLevel aFilterLevel, const std::string& aDeviceName, const std::string& aLocation, const std::string& aMessage, int aErrorCode) + { + if(mIgnoreCodes.find(aErrorCode) == mIgnoreCodes.end()) { //only log messages that aren't ignored + + LogEntry item( aFilterLevel, aDeviceName, aLocation, aMessage, aErrorCode ); + size_t num = 0; + { + CriticalSection cs(&mLock); + num = mItemQueue.size(); + mItemQueue.push_back(item); + if(mItemQueue.size() > mMaxEntries) + { mItemQueue.pop_front(); } + cs.Signal(); + } + + // only notify if the queue was empty + if(num == 0) this->NotifyAll(); + } + } + + void LogEntryCircularBuffer :: SetMaxEntries(size_t aMax) + { + CriticalSection cs(&mLock); + mMaxEntries = aMax; + while(mItemQueue.size() > aMax) mItemQueue.pop_front(); + } +} diff --git a/APL/LogEntryCircularBuffer.h b/APL/LogEntryCircularBuffer.h index ecadd500..744e2e63 100644 --- a/APL/LogEntryCircularBuffer.h +++ b/APL/LogEntryCircularBuffer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOG_ENTRY_CIRCULAR_BUFFER_H_ #define __LOG_ENTRY_CIRCULAR_BUFFER_H_ @@ -34,21 +34,21 @@ namespace apl { class LogEntryCircularBuffer : public ILogBase, public SubjectBase, private Uncopyable { public: - LogEntryCircularBuffer(size_t aMaxEntries = 100); - - bool ReadLog(LogEntry&, int aTimeout = 0); + LogEntryCircularBuffer(size_t aMaxEntries = 100); + + bool ReadLog(LogEntry&, int aTimeout = 0); void SetMaxEntries(size_t aMax); void Log( FilterLevel aFilterLevel, const std::string& aDeviceName, const std::string& aLocation, const std::string& aMessage, int aErrorCode); size_t Count(); void AddIgnoreCode(int aCode); - protected: + protected: void BlockUntilEntry(); SigLock mLock; private: bool CheckRead(LogEntry& aEntry); - size_t mMaxEntries; + size_t mMaxEntries; std::deque mItemQueue; std::set mIgnoreCodes; }; diff --git a/APL/LogToFile.h b/APL/LogToFile.h index 66bb9f26..db558c29 100644 --- a/APL/LogToFile.h +++ b/APL/LogToFile.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _LOG_TO_FILE_H_ @@ -32,7 +32,7 @@ #include "Thread.h" namespace apl{ - + /** Logging backend that uses a buffer and thread to do a non-blocking writeof all the log entries to a text file. */ class LogToFile: public LogEntryCircularBuffer, public Threadable diff --git a/APL/LogToStdio.cpp b/APL/LogToStdio.cpp index f97887bb..77e67d0b 100644 --- a/APL/LogToStdio.cpp +++ b/APL/LogToStdio.cpp @@ -16,20 +16,20 @@ // specific language governing permissions and limitations // under the License. // -#include "LogToStdio.h" - -#include "LogEntry.h" -#include - -namespace apl { - -LogToStdio LogToStdio::mInstance; - -void LogToStdio::Log( FilterLevel aFilter, const std::string& aDevice, const std::string& aLocation, const std::string& aMessage, int aErrorCode) -{ - LogEntry item( aFilter, aDevice, aLocation, aMessage, aErrorCode ); - CriticalSection cs(&mLock); - std::cout << "IMMEDIATE: " << item.LogString() << std::endl; -} - -} //end ns +#include "LogToStdio.h" + +#include "LogEntry.h" +#include + +namespace apl { + +LogToStdio LogToStdio::mInstance; + +void LogToStdio::Log( FilterLevel aFilter, const std::string& aDevice, const std::string& aLocation, const std::string& aMessage, int aErrorCode) +{ + LogEntry item( aFilter, aDevice, aLocation, aMessage, aErrorCode ); + CriticalSection cs(&mLock); + std::cout << "IMMEDIATE: " << item.LogString() << std::endl; +} + +} //end ns diff --git a/APL/LogToStdio.h b/APL/LogToStdio.h index 03fd0dd6..e362a255 100644 --- a/APL/LogToStdio.h +++ b/APL/LogToStdio.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,36 +6,36 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __LOG_TO_STDIO_H_ -#define __LOG_TO_STDIO_H_ - -#include "Lock.h" -#include "LogBase.h" -#include "Singleton.h" - -namespace apl { - -class LogToStdio : public ILogBase -{ - MACRO_SINGLETON_INSTANCE(LogToStdio); - - public: - void Log( FilterLevel aFilter, const std::string& aDevice, const std::string& aLocation, const std::string& aMessage, int aErrorCode); - - private: - SigLock mLock; -}; - -} - -#endif +// +#ifndef __LOG_TO_STDIO_H_ +#define __LOG_TO_STDIO_H_ + +#include "Lock.h" +#include "LogBase.h" +#include "Singleton.h" + +namespace apl { + +class LogToStdio : public ILogBase +{ + MACRO_SINGLETON_INSTANCE(LogToStdio); + + public: + void Log( FilterLevel aFilter, const std::string& aDevice, const std::string& aLocation, const std::string& aMessage, int aErrorCode); + + private: + SigLock mLock; +}; + +} + +#endif diff --git a/APL/LogTypes.cpp b/APL/LogTypes.cpp index 4c604e73..3a77d541 100755 --- a/APL/LogTypes.cpp +++ b/APL/LogTypes.cpp @@ -16,18 +16,18 @@ // specific language governing permissions and limitations // under the License. // - -#include "LogTypes.h" - -namespace apl { - -int FilterLevelToMask(FilterLevel aFilter) -{ + +#include "LogTypes.h" + +namespace apl { + +int FilterLevelToMask(FilterLevel aFilter) +{ //since FilterLevel is a power of 2 (single bit), subtracting 1 will //set all the bits below the set bit. //set the filter bit and all the bits below it - return aFilter | (aFilter-1); -} - -} - + return aFilter | (aFilter-1); +} + +} + diff --git a/APL/LogTypes.h b/APL/LogTypes.h index 2731b95a..6a4275c6 100644 --- a/APL/LogTypes.h +++ b/APL/LogTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,36 +6,36 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __LOG_TYPES_H_ -#define __LOG_TYPES_H_ - -namespace apl { - -enum FilterLevel -{ - LEV_EVENT = 0x01, - LEV_ERROR = 0x02, - LEV_WARNING = 0x04, - LEV_INFO = 0x08, - LEV_INTERPRET = 0x10, - LEV_COMM = 0x20, - LEV_DEBUG = 0x40 -}; - -/// Converts a filter level enumeration to a mask with all higher levels set -int FilterLevelToMask(FilterLevel); - -} - -#endif - +// +#ifndef __LOG_TYPES_H_ +#define __LOG_TYPES_H_ + +namespace apl { + +enum FilterLevel +{ + LEV_EVENT = 0x01, + LEV_ERROR = 0x02, + LEV_WARNING = 0x04, + LEV_INFO = 0x08, + LEV_INTERPRET = 0x10, + LEV_COMM = 0x20, + LEV_DEBUG = 0x40 +}; + +/// Converts a filter level enumeration to a mask with all higher levels set +int FilterLevelToMask(FilterLevel); + +} + +#endif + diff --git a/APL/LogVar.h b/APL/LogVar.h index 2e3865c7..a5cbce73 100644 --- a/APL/LogVar.h +++ b/APL/LogVar.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOG_VAR_H_ #define __LOG_VAR_H_ @@ -39,7 +39,7 @@ class LogVar T Add(T aValue) { return (mValue += aValue); } private: - T mValue; + T mValue; }; diff --git a/APL/Loggable.h b/APL/Loggable.h index 09f06e39..18325fef 100644 --- a/APL/Loggable.h +++ b/APL/Loggable.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOGGABLE_H_ #define __LOGGABLE_H_ @@ -40,7 +40,7 @@ namespace apl #define LOG_BLOCK(severity, string) ERROR_BLOCK(severity, string, -1) #define EXCEPTION_BLOCK(severity, ex) ERROR_BLOCK(severity, ex.GetErrorString(), ex.ErrorCode()) - + //macro to remove boiler-plate code for logging messages with an error code #define ERROR_BLOCK(severity, string, code) ERROR_LOGGER_BLOCK(this->mpLogger, severity, string, code) diff --git a/APL/Logger.h b/APL/Logger.h index be621553..bc92c38a 100644 --- a/APL/Logger.h +++ b/APL/Logger.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOGGER_H_ #define __LOGGER_H_ @@ -43,20 +43,20 @@ namespace apl Logger( EventLog* apLog, FilterLevel aFilter, const std::string& aName); void SetVarName(const std::string& arVarName) { mVarName = arVarName; } - void Log( FilterLevel aFilterLevel, const std::string& aLocation, const std::string& aMessage, int aErrorCode = -1); + void Log( FilterLevel aFilterLevel, const std::string& aLocation, const std::string& aMessage, int aErrorCode = -1); std::string GetName() const { return mName; } - + //functions for manipulating filter levels inline bool IsEnabled(FilterLevel aFilter) { return (mLevel & aFilter) != 0; } - inline void SetFilters(int aLevel) { mLevel = aLevel; } + inline void SetFilters(int aLevel) { mLevel = aLevel; } void SetFilterLevel(FilterLevel aFilter); Logger* GetSubLogger(std::string aName); Logger* GetSubLogger(std::string aSubName, int aFilterBits); - Logger* GetSubLogger(std::string aSubName, FilterLevel aFilter); + Logger* GetSubLogger(std::string aSubName, FilterLevel aFilter); private: - + void Set(const std::string& aVar, int aValue); int mLevel; // bit field describing what is being logged @@ -89,9 +89,9 @@ namespace apl public: LogVariable(Logger* apLogger, const std::string& arName) : mpLogger(apLogger), - mName(arName) + mName(arName) { - + } void Set(int aVal) { mpLogger->Set(mName, aVal); } diff --git a/APL/LowerLayerToPhysAdapter.h b/APL/LowerLayerToPhysAdapter.h index 2238a0fd..e1fbb2c4 100644 --- a/APL/LowerLayerToPhysAdapter.h +++ b/APL/LowerLayerToPhysAdapter.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOWER_LAYER_TO_PHYS_ADAPTER_H_ #define __LOWER_LAYER_TO_PHYS_ADAPTER_H_ @@ -40,7 +40,7 @@ class LowerLayerToPhysAdapter : public IHandlerAsync, public ILowerLayer void StartRead(); - + private: @@ -64,9 +64,9 @@ class LowerLayerToPhysAdapter : public IHandlerAsync, public ILowerLayer void _OnLowerLayerUp(); void _OnLowerLayerDown(); void _OnLowerLayerShutdown(); - + IPhysicalLayerAsync* mpPhys; - + /* Implement ILowerLayer */ void _Send(const apl::byte_t*, size_t); }; diff --git a/APL/MetricBuffer.h b/APL/MetricBuffer.h index 1046895b..e214fb43 100644 --- a/APL/MetricBuffer.h +++ b/APL/MetricBuffer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __METRIC_BUFFER_H_ #define __METRIC_BUFFER_H_ @@ -31,7 +31,7 @@ namespace apl { class MetricBuffer : public ILogBase, public SubjectBase, private Uncopyable { - public: + public: struct Var { @@ -51,7 +51,7 @@ class MetricBuffer : public ILogBase, public SubjectBase, private Uncop void SetVar(const std::string& aSource, const std::string& aVarName, int aValue); void Read(std::vector&); - + private: SigLock mLock; std::map mValues; diff --git a/APL/MultiplexingDataObserver.h b/APL/MultiplexingDataObserver.h index e3657dce..4000ed0d 100644 --- a/APL/MultiplexingDataObserver.h +++ b/APL/MultiplexingDataObserver.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MULTIPLEXING_DATA_OBSERVER_H_ #define __MULTIPLEXING_DATA_OBSERVER_H_ @@ -35,7 +35,7 @@ namespace apl MultiplexingDataObserver(); MultiplexingDataObserver(IDataObserver* apObserver1); MultiplexingDataObserver(IDataObserver* apObserver1, IDataObserver* apObserver2); - + void AddObserver(IDataObserver* apObserver1); private: diff --git a/APL/Notifier.h b/APL/Notifier.h index 5321061a..a455915c 100644 --- a/APL/Notifier.h +++ b/APL/Notifier.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __NOTIFIER_H_ #define __NOTIFIER_H_ @@ -43,7 +43,7 @@ namespace apl { M_VAL(arVal), mpEventLock(apEventLock) { - + } template diff --git a/APL/PackingTemplates.h b/APL/PackingTemplates.h index 6922912b..95cc5568 100644 --- a/APL/PackingTemplates.h +++ b/APL/PackingTemplates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PACKING_TEMPLATES_H_ #define __PACKING_TEMPLATES_H_ diff --git a/APL/PackingUnpacking.h b/APL/PackingUnpacking.h index ce888465..98cd31f8 100644 --- a/APL/PackingUnpacking.h +++ b/APL/PackingUnpacking.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PACKING_UNPACKING_H_ #define __PACKING_UNPACKING_H_ @@ -46,7 +46,7 @@ namespace apl const static size_t Size = 1; const static byte_t Max; const static byte_t Min; - + typedef byte_t Type; }; @@ -88,7 +88,7 @@ namespace apl { public: static T Read(const apl::byte_t* apStart) - { + { T ret = *(apStart); ret |= *(++apStart) << 8; return ret; @@ -96,12 +96,12 @@ namespace apl static void Write(apl::byte_t* apStart, T aValue) { - *(apStart) = static_cast(aValue & 0xFF); - *(++apStart) = static_cast((aValue >> 8) & 0xFF); + *(apStart) = static_cast(aValue & 0xFF); + *(++apStart) = static_cast((aValue >> 8) & 0xFF); } typedef T Type; - + const static size_t Size = 2; const static T Max; const static T Min; @@ -118,16 +118,16 @@ namespace apl { public: static T Read(const apl::byte_t* apStart) - { + { T ret = *(apStart); ret |= *(++apStart) << 8; - ret |= *(++apStart) << 16; + ret |= *(++apStart) << 16; ret |= *(++apStart) << 24; return ret; } static void Write(apl::byte_t* apStart, T aValue) - { - *(apStart) = static_cast(aValue & 0xFF); + { + *(apStart) = static_cast(aValue & 0xFF); *(++apStart) = static_cast((aValue >> 8) & 0xFF); *(++apStart) = static_cast((aValue >> 16) & 0xFF); *(++apStart) = static_cast((aValue >> 24) & 0xFF); @@ -146,7 +146,7 @@ namespace apl template const T Bit32LE::Min = std::numeric_limits::min(); - + typedef Bit16LE Int16LE; typedef Bit16LE UInt16LE; @@ -160,16 +160,16 @@ namespace apl typedef BytesBE UInt64BE; typedef BytesBE Int64BE; - + class UInt48LE { public: static int_64_t Read(const apl::byte_t* apStart) - { + { apl::int_64_t ret = *(apStart); ret |= static_cast(*(++apStart)) << 8; - ret |= static_cast(*(++apStart)) << 16; + ret |= static_cast(*(++apStart)) << 16; ret |= static_cast(*(++apStart)) << 24; ret |= static_cast(*(++apStart)) << 32; ret |= static_cast(*(++apStart)) << 40; @@ -178,21 +178,21 @@ namespace apl } static void Write(apl::byte_t* apStart, int_64_t aValue) - { + { if(aValue > MAX) aValue = MAX; - *(apStart) = static_cast(aValue & 0xFF); + *(apStart) = static_cast(aValue & 0xFF); *(++apStart) = static_cast((aValue >> 8) & 0xFF); *(++apStart) = static_cast((aValue >> 16) & 0xFF); *(++apStart) = static_cast((aValue >> 24) & 0xFF); *(++apStart) = static_cast((aValue >> 32) & 0xFF); *(++apStart) = static_cast((aValue >> 40) & 0xFF); } - - const static int_64_t MAX = 281474976710655ULL; // 2^48 -1 + + const static int_64_t MAX = 281474976710655ULL; // 2^48 -1 const static size_t Size = 6; - + typedef int_64_t Type; }; @@ -201,24 +201,24 @@ namespace apl { public: typedef T Type; - + const static size_t Size = sizeof(T); const static T Max; const static T Min; protected: - + static T NaiveRead(const apl::byte_t* apStart) { return *reinterpret_cast(apStart); } - + static void NaiveWrite(apl::byte_t* apStart, T aValue) { //for(size_t i=0; i(apStart) = aValue; - - //* + + //* } }; @@ -231,9 +231,9 @@ namespace apl class SingleFloat : public Float { public: - static float Read(const apl::byte_t* apStart); - - static void Write(apl::byte_t* apStart, float aValue); + static float Read(const apl::byte_t* apStart); + + static void Write(apl::byte_t* apStart, float aValue); }; class DoubleFloat : public Float @@ -241,9 +241,9 @@ namespace apl public: static double Read(const apl::byte_t* apStart); static void Write(apl::byte_t* apStart, double aValue); - + private: - + #ifdef ARM static double FlipWord32(double aValue); #endif diff --git a/APL/Parsing.cpp b/APL/Parsing.cpp index e3abe0a2..bdc80819 100644 --- a/APL/Parsing.cpp +++ b/APL/Parsing.cpp @@ -16,26 +16,26 @@ // specific language governing permissions and limitations // under the License. // -#include "Parsing.h" - -#include - -namespace apl { - - bool Parsing::Get(const std::string& aArg, bool& arValue) - { - if(aArg == "true") { - arValue = true; - return true; - } - else if(aArg == "false") { - arValue = false; - return true; - } - else { - return Get(aArg, arValue); - } - } - -} - +#include "Parsing.h" + +#include + +namespace apl { + + bool Parsing::Get(const std::string& aArg, bool& arValue) + { + if(aArg == "true") { + arValue = true; + return true; + } + else if(aArg == "false") { + arValue = false; + return true; + } + else { + return Get(aArg, arValue); + } + } + +} + diff --git a/APL/Parsing.h b/APL/Parsing.h index 39b48693..b14687b3 100644 --- a/APL/Parsing.h +++ b/APL/Parsing.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,44 +6,44 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __PARSING_H_ -#define __PARSING_H_ - -#include -#include - -namespace apl { - - class Parsing - { - public: - - template - static bool Get(const std::string& aArg, T& arValue) - { - std::stringstream ss; - ss << aArg; - return !(ss >> arValue).fail(); - } - - static bool Get(const std::string& aArg, bool& arValue); - - template - static bool GetPositive(const std::string& aArg, T& arValue) - { - return Get(aArg,arValue) && arValue >= 0; - } - }; -} - -#endif +// +#ifndef __PARSING_H_ +#define __PARSING_H_ + +#include +#include + +namespace apl { + + class Parsing + { + public: + + template + static bool Get(const std::string& aArg, T& arValue) + { + std::stringstream ss; + ss << aArg; + return !(ss >> arValue).fail(); + } + + static bool Get(const std::string& aArg, bool& arValue); + + template + static bool GetPositive(const std::string& aArg, T& arValue) + { + return Get(aArg,arValue) && arValue >= 0; + } + }; +} + +#endif diff --git a/APL/PhysLayerSettings.h b/APL/PhysLayerSettings.h index 2a680a59..434e2a17 100644 --- a/APL/PhysLayerSettings.h +++ b/APL/PhysLayerSettings.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,38 +6,38 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __PHYS_LAYER_SETTINGS_H_ -#define __PHYS_LAYER_SETTINGS_H_ - -#include "Types.h" -#include "LogTypes.h" - -namespace apl { - -struct PhysLayerSettings -{ - public: - PhysLayerSettings() {} - - PhysLayerSettings(FilterLevel aLevel, millis_t aRetryTimeout) : - LogLevel(aLevel), - RetryTimeout(aRetryTimeout) - {} - - FilterLevel LogLevel; - millis_t RetryTimeout; -}; - -} - -#endif +// +#ifndef __PHYS_LAYER_SETTINGS_H_ +#define __PHYS_LAYER_SETTINGS_H_ + +#include "Types.h" +#include "LogTypes.h" + +namespace apl { + +struct PhysLayerSettings +{ + public: + PhysLayerSettings() {} + + PhysLayerSettings(FilterLevel aLevel, millis_t aRetryTimeout) : + LogLevel(aLevel), + RetryTimeout(aRetryTimeout) + {} + + FilterLevel LogLevel; + millis_t RetryTimeout; +}; + +} + +#endif diff --git a/APL/PhysicalLayerAsyncASIO.h b/APL/PhysicalLayerAsyncASIO.h index 85ae6ea7..977a354b 100644 --- a/APL/PhysicalLayerAsyncASIO.h +++ b/APL/PhysicalLayerAsyncASIO.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_ASYNC_ASIO_H_ #define __PHYSICAL_LAYER_ASYNC_ASIO_H_ diff --git a/APL/PhysicalLayerAsyncBase.h b/APL/PhysicalLayerAsyncBase.h index fcd26579..f8553529 100644 --- a/APL/PhysicalLayerAsyncBase.h +++ b/APL/PhysicalLayerAsyncBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_ASYNC_BASE_H_ #define __PHYSICAL_LAYER_ASYNC_BASE_H_ @@ -46,7 +46,7 @@ namespace apl { bool CanClose(); bool CanRead(); bool CanWrite(); - + bool CallbacksPending(); bool CheckForClose(); @@ -59,7 +59,7 @@ namespace apl { /// destructor should only be called once the object is totally finished with all of its async operations /// to avoid segfaulting. There are a # of asserts that make sure the object has been shutdown properly. virtual ~PhysicalLayerAsyncBase() {} - + bool IsReading() { return mState.mReading; } bool IsWriting() { return mState.mWriting; } bool IsClosing() { return mState.mClosing; } @@ -75,7 +75,7 @@ namespace apl { // Not an event delegated to the states void SetHandler(IHandlerAsync* apHandler); - /* Actions taken by the states - These must be implemented by the concrete + /* Actions taken by the states - These must be implemented by the concrete classes inherited from this class */ virtual void DoOpen() = 0; virtual void DoClose() = 0; @@ -86,7 +86,7 @@ namespace apl { // These can be optionally overriden to do something more interesting, i.e. specific logging virtual void DoOpenSuccess() {} virtual void DoOpenFailure() {} - + void DoWriteSuccess(); void DoThisLayerDown(); void DoReadCallback(byte_t*, size_t); @@ -95,14 +95,14 @@ namespace apl { Logger* GetLogger() { return mpLogger; } protected: - + //Internally produced events void OnOpenCallback(const boost::system::error_code& arError); void OnReadCallback(const boost::system::error_code& arError, byte_t*, size_t aSize); void OnWriteCallback(const boost::system::error_code& arError, size_t aSize); - + /// "user" object that recieves the callbacks - IHandlerAsync* mpHandler; + IHandlerAsync* mpHandler; /// State object that tracks the activities of the class, state pattern too heavy PhysicalLayerAsyncBase::State mState; diff --git a/APL/PhysicalLayerAsyncBaseTCP.cpp b/APL/PhysicalLayerAsyncBaseTCP.cpp index c2c5e7ed..7928121f 100644 --- a/APL/PhysicalLayerAsyncBaseTCP.cpp +++ b/APL/PhysicalLayerAsyncBaseTCP.cpp @@ -16,63 +16,63 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" -#include "PhysicalLayerAsyncBaseTCP.h" - -#include -#include -#include - -#include "Exception.h" -#include "IHandlerAsync.h" -#include "Logger.h" - -using namespace boost; -using namespace boost::asio; -using namespace boost::system; -using namespace std; - -namespace apl { - -PhysicalLayerAsyncBaseTCP::PhysicalLayerAsyncBaseTCP(Logger* apLogger, boost::asio::io_service* apIOService) : -PhysicalLayerAsyncASIO(apLogger, apIOService), -mSocket(*apIOService) -{ - //mSocket.set_option(ip::tcp::no_delay(true)); -} - -/* Implement the actions */ - -void PhysicalLayerAsyncBaseTCP::DoClose() -{ - error_code ec; - mSocket.close(ec); - if(ec) LOG_BLOCK(LEV_WARNING, ec.message()); -} - -void PhysicalLayerAsyncBaseTCP::DoOpenSuccess() -{ - //mSocket.set_option(ip::tcp::no_delay(true)); - LOG_BLOCK(LEV_INFO, "Successful conneciton"); -} - -void PhysicalLayerAsyncBaseTCP::DoAsyncRead(byte_t* apBuffer, size_t aMaxBytes) -{ - mSocket.async_read_some(buffer(apBuffer, aMaxBytes), - boost::bind(&PhysicalLayerAsyncBaseTCP::OnReadCallback, this, placeholders::error, apBuffer, placeholders::bytes_transferred)); -} - -void PhysicalLayerAsyncBaseTCP::DoAsyncWrite(const byte_t* apBuffer, size_t aNumBytes) -{ - async_write(mSocket, buffer(apBuffer, aNumBytes), - boost::bind(&PhysicalLayerAsyncBaseTCP::OnWriteCallback, this, placeholders::error, aNumBytes)); -} - -void PhysicalLayerAsyncBaseTCP::DoOpenFailure() -{ - LOG_BLOCK(LEV_INFO, "Failed socket open, reclosing"); - DoClose(); -} - -} - +#include "ASIOIncludes.h" +#include "PhysicalLayerAsyncBaseTCP.h" + +#include +#include +#include + +#include "Exception.h" +#include "IHandlerAsync.h" +#include "Logger.h" + +using namespace boost; +using namespace boost::asio; +using namespace boost::system; +using namespace std; + +namespace apl { + +PhysicalLayerAsyncBaseTCP::PhysicalLayerAsyncBaseTCP(Logger* apLogger, boost::asio::io_service* apIOService) : +PhysicalLayerAsyncASIO(apLogger, apIOService), +mSocket(*apIOService) +{ + //mSocket.set_option(ip::tcp::no_delay(true)); +} + +/* Implement the actions */ + +void PhysicalLayerAsyncBaseTCP::DoClose() +{ + error_code ec; + mSocket.close(ec); + if(ec) LOG_BLOCK(LEV_WARNING, ec.message()); +} + +void PhysicalLayerAsyncBaseTCP::DoOpenSuccess() +{ + //mSocket.set_option(ip::tcp::no_delay(true)); + LOG_BLOCK(LEV_INFO, "Successful conneciton"); +} + +void PhysicalLayerAsyncBaseTCP::DoAsyncRead(byte_t* apBuffer, size_t aMaxBytes) +{ + mSocket.async_read_some(buffer(apBuffer, aMaxBytes), + boost::bind(&PhysicalLayerAsyncBaseTCP::OnReadCallback, this, placeholders::error, apBuffer, placeholders::bytes_transferred)); +} + +void PhysicalLayerAsyncBaseTCP::DoAsyncWrite(const byte_t* apBuffer, size_t aNumBytes) +{ + async_write(mSocket, buffer(apBuffer, aNumBytes), + boost::bind(&PhysicalLayerAsyncBaseTCP::OnWriteCallback, this, placeholders::error, aNumBytes)); +} + +void PhysicalLayerAsyncBaseTCP::DoOpenFailure() +{ + LOG_BLOCK(LEV_INFO, "Failed socket open, reclosing"); + DoClose(); +} + +} + diff --git a/APL/PhysicalLayerAsyncBaseTCP.h b/APL/PhysicalLayerAsyncBaseTCP.h index edb2559c..4523d947 100644 --- a/APL/PhysicalLayerAsyncBaseTCP.h +++ b/APL/PhysicalLayerAsyncBaseTCP.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_ASYNC_BASE_TCP_H_ #define __PHYSICAL_LAYER_ASYNC_BASE_TCP_H_ diff --git a/APL/PhysicalLayerAsyncSerial.cpp b/APL/PhysicalLayerAsyncSerial.cpp index e848721a..8b0b8ab6 100644 --- a/APL/PhysicalLayerAsyncSerial.cpp +++ b/APL/PhysicalLayerAsyncSerial.cpp @@ -16,75 +16,75 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" -#include "PhysicalLayerAsyncSerial.h" - -#include -#include -//#include -#include - -#include "Exception.h" -#include "IHandlerAsync.h" -#include "Logger.h" -#include "ASIOSerialHelpers.h" - -using namespace boost; -using namespace boost::asio; -using namespace boost::system; -using namespace std; - -namespace apl { - -PhysicalLayerAsyncSerial::PhysicalLayerAsyncSerial( - Logger* apLogger, - boost::asio::io_service* apIOService, - const SerialSettings& arSettings) : - -PhysicalLayerAsyncASIO(apLogger, apIOService), -mSettings(arSettings), -mpService(apIOService), -mPort(*apIOService) -{ - -} - -/* Implement the actions */ - -void PhysicalLayerAsyncSerial::DoOpen() -{ - boost::system::error_code ec; - mPort.open(mSettings.mDevice, ec); - - //use post to simulate an async open operation - if(!ec) asio_serial::Configure(mSettings, mPort, ec); - - mpService->post(bind(&PhysicalLayerAsyncSerial::OnOpenCallback, this, ec)); -} - -void PhysicalLayerAsyncSerial::DoClose() -{ - error_code ec; - mPort.close(ec); - if(ec) LOG_BLOCK(LEV_WARNING, ec.message()); -} - -void PhysicalLayerAsyncSerial::DoOpenSuccess() -{ - LOG_BLOCK(LEV_INFO, "Port successfully opened"); -} - -void PhysicalLayerAsyncSerial::DoAsyncRead(byte_t* apBuffer, size_t aMaxBytes) -{ - mPort.async_read_some(buffer(apBuffer, aMaxBytes), - boost::bind(&PhysicalLayerAsyncSerial::OnReadCallback, this, placeholders::error, apBuffer, placeholders::bytes_transferred)); -} - -void PhysicalLayerAsyncSerial::DoAsyncWrite(const byte_t* apBuffer, size_t aNumBytes) -{ - async_write(mPort, buffer(apBuffer, aNumBytes), - boost::bind(&PhysicalLayerAsyncSerial::OnWriteCallback, this, placeholders::error, aNumBytes)); -} - -} - +#include "ASIOIncludes.h" +#include "PhysicalLayerAsyncSerial.h" + +#include +#include +//#include +#include + +#include "Exception.h" +#include "IHandlerAsync.h" +#include "Logger.h" +#include "ASIOSerialHelpers.h" + +using namespace boost; +using namespace boost::asio; +using namespace boost::system; +using namespace std; + +namespace apl { + +PhysicalLayerAsyncSerial::PhysicalLayerAsyncSerial( + Logger* apLogger, + boost::asio::io_service* apIOService, + const SerialSettings& arSettings) : + +PhysicalLayerAsyncASIO(apLogger, apIOService), +mSettings(arSettings), +mpService(apIOService), +mPort(*apIOService) +{ + +} + +/* Implement the actions */ + +void PhysicalLayerAsyncSerial::DoOpen() +{ + boost::system::error_code ec; + mPort.open(mSettings.mDevice, ec); + + //use post to simulate an async open operation + if(!ec) asio_serial::Configure(mSettings, mPort, ec); + + mpService->post(bind(&PhysicalLayerAsyncSerial::OnOpenCallback, this, ec)); +} + +void PhysicalLayerAsyncSerial::DoClose() +{ + error_code ec; + mPort.close(ec); + if(ec) LOG_BLOCK(LEV_WARNING, ec.message()); +} + +void PhysicalLayerAsyncSerial::DoOpenSuccess() +{ + LOG_BLOCK(LEV_INFO, "Port successfully opened"); +} + +void PhysicalLayerAsyncSerial::DoAsyncRead(byte_t* apBuffer, size_t aMaxBytes) +{ + mPort.async_read_some(buffer(apBuffer, aMaxBytes), + boost::bind(&PhysicalLayerAsyncSerial::OnReadCallback, this, placeholders::error, apBuffer, placeholders::bytes_transferred)); +} + +void PhysicalLayerAsyncSerial::DoAsyncWrite(const byte_t* apBuffer, size_t aNumBytes) +{ + async_write(mPort, buffer(apBuffer, aNumBytes), + boost::bind(&PhysicalLayerAsyncSerial::OnWriteCallback, this, placeholders::error, aNumBytes)); +} + +} + diff --git a/APL/PhysicalLayerAsyncSerial.h b/APL/PhysicalLayerAsyncSerial.h index b88a953c..e8652c3d 100644 --- a/APL/PhysicalLayerAsyncSerial.h +++ b/APL/PhysicalLayerAsyncSerial.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_ASYNC_SERIAL_H_ #define __PHYSICAL_LAYER_ASYNC_SERIAL_H_ @@ -43,7 +43,7 @@ namespace apl { void DoOpen(); protected: - + SerialSettings mSettings; boost::asio::io_service* mpService; boost::asio::serial_port mPort; diff --git a/APL/PhysicalLayerAsyncTCPClient.cpp b/APL/PhysicalLayerAsyncTCPClient.cpp index 34a9c3ed..40339c37 100644 --- a/APL/PhysicalLayerAsyncTCPClient.cpp +++ b/APL/PhysicalLayerAsyncTCPClient.cpp @@ -16,49 +16,49 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" -#include "PhysicalLayerAsyncTCPClient.h" - - -#include -#include - -#include "Exception.h" -#include "IHandlerAsync.h" -#include "Logger.h" - -using namespace boost; -using namespace boost::asio; -using namespace std; - -namespace apl { - -PhysicalLayerAsyncTCPClient::PhysicalLayerAsyncTCPClient( - Logger* apLogger, - boost::asio::io_service* apIOService, - const std::string& arAddress, - uint_16_t aPort) : - - PhysicalLayerAsyncBaseTCP(apLogger, apIOService), - mAddr(arAddress), - mPort(aPort) -{ - -} - -/* Implement the actions */ -void PhysicalLayerAsyncTCPClient::DoOpen() -{ - ip::address_v4 address; - boost::system::error_code ec; - string ipstring(mAddr); - address = address.from_string(ipstring, ec); - if(ec) throw ArgumentException(LOCATION, "string Address: " + ipstring + " cannot be resolved"); - - ip::tcp::endpoint serverEndpoint(address, mPort); - - mSocket.async_connect(serverEndpoint, boost::bind(&PhysicalLayerAsyncTCPClient::OnOpenCallback, this, placeholders::error)); -} - -} - +#include "ASIOIncludes.h" +#include "PhysicalLayerAsyncTCPClient.h" + + +#include +#include + +#include "Exception.h" +#include "IHandlerAsync.h" +#include "Logger.h" + +using namespace boost; +using namespace boost::asio; +using namespace std; + +namespace apl { + +PhysicalLayerAsyncTCPClient::PhysicalLayerAsyncTCPClient( + Logger* apLogger, + boost::asio::io_service* apIOService, + const std::string& arAddress, + uint_16_t aPort) : + + PhysicalLayerAsyncBaseTCP(apLogger, apIOService), + mAddr(arAddress), + mPort(aPort) +{ + +} + +/* Implement the actions */ +void PhysicalLayerAsyncTCPClient::DoOpen() +{ + ip::address_v4 address; + boost::system::error_code ec; + string ipstring(mAddr); + address = address.from_string(ipstring, ec); + if(ec) throw ArgumentException(LOCATION, "string Address: " + ipstring + " cannot be resolved"); + + ip::tcp::endpoint serverEndpoint(address, mPort); + + mSocket.async_connect(serverEndpoint, boost::bind(&PhysicalLayerAsyncTCPClient::OnOpenCallback, this, placeholders::error)); +} + +} + diff --git a/APL/PhysicalLayerAsyncTCPClient.h b/APL/PhysicalLayerAsyncTCPClient.h index f36b7901..679dbf9a 100644 --- a/APL/PhysicalLayerAsyncTCPClient.h +++ b/APL/PhysicalLayerAsyncTCPClient.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_ASYNC_TCP_CLIENT_H_ #define __PHYSICAL_LAYER_ASYNC_TCP_CLIENT_H_ diff --git a/APL/PhysicalLayerAsyncTCPServer.cpp b/APL/PhysicalLayerAsyncTCPServer.cpp index 70a2f9de..10091b0d 100644 --- a/APL/PhysicalLayerAsyncTCPServer.cpp +++ b/APL/PhysicalLayerAsyncTCPServer.cpp @@ -16,55 +16,55 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" -#include "PhysicalLayerAsyncTCPServer.h" - -#include -#include - -#include "Exception.h" -#include "IHandlerAsync.h" -#include "Logger.h" - -using namespace boost; -using namespace boost::system; -using namespace boost::asio; -using namespace std; - -namespace apl { - -PhysicalLayerAsyncTCPServer::PhysicalLayerAsyncTCPServer(Logger* apLogger, io_service* apIOService, uint_16_t aPort) : -PhysicalLayerAsyncBaseTCP(apLogger, apIOService), -mEndpoint(ip::tcp::v4(), aPort), -mAcceptor(*apIOService) -{ - -} - -/* Implement the actions */ -void PhysicalLayerAsyncTCPServer::DoOpen() -{ - if(!mAcceptor.is_open()) - { - error_code ec; - mAcceptor.open(mEndpoint.protocol(), ec); - if(ec) throw Exception(LOCATION, ec.message()); - - mAcceptor.set_option(ip::tcp::acceptor::reuse_address(true)); - mAcceptor.bind(mEndpoint, ec); - if(ec) throw Exception(LOCATION, ec.message()); - - mAcceptor.listen(socket_base::max_connections, ec); - if(ec) throw Exception(LOCATION, ec.message()); - } - - mAcceptor.async_accept(mSocket, mEndpoint, boost::bind(&PhysicalLayerAsyncTCPServer::OnOpenCallback, this, placeholders::error)); -} - -void PhysicalLayerAsyncTCPServer::DoOpeningClose() -{ - mAcceptor.cancel(); -} - -} - +#include "ASIOIncludes.h" +#include "PhysicalLayerAsyncTCPServer.h" + +#include +#include + +#include "Exception.h" +#include "IHandlerAsync.h" +#include "Logger.h" + +using namespace boost; +using namespace boost::system; +using namespace boost::asio; +using namespace std; + +namespace apl { + +PhysicalLayerAsyncTCPServer::PhysicalLayerAsyncTCPServer(Logger* apLogger, io_service* apIOService, uint_16_t aPort) : +PhysicalLayerAsyncBaseTCP(apLogger, apIOService), +mEndpoint(ip::tcp::v4(), aPort), +mAcceptor(*apIOService) +{ + +} + +/* Implement the actions */ +void PhysicalLayerAsyncTCPServer::DoOpen() +{ + if(!mAcceptor.is_open()) + { + error_code ec; + mAcceptor.open(mEndpoint.protocol(), ec); + if(ec) throw Exception(LOCATION, ec.message()); + + mAcceptor.set_option(ip::tcp::acceptor::reuse_address(true)); + mAcceptor.bind(mEndpoint, ec); + if(ec) throw Exception(LOCATION, ec.message()); + + mAcceptor.listen(socket_base::max_connections, ec); + if(ec) throw Exception(LOCATION, ec.message()); + } + + mAcceptor.async_accept(mSocket, mEndpoint, boost::bind(&PhysicalLayerAsyncTCPServer::OnOpenCallback, this, placeholders::error)); +} + +void PhysicalLayerAsyncTCPServer::DoOpeningClose() +{ + mAcceptor.cancel(); +} + +} + diff --git a/APL/PhysicalLayerAsyncTCPServer.h b/APL/PhysicalLayerAsyncTCPServer.h index ed7e3605..484ff4bb 100644 --- a/APL/PhysicalLayerAsyncTCPServer.h +++ b/APL/PhysicalLayerAsyncTCPServer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_ASYNC_TCP_SERVER_H_ #define __PHYSICAL_LAYER_ASYNC_TCP_SERVER_H_ @@ -32,13 +32,13 @@ namespace apl { /* Implement the remainging actions */ void DoOpen(); void DoOpeningClose(); //override this to cancel the acceptor instead of the socket - + private: /* This object appears to be used referentially as in the asynchronous code as having it disappear from the stack was causing a stack corruption. */ boost::asio::ip::tcp::endpoint mEndpoint; boost::asio::ip::tcp::acceptor mAcceptor; - + }; } diff --git a/APL/PhysicalLayerFactory.h b/APL/PhysicalLayerFactory.h index fc7c8dc3..119d6646 100644 --- a/APL/PhysicalLayerFactory.h +++ b/APL/PhysicalLayerFactory.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _PHYSICAL_LAYER_FACTORY_H_ #define _PHYSICAL_LAYER_FACTORY_H_ @@ -28,10 +28,10 @@ namespace apl{ - class PhysicalLayerFactory + class PhysicalLayerFactory { public: - + static IPhysicalLayerAsyncFactory GetSerialAsync(SerialSettings s); static IPhysicalLayerAsyncFactory GetTCPClientAsync(std::string aAddress, uint_16_t aPort); static IPhysicalLayerAsyncFactory GetTCPServerAsync(uint_16_t aPort); @@ -39,7 +39,7 @@ namespace apl{ //normal factory functions static IPhysicalLayerAsync* FGetSerialAsync(SerialSettings s, boost::asio::io_service* apSrv, Logger* apLogger); static IPhysicalLayerAsync* FGetTCPClientAsync(std::string aAddress, uint_16_t aPort, boost::asio::io_service* apSrv, Logger* apLogger); - static IPhysicalLayerAsync* FGetTCPServerAsync(uint_16_t aPort, boost::asio::io_service* apSrv, Logger* apLogger); + static IPhysicalLayerAsync* FGetTCPServerAsync(uint_16_t aPort, boost::asio::io_service* apSrv, Logger* apLogger); }; } diff --git a/APL/PhysicalLayerFunctors.h b/APL/PhysicalLayerFunctors.h index 2b7f1a1d..6826b3a5 100644 --- a/APL/PhysicalLayerFunctors.h +++ b/APL/PhysicalLayerFunctors.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,34 +6,34 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __PHYSICAL_LAYER_FUNCTORS_H_ -#define __PHYSICAL_LAYER_FUNCTORS_H_ - -#include - -namespace boost { namespace asio { - class io_service; -}} - -namespace apl { - - class Logger; - class IPhysicalLayerSync; - class IPhysicalLayerAsync; - - typedef boost::function IPhysicalLayerSyncFactory; - typedef boost::function IPhysicalLayerAsyncFactory; -} - -#endif - +// +#ifndef __PHYSICAL_LAYER_FUNCTORS_H_ +#define __PHYSICAL_LAYER_FUNCTORS_H_ + +#include + +namespace boost { namespace asio { + class io_service; +}} + +namespace apl { + + class Logger; + class IPhysicalLayerSync; + class IPhysicalLayerAsync; + + typedef boost::function IPhysicalLayerSyncFactory; + typedef boost::function IPhysicalLayerAsyncFactory; +} + +#endif + diff --git a/APL/PhysicalLayerInstance.h b/APL/PhysicalLayerInstance.h index 76ae8e66..714b10e7 100644 --- a/APL/PhysicalLayerInstance.h +++ b/APL/PhysicalLayerInstance.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_INSTANCE_H_ #define __PHYSICAL_LAYER_INSTANCE_H_ @@ -34,20 +34,20 @@ class PhysLayerInstance PhysLayerInstance() : mpLayer(NULL), mpLogger(NULL) {} - PhysLayerInstance(IPhysicalLayerAsyncFactory); + PhysLayerInstance(IPhysicalLayerAsyncFactory); PhysLayerInstance(IPhysicalLayerAsync* apPhys, Logger*); - - IPhysicalLayerAsync* GetAsync(Logger*, boost::asio::io_service*); + + IPhysicalLayerAsync* GetAsync(Logger*, boost::asio::io_service*); void Release(); - - private: - - IPhysicalLayerAsyncFactory mFactoryAsync; - IPhysicalLayerAsync* mpLayer; + + private: + + IPhysicalLayerAsyncFactory mFactoryAsync; + IPhysicalLayerAsync* mpLayer; Logger* mpLogger; - void SetLayer(IPhysicalLayerAsync* apLayer, Logger* apLogger); + void SetLayer(IPhysicalLayerAsync* apLayer, Logger* apLogger); }; } diff --git a/APL/PhysicalLayerManager.h b/APL/PhysicalLayerManager.h index 7b8a1d30..281cdf9f 100644 --- a/APL/PhysicalLayerManager.h +++ b/APL/PhysicalLayerManager.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PhysicalLayerManager_H_ #define __PhysicalLayerManager_H_ @@ -30,7 +30,7 @@ namespace apl class PhysicalLayerManager : public PhysicalLayerMap { public: - + /// Constructor can specify whether or not the class will delete it's own physical layers via aOwnsLayer. PhysicalLayerManager(Logger*, bool aOwnsLayers = true); virtual ~PhysicalLayerManager(); @@ -45,9 +45,9 @@ namespace apl void Remove(const std::string& arName); private: - bool mOwnsLayers; + bool mOwnsLayers; }; } #endif - + diff --git a/APL/PhysicalLayerMap.h b/APL/PhysicalLayerMap.h index eab284cf..36d72bc6 100644 --- a/APL/PhysicalLayerMap.h +++ b/APL/PhysicalLayerMap.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PHYSICAL_LAYER_MAP_H_ #define __PHYSICAL_LAYER_MAP_H_ @@ -33,9 +33,9 @@ namespace apl virtual ~PhysicalLayerMap() {} PhysLayerSettings GetSettings(const std::string& arName); - IPhysicalLayerAsync* GetLayer(const std::string& arName, boost::asio::io_service*); - - + IPhysicalLayerAsync* GetLayer(const std::string& arName, boost::asio::io_service*); + + protected: Logger* MakeLogger(const std::string& arName, FilterLevel); @@ -54,4 +54,4 @@ namespace apl } #endif - + diff --git a/APL/PostingNotifier.cpp b/APL/PostingNotifier.cpp index 79c4cece..e1ec276d 100644 --- a/APL/PostingNotifier.cpp +++ b/APL/PostingNotifier.cpp @@ -16,20 +16,20 @@ // specific language governing permissions and limitations // under the License. // -#include "PostingNotifier.h" - -namespace apl { - -PostingNotifier::PostingNotifier(ITimerSource* apTimerSrc, const ExpirationHandler& arHandler) : -mpTimerSrc(apTimerSrc), -mHandler(arHandler) -{ - -} - -void PostingNotifier::Notify() -{ - mpTimerSrc->Post(mHandler); -} - -} +#include "PostingNotifier.h" + +namespace apl { + +PostingNotifier::PostingNotifier(ITimerSource* apTimerSrc, const ExpirationHandler& arHandler) : +mpTimerSrc(apTimerSrc), +mHandler(arHandler) +{ + +} + +void PostingNotifier::Notify() +{ + mpTimerSrc->Post(mHandler); +} + +} diff --git a/APL/PostingNotifier.h b/APL/PostingNotifier.h index 91f0978d..90944b08 100644 --- a/APL/PostingNotifier.h +++ b/APL/PostingNotifier.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,39 +6,39 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __POSTING_NOTIFIER_H_ -#define __POSTING_NOTIFIER_H_ - -#include "INotifier.h" -#include "TimerInterfaces.h" - -namespace apl { - -class PostingNotifier : public INotifier -{ - public: - - PostingNotifier(ITimerSource* apTimerSrc, const ExpirationHandler& arHandler); - - virtual ~PostingNotifier(){} - - void Notify(); - - private: - ITimerSource* mpTimerSrc; - ExpirationHandler mHandler; -}; - -} - -#endif +// +#ifndef __POSTING_NOTIFIER_H_ +#define __POSTING_NOTIFIER_H_ + +#include "INotifier.h" +#include "TimerInterfaces.h" + +namespace apl { + +class PostingNotifier : public INotifier +{ + public: + + PostingNotifier(ITimerSource* apTimerSrc, const ExpirationHandler& arHandler); + + virtual ~PostingNotifier(){} + + void Notify(); + + private: + ITimerSource* mpTimerSrc; + ExpirationHandler mHandler; +}; + +} + +#endif diff --git a/APL/PostingNotifierSource.cpp b/APL/PostingNotifierSource.cpp index 36e7823e..50d09661 100644 --- a/APL/PostingNotifierSource.cpp +++ b/APL/PostingNotifierSource.cpp @@ -16,24 +16,24 @@ // specific language governing permissions and limitations // under the License. // -#include "PostingNotifierSource.h" - -#include "PostingNotifier.h" -#include - -namespace apl { - -PostingNotifierSource::~PostingNotifierSource() -{ - BOOST_FOREACH(PostingNotifier* p, mNotifiers) { delete p; } -} - -INotifier* PostingNotifierSource::Get(const ExpirationHandler& arHandler, ITimerSource* apTimerSrc) -{ - PostingNotifier* pRet = new PostingNotifier(apTimerSrc, arHandler); - mNotifiers.push_back(pRet); - return pRet; -} - -} - +#include "PostingNotifierSource.h" + +#include "PostingNotifier.h" +#include + +namespace apl { + +PostingNotifierSource::~PostingNotifierSource() +{ + BOOST_FOREACH(PostingNotifier* p, mNotifiers) { delete p; } +} + +INotifier* PostingNotifierSource::Get(const ExpirationHandler& arHandler, ITimerSource* apTimerSrc) +{ + PostingNotifier* pRet = new PostingNotifier(apTimerSrc, arHandler); + mNotifiers.push_back(pRet); + return pRet; +} + +} + diff --git a/APL/PostingNotifierSource.h b/APL/PostingNotifierSource.h index 10a1a9ad..42f7e004 100644 --- a/APL/PostingNotifierSource.h +++ b/APL/PostingNotifierSource.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,39 +6,39 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __POSTING_NOTIFIER_SOURCE_H_ -#define __POSTING_NOTIFIER_SOURCE_H_ - -#include "TimerInterfaces.h" - -#include - -namespace apl { - -class INotifier; -class PostingNotifier; - -class PostingNotifierSource -{ - public: - ~PostingNotifierSource(); - - INotifier* Get(const ExpirationHandler&, ITimerSource*); - - private: - std::vector mNotifiers; -}; - -} - -#endif +// +#ifndef __POSTING_NOTIFIER_SOURCE_H_ +#define __POSTING_NOTIFIER_SOURCE_H_ + +#include "TimerInterfaces.h" + +#include + +namespace apl { + +class INotifier; +class PostingNotifier; + +class PostingNotifierSource +{ + public: + ~PostingNotifierSource(); + + INotifier* Get(const ExpirationHandler&, ITimerSource*); + + private: + std::vector mNotifiers; +}; + +} + +#endif diff --git a/APL/ProtocolUtil.cpp b/APL/ProtocolUtil.cpp index 3f61ca06..7f58e266 100644 --- a/APL/ProtocolUtil.cpp +++ b/APL/ProtocolUtil.cpp @@ -16,23 +16,23 @@ // specific language governing permissions and limitations // under the License. // -#include "ProtocolUtil.h" - -namespace apl { - -/// Given a buffer and max packet size, calculcate the -/// maximum number of packets the buffer can hold -size_t CalcMaxPackets(size_t aBuffer, size_t aPayload) -{ - size_t remain = aBuffer%aPayload; - size_t num = aBuffer/aPayload; - return (remain == 0) ? num : num + 1; -} - -size_t CalcLastPacketSize(size_t aBuffer, size_t aPayload) -{ - size_t remain = aBuffer%aPayload; - return (remain == 0) ? aPayload : remain; -} - -} //end namespace +#include "ProtocolUtil.h" + +namespace apl { + +/// Given a buffer and max packet size, calculcate the +/// maximum number of packets the buffer can hold +size_t CalcMaxPackets(size_t aBuffer, size_t aPayload) +{ + size_t remain = aBuffer%aPayload; + size_t num = aBuffer/aPayload; + return (remain == 0) ? num : num + 1; +} + +size_t CalcLastPacketSize(size_t aBuffer, size_t aPayload) +{ + size_t remain = aBuffer%aPayload; + return (remain == 0) ? aPayload : remain; +} + +} //end namespace diff --git a/APL/ProtocolUtil.h b/APL/ProtocolUtil.h index ee40b4fd..31036a3c 100644 --- a/APL/ProtocolUtil.h +++ b/APL/ProtocolUtil.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PROTOCOL_UTIL_H_ #define __PROTOCOL_UTIL_H_ @@ -24,12 +24,12 @@ namespace apl { -/// Given a buffer and max packet size, calculcate the +/// Given a buffer and max packet size, calculcate the /// maximum number of packets the buffer can hold size_t CalcMaxPackets(size_t aBuffer, size_t aPayload); -/// Given a buffer and max packet size, calculcate the +/// Given a buffer and max packet size, calculcate the /// size of the last packet. size_t CalcLastPacketSize(size_t aBuffer, size_t aPayload); diff --git a/APL/QualityMasks.h b/APL/QualityMasks.h index f4659a8e..3bd68698 100644 --- a/APL/QualityMasks.h +++ b/APL/QualityMasks.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __QUALITY_MASKS_H_ #define __QUALITY_MASKS_H_ @@ -24,7 +24,7 @@ namespace apl { - + /** Bitmasks that make make up the quality field for binaries. The first 5 field are common across all of the data types. */ @@ -63,14 +63,14 @@ namespace apl Bitmasks that make make up the quality field for counters. See BinaryQuality for common (unlabeled) bitmasks. */ enum CounterQuality - { + { CQ_ONLINE = 0x01, CQ_RESTART= 0x02, CQ_COMM_LOST = 0x04, CQ_REMOTE_FORCED_DATA = 0x08, CQ_LOCAL_FORCED_DATA = 0x10, CQ_ROLLOVER = 0x20, //!< used to indicate that the counter filled up and rolledover, cleared automatically after reading - CQ_DISCONTINUITY = 0x40, //!< indicates an unusual change in value + CQ_DISCONTINUITY = 0x40, //!< indicates an unusual change in value CQ_RESERVED = 0x80 }; diff --git a/APL/SerialTypes.h b/APL/SerialTypes.h index f7d425a2..49252855 100644 --- a/APL/SerialTypes.h +++ b/APL/SerialTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __SERIAL_TYPES_H_ #define __SERIAL_TYPES_H_ @@ -44,7 +44,7 @@ namespace apl { int mDataBits; int mStopBits; ParityType mParity; - FlowType mFlowType; + FlowType mFlowType; }; } diff --git a/APL/ShiftableBuffer.cpp b/APL/ShiftableBuffer.cpp index 8913a10f..d24abc88 100644 --- a/APL/ShiftableBuffer.cpp +++ b/APL/ShiftableBuffer.cpp @@ -16,89 +16,89 @@ // specific language governing permissions and limitations // under the License. // -#include "ShiftableBuffer.h" - -#include "Exception.h" - -#include - -namespace apl { - -ShiftableBuffer::ShiftableBuffer(size_t aSize) : -mpBuffer(new byte_t[aSize]), -M_SIZE(aSize), -mWritePos(0), -mReadPos(0) -{ -} - - -ShiftableBuffer::ShiftableBuffer( const byte_t * aBuffer, size_t aSize) : -mpBuffer(new byte_t[aSize]), -M_SIZE(aSize), -mWritePos(0), -mReadPos(0) -{ - if( aBuffer) { - memcpy( mpBuffer, aBuffer, aSize) ; - mWritePos += aSize ; - } -} - - -void ShiftableBuffer::Shift() -{ - //copy all unread data to the front of the buffer - memmove(mpBuffer, this->ReadBuff(), this->NumReadBytes()); - mWritePos = this->NumReadBytes(); - mReadPos = 0; -} - -ShiftableBuffer::~ShiftableBuffer() -{ delete[] mpBuffer; } - - -void ShiftableBuffer::AdvanceRead(size_t aNumBytes) -{ - if(aNumBytes > this->NumReadBytes()) - throw ArgumentException(LOCATION, "Cannot be greater than the number of currently available reader bytes"); - - mReadPos += aNumBytes; -} - -void ShiftableBuffer::AdvanceWrite(size_t aNumBytes) -{ - - if(aNumBytes > this->NumWriteBytes()) // This could indicate a buffer overflow - throw ArgumentException(LOCATION, "Cannot be greater than the number of currently available writer bytes"); - - mWritePos += aNumBytes; -} - -bool ShiftableBuffer::Sync(const byte_t* apPattern, size_t aNumBytes) -{ - if(aNumBytes < 1) throw ArgumentException(LOCATION, "Pattern must be at least 1 byte"); - - size_t offset = SyncSubsequence(apPattern, aNumBytes, 0); - bool res = (this->NumReadBytes() - offset) >= aNumBytes; - if(offset > 0) this->AdvanceRead(offset); - - return res; -} - -size_t ShiftableBuffer::SyncSubsequence(const byte_t* apPattern, size_t aNumPatternBytes, size_t aOffset) -{ - size_t read_bytes = this->NumReadBytes() - aOffset; - if(aNumPatternBytes > read_bytes) aNumPatternBytes = read_bytes; - - const byte_t* pRead = this->ReadBuff() + aOffset; - - for(size_t i=0; i + +namespace apl { + +ShiftableBuffer::ShiftableBuffer(size_t aSize) : +mpBuffer(new byte_t[aSize]), +M_SIZE(aSize), +mWritePos(0), +mReadPos(0) +{ +} + + +ShiftableBuffer::ShiftableBuffer( const byte_t * aBuffer, size_t aSize) : +mpBuffer(new byte_t[aSize]), +M_SIZE(aSize), +mWritePos(0), +mReadPos(0) +{ + if( aBuffer) { + memcpy( mpBuffer, aBuffer, aSize) ; + mWritePos += aSize ; + } +} + + +void ShiftableBuffer::Shift() +{ + //copy all unread data to the front of the buffer + memmove(mpBuffer, this->ReadBuff(), this->NumReadBytes()); + mWritePos = this->NumReadBytes(); + mReadPos = 0; +} + +ShiftableBuffer::~ShiftableBuffer() +{ delete[] mpBuffer; } + + +void ShiftableBuffer::AdvanceRead(size_t aNumBytes) +{ + if(aNumBytes > this->NumReadBytes()) + throw ArgumentException(LOCATION, "Cannot be greater than the number of currently available reader bytes"); + + mReadPos += aNumBytes; +} + +void ShiftableBuffer::AdvanceWrite(size_t aNumBytes) +{ + + if(aNumBytes > this->NumWriteBytes()) // This could indicate a buffer overflow + throw ArgumentException(LOCATION, "Cannot be greater than the number of currently available writer bytes"); + + mWritePos += aNumBytes; +} + +bool ShiftableBuffer::Sync(const byte_t* apPattern, size_t aNumBytes) +{ + if(aNumBytes < 1) throw ArgumentException(LOCATION, "Pattern must be at least 1 byte"); + + size_t offset = SyncSubsequence(apPattern, aNumBytes, 0); + bool res = (this->NumReadBytes() - offset) >= aNumBytes; + if(offset > 0) this->AdvanceRead(offset); + + return res; +} + +size_t ShiftableBuffer::SyncSubsequence(const byte_t* apPattern, size_t aNumPatternBytes, size_t aOffset) +{ + size_t read_bytes = this->NumReadBytes() - aOffset; + if(aNumPatternBytes > read_bytes) aNumPatternBytes = read_bytes; + + const byte_t* pRead = this->ReadBuff() + aOffset; + + for(size_t i=0; i NotifierSet; - public: + public: virtual ~SubjectBase() {} // implement the ISubject interface @@ -41,7 +41,7 @@ class SubjectBase : public ISubject CriticalSection cs(&mSubjectLock); mNotifiers.insert(apNotifier); } - + void RemoveObserver(INotifier* apNotifier) { CriticalSection cs(&mSubjectLock); @@ -49,7 +49,7 @@ class SubjectBase : public ISubject } protected: - + void NotifyAll() { CriticalSection cs(&mSubjectLock); @@ -59,7 +59,7 @@ class SubjectBase : public ISubject } private: - LockType mSubjectLock; + LockType mSubjectLock; NotifierSet mNotifiers; }; diff --git a/APL/SyncVar.h b/APL/SyncVar.h index e6e7cb10..bcda1934 100644 --- a/APL/SyncVar.h +++ b/APL/SyncVar.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __SYNC_VAR_H_ #define __SYNC_VAR_H_ @@ -33,12 +33,12 @@ namespace apl { public: - SyncVar(const T& arInitial) : + SyncVar(const T& arInitial) : mChange(false), mValue(arInitial) {} - SyncVar() : + SyncVar() : mChange(false) {} @@ -47,12 +47,12 @@ namespace apl bool ChangeSinceRead() { return mChange; } /// sets the value to arVal and returns whether the new value == the previous value. - bool Set(const T& arVal) - { + bool Set(const T& arVal) + { bool changed; { - CriticalSection cs(&mLock); - changed = !(mValue == arVal); + CriticalSection cs(&mLock); + changed = !(mValue == arVal); if(changed){ mChange = true; mLock.Broadcast(); @@ -62,10 +62,10 @@ namespace apl if(changed) this->NotifyAll(); return changed; } - - T Get() + + T Get() { CriticalSection cs(&mLock); mChange = false; return mValue; } - + bool WaitUntil(const T& arVal, millis_t aTimeout) { CriticalSection cs(&mLock); @@ -101,7 +101,7 @@ namespace apl bool mChange; // protects the variable. The variable may be something may not be atomically writable. T mValue; - + }; diff --git a/APL/Thread.h b/APL/Thread.h index 9095fcb6..ddda3f88 100644 --- a/APL/Thread.h +++ b/APL/Thread.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __THREAD_H_ #define __THREAD_H_ diff --git a/APL/ThreadBase.h b/APL/ThreadBase.h index 72f8768e..ad47ccef 100644 --- a/APL/ThreadBase.h +++ b/APL/ThreadBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __THREAD_BASE_H_ #define __THREAD_BASE_H_ @@ -33,10 +33,10 @@ class ThreadBase virtual void Start() = 0; virtual void RequestStop(); - virtual void WaitForStop() = 0; + virtual void WaitForStop() = 0; protected: - + //pointer to obejct that conforms to the IThreadable interface Threadable* mpThreadable; diff --git a/APL/ThreadBoost.h b/APL/ThreadBoost.h index 48355f13..7c6207e2 100644 --- a/APL/ThreadBoost.h +++ b/APL/ThreadBoost.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __THREAD_BOOST_H_ #define __THREAD_BOOST_H_ @@ -37,7 +37,7 @@ class ThreadBoost : public ThreadBase { static void SleepFor(millis_t millis, bool ensureSleepForCorrectTime = false); private: - + boost::function0 mEntryPoint; boost::thread* mpThread; diff --git a/APL/Threadable.h b/APL/Threadable.h index 4351fa4b..7be3d597 100644 --- a/APL/Threadable.h +++ b/APL/Threadable.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __THREADABLE_H_ #define __THREADABLE_H_ @@ -39,7 +39,7 @@ class Threadable /// This way any pre/post conditions of Start() can be enforced by the base class void Start(); void RequestStop(); - + ///allows a client to see if the thread is running inline bool IsRunning() { return mIsRunning; } @@ -49,10 +49,10 @@ class Threadable void ResetStopRequest(); virtual std::string Description() const { return "Undescribed threadable"; } - + protected: - + /// allows inherited classes to override and do something to wake the thread virtual void SignalStop(); @@ -64,10 +64,10 @@ class Threadable bool mIsRunning; - + /// inherited objects must implement a run function virtual void Run() = 0; - + }; diff --git a/APL/TimeBase.h b/APL/TimeBase.h index f025df49..5e065575 100644 --- a/APL/TimeBase.h +++ b/APL/TimeBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TIME_BASE_H_ #define __TIME_BASE_H_ @@ -27,7 +27,7 @@ namespace apl { - /** Provides an interface to which any platform-specific + /** Provides an interface to which any platform-specific */ class TimeBase { @@ -37,7 +37,7 @@ namespace apl virtual ~TimeBase(){} virtual void SetToNow() = 0; - virtual apl::millis_t GetElapsedMS() const = 0; + virtual apl::millis_t GetElapsedMS() const = 0; virtual std::string GetTimeString() const = 0; inline size_t GetSecSinceEpoch() const { return mSec; } @@ -48,10 +48,10 @@ namespace apl apl::millis_t GetValueMS() const; static apl::millis_t CalcDeltaMS(const TimeBase& aTime1, const TimeBase& aTime2); - + protected: - + size_t mSec; // seconds since epoch size_t mUsec; // additional micro seconds diff --git a/APL/TimeBoost.h b/APL/TimeBoost.h index efe17e45..83f51d53 100644 --- a/APL/TimeBoost.h +++ b/APL/TimeBoost.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _TIME_BOOST_H_ #define _TIME_BOOST_H_ @@ -34,7 +34,7 @@ using namespace boost::posix_time; namespace apl{ - + class TimeBoost { public: @@ -45,9 +45,9 @@ namespace apl{ ~TimeBoost(); void SetToNow(); - + apl::millis_t GetElapsedMS() const; - + void SetTo(millis_t aTimeMS); void AddMS(millis_t aAddMS); diff --git a/APL/TimeSource.cpp b/APL/TimeSource.cpp index 08a9f34a..db2b52ad 100644 --- a/APL/TimeSource.cpp +++ b/APL/TimeSource.cpp @@ -16,70 +16,70 @@ // specific language governing permissions and limitations // under the License. // -#include "TimeSource.h" - -#include "TimingTools.h" - -using namespace boost::posix_time; - -namespace apl -{ - -//real time source - -TimeSource TimeSource::mInstance; - -ptime TimeSource::GetUTC() -{ - return microsec_clock::universal_time(); -} - -TimeStamp_t TimeSource::GetTimeStampUTC() -{ - return TimeStamp::GetTimeStamp(); -} - -//mock time source -MockTimeSource::MockTimeSource() : -mTime(min_date_time) -{ - -} - -void MockTimeSource::SetTime(TimeStamp_t aTime) -{ - mTime = TimeBoost::GetPTimeFromMS(aTime); -} - -TimeStamp_t MockTimeSource::GetTimeStampUTC() -{ - TimeBoost t(mTime); TimeStamp_t ret(t.GetValueMS()); return ret; -} - -void MockTimeSource::Advance(millis_t aDuration) -{ - mTime += milliseconds(aDuration); -} - -void MockTimeSource::SetToNow() -{ - mTime = microsec_clock::universal_time(); -} - - -TimeSourceSystemOffset::TimeSourceSystemOffset() -: mOffset(0) -{ -} - - -millis_t TimeSourceSystemOffset::GetTime() -{ - return TimeStamp::GetTimeStamp() + mOffset; -} -void TimeSourceSystemOffset::SetTime(millis_t aTime) -{ - mOffset = aTime - TimeStamp::GetTimeStamp(); -} - -} +#include "TimeSource.h" + +#include "TimingTools.h" + +using namespace boost::posix_time; + +namespace apl +{ + +//real time source + +TimeSource TimeSource::mInstance; + +ptime TimeSource::GetUTC() +{ + return microsec_clock::universal_time(); +} + +TimeStamp_t TimeSource::GetTimeStampUTC() +{ + return TimeStamp::GetTimeStamp(); +} + +//mock time source +MockTimeSource::MockTimeSource() : +mTime(min_date_time) +{ + +} + +void MockTimeSource::SetTime(TimeStamp_t aTime) +{ + mTime = TimeBoost::GetPTimeFromMS(aTime); +} + +TimeStamp_t MockTimeSource::GetTimeStampUTC() +{ + TimeBoost t(mTime); TimeStamp_t ret(t.GetValueMS()); return ret; +} + +void MockTimeSource::Advance(millis_t aDuration) +{ + mTime += milliseconds(aDuration); +} + +void MockTimeSource::SetToNow() +{ + mTime = microsec_clock::universal_time(); +} + + +TimeSourceSystemOffset::TimeSourceSystemOffset() +: mOffset(0) +{ +} + + +millis_t TimeSourceSystemOffset::GetTime() +{ + return TimeStamp::GetTimeStamp() + mOffset; +} +void TimeSourceSystemOffset::SetTime(millis_t aTime) +{ + mOffset = aTime - TimeStamp::GetTimeStamp(); +} + +} diff --git a/APL/TimeSource.h b/APL/TimeSource.h index b48cacde..bc6aaeef 100644 --- a/APL/TimeSource.h +++ b/APL/TimeSource.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,79 +6,79 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __TIME_SOURCE_H_ -#define __TIME_SOURCE_H_ - -#include "ITimeSource.h" -#include "Singleton.h" -#include "Types.h" - -#include - -namespace apl -{ - class TimeSource : public ITimeSource - { - MACRO_SINGLETON_INSTANCE(TimeSource) - - /// Implement ITimeSource - boost::posix_time::ptime GetUTC(); - TimeStamp_t GetTimeStampUTC(); - }; - - class MockTimeSource : public ITimeSource - { - public: - - MockTimeSource(); - - /// Implement ITimeSource - boost::posix_time::ptime GetUTC() { return mTime; } - TimeStamp_t GetTimeStampUTC(); - - void SetTime(const boost::posix_time::ptime& arTime) { mTime = arTime; } - void SetTime(TimeStamp_t aTime); - void Advance(millis_t aDuration); - void SetToNow(); - - private: - - boost::posix_time::ptime mTime; - }; - - /** Maintains an external time by keeping an offset from system time. - */ - class TimeSourceSystemOffset : public ITimeManager - { - public: - TimeSourceSystemOffset(); - - millis_t GetTime(); - void SetTime(millis_t aTime); - private: - int_64_t mOffset; - }; - - class MockTimeManager : public ITimeManager - { - public: - MockTimeManager() : mTime(0) {} - millis_t GetTime() { return mTime; } - void SetTime(millis_t aTime) { mTime = aTime; } - private: - millis_t mTime; - }; -} - -#endif - +// +#ifndef __TIME_SOURCE_H_ +#define __TIME_SOURCE_H_ + +#include "ITimeSource.h" +#include "Singleton.h" +#include "Types.h" + +#include + +namespace apl +{ + class TimeSource : public ITimeSource + { + MACRO_SINGLETON_INSTANCE(TimeSource) + + /// Implement ITimeSource + boost::posix_time::ptime GetUTC(); + TimeStamp_t GetTimeStampUTC(); + }; + + class MockTimeSource : public ITimeSource + { + public: + + MockTimeSource(); + + /// Implement ITimeSource + boost::posix_time::ptime GetUTC() { return mTime; } + TimeStamp_t GetTimeStampUTC(); + + void SetTime(const boost::posix_time::ptime& arTime) { mTime = arTime; } + void SetTime(TimeStamp_t aTime); + void Advance(millis_t aDuration); + void SetToNow(); + + private: + + boost::posix_time::ptime mTime; + }; + + /** Maintains an external time by keeping an offset from system time. + */ + class TimeSourceSystemOffset : public ITimeManager + { + public: + TimeSourceSystemOffset(); + + millis_t GetTime(); + void SetTime(millis_t aTime); + private: + int_64_t mOffset; + }; + + class MockTimeManager : public ITimeManager + { + public: + MockTimeManager() : mTime(0) {} + millis_t GetTime() { return mTime; } + void SetTime(millis_t aTime) { mTime = aTime; } + private: + millis_t mTime; + }; +} + +#endif + diff --git a/APL/TimeTypes.h b/APL/TimeTypes.h index fb953192..a0b1be98 100644 --- a/APL/TimeTypes.h +++ b/APL/TimeTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TIME_TYPES_H_ #define __TIME_TYPES_H_ diff --git a/APL/Timeout.cpp b/APL/Timeout.cpp index d85c9956..07627ffd 100644 --- a/APL/Timeout.cpp +++ b/APL/Timeout.cpp @@ -16,51 +16,51 @@ // specific language governing permissions and limitations // under the License. // -#include "Timeout.h" - -namespace apl{ - ////////////////////////////////////////////////////////////////////// - // Timeout - ////////////////////////////////////////////////////////////////////// - - Timeout :: Timeout(apl::millis_t aTimeout) - : mTimeout(aTimeout), mRemaining(aTimeout) - { - - } - - bool Timeout :: IsExpired(bool aUpdateRemaining){ - if(mRemaining <= 0) return true; - if(aUpdateRemaining) UpdateRemaining(); - return mRemaining <= 0; - } - - apl::millis_t Timeout :: Remaining(bool aUpdateRemaining){ - if(mRemaining <= 0) return 0; - if(aUpdateRemaining) UpdateRemaining(); - if(mRemaining < 0) return 0; - return mRemaining; - } - - void Timeout :: Reset(apl::millis_t aTimeout){ - mTimeout = aTimeout; - mRemaining = aTimeout; - mExpireTime.SetToNow(); - } - - void Timeout :: UpdateRemaining(){ - mRemaining = mTimeout - mExpireTime.GetElapsedMS(); - } - apl::Time Timeout :: ExpiryTime() { - Time t = mExpireTime; - t.AddMS(mTimeout); - return t; - } - - apl::TimeStamp_t Timeout :: ExpiryTimeStamp() - { - Time t = mExpireTime; - t.AddMS(mTimeout); - return static_cast(t.GetValueMS()); - } -} +#include "Timeout.h" + +namespace apl{ + ////////////////////////////////////////////////////////////////////// + // Timeout + ////////////////////////////////////////////////////////////////////// + + Timeout :: Timeout(apl::millis_t aTimeout) + : mTimeout(aTimeout), mRemaining(aTimeout) + { + + } + + bool Timeout :: IsExpired(bool aUpdateRemaining){ + if(mRemaining <= 0) return true; + if(aUpdateRemaining) UpdateRemaining(); + return mRemaining <= 0; + } + + apl::millis_t Timeout :: Remaining(bool aUpdateRemaining){ + if(mRemaining <= 0) return 0; + if(aUpdateRemaining) UpdateRemaining(); + if(mRemaining < 0) return 0; + return mRemaining; + } + + void Timeout :: Reset(apl::millis_t aTimeout){ + mTimeout = aTimeout; + mRemaining = aTimeout; + mExpireTime.SetToNow(); + } + + void Timeout :: UpdateRemaining(){ + mRemaining = mTimeout - mExpireTime.GetElapsedMS(); + } + apl::Time Timeout :: ExpiryTime() { + Time t = mExpireTime; + t.AddMS(mTimeout); + return t; + } + + apl::TimeStamp_t Timeout :: ExpiryTimeStamp() + { + Time t = mExpireTime; + t.AddMS(mTimeout); + return static_cast(t.GetValueMS()); + } +} diff --git a/APL/Timeout.h b/APL/Timeout.h index 0d721c69..0059f12c 100644 --- a/APL/Timeout.h +++ b/APL/Timeout.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TIMEOUT_H_ #define __TIMEOUT_H_ @@ -28,7 +28,7 @@ namespace apl{ /// it minimizes the number of calls to get datetime and allows /// us to easily replace the implementation later if we find an /// even more effecient way to implement the timeout checking. - /// + /// /// Intended Usage: /// /// Timeout to(5000); @@ -62,10 +62,10 @@ namespace apl{ private: void UpdateRemaining(); //actually reread the clock. - + apl::millis_t mTimeout; apl::millis_t mRemaining; - + apl::Time mExpireTime; }; diff --git a/APL/TimerASIO.cpp b/APL/TimerASIO.cpp index 4c49f6eb..b02af43d 100644 --- a/APL/TimerASIO.cpp +++ b/APL/TimerASIO.cpp @@ -16,30 +16,30 @@ // specific language governing permissions and limitations // under the License. // -#include "TimerASIO.h" - -namespace apl { - -TimerASIO::TimerASIO(boost::asio::io_service& arService) : -mCanceled(false), -mTimer(arService) -{ - -} - -/** - * Return the timer's expiry time as an absolute time. - */ -boost::posix_time::ptime TimerASIO::ExpiresAt() -{ - return mTimer.expires_at(); -} - -void TimerASIO::Cancel() -{ - assert(!mCanceled); - mTimer.cancel(); - mCanceled = true; -} - -} +#include "TimerASIO.h" + +namespace apl { + +TimerASIO::TimerASIO(boost::asio::io_service& arService) : +mCanceled(false), +mTimer(arService) +{ + +} + +/** + * Return the timer's expiry time as an absolute time. + */ +boost::posix_time::ptime TimerASIO::ExpiresAt() +{ + return mTimer.expires_at(); +} + +void TimerASIO::Cancel() +{ + assert(!mCanceled); + mTimer.cancel(); + mCanceled = true; +} + +} diff --git a/APL/TimerASIO.h b/APL/TimerASIO.h index 9cfbace1..14f498b1 100644 --- a/APL/TimerASIO.h +++ b/APL/TimerASIO.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TIMER_ASIO_H_ #define __TIMER_ASIO_H_ diff --git a/APL/TimerInterfaces.h b/APL/TimerInterfaces.h index 74897b0d..90d3e6b9 100644 --- a/APL/TimerInterfaces.h +++ b/APL/TimerInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TIMER_INTERFACES_H_ #define __TIMER_INTERFACES_H_ @@ -75,7 +75,7 @@ class ITimerSource ITimer* StartInfininte(const ExpirationHandler& arHandler) { - boost::posix_time::ptime t(boost::date_time::max_date_time); + boost::posix_time::ptime t(boost::date_time::max_date_time); return this->Start(t, arHandler); } diff --git a/APL/TimerSourceASIO.cpp b/APL/TimerSourceASIO.cpp index 038981ba..a8544ecb 100644 --- a/APL/TimerSourceASIO.cpp +++ b/APL/TimerSourceASIO.cpp @@ -16,73 +16,73 @@ // specific language governing permissions and limitations // under the License. // -#include "ASIOIncludes.h" - -#include "TimerSourceASIO.h" - -#include "TimerASIO.h" - -#include -#include - -namespace apl { - -TimerSourceASIO::TimerSourceASIO(boost::asio::io_service* apService) : -mpService(apService) -{} - -TimerSourceASIO::~TimerSourceASIO() -{ - BOOST_FOREACH(TimerASIO* pTimer, mAllTimers) { delete pTimer; } -} - -ITimer* TimerSourceASIO::Start(millis_t aDelay, const ExpirationHandler& arCallback) -{ - TimerASIO* pTimer = GetTimer(); - pTimer->mTimer.expires_from_now(boost::posix_time::milliseconds(aDelay)); - this->StartTimer(pTimer, arCallback); - return pTimer; -} - -ITimer* TimerSourceASIO::Start(const boost::posix_time::ptime& arTime, const ExpirationHandler& arCallback) -{ - TimerASIO* pTimer = GetTimer(); - pTimer->mTimer.expires_at(arTime); - this->StartTimer(pTimer, arCallback); - return pTimer; -} - -void TimerSourceASIO::Post(const ExpirationHandler& arHandler) -{ - mpService->post(arHandler); -} - -TimerASIO* TimerSourceASIO::GetTimer() -{ - TimerASIO* pTimer; - if(mIdleTimers.size() == 0) { - pTimer = new TimerASIO(*mpService); - mAllTimers.push_back(pTimer); - } - else { - pTimer = mIdleTimers.front(); - mIdleTimers.pop_front(); - } - - pTimer->mCanceled = false; - return pTimer; -} - -void TimerSourceASIO::StartTimer(TimerASIO* apTimer, const ExpirationHandler& arCallback) -{ - apTimer->mTimer.async_wait(boost::bind(&TimerSourceASIO::OnTimerCallback, this, _1, apTimer, arCallback)); -} - -void TimerSourceASIO::OnTimerCallback(const boost::system::error_code& ec, TimerASIO* apTimer, ExpirationHandler aCallback) -{ - mIdleTimers.push_back(apTimer); - if(! (ec || apTimer->mCanceled) ) aCallback(); -} - -} //end namespace - +#include "ASIOIncludes.h" + +#include "TimerSourceASIO.h" + +#include "TimerASIO.h" + +#include +#include + +namespace apl { + +TimerSourceASIO::TimerSourceASIO(boost::asio::io_service* apService) : +mpService(apService) +{} + +TimerSourceASIO::~TimerSourceASIO() +{ + BOOST_FOREACH(TimerASIO* pTimer, mAllTimers) { delete pTimer; } +} + +ITimer* TimerSourceASIO::Start(millis_t aDelay, const ExpirationHandler& arCallback) +{ + TimerASIO* pTimer = GetTimer(); + pTimer->mTimer.expires_from_now(boost::posix_time::milliseconds(aDelay)); + this->StartTimer(pTimer, arCallback); + return pTimer; +} + +ITimer* TimerSourceASIO::Start(const boost::posix_time::ptime& arTime, const ExpirationHandler& arCallback) +{ + TimerASIO* pTimer = GetTimer(); + pTimer->mTimer.expires_at(arTime); + this->StartTimer(pTimer, arCallback); + return pTimer; +} + +void TimerSourceASIO::Post(const ExpirationHandler& arHandler) +{ + mpService->post(arHandler); +} + +TimerASIO* TimerSourceASIO::GetTimer() +{ + TimerASIO* pTimer; + if(mIdleTimers.size() == 0) { + pTimer = new TimerASIO(*mpService); + mAllTimers.push_back(pTimer); + } + else { + pTimer = mIdleTimers.front(); + mIdleTimers.pop_front(); + } + + pTimer->mCanceled = false; + return pTimer; +} + +void TimerSourceASIO::StartTimer(TimerASIO* apTimer, const ExpirationHandler& arCallback) +{ + apTimer->mTimer.async_wait(boost::bind(&TimerSourceASIO::OnTimerCallback, this, _1, apTimer, arCallback)); +} + +void TimerSourceASIO::OnTimerCallback(const boost::system::error_code& ec, TimerASIO* apTimer, ExpirationHandler aCallback) +{ + mIdleTimers.push_back(apTimer); + if(! (ec || apTimer->mCanceled) ) aCallback(); +} + +} //end namespace + diff --git a/APL/TimerSourceASIO.h b/APL/TimerSourceASIO.h index 1e89c2c3..90ad3d66 100644 --- a/APL/TimerSourceASIO.h +++ b/APL/TimerSourceASIO.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,59 +6,59 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __TIMER_SOURCE_ASIO_H_ -#define __TIMER_SOURCE_ASIO_H_ - -#include "TimerInterfaces.h" - -#include - -namespace boost { - -namespace asio { class io_service; } -namespace system { class error_code; } - -} - -namespace apl { - - class TimerASIO; - - class TimerSourceASIO : public ITimerSource - { - public: - TimerSourceASIO(boost::asio::io_service*); - ~TimerSourceASIO(); - - ITimer* Start(millis_t, const ExpirationHandler&); - ITimer* Start(const boost::posix_time::ptime&, const ExpirationHandler&); - void Post(const ExpirationHandler&); - - private: - - TimerASIO* GetTimer(); - void StartTimer(TimerASIO*, const ExpirationHandler&); - - boost::asio::io_service* mpService; - - typedef std::deque TimerQueue; - - TimerQueue mAllTimers; - TimerQueue mIdleTimers; - - void OnTimerCallback(const boost::system::error_code&, TimerASIO*, ExpirationHandler); - }; -} - -#endif - +// +#ifndef __TIMER_SOURCE_ASIO_H_ +#define __TIMER_SOURCE_ASIO_H_ + +#include "TimerInterfaces.h" + +#include + +namespace boost { + +namespace asio { class io_service; } +namespace system { class error_code; } + +} + +namespace apl { + + class TimerASIO; + + class TimerSourceASIO : public ITimerSource + { + public: + TimerSourceASIO(boost::asio::io_service*); + ~TimerSourceASIO(); + + ITimer* Start(millis_t, const ExpirationHandler&); + ITimer* Start(const boost::posix_time::ptime&, const ExpirationHandler&); + void Post(const ExpirationHandler&); + + private: + + TimerASIO* GetTimer(); + void StartTimer(TimerASIO*, const ExpirationHandler&); + + boost::asio::io_service* mpService; + + typedef std::deque TimerQueue; + + TimerQueue mAllTimers; + TimerQueue mIdleTimers; + + void OnTimerCallback(const boost::system::error_code&, TimerASIO*, ExpirationHandler); + }; +} + +#endif + diff --git a/APL/TimingTools.h b/APL/TimingTools.h index 7c5c0720..d11739ba 100644 --- a/APL/TimingTools.h +++ b/APL/TimingTools.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _TIMINGTOOLS_H__ @@ -46,7 +46,7 @@ namespace apl{ apl::Time mStartTime; }; - /** Light-weight alternative to Time class. + /** Light-weight alternative to Time class. */ class TimeStamp{ public: @@ -57,7 +57,7 @@ namespace apl{ const static TimeStamp_t MAX; const static TimeStamp_t MIN; - + }; } diff --git a/APL/ToHex.cpp b/APL/ToHex.cpp index db7ddb35..4d541804 100644 --- a/APL/ToHex.cpp +++ b/APL/ToHex.cpp @@ -16,24 +16,24 @@ // specific language governing permissions and limitations // under the License. // -#include "ToHex.h" - - - -namespace apl { - -char toHex(char c) -{ - if(c > 9) return 'A' + (c-10); - return '0' + c; -} - -std::string ByteToHex(byte_t b) -{ - std::ostringstream oss; - oss << toHex((b&0xf0)>>4) << toHex(b&0xf); - return oss.str(); -} - -} - +#include "ToHex.h" + + + +namespace apl { + +char toHex(char c) +{ + if(c > 9) return 'A' + (c-10); + return '0' + c; +} + +std::string ByteToHex(byte_t b) +{ + std::ostringstream oss; + oss << toHex((b&0xf0)>>4) << toHex(b&0xf); + return oss.str(); +} + +} + diff --git a/APL/ToHex.h b/APL/ToHex.h index 93a87a64..53686095 100644 --- a/APL/ToHex.h +++ b/APL/ToHex.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,46 +6,46 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __TO_HEX_H_ -#define __TO_HEX_H_ - -#include "Types.h" -#include -#include - -namespace apl { - - char toHex(char c); - std::string ByteToHex(byte_t b); - - template - std::string toHex(T aBuff, size_t aLength, bool spaced = false) - { - std::ostringstream oss; - size_t last = aLength - 1; - for(size_t i=0; i < aLength; i++){ - char c = aBuff[i]; - oss << toHex((c&0xf0)>>4) << toHex(c&0xf); - if(spaced && i!=last)oss << " "; - } - return oss.str(); - }; - - template - std::string TypeToHex(T x) - { - return toHex(reinterpret_cast(&x), sizeof(T), true); - } -} - -#endif +// +#ifndef __TO_HEX_H_ +#define __TO_HEX_H_ + +#include "Types.h" +#include +#include + +namespace apl { + + char toHex(char c); + std::string ByteToHex(byte_t b); + + template + std::string toHex(T aBuff, size_t aLength, bool spaced = false) + { + std::ostringstream oss; + size_t last = aLength - 1; + for(size_t i=0; i < aLength; i++){ + char c = aBuff[i]; + oss << toHex((c&0xf0)>>4) << toHex(c&0xf); + if(spaced && i!=last)oss << " "; + } + return oss.str(); + }; + + template + std::string TypeToHex(T x) + { + return toHex(reinterpret_cast(&x), sizeof(T), true); + } +} + +#endif diff --git a/APL/Types.h b/APL/Types.h index 14f5d8bb..2604f839 100644 --- a/APL/Types.h +++ b/APL/Types.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TYPES_H_ #define __TYPES_H_ @@ -23,11 +23,11 @@ namespace apl { //byte types typedef unsigned char byte_t; - + //16 bit types typedef signed short int_16_t; typedef unsigned short uint_16_t; - + //32 bit types typedef signed int int_32_t; typedef unsigned int uint_32_t; @@ -35,7 +35,7 @@ namespace apl //64 bit types typedef long long int_64_t; typedef unsigned long long uint_64_t; - + #ifndef SIZE_MAX #define SIZE_MAX ~0 #endif diff --git a/APL/Uncopyable.h b/APL/Uncopyable.h index cbdf4a43..acbea5fb 100644 --- a/APL/Uncopyable.h +++ b/APL/Uncopyable.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __UNCOPYABLE_H_ #define __UNCOPYABLE_H_ diff --git a/APL/Util.cpp b/APL/Util.cpp index 048a37ce..ad6f0148 100644 --- a/APL/Util.cpp +++ b/APL/Util.cpp @@ -16,105 +16,105 @@ // specific language governing permissions and limitations // under the License. // -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Util.h" - -#ifdef WIN32 -#define sscanf sscanf_s -#endif - -#include "TimingTools.h" -#include "Exception.h" - -using namespace std; -using namespace boost::posix_time; - -#include -#include - - -namespace apl{ - - std::string Month(int aMonth) - { - switch(aMonth) - { - case(1): return "Jan"; - case(2): return "Feb"; - case(3): return "Mar"; - case(4): return "Apr"; - case(5): return "May"; - case(6): return "Jun"; - case(7): return "Jul"; - case(8): return "Aug"; - case(9): return "Sep"; - case(10): return "Oct"; - case(11): return "Nov"; - case(12): return "Dec"; - default: return "Unknown month"; - } - } - - std::string ToNormalizedString(const boost::posix_time::ptime& arTime) - { - ostringstream oss; - time_duration tod = arTime.time_of_day(); - int year = arTime.date().year(); - int month = arTime.date().month(); - int day = arTime.date().day(); - int_64_t millisec = tod.fractional_seconds()/1000; - oss.precision(2); - oss << year << "-" << Month(month) << "-"; - oss << setw(2) << setfill('0') << day << " "; - oss << setw(2) << setfill('0') << tod.hours() << ":"; - oss << setw(2) << setfill('0') << tod.minutes() << ":"; - oss << setw(2) << setfill('0') << tod.seconds() << "."; - oss << setw(3) << setfill('0') << millisec; - return oss.str(); - } - - void ClearScreen() - { - #ifdef APL_PLATFORM_WIN - system("cls"); - #else - system("clear"); - #endif - } - - double SafeCastInt64ToDouble(int_64_t aInput){ - // fix for arm compiler bug -#ifdef ARM - long upper = (aInput & 0xFFFFFFFF00000000LL) >> 32; - unsigned long lower = (aInput & 0x00000000FFFFFFFFLL); - - //Shift the upper portion back into the correct range ( e1<(aInput); -#endif - } - - void toUpperCase(std::string& apStr){ - //from http://gethelp.devx.com/techtips/cpp_pro/10min/2002/Oct/10min1002-2.asp - std::transform(apStr.begin(), apStr.end(), apStr.begin(), (int(*)(int)) toupper); - } - void toLowerCase(std::string& apStr){ - //from http://gethelp.devx.com/techtips/cpp_pro/10min/2002/Oct/10min1002-2.asp - std::transform(apStr.begin(), apStr.end(), apStr.begin(), (int(*)(int)) tolower); - } - -} +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Util.h" + +#ifdef WIN32 +#define sscanf sscanf_s +#endif + +#include "TimingTools.h" +#include "Exception.h" + +using namespace std; +using namespace boost::posix_time; + +#include +#include + + +namespace apl{ + + std::string Month(int aMonth) + { + switch(aMonth) + { + case(1): return "Jan"; + case(2): return "Feb"; + case(3): return "Mar"; + case(4): return "Apr"; + case(5): return "May"; + case(6): return "Jun"; + case(7): return "Jul"; + case(8): return "Aug"; + case(9): return "Sep"; + case(10): return "Oct"; + case(11): return "Nov"; + case(12): return "Dec"; + default: return "Unknown month"; + } + } + + std::string ToNormalizedString(const boost::posix_time::ptime& arTime) + { + ostringstream oss; + time_duration tod = arTime.time_of_day(); + int year = arTime.date().year(); + int month = arTime.date().month(); + int day = arTime.date().day(); + int_64_t millisec = tod.fractional_seconds()/1000; + oss.precision(2); + oss << year << "-" << Month(month) << "-"; + oss << setw(2) << setfill('0') << day << " "; + oss << setw(2) << setfill('0') << tod.hours() << ":"; + oss << setw(2) << setfill('0') << tod.minutes() << ":"; + oss << setw(2) << setfill('0') << tod.seconds() << "."; + oss << setw(3) << setfill('0') << millisec; + return oss.str(); + } + + void ClearScreen() + { + #ifdef APL_PLATFORM_WIN + system("cls"); + #else + system("clear"); + #endif + } + + double SafeCastInt64ToDouble(int_64_t aInput){ + // fix for arm compiler bug +#ifdef ARM + long upper = (aInput & 0xFFFFFFFF00000000LL) >> 32; + unsigned long lower = (aInput & 0x00000000FFFFFFFFLL); + + //Shift the upper portion back into the correct range ( e1<(aInput); +#endif + } + + void toUpperCase(std::string& apStr){ + //from http://gethelp.devx.com/techtips/cpp_pro/10min/2002/Oct/10min1002-2.asp + std::transform(apStr.begin(), apStr.end(), apStr.begin(), (int(*)(int)) toupper); + } + void toLowerCase(std::string& apStr){ + //from http://gethelp.devx.com/techtips/cpp_pro/10min/2002/Oct/10min1002-2.asp + std::transform(apStr.begin(), apStr.end(), apStr.begin(), (int(*)(int)) tolower); + } + +} diff --git a/APL/Util.h b/APL/Util.h index 7806d70d..60c4a3e5 100644 --- a/APL/Util.h +++ b/APL/Util.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,52 +6,52 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include -#include -#include -#include -#include - -#include "Types.h" -#include "Configure.h" - -namespace boost { namespace posix_time { class ptime; } } - -namespace apl -{ - void ClearScreen(); - - template - bool FloatEqual(T a, T b, T eapllon = 1e-6) - { - T diff = a - b; - if(diff < 0) diff = -diff; - return diff <= eapllon; - } - - - double SafeCastInt64ToDouble(int_64_t aInput); - - void toUpperCase(std::string& aStr); - void toLowerCase(std::string& aStr); - - - std::string ToNormalizedString(const boost::posix_time::ptime& arTime); - - -} - -#endif +// +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include +#include +#include +#include +#include + +#include "Types.h" +#include "Configure.h" + +namespace boost { namespace posix_time { class ptime; } } + +namespace apl +{ + void ClearScreen(); + + template + bool FloatEqual(T a, T b, T eapllon = 1e-6) + { + T diff = a - b; + if(diff < 0) diff = -diff; + return diff <= eapllon; + } + + + double SafeCastInt64ToDouble(int_64_t aInput); + + void toUpperCase(std::string& aStr); + void toLowerCase(std::string& aStr); + + + std::string ToNormalizedString(const boost::posix_time::ptime& arTime); + + +} + +#endif diff --git a/APL/rake.project.rb b/APL/rake.project.rb index ab6dfc30..ec1c3766 100644 --- a/APL/rake.project.rb +++ b/APL/rake.project.rb @@ -16,8 +16,8 @@ # specific language governing permissions and limitations # under the License. # - -$options = { -:target => 'libapl.a', -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -} + +$options = { +:target => 'libapl.a', +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +} diff --git a/APLTestTools/APLTestTools.vcproj b/APLTestTools/APLTestTools.vcproj index 65c9f918..2ee09790 100755 --- a/APLTestTools/APLTestTools.vcproj +++ b/APLTestTools/APLTestTools.vcproj @@ -1,294 +1,294 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/APLTestTools/AsyncTestObject.h b/APLTestTools/AsyncTestObject.h index 4dddab80..50bbef75 100644 --- a/APLTestTools/AsyncTestObject.h +++ b/APLTestTools/AsyncTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TEST_OBJECT_H_ #define __ASYNC_TEST_OBJECT_H_ @@ -29,12 +29,12 @@ namespace apl { { public: AsyncTestObject(){} - + bool ProceedUntil(const EvalFunc& arFunc, millis_t aTimeout = G_TEST_TIMEOUT); - bool ProceedUntilFalse(const EvalFunc& arFunc, millis_t aTimeout = G_TEST_TIMEOUT); + bool ProceedUntilFalse(const EvalFunc& arFunc, millis_t aTimeout = G_TEST_TIMEOUT); static bool Negate(const EvalFunc& arFunc) { return !arFunc(); } - + protected: /// Inherited classes implement this function. Test functions iteratively call this function /// to try and make progress diff --git a/APLTestTools/AsyncTestObjectASIO.h b/APLTestTools/AsyncTestObjectASIO.h index e868f792..8392be3b 100644 --- a/APLTestTools/AsyncTestObjectASIO.h +++ b/APLTestTools/AsyncTestObjectASIO.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TEST_OBJECT_ASIO_H_ #define __ASYNC_TEST_OBJECT_ASIO_H_ @@ -33,9 +33,9 @@ namespace apl { AsyncTestObjectASIO(); AsyncTestObjectASIO(boost::asio::io_service*); virtual ~AsyncTestObjectASIO(); - + boost::asio::io_service* GetService() { return mpTestObjectService; } - + private: boost::asio::io_service* mpTestObjectService; bool mOwner; diff --git a/APLTestTools/BufferHelpers.cpp b/APLTestTools/BufferHelpers.cpp index 4d36df68..1572eab0 100644 --- a/APLTestTools/BufferHelpers.cpp +++ b/APLTestTools/BufferHelpers.cpp @@ -16,89 +16,89 @@ // specific language governing permissions and limitations // under the License. // -#include "BufferHelpers.h" - -#include -#include - -#include - -using namespace std; - -namespace apl { - - - ByteStr::ByteStr(size_t aLength) : CopyableBuffer(aLength) - {} - - ByteStr::ByteStr(size_t aLength, byte_t aSeed) : CopyableBuffer(aLength) - { - for(size_t i=0; i((i+aSeed)%256); - } - - ByteStr::ByteStr(const byte_t* apData, size_t aLength) : CopyableBuffer(aLength) - { - memcpy(mpBuff, apData, aLength); - } - - ByteStr::ByteStr(const std::string& aChars) : CopyableBuffer(aChars.size()) - { - memcpy(mpBuff, aChars.c_str(), aChars.size()); - } - - bool ByteStr::operator==(const ByteStr& arRHS) const - { - if(Size() != arRHS.Size()) return false; - - for(size_t i=0; i> val).fail()) { - throw ArgumentException(LOCATION, aSequence); - } - mpBuff[index] = static_cast(val); - } - } - - std::string HexSequence::RemoveSpaces(const std::string& aSequence) - { - std::string copy(aSequence); - RemoveSpacesInPlace(copy); - return copy; - } - - void HexSequence::RemoveSpacesInPlace(std::string& s) - { - size_t pos = s.find_first_of(' '); - if(pos != string::npos) { - s.replace(pos, 1, ""); - RemoveSpacesInPlace(s); - } - } - - size_t HexSequence::Validate(const std::string& s) - { - //annoying when you accidentally put an 'O' instead of zero '0' - if(s.find_first_of( "oO") != string::npos) - throw ArgumentException(LOCATION, "Sequence contains 'o' or 'O'"); - - if(s.size()%2 != 0) throw ArgumentException(LOCATION, s); - return s.size()/2; - } - -} - - +#include "BufferHelpers.h" + +#include +#include + +#include + +using namespace std; + +namespace apl { + + + ByteStr::ByteStr(size_t aLength) : CopyableBuffer(aLength) + {} + + ByteStr::ByteStr(size_t aLength, byte_t aSeed) : CopyableBuffer(aLength) + { + for(size_t i=0; i((i+aSeed)%256); + } + + ByteStr::ByteStr(const byte_t* apData, size_t aLength) : CopyableBuffer(aLength) + { + memcpy(mpBuff, apData, aLength); + } + + ByteStr::ByteStr(const std::string& aChars) : CopyableBuffer(aChars.size()) + { + memcpy(mpBuff, aChars.c_str(), aChars.size()); + } + + bool ByteStr::operator==(const ByteStr& arRHS) const + { + if(Size() != arRHS.Size()) return false; + + for(size_t i=0; i> val).fail()) { + throw ArgumentException(LOCATION, aSequence); + } + mpBuff[index] = static_cast(val); + } + } + + std::string HexSequence::RemoveSpaces(const std::string& aSequence) + { + std::string copy(aSequence); + RemoveSpacesInPlace(copy); + return copy; + } + + void HexSequence::RemoveSpacesInPlace(std::string& s) + { + size_t pos = s.find_first_of(' '); + if(pos != string::npos) { + s.replace(pos, 1, ""); + RemoveSpacesInPlace(s); + } + } + + size_t HexSequence::Validate(const std::string& s) + { + //annoying when you accidentally put an 'O' instead of zero '0' + if(s.find_first_of( "oO") != string::npos) + throw ArgumentException(LOCATION, "Sequence contains 'o' or 'O'"); + + if(s.size()%2 != 0) throw ArgumentException(LOCATION, s); + return s.size()/2; + } + +} + + diff --git a/APLTestTools/BufferHelpers.h b/APLTestTools/BufferHelpers.h index ceacd456..af43154a 100644 --- a/APLTestTools/BufferHelpers.h +++ b/APLTestTools/BufferHelpers.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,53 +6,53 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __BUFFER_HELPERS_H_ -#define __BUFFER_HELPERS_H_ - -#include -#include - -namespace apl { - - -class ByteStr : public CopyableBuffer -{ - - public: - ByteStr(size_t aLength); - ByteStr(size_t aLength, byte_t aSeed); - ByteStr(const byte_t* apData, size_t aLength); - ByteStr(const std::string& aChars); - bool operator==(const ByteStr& arRHS) const; -}; - -/** - * A sequence of hex values in the form "01 02 03 04" that - * are stored as a ByteStr. - * - */ -class HexSequence : public ByteStr -{ - public: - HexSequence(const std::string& aSequence); - - private: - std::string RemoveSpaces(const std::string& aSequence); - void RemoveSpacesInPlace(std::string& aSequence); - static size_t Validate(const std::string& aSequence); -}; - - -} - -#endif +// +#ifndef __BUFFER_HELPERS_H_ +#define __BUFFER_HELPERS_H_ + +#include +#include + +namespace apl { + + +class ByteStr : public CopyableBuffer +{ + + public: + ByteStr(size_t aLength); + ByteStr(size_t aLength, byte_t aSeed); + ByteStr(const byte_t* apData, size_t aLength); + ByteStr(const std::string& aChars); + bool operator==(const ByteStr& arRHS) const; +}; + +/** + * A sequence of hex values in the form "01 02 03 04" that + * are stored as a ByteStr. + * + */ +class HexSequence : public ByteStr +{ + public: + HexSequence(const std::string& aSequence); + + private: + std::string RemoveSpaces(const std::string& aSequence); + void RemoveSpacesInPlace(std::string& aSequence); + static size_t Validate(const std::string& aSequence); +}; + + +} + +#endif diff --git a/APLTestTools/BufferTestObject.cpp b/APLTestTools/BufferTestObject.cpp index 4e641fb6..dba4cac9 100644 --- a/APLTestTools/BufferTestObject.cpp +++ b/APLTestTools/BufferTestObject.cpp @@ -16,78 +16,78 @@ // specific language governing permissions and limitations // under the License. // -#include "BufferTestObject.h" - -#include "BufferHelpers.h" - -#include -#include -#include - -#include - -namespace apl { - -BufferTestObject::BufferTestObject() : -mNumWrites(0) -{ - -} - -BufferTestObject::~BufferTestObject() -{ - -} - -void BufferTestObject::ClearBuffer() -{ - mNumWrites = 0; - mBuffer.clear(); -} - -bool BufferTestObject::BufferEquals(const byte_t* apData, size_t aNumBytes) -{ - - if(aNumBytes != mBuffer.size()) return false; - for(size_t i=0; i< aNumBytes; i++) - if(apData[i] != mBuffer[i]) { - return false; - } - return true; -} - -bool BufferTestObject::BufferContains(const std::string& arPattern) -{ - std::string s; - for(size_t i = 0; i < mBuffer.size(); ++i) { - std::string c(1, static_cast(mBuffer[i])); - s.append(c); - } - return s.find(arPattern) != std::string::npos; -} - -bool BufferTestObject::BufferEquals(const std::string& arData) -{ - HexSequence hs(arData); - return BufferEquals(hs.Buffer(), hs.Size()); -} - -bool BufferTestObject::BufferEqualsString(const std::string& arData) -{ - if(arData.size() != mBuffer.size()) return false; - for(size_t i=0; i< mBuffer.size(); i++) - if(arData[i] != mBuffer[i]) { - return false; - } - return true; -} - -void BufferTestObject::WriteToBuffer(const byte_t* apData, size_t aNumBytes) -{ - if( (mBuffer.size() + aNumBytes) > MAX_SIZE ) throw Exception(LOCATION, "Max size exceeded"); - ++mNumWrites; - for(size_t i=0; i +#include +#include + +#include + +namespace apl { + +BufferTestObject::BufferTestObject() : +mNumWrites(0) +{ + +} + +BufferTestObject::~BufferTestObject() +{ + +} + +void BufferTestObject::ClearBuffer() +{ + mNumWrites = 0; + mBuffer.clear(); +} + +bool BufferTestObject::BufferEquals(const byte_t* apData, size_t aNumBytes) +{ + + if(aNumBytes != mBuffer.size()) return false; + for(size_t i=0; i< aNumBytes; i++) + if(apData[i] != mBuffer[i]) { + return false; + } + return true; +} + +bool BufferTestObject::BufferContains(const std::string& arPattern) +{ + std::string s; + for(size_t i = 0; i < mBuffer.size(); ++i) { + std::string c(1, static_cast(mBuffer[i])); + s.append(c); + } + return s.find(arPattern) != std::string::npos; +} + +bool BufferTestObject::BufferEquals(const std::string& arData) +{ + HexSequence hs(arData); + return BufferEquals(hs.Buffer(), hs.Size()); +} + +bool BufferTestObject::BufferEqualsString(const std::string& arData) +{ + if(arData.size() != mBuffer.size()) return false; + for(size_t i=0; i< mBuffer.size(); i++) + if(arData[i] != mBuffer[i]) { + return false; + } + return true; +} + +void BufferTestObject::WriteToBuffer(const byte_t* apData, size_t aNumBytes) +{ + if( (mBuffer.size() + aNumBytes) > MAX_SIZE ) throw Exception(LOCATION, "Max size exceeded"); + ++mNumWrites; + for(size_t i=0; i #include -namespace apl { +namespace apl { class ByteStr; - + class BufferTestObject { static const size_t MAX_SIZE = 1024*1024; @@ -33,7 +33,7 @@ class BufferTestObject public: BufferTestObject(); ~BufferTestObject(); - + bool BufferEquals(const byte_t*, size_t); bool BufferEquals(const std::string& arData); bool BufferEqualsString(const std::string& arData); @@ -46,7 +46,7 @@ class BufferTestObject protected: void WriteToBuffer(const byte_t*, size_t); - + private: size_t mNumWrites; std::vector mBuffer; diff --git a/APLTestTools/LogTester.cpp b/APLTestTools/LogTester.cpp index 2d4d94c5..cef484fc 100644 --- a/APLTestTools/LogTester.cpp +++ b/APLTestTools/LogTester.cpp @@ -16,49 +16,49 @@ // specific language governing permissions and limitations // under the License. // -#include "LogTester.h" - -#include - -namespace apl { - -LogTester::LogTester(bool aImmediate) : -mBuffer(100) -{ - mLog.AddLogSubscriber(&mBuffer); - if(aImmediate) mLog.AddLogSubscriber(LogToStdio::Inst()); -} - -int LogTester::ClearLog() -{ - int max = -1; - LogEntry le; - while(mBuffer.ReadLog(le)) { - if(le.GetErrorCode() > max) max = le.GetErrorCode(); - } - - return max; -} - -void LogTester::SetVar(const std::string& aSource, const std::string& aVarName, int aValue) -{ - -} - -int LogTester::NextErrorCode() -{ - LogEntry le; - while(mBuffer.ReadLog(le)) - { - if(le.GetErrorCode() >= 0) return le.GetErrorCode(); - } - return -1; -} - -bool LogTester::IsLogErrorFree() -{ - return ClearLog() < 0; -} - -} - +#include "LogTester.h" + +#include + +namespace apl { + +LogTester::LogTester(bool aImmediate) : +mBuffer(100) +{ + mLog.AddLogSubscriber(&mBuffer); + if(aImmediate) mLog.AddLogSubscriber(LogToStdio::Inst()); +} + +int LogTester::ClearLog() +{ + int max = -1; + LogEntry le; + while(mBuffer.ReadLog(le)) { + if(le.GetErrorCode() > max) max = le.GetErrorCode(); + } + + return max; +} + +void LogTester::SetVar(const std::string& aSource, const std::string& aVarName, int aValue) +{ + +} + +int LogTester::NextErrorCode() +{ + LogEntry le; + while(mBuffer.ReadLog(le)) + { + if(le.GetErrorCode() >= 0) return le.GetErrorCode(); + } + return -1; +} + +bool LogTester::IsLogErrorFree() +{ + return ClearLog() < 0; +} + +} + diff --git a/APLTestTools/LogTester.h b/APLTestTools/LogTester.h index 585e2833..3d4ad605 100644 --- a/APLTestTools/LogTester.h +++ b/APLTestTools/LogTester.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LOG_TESTER_H_ #define __LOG_TESTER_H_ @@ -38,7 +38,7 @@ class LogTester : public ILogBase EventLog& GetLog(){return mLog;} protected: - + EventLog mLog; LogEntryCircularBuffer mBuffer; diff --git a/APLTestTools/LoopbackPhysicalLayerAsync.cpp b/APLTestTools/LoopbackPhysicalLayerAsync.cpp index 1066e436..472bad0b 100644 --- a/APLTestTools/LoopbackPhysicalLayerAsync.cpp +++ b/APLTestTools/LoopbackPhysicalLayerAsync.cpp @@ -16,88 +16,88 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "LoopbackPhysicalLayerAsync.h" - -#include -#include - -using namespace boost; -using namespace boost::system; - -namespace apl { - -LoopbackPhysicalLayerAsync::LoopbackPhysicalLayerAsync(Logger* apLogger, boost::asio::io_service* apSrv) : -PhysicalLayerAsyncBase(apLogger), -mpService(apSrv), -mReadSize(0), -mpReadBuff(NULL) -{ - -} - -void LoopbackPhysicalLayerAsync::DoOpen() -{ - //always open successfully - error_code ec(errc::success, get_generic_category()); - mpService->post(bind(&LoopbackPhysicalLayerAsync::OnOpenCallback, this, ec)); -} - -void LoopbackPhysicalLayerAsync::DoOpenSuccess() -{ - LOG_BLOCK(LEV_INFO, "Loopback Open Success"); -} - -void LoopbackPhysicalLayerAsync::DoClose() -{ - //empty any remaining written data - mWritten.erase(mWritten.begin(), mWritten.end()); - - //dispatch any pending reads with failures - if(mReadSize > 0) { - mReadSize = 0; - error_code ec(errc::permission_denied, get_generic_category()); - mpService->post(bind(&LoopbackPhysicalLayerAsync::OnReadCallback, this, ec, mpReadBuff, 0)); - } -} - -void LoopbackPhysicalLayerAsync::DoAsyncRead(byte_t* apBuff, size_t aNumBytes) -{ - assert(mReadSize == 0); - mReadSize = aNumBytes; - mpReadBuff = apBuff; - - this->CheckForReadDispatch(); -} - -void LoopbackPhysicalLayerAsync::DoAsyncWrite(const byte_t* apData, size_t aNumBytes) -{ - for(size_t i=0; ipost(bind(&LoopbackPhysicalLayerAsync::OnWriteCallback, this, ec, aNumBytes)); - - //now check to see if this write will dispatch a read - this->CheckForReadDispatch(); -} - -void LoopbackPhysicalLayerAsync::CheckForReadDispatch() -{ - if(mReadSize > 0 && mWritten.size() > 0) { - size_t num = (mReadSize < mWritten.size()) ? mReadSize : mWritten.size(); - - for(size_t i=0; ipost(bind(&LoopbackPhysicalLayerAsync::OnReadCallback, this, ec, mpReadBuff, num)); - } - -} - -} +#include +#include "LoopbackPhysicalLayerAsync.h" + +#include +#include + +using namespace boost; +using namespace boost::system; + +namespace apl { + +LoopbackPhysicalLayerAsync::LoopbackPhysicalLayerAsync(Logger* apLogger, boost::asio::io_service* apSrv) : +PhysicalLayerAsyncBase(apLogger), +mpService(apSrv), +mReadSize(0), +mpReadBuff(NULL) +{ + +} + +void LoopbackPhysicalLayerAsync::DoOpen() +{ + //always open successfully + error_code ec(errc::success, get_generic_category()); + mpService->post(bind(&LoopbackPhysicalLayerAsync::OnOpenCallback, this, ec)); +} + +void LoopbackPhysicalLayerAsync::DoOpenSuccess() +{ + LOG_BLOCK(LEV_INFO, "Loopback Open Success"); +} + +void LoopbackPhysicalLayerAsync::DoClose() +{ + //empty any remaining written data + mWritten.erase(mWritten.begin(), mWritten.end()); + + //dispatch any pending reads with failures + if(mReadSize > 0) { + mReadSize = 0; + error_code ec(errc::permission_denied, get_generic_category()); + mpService->post(bind(&LoopbackPhysicalLayerAsync::OnReadCallback, this, ec, mpReadBuff, 0)); + } +} + +void LoopbackPhysicalLayerAsync::DoAsyncRead(byte_t* apBuff, size_t aNumBytes) +{ + assert(mReadSize == 0); + mReadSize = aNumBytes; + mpReadBuff = apBuff; + + this->CheckForReadDispatch(); +} + +void LoopbackPhysicalLayerAsync::DoAsyncWrite(const byte_t* apData, size_t aNumBytes) +{ + for(size_t i=0; ipost(bind(&LoopbackPhysicalLayerAsync::OnWriteCallback, this, ec, aNumBytes)); + + //now check to see if this write will dispatch a read + this->CheckForReadDispatch(); +} + +void LoopbackPhysicalLayerAsync::CheckForReadDispatch() +{ + if(mReadSize > 0 && mWritten.size() > 0) { + size_t num = (mReadSize < mWritten.size()) ? mReadSize : mWritten.size(); + + for(size_t i=0; ipost(bind(&LoopbackPhysicalLayerAsync::OnReadCallback, this, ec, mpReadBuff, num)); + } + +} + +} diff --git a/APLTestTools/LoopbackPhysicalLayerAsync.h b/APLTestTools/LoopbackPhysicalLayerAsync.h index c04143bb..d6b954e3 100644 --- a/APLTestTools/LoopbackPhysicalLayerAsync.h +++ b/APLTestTools/LoopbackPhysicalLayerAsync.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,54 +6,54 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __LOOP_BACK_PHYSICAL_LAYER_ASYNC_H_ -#define __LOOP_BACK_PHYSICAL_LAYER_ASYNC_H_ - -#include -#include - -#include - -namespace boost { namespace asio { - class io_service; -}} - -namespace apl { - - /// Provides a backend for testing physical layers - class LoopbackPhysicalLayerAsync : public PhysicalLayerAsyncBase - { - public: - LoopbackPhysicalLayerAsync(Logger*, boost::asio::io_service* apSrv); - - - private: - - void DoOpen(); - void DoClose(); - void DoOpenSuccess(); - void DoAsyncRead(byte_t* apBuff, size_t aNumBytes); - void DoAsyncWrite(const byte_t*, size_t aNumBytes); - - - void CheckForReadDispatch(); - - boost::asio::io_service* mpService; - std::deque mWritten; - - size_t mReadSize; - byte_t* mpReadBuff; - }; -} - -#endif +// +#ifndef __LOOP_BACK_PHYSICAL_LAYER_ASYNC_H_ +#define __LOOP_BACK_PHYSICAL_LAYER_ASYNC_H_ + +#include +#include + +#include + +namespace boost { namespace asio { + class io_service; +}} + +namespace apl { + + /// Provides a backend for testing physical layers + class LoopbackPhysicalLayerAsync : public PhysicalLayerAsyncBase + { + public: + LoopbackPhysicalLayerAsync(Logger*, boost::asio::io_service* apSrv); + + + private: + + void DoOpen(); + void DoClose(); + void DoOpenSuccess(); + void DoAsyncRead(byte_t* apBuff, size_t aNumBytes); + void DoAsyncWrite(const byte_t*, size_t aNumBytes); + + + void CheckForReadDispatch(); + + boost::asio::io_service* mpService; + std::deque mWritten; + + size_t mReadSize; + byte_t* mpReadBuff; + }; +} + +#endif diff --git a/APLTestTools/MockCommandAcceptor.h b/APLTestTools/MockCommandAcceptor.h index 6579c6db..9241091b 100644 --- a/APLTestTools/MockCommandAcceptor.h +++ b/APLTestTools/MockCommandAcceptor.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,69 +6,69 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MOCK_COMMAND_ACCEPTOR_H_ -#define __MOCK_COMMAND_ACCEPTOR_H_ - -#include -#include -#include - -namespace apl { - - class MockCommandAcceptor : public ICommandAcceptor - { - public: - - void AcceptCommand(const BinaryOutput& aBo, size_t, int aSequence, IResponseAcceptor* apRspAcceptor) - { mBinaryOutputs.push(aBo); this->AcceptCommand(aSequence, apRspAcceptor); } - - void AcceptCommand(const Setpoint& aSt, size_t, int aSequence, IResponseAcceptor* apRspAcceptor) - { mSetpoints.push(aSt); this->AcceptCommand(aSequence, apRspAcceptor); } - - void Queue(CommandStatus aStatus) { mResponses.push(aStatus); } - - Setpoint NextSetpoint(){ - if(mSetpoints.size() == 0) throw Exception(LOCATION, "no setpoints recieved"); - Setpoint s = mSetpoints.front(); - mSetpoints.pop(); - return s; - } - BinaryOutput NextBinaryOutput(){ - if(mBinaryOutputs.size() == 0) throw Exception(LOCATION, "no binary outputs recieved"); - BinaryOutput b = mBinaryOutputs.front(); - mBinaryOutputs.pop(); - return b; - } - - private: - - void AcceptCommand(int aSeq, IResponseAcceptor* apRspAcceptor) - { - if(mResponses.empty()) throw Exception(LOCATION, "response queue is empty"); - else - { - CommandResponse rsp(mResponses.front()); - mResponses.pop(); - apRspAcceptor->AcceptResponse(rsp, aSeq); - } - - } - - std::queue mResponses; - std::queue mSetpoints; - std::queue mBinaryOutputs; - }; - -} - -#endif +// +#ifndef __MOCK_COMMAND_ACCEPTOR_H_ +#define __MOCK_COMMAND_ACCEPTOR_H_ + +#include +#include +#include + +namespace apl { + + class MockCommandAcceptor : public ICommandAcceptor + { + public: + + void AcceptCommand(const BinaryOutput& aBo, size_t, int aSequence, IResponseAcceptor* apRspAcceptor) + { mBinaryOutputs.push(aBo); this->AcceptCommand(aSequence, apRspAcceptor); } + + void AcceptCommand(const Setpoint& aSt, size_t, int aSequence, IResponseAcceptor* apRspAcceptor) + { mSetpoints.push(aSt); this->AcceptCommand(aSequence, apRspAcceptor); } + + void Queue(CommandStatus aStatus) { mResponses.push(aStatus); } + + Setpoint NextSetpoint(){ + if(mSetpoints.size() == 0) throw Exception(LOCATION, "no setpoints recieved"); + Setpoint s = mSetpoints.front(); + mSetpoints.pop(); + return s; + } + BinaryOutput NextBinaryOutput(){ + if(mBinaryOutputs.size() == 0) throw Exception(LOCATION, "no binary outputs recieved"); + BinaryOutput b = mBinaryOutputs.front(); + mBinaryOutputs.pop(); + return b; + } + + private: + + void AcceptCommand(int aSeq, IResponseAcceptor* apRspAcceptor) + { + if(mResponses.empty()) throw Exception(LOCATION, "response queue is empty"); + else + { + CommandResponse rsp(mResponses.front()); + mResponses.pop(); + apRspAcceptor->AcceptResponse(rsp, aSeq); + } + + } + + std::queue mResponses; + std::queue mSetpoints; + std::queue mBinaryOutputs; + }; + +} + +#endif diff --git a/APLTestTools/MockCommandHandler.h b/APLTestTools/MockCommandHandler.h index b08bf3c7..e039322a 100644 --- a/APLTestTools/MockCommandHandler.h +++ b/APLTestTools/MockCommandHandler.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,35 +6,35 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MOCK_COMMAND_HANDLER_H_ -#define __MOCK_COMMAND_HANDLER_H_ - -#include - -namespace apl { - - class MockCommandHandler : public ICommandHandler { - public: - - MockCommandHandler() : num_bo(0), num_sp(0) {} - - CommandStatus HandleControl(BinaryOutput& aControl, size_t aIndex) { ++num_bo; return CS_SUCCESS; } - CommandStatus HandleControl(Setpoint& aControl, size_t aIndex) { ++num_sp; return CS_SUCCESS; } - - size_t num_bo; - size_t num_sp; -}; - -} - -#endif +// +#ifndef __MOCK_COMMAND_HANDLER_H_ +#define __MOCK_COMMAND_HANDLER_H_ + +#include + +namespace apl { + + class MockCommandHandler : public ICommandHandler { + public: + + MockCommandHandler() : num_bo(0), num_sp(0) {} + + CommandStatus HandleControl(BinaryOutput& aControl, size_t aIndex) { ++num_bo; return CS_SUCCESS; } + CommandStatus HandleControl(Setpoint& aControl, size_t aIndex) { ++num_sp; return CS_SUCCESS; } + + size_t num_bo; + size_t num_sp; +}; + +} + +#endif diff --git a/APLTestTools/MockLowerLayer.cpp b/APLTestTools/MockLowerLayer.cpp index 71965a1f..6974cef5 100644 --- a/APLTestTools/MockLowerLayer.cpp +++ b/APLTestTools/MockLowerLayer.cpp @@ -16,72 +16,72 @@ // specific language governing permissions and limitations // under the License. // -#include "MockLowerLayer.h" - -#include "BufferHelpers.h" -#include - -namespace apl { - -MockLowerLayer::MockLowerLayer(Logger* apLogger) : -Loggable(apLogger), -ILowerLayer(apLogger), -mAutoSendCallback(true), -mIsSuccess(true) -{ - -} - +#include "MockLowerLayer.h" + +#include "BufferHelpers.h" +#include + +namespace apl { + +MockLowerLayer::MockLowerLayer(Logger* apLogger) : +Loggable(apLogger), +ILowerLayer(apLogger), +mAutoSendCallback(true), +mIsSuccess(true) +{ + +} + void MockLowerLayer::EnableAutoSendCallback(bool aIsSuccess) { mAutoSendCallback = true; mIsSuccess = aIsSuccess; } - -void MockLowerLayer::DisableAutoSendCallback() -{ - mAutoSendCallback = false; -} - -void MockLowerLayer::_Send(const apl::byte_t* apData, size_t aNumBytes) -{ - this->WriteToBuffer(apData, aNumBytes); - if(mAutoSendCallback && mpUpperLayer != NULL) { - if(mIsSuccess) mpUpperLayer->OnSendSuccess(); - else mpUpperLayer->OnSendFailure(); - } -} - -void MockLowerLayer::SendUp(const byte_t* apData, size_t aNumBytes) -{ - if(this->mpUpperLayer != NULL) - mpUpperLayer->OnReceive(apData, aNumBytes); -} - -void MockLowerLayer::SendUp(const std::string& arHexData) -{ - HexSequence hs(arHexData); - this->SendUp(hs.Buffer(), hs.Size()); -} - -void MockLowerLayer::SendSuccess() -{ - if(mpUpperLayer != NULL) mpUpperLayer->OnSendSuccess(); -} - -void MockLowerLayer::SendFailure() -{ - if(mpUpperLayer != NULL) mpUpperLayer->OnSendFailure(); -} - -void MockLowerLayer::ThisLayerUp() -{ - if(mpUpperLayer != NULL) mpUpperLayer->OnLowerLayerUp(); -} -void MockLowerLayer::ThisLayerDown() -{ - if(mpUpperLayer != NULL) mpUpperLayer->OnLowerLayerDown(); -} - -} + +void MockLowerLayer::DisableAutoSendCallback() +{ + mAutoSendCallback = false; +} + +void MockLowerLayer::_Send(const apl::byte_t* apData, size_t aNumBytes) +{ + this->WriteToBuffer(apData, aNumBytes); + if(mAutoSendCallback && mpUpperLayer != NULL) { + if(mIsSuccess) mpUpperLayer->OnSendSuccess(); + else mpUpperLayer->OnSendFailure(); + } +} + +void MockLowerLayer::SendUp(const byte_t* apData, size_t aNumBytes) +{ + if(this->mpUpperLayer != NULL) + mpUpperLayer->OnReceive(apData, aNumBytes); +} + +void MockLowerLayer::SendUp(const std::string& arHexData) +{ + HexSequence hs(arHexData); + this->SendUp(hs.Buffer(), hs.Size()); +} + +void MockLowerLayer::SendSuccess() +{ + if(mpUpperLayer != NULL) mpUpperLayer->OnSendSuccess(); +} + +void MockLowerLayer::SendFailure() +{ + if(mpUpperLayer != NULL) mpUpperLayer->OnSendFailure(); +} + +void MockLowerLayer::ThisLayerUp() +{ + if(mpUpperLayer != NULL) mpUpperLayer->OnLowerLayerUp(); +} +void MockLowerLayer::ThisLayerDown() +{ + if(mpUpperLayer != NULL) mpUpperLayer->OnLowerLayerDown(); +} + +} diff --git a/APLTestTools/MockLowerLayer.h b/APLTestTools/MockLowerLayer.h index 86eb0b4c..ad9a653e 100644 --- a/APLTestTools/MockLowerLayer.h +++ b/APLTestTools/MockLowerLayer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MOCK_LOWER_LAYER_H_ #define __MOCK_LOWER_LAYER_H_ @@ -40,7 +40,7 @@ class MockLowerLayer : public ILowerLayer, public BufferTestObject void EnableAutoSendCallback(bool aIsSuccess); void DisableAutoSendCallback(); - + private: bool mAutoSendCallback; diff --git a/APLTestTools/MockNodeSaver.h b/APLTestTools/MockNodeSaver.h index bbcd11b8..e3755f89 100644 --- a/APLTestTools/MockNodeSaver.h +++ b/APLTestTools/MockNodeSaver.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _MOCK_NODE_SAVER_H_ @@ -38,7 +38,7 @@ namespace apl{ mLocalCopy = aNode; //copy return !mFailSave; } - + public: RootNode mLocalCopy; bool mFailLoad; diff --git a/APLTestTools/MockNotifier.h b/APLTestTools/MockNotifier.h index 8b1cc9ad..75f65242 100644 --- a/APLTestTools/MockNotifier.h +++ b/APLTestTools/MockNotifier.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _MOCK_NOTIFIER_H_ #define _MOCK_NOTIFIER_H_ diff --git a/APLTestTools/MockPhysicalLayerAsync.cpp b/APLTestTools/MockPhysicalLayerAsync.cpp index d9bbc1b8..039f7213 100644 --- a/APLTestTools/MockPhysicalLayerAsync.cpp +++ b/APLTestTools/MockPhysicalLayerAsync.cpp @@ -16,67 +16,67 @@ // specific language governing permissions and limitations // under the License. // -#include "MockPhysicalLayerAsync.h" - -#include "BufferHelpers.h" - -using namespace boost::system; - -namespace apl { - -MockPhysicalLayerAsync::MockPhysicalLayerAsync(Logger* apLogger) : -PhysicalLayerAsyncBase(apLogger), -mpWriteBuff(NULL), -mNumToRead(0), -mNumToWrite(0), -mNumWrites(0), -mNumOpen(0), -mNumOpenSuccess(0), -mNumOpenFailure(0), -mNumClose(0) -{} - -void MockPhysicalLayerAsync::SignalOpenSuccess() -{ - error_code ec(errc::success, get_generic_category()); - this->OnOpenCallback(ec); -} - -void MockPhysicalLayerAsync::SignalOpenFailure() -{ - error_code ec(errc::permission_denied, get_generic_category()); - this->OnOpenCallback(ec); -} - -void MockPhysicalLayerAsync::SignalSendSuccess() -{ - size_t num = mNumToWrite; mNumToWrite = 0; - error_code ec(errc::success, get_generic_category()); - this->OnWriteCallback(ec, num); -} - -void MockPhysicalLayerAsync::SignalSendFailure() -{ - mNumToWrite = 0; - error_code ec(errc::permission_denied, get_generic_category()); - this->OnWriteCallback(ec, 0); -} - -void MockPhysicalLayerAsync::SignalReadFailure() -{ - mNumToRead = 0; - error_code ec(errc::permission_denied, get_generic_category()); - this->OnReadCallback(ec, mpWriteBuff, 0); -} - -void MockPhysicalLayerAsync::TriggerRead(const std::string& arData) -{ - HexSequence hs(arData); - assert(hs.Size() <= this->mNumToRead); - memcpy(mpWriteBuff, hs.Buffer(), hs.Size()); - mNumToRead = 0; - error_code ec(errc::success, get_generic_category()); - this->OnReadCallback(ec, mpWriteBuff, hs.Size()); -} - -} +#include "MockPhysicalLayerAsync.h" + +#include "BufferHelpers.h" + +using namespace boost::system; + +namespace apl { + +MockPhysicalLayerAsync::MockPhysicalLayerAsync(Logger* apLogger) : +PhysicalLayerAsyncBase(apLogger), +mpWriteBuff(NULL), +mNumToRead(0), +mNumToWrite(0), +mNumWrites(0), +mNumOpen(0), +mNumOpenSuccess(0), +mNumOpenFailure(0), +mNumClose(0) +{} + +void MockPhysicalLayerAsync::SignalOpenSuccess() +{ + error_code ec(errc::success, get_generic_category()); + this->OnOpenCallback(ec); +} + +void MockPhysicalLayerAsync::SignalOpenFailure() +{ + error_code ec(errc::permission_denied, get_generic_category()); + this->OnOpenCallback(ec); +} + +void MockPhysicalLayerAsync::SignalSendSuccess() +{ + size_t num = mNumToWrite; mNumToWrite = 0; + error_code ec(errc::success, get_generic_category()); + this->OnWriteCallback(ec, num); +} + +void MockPhysicalLayerAsync::SignalSendFailure() +{ + mNumToWrite = 0; + error_code ec(errc::permission_denied, get_generic_category()); + this->OnWriteCallback(ec, 0); +} + +void MockPhysicalLayerAsync::SignalReadFailure() +{ + mNumToRead = 0; + error_code ec(errc::permission_denied, get_generic_category()); + this->OnReadCallback(ec, mpWriteBuff, 0); +} + +void MockPhysicalLayerAsync::TriggerRead(const std::string& arData) +{ + HexSequence hs(arData); + assert(hs.Size() <= this->mNumToRead); + memcpy(mpWriteBuff, hs.Buffer(), hs.Size()); + mNumToRead = 0; + error_code ec(errc::success, get_generic_category()); + this->OnReadCallback(ec, mpWriteBuff, hs.Size()); +} + +} diff --git a/APLTestTools/MockPhysicalLayerAsync.h b/APLTestTools/MockPhysicalLayerAsync.h index c72b4e62..273a6146 100644 --- a/APLTestTools/MockPhysicalLayerAsync.h +++ b/APLTestTools/MockPhysicalLayerAsync.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,66 +6,66 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MOCK_PHYSICAL_LAYER_ASYNC_H_ -#define __MOCK_PHYSICAL_LAYER_ASYNC_H_ - -#include -#include - -#include "BufferTestObject.h" - -namespace apl { - - /// Provides a backend for testing physical layers - class MockPhysicalLayerAsync : public PhysicalLayerAsyncBase, public BufferTestObject - { - public: - MockPhysicalLayerAsync(Logger*); - - void SignalOpenSuccess(); - void SignalOpenFailure(); - void SignalSendSuccess(); - void SignalSendFailure(); - void SignalReadFailure(); - void TriggerRead(const std::string& arData); - - size_t NumWrites() { return mNumWrites; } - size_t NumOpen() { return mNumOpen; } - size_t NumOpenSuccess() { return mNumOpenSuccess; } - size_t NumOpenFailure() { return mNumOpenFailure; } - size_t NumClose() { return mNumClose; } - - private: - void DoOpen() {++mNumOpen; } - void DoClose() { ++mNumClose; } - void DoOpenSuccess() { ++mNumOpenSuccess; } - void DoOpenFailure() { ++mNumOpenFailure; } - void DoAsyncRead(byte_t* apBuff, size_t aNumBytes) { mpWriteBuff = apBuff; mNumToRead = aNumBytes; } - void DoAsyncWrite(const byte_t* apData, size_t aNumBytes) { - mNumToWrite = aNumBytes; - ++mNumWrites; - WriteToBuffer(apData, aNumBytes); - } - - byte_t* mpWriteBuff; - size_t mNumToRead; - size_t mNumToWrite; - size_t mNumWrites; - size_t mNumOpen; - size_t mNumOpenSuccess; - size_t mNumOpenFailure; - size_t mNumClose; - }; -} - -#endif +// +#ifndef __MOCK_PHYSICAL_LAYER_ASYNC_H_ +#define __MOCK_PHYSICAL_LAYER_ASYNC_H_ + +#include +#include + +#include "BufferTestObject.h" + +namespace apl { + + /// Provides a backend for testing physical layers + class MockPhysicalLayerAsync : public PhysicalLayerAsyncBase, public BufferTestObject + { + public: + MockPhysicalLayerAsync(Logger*); + + void SignalOpenSuccess(); + void SignalOpenFailure(); + void SignalSendSuccess(); + void SignalSendFailure(); + void SignalReadFailure(); + void TriggerRead(const std::string& arData); + + size_t NumWrites() { return mNumWrites; } + size_t NumOpen() { return mNumOpen; } + size_t NumOpenSuccess() { return mNumOpenSuccess; } + size_t NumOpenFailure() { return mNumOpenFailure; } + size_t NumClose() { return mNumClose; } + + private: + void DoOpen() {++mNumOpen; } + void DoClose() { ++mNumClose; } + void DoOpenSuccess() { ++mNumOpenSuccess; } + void DoOpenFailure() { ++mNumOpenFailure; } + void DoAsyncRead(byte_t* apBuff, size_t aNumBytes) { mpWriteBuff = apBuff; mNumToRead = aNumBytes; } + void DoAsyncWrite(const byte_t* apData, size_t aNumBytes) { + mNumToWrite = aNumBytes; + ++mNumWrites; + WriteToBuffer(apData, aNumBytes); + } + + byte_t* mpWriteBuff; + size_t mNumToRead; + size_t mNumToWrite; + size_t mNumWrites; + size_t mNumOpen; + size_t mNumOpenSuccess; + size_t mNumOpenFailure; + size_t mNumClose; + }; +} + +#endif diff --git a/APLTestTools/MockPhysicalLayerAsyncTS.cpp b/APLTestTools/MockPhysicalLayerAsyncTS.cpp index 432e1575..e3b829e5 100644 --- a/APLTestTools/MockPhysicalLayerAsyncTS.cpp +++ b/APLTestTools/MockPhysicalLayerAsyncTS.cpp @@ -16,100 +16,100 @@ // specific language governing permissions and limitations // under the License. // -#include "MockPhysicalLayerAsyncTS.h" - -#include -#include -#include - -using namespace boost::system; - -namespace apl { - -MockPhysicalLayerAsyncTS::MockPhysicalLayerAsyncTS(Logger* apLogger, MockTimerSource* apTimerSrc) : -PhysicalLayerAsyncBase(apLogger), -mpTimerSrc(apTimerSrc), -mpOpenTimer(NULL), -mErrorCode(errc::permission_denied, get_generic_category()), -mWriteBuffer(1024) -{ - this->Reset(); -} - -void MockPhysicalLayerAsyncTS::WriteToLayer(const byte_t* apData, size_t aNumBytes) -{ - memcpy(mWriteBuffer.WriteBuff(), apData, aNumBytes); - mWriteBuffer.AdvanceWrite(aNumBytes); - this->CheckForRead(); -} - -void MockPhysicalLayerAsyncTS::Advance() -{ - while(mpTimerSrc->DispatchOne()); -} - -void MockPhysicalLayerAsyncTS::Reset() -{ - mpBuff = NULL; - mNumBytes = 0; -} - -void MockPhysicalLayerAsyncTS::DoOpen() -{ - mpOpenTimer = mpTimerSrc->Start(2000, boost::bind(&MockPhysicalLayerAsyncTS::OnOpenCallback, this, mSuccessCode)); -} - -//we might have outstanding -void MockPhysicalLayerAsyncTS::DoClose() -{ - this->Reset(); - - if(mState.mReading) { - mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnReadCallback, this, mErrorCode, mpBuff, 0)); - } - - if(mState.mWriting) { - mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnWriteCallback, this, mErrorCode, 0)); - } -} - -void MockPhysicalLayerAsyncTS::DoOpeningClose() -{ - mpOpenTimer->Cancel(); - mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnOpenCallback, this, mErrorCode)); -} - - -void MockPhysicalLayerAsyncTS::DoOpenSuccess() -{ - LOG_BLOCK(LEV_INFO, "Open success"); -} - -void MockPhysicalLayerAsyncTS::DoOpenFailure() {} - -void MockPhysicalLayerAsyncTS::DoAsyncRead(byte_t* apBuff, size_t aNumBytes) -{ - mpBuff = apBuff; - mNumBytes = aNumBytes; - mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::CheckForRead, this)); -} - -void MockPhysicalLayerAsyncTS::DoAsyncWrite(const byte_t* apData, size_t aNumBytes) -{ - this->WriteToBuffer(apData, aNumBytes); //record to BufferTestObject - mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnWriteCallback, this, mSuccessCode, aNumBytes)); -} - -void MockPhysicalLayerAsyncTS::CheckForRead() -{ - if(mNumBytes > 0 && mWriteBuffer.NumReadBytes() > 0) { - size_t min = mNumBytes > mWriteBuffer.NumReadBytes() ? mWriteBuffer.NumReadBytes() : mNumBytes; - memcpy(mpBuff, mWriteBuffer.ReadBuff(), min); - mNumBytes = 0; - this->OnReadCallback(mSuccessCode, mpBuff, min); - mWriteBuffer.AdvanceRead(min); - mWriteBuffer.Shift(); - } -} - -} //end namespace +#include "MockPhysicalLayerAsyncTS.h" + +#include +#include +#include + +using namespace boost::system; + +namespace apl { + +MockPhysicalLayerAsyncTS::MockPhysicalLayerAsyncTS(Logger* apLogger, MockTimerSource* apTimerSrc) : +PhysicalLayerAsyncBase(apLogger), +mpTimerSrc(apTimerSrc), +mpOpenTimer(NULL), +mErrorCode(errc::permission_denied, get_generic_category()), +mWriteBuffer(1024) +{ + this->Reset(); +} + +void MockPhysicalLayerAsyncTS::WriteToLayer(const byte_t* apData, size_t aNumBytes) +{ + memcpy(mWriteBuffer.WriteBuff(), apData, aNumBytes); + mWriteBuffer.AdvanceWrite(aNumBytes); + this->CheckForRead(); +} + +void MockPhysicalLayerAsyncTS::Advance() +{ + while(mpTimerSrc->DispatchOne()); +} + +void MockPhysicalLayerAsyncTS::Reset() +{ + mpBuff = NULL; + mNumBytes = 0; +} + +void MockPhysicalLayerAsyncTS::DoOpen() +{ + mpOpenTimer = mpTimerSrc->Start(2000, boost::bind(&MockPhysicalLayerAsyncTS::OnOpenCallback, this, mSuccessCode)); +} + +//we might have outstanding +void MockPhysicalLayerAsyncTS::DoClose() +{ + this->Reset(); + + if(mState.mReading) { + mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnReadCallback, this, mErrorCode, mpBuff, 0)); + } + + if(mState.mWriting) { + mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnWriteCallback, this, mErrorCode, 0)); + } +} + +void MockPhysicalLayerAsyncTS::DoOpeningClose() +{ + mpOpenTimer->Cancel(); + mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnOpenCallback, this, mErrorCode)); +} + + +void MockPhysicalLayerAsyncTS::DoOpenSuccess() +{ + LOG_BLOCK(LEV_INFO, "Open success"); +} + +void MockPhysicalLayerAsyncTS::DoOpenFailure() {} + +void MockPhysicalLayerAsyncTS::DoAsyncRead(byte_t* apBuff, size_t aNumBytes) +{ + mpBuff = apBuff; + mNumBytes = aNumBytes; + mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::CheckForRead, this)); +} + +void MockPhysicalLayerAsyncTS::DoAsyncWrite(const byte_t* apData, size_t aNumBytes) +{ + this->WriteToBuffer(apData, aNumBytes); //record to BufferTestObject + mpTimerSrc->Post(boost::bind(&MockPhysicalLayerAsyncTS::OnWriteCallback, this, mSuccessCode, aNumBytes)); +} + +void MockPhysicalLayerAsyncTS::CheckForRead() +{ + if(mNumBytes > 0 && mWriteBuffer.NumReadBytes() > 0) { + size_t min = mNumBytes > mWriteBuffer.NumReadBytes() ? mWriteBuffer.NumReadBytes() : mNumBytes; + memcpy(mpBuff, mWriteBuffer.ReadBuff(), min); + mNumBytes = 0; + this->OnReadCallback(mSuccessCode, mpBuff, min); + mWriteBuffer.AdvanceRead(min); + mWriteBuffer.Shift(); + } +} + +} //end namespace diff --git a/APLTestTools/MockPhysicalLayerAsyncTS.h b/APLTestTools/MockPhysicalLayerAsyncTS.h index 337ef757..dc90b6cb 100644 --- a/APLTestTools/MockPhysicalLayerAsyncTS.h +++ b/APLTestTools/MockPhysicalLayerAsyncTS.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,62 +6,62 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MOCK_PHYSICAL_LAYER_ASYNC_TS_H_ -#define __MOCK_PHYSICAL_LAYER_ASYNC_TS_H_ - -#include -#include -#include - -#include - -#include "BufferTestObject.h" - -namespace apl { - - class MockTimerSource; - class ITimer; - - /// Provides a backend for testing physical layers - class MockPhysicalLayerAsyncTS : public PhysicalLayerAsyncBase, public BufferTestObject - { - public: - MockPhysicalLayerAsyncTS(Logger*, MockTimerSource*); - - void WriteToLayer(const byte_t* apData, size_t aNumBytes); - void Advance(); - - private: - - void DoOpen(); - void DoClose(); - void DoOpeningClose(); - void DoOpenSuccess(); - void DoOpenFailure(); - void DoAsyncRead(byte_t* apBuff, size_t aNumBytes); - void DoAsyncWrite(const byte_t* apData, size_t aNumBytes); - - void Reset(); - void CheckForRead(); - - MockTimerSource* mpTimerSrc; - ITimer* mpOpenTimer; - boost::system::error_code mSuccessCode; - boost::system::error_code mErrorCode; - byte_t* mpBuff; - size_t mNumBytes; - ShiftableBuffer mWriteBuffer; - }; -} - -#endif +// +#ifndef __MOCK_PHYSICAL_LAYER_ASYNC_TS_H_ +#define __MOCK_PHYSICAL_LAYER_ASYNC_TS_H_ + +#include +#include +#include + +#include + +#include "BufferTestObject.h" + +namespace apl { + + class MockTimerSource; + class ITimer; + + /// Provides a backend for testing physical layers + class MockPhysicalLayerAsyncTS : public PhysicalLayerAsyncBase, public BufferTestObject + { + public: + MockPhysicalLayerAsyncTS(Logger*, MockTimerSource*); + + void WriteToLayer(const byte_t* apData, size_t aNumBytes); + void Advance(); + + private: + + void DoOpen(); + void DoClose(); + void DoOpeningClose(); + void DoOpenSuccess(); + void DoOpenFailure(); + void DoAsyncRead(byte_t* apBuff, size_t aNumBytes); + void DoAsyncWrite(const byte_t* apData, size_t aNumBytes); + + void Reset(); + void CheckForRead(); + + MockTimerSource* mpTimerSrc; + ITimer* mpOpenTimer; + boost::system::error_code mSuccessCode; + boost::system::error_code mErrorCode; + byte_t* mpBuff; + size_t mNumBytes; + ShiftableBuffer mWriteBuffer; + }; +} + +#endif diff --git a/APLTestTools/MockResponseAcceptor.cpp b/APLTestTools/MockResponseAcceptor.cpp index 5ec020b9..628e5e09 100644 --- a/APLTestTools/MockResponseAcceptor.cpp +++ b/APLTestTools/MockResponseAcceptor.cpp @@ -16,31 +16,31 @@ // specific language governing permissions and limitations // under the License. // -#include "MockResponseAcceptor.h" - - -namespace apl { - - void MockResponseAcceptor::AcceptResponse(const CommandResponse& aResponse, int aSequence) - { - CriticalSection cs(&mLock); - MockResponse mr(aResponse, aSequence); - mResponses.push_back(mr); - mLock.Broadcast(); - } - - MockResponse MockResponseAcceptor::PopResponse() - { - CriticalSection cs(&mLock); - //if(mResponse.size() == 0) throw ArgumentException(LOCATION, - MockResponse mr = mResponses.front(); - mResponses.pop_front(); - return mr; - } - - size_t MockResponseAcceptor::NumResponses() - { - CriticalSection cs(&mLock); - return mResponses.size(); - } -} +#include "MockResponseAcceptor.h" + + +namespace apl { + + void MockResponseAcceptor::AcceptResponse(const CommandResponse& aResponse, int aSequence) + { + CriticalSection cs(&mLock); + MockResponse mr(aResponse, aSequence); + mResponses.push_back(mr); + mLock.Broadcast(); + } + + MockResponse MockResponseAcceptor::PopResponse() + { + CriticalSection cs(&mLock); + //if(mResponse.size() == 0) throw ArgumentException(LOCATION, + MockResponse mr = mResponses.front(); + mResponses.pop_front(); + return mr; + } + + size_t MockResponseAcceptor::NumResponses() + { + CriticalSection cs(&mLock); + return mResponses.size(); + } +} diff --git a/APLTestTools/MockResponseAcceptor.h b/APLTestTools/MockResponseAcceptor.h index 6dd64319..eb821db9 100644 --- a/APLTestTools/MockResponseAcceptor.h +++ b/APLTestTools/MockResponseAcceptor.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MOCK_RESPONSE_ACCEPTOR_H_ #define __MOCK_RESPONSE_ACCEPTOR_H_ @@ -44,10 +44,10 @@ namespace apl public: void AcceptResponse(const apl::CommandResponse& aResponse, int aSequence); - + MockResponse PopResponse(); size_t NumResponses(); - + private: apl::SigLock mLock; std::deque mResponses; diff --git a/APLTestTools/MockTimerSource.h b/APLTestTools/MockTimerSource.h index 12445348..0072d3aa 100644 --- a/APLTestTools/MockTimerSource.h +++ b/APLTestTools/MockTimerSource.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MOCK_TIMER_SOURCE_H_ #define __MOCK_TIMER_SOURCE_H_ @@ -61,7 +61,7 @@ class MockTimerSource : public ITimerSource TimerMap mTimerMap; TimerQueue mIdle; TimerQueue mAllTimers; - + }; /** @section desc Test timer class used in conjunction with MockTimerSource */ diff --git a/APLTestTools/MockUpperLayer.cpp b/APLTestTools/MockUpperLayer.cpp index 89054284..9bf214a2 100644 --- a/APLTestTools/MockUpperLayer.cpp +++ b/APLTestTools/MockUpperLayer.cpp @@ -16,60 +16,60 @@ // specific language governing permissions and limitations // under the License. // -#include "MockUpperLayer.h" - -#include "BufferHelpers.h" - -#include -#include -#include - -namespace apl { - -MockUpperLayer::MockUpperLayer(Logger* apLogger) : -Loggable(apLogger), -IUpperLayer(apLogger) -{} - -void MockUpperLayer::_OnReceive(const apl::byte_t* apData, size_t aLength) -{ - this->WriteToBuffer(apData, aLength); - if(mOnReceiveHandler) mOnReceiveHandler(apData, aLength); -} - -void MockUpperLayer::_OnSendSuccess() -{ - LOG_BLOCK(LEV_DEBUG, "OnSendSuccess"); - ++mState.mSuccessCnt; -} - -void MockUpperLayer::_OnSendFailure() -{ - LOG_BLOCK(LEV_DEBUG, "OnSendFailure"); - ++mState.mFailureCnt; -} - -void MockUpperLayer::_OnLowerLayerUp() -{ - LOG_BLOCK(LEV_DEBUG, "OnLowerLayerUp"); - ++mState.mNumLayerUp; -} - -void MockUpperLayer::_OnLowerLayerDown() -{ - LOG_BLOCK(LEV_DEBUG, "OnLowerLayerDown"); - ++mState.mNumLayerDown; -} - -void MockUpperLayer::SendDown(const byte_t* apData, size_t aNumBytes) -{ - if(this->mpLowerLayer) mpLowerLayer->Send(apData, aNumBytes); -} - -void MockUpperLayer::SendDown(const std::string& arHexData) -{ - HexSequence hs(arHexData); - this->SendDown(hs.Buffer(), hs.Size()); -} - -} +#include "MockUpperLayer.h" + +#include "BufferHelpers.h" + +#include +#include +#include + +namespace apl { + +MockUpperLayer::MockUpperLayer(Logger* apLogger) : +Loggable(apLogger), +IUpperLayer(apLogger) +{} + +void MockUpperLayer::_OnReceive(const apl::byte_t* apData, size_t aLength) +{ + this->WriteToBuffer(apData, aLength); + if(mOnReceiveHandler) mOnReceiveHandler(apData, aLength); +} + +void MockUpperLayer::_OnSendSuccess() +{ + LOG_BLOCK(LEV_DEBUG, "OnSendSuccess"); + ++mState.mSuccessCnt; +} + +void MockUpperLayer::_OnSendFailure() +{ + LOG_BLOCK(LEV_DEBUG, "OnSendFailure"); + ++mState.mFailureCnt; +} + +void MockUpperLayer::_OnLowerLayerUp() +{ + LOG_BLOCK(LEV_DEBUG, "OnLowerLayerUp"); + ++mState.mNumLayerUp; +} + +void MockUpperLayer::_OnLowerLayerDown() +{ + LOG_BLOCK(LEV_DEBUG, "OnLowerLayerDown"); + ++mState.mNumLayerDown; +} + +void MockUpperLayer::SendDown(const byte_t* apData, size_t aNumBytes) +{ + if(this->mpLowerLayer) mpLowerLayer->Send(apData, aNumBytes); +} + +void MockUpperLayer::SendDown(const std::string& arHexData) +{ + HexSequence hs(arHexData); + this->SendDown(hs.Buffer(), hs.Size()); +} + +} diff --git a/APLTestTools/MockUpperLayer.h b/APLTestTools/MockUpperLayer.h index 3e67fa3e..78a43065 100644 --- a/APLTestTools/MockUpperLayer.h +++ b/APLTestTools/MockUpperLayer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MOCK_UPPER_LAYER_H_ #define __MOCK_UPPER_LAYER_H_ @@ -27,14 +27,14 @@ namespace apl { class MockUpperLayer : public IUpperLayer, public BufferTestObject -{ +{ public: typedef boost::function OnReceiveHandler; - - struct State + + struct State { - + State() { Reset(); } size_t mSuccessCnt; @@ -60,18 +60,18 @@ class MockUpperLayer : public IUpperLayer, public BufferTestObject } bool StateEquals(const State& s) - { + { return (mState.mSuccessCnt == s.mSuccessCnt) && (mState.mFailureCnt == s.mFailureCnt) && (mState.mNumLayerUp == s.mNumLayerUp) && (mState.mNumLayerDown == s.mNumLayerDown); - } + } void Reset() { mState.Reset(); } State GetState() { return mState; } void SetReceiveHandler(const OnReceiveHandler& arHandler) { mOnReceiveHandler = arHandler; } - + private: virtual std::string RecvString() const { return "MockUpperLayer <-"; } diff --git a/APLTestTools/TestHelpers.h b/APLTestTools/TestHelpers.h index 3bfca63c..5f1b40ff 100644 --- a/APLTestTools/TestHelpers.h +++ b/APLTestTools/TestHelpers.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TEST_HELPERS_H_ #define __TEST_HELPERS_H_ diff --git a/APLTestTools/TestTypedefs.h b/APLTestTools/TestTypedefs.h index 29053a3d..9082d038 100644 --- a/APLTestTools/TestTypedefs.h +++ b/APLTestTools/TestTypedefs.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TEST_TYPEDEFS_H_ #define __TEST_TYPEDEFS_H_ diff --git a/APLTestTools/rake.project.rb b/APLTestTools/rake.project.rb index adde78fa..db1cc6d6 100644 --- a/APLTestTools/rake.project.rb +++ b/APLTestTools/rake.project.rb @@ -16,8 +16,8 @@ # specific language governing permissions and limitations # under the License. # - -$options = { -:target => 'libapltesttools.a', -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -} + +$options = { +:target => 'libapltesttools.a', +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +} diff --git a/APLXML/APLXML.vcproj b/APLXML/APLXML.vcproj index 6f369121..5372a15a 100755 --- a/APLXML/APLXML.vcproj +++ b/APLXML/APLXML.vcproj @@ -1,199 +1,199 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/APLXML/INodeSaver.h b/APLXML/INodeSaver.h index fdcea9a3..7b3835b6 100644 --- a/APLXML/INodeSaver.h +++ b/APLXML/INodeSaver.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _XML_SAVE_FILE_H_ @@ -25,7 +25,7 @@ namespace apl{ template class INodeSaver{ - + public: virtual ~INodeSaver(){} diff --git a/APLXML/PhysicalLayerManagerXML.cpp b/APLXML/PhysicalLayerManagerXML.cpp index 85722018..5e495c55 100644 --- a/APLXML/PhysicalLayerManagerXML.cpp +++ b/APLXML/PhysicalLayerManagerXML.cpp @@ -16,58 +16,58 @@ // specific language governing permissions and limitations // under the License. // -#include "PhysicalLayerManagerXML.h" - -#include -#include "PhysicalLayerXMLFactory.h" -#include "XMLConversion.h" - -#include - -namespace apl { class EventLog; } - -using namespace APLXML_Base; - -namespace apl { namespace xml { - - - PhysicalLayerManagerXML::PhysicalLayerManagerXML(Logger* apLogger) : PhysicalLayerManager(apLogger) - {} - - PhysicalLayerManagerXML::PhysicalLayerManagerXML(Logger* apLogger, const APLXML_Base::PhysicalLayerList_t* apList, FilterLevel aLevel) : - PhysicalLayerManager(apLogger) - { - this->AddList(apList, aLevel); - } - - void PhysicalLayerManagerXML :: AddList(const APLXML_Base::PhysicalLayerList_t* apList, FilterLevel aLevel) - { - AddStandalones(apList->SerialVector, aLevel); - AddStandalones(apList->TCPClientVector, aLevel); - AddStandalones(apList->TCPServerVector, aLevel); - } - - // Created helper function to remove ugly loops. - template - void PhysicalLayerManagerXML :: AddStandalones(const std::vector& arVector, FilterLevel aLevel) - { - for(size_t i=0; i(arVector[i]->Name, aLevel, arVector[i]); - } - } - - template - void PhysicalLayerManagerXML :: AddPhysLayer(const std::string& aName, FilterLevel aLevel, const T* apConfig) - { - PhysLayerSettings s(aLevel, apConfig->OpenRetryMS); - IPhysicalLayerAsyncFactory fac = PhysicalLayerXMLFactory::GetFactoryAsync(apConfig); - PhysLayerInstance i(fac); - this->AddLayer(aName, s, i); - } - - -}} - - - +#include "PhysicalLayerManagerXML.h" + +#include +#include "PhysicalLayerXMLFactory.h" +#include "XMLConversion.h" + +#include + +namespace apl { class EventLog; } + +using namespace APLXML_Base; + +namespace apl { namespace xml { + + + PhysicalLayerManagerXML::PhysicalLayerManagerXML(Logger* apLogger) : PhysicalLayerManager(apLogger) + {} + + PhysicalLayerManagerXML::PhysicalLayerManagerXML(Logger* apLogger, const APLXML_Base::PhysicalLayerList_t* apList, FilterLevel aLevel) : + PhysicalLayerManager(apLogger) + { + this->AddList(apList, aLevel); + } + + void PhysicalLayerManagerXML :: AddList(const APLXML_Base::PhysicalLayerList_t* apList, FilterLevel aLevel) + { + AddStandalones(apList->SerialVector, aLevel); + AddStandalones(apList->TCPClientVector, aLevel); + AddStandalones(apList->TCPServerVector, aLevel); + } + + // Created helper function to remove ugly loops. + template + void PhysicalLayerManagerXML :: AddStandalones(const std::vector& arVector, FilterLevel aLevel) + { + for(size_t i=0; i(arVector[i]->Name, aLevel, arVector[i]); + } + } + + template + void PhysicalLayerManagerXML :: AddPhysLayer(const std::string& aName, FilterLevel aLevel, const T* apConfig) + { + PhysLayerSettings s(aLevel, apConfig->OpenRetryMS); + IPhysicalLayerAsyncFactory fac = PhysicalLayerXMLFactory::GetFactoryAsync(apConfig); + PhysLayerInstance i(fac); + this->AddLayer(aName, s, i); + } + + +}} + + + diff --git a/APLXML/PhysicalLayerManagerXML.h b/APLXML/PhysicalLayerManagerXML.h index 857cf13f..ac353582 100644 --- a/APLXML/PhysicalLayerManagerXML.h +++ b/APLXML/PhysicalLayerManagerXML.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,50 +6,50 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __PHYSICAL_LAYER_MANAGER_XML_ -#define __PHYSICAL_LAYER_MANAGER_XML_ - -#include -#include - - -namespace APLXML_Base { - class PhysicalLayerList_t; -} - -namespace apl { class EventLog; } - -namespace apl { namespace xml { - -class PhysicalLayerManagerXML : public PhysicalLayerManager -{ - public: - PhysicalLayerManagerXML(Logger*); - PhysicalLayerManagerXML(Logger*, const APLXML_Base::PhysicalLayerList_t*, FilterLevel aLevel); - virtual ~PhysicalLayerManagerXML() {} - - void AddList(const APLXML_Base::PhysicalLayerList_t*, FilterLevel aLevel); - - private: - - template - void AddStandalones(const std::vector& arVector, FilterLevel aLevel); - - template - void AddPhysLayer(const std::string& aName, FilterLevel aLevel, const T* apConfig); -}; - -}} - -#endif - +// +#ifndef __PHYSICAL_LAYER_MANAGER_XML_ +#define __PHYSICAL_LAYER_MANAGER_XML_ + +#include +#include + + +namespace APLXML_Base { + class PhysicalLayerList_t; +} + +namespace apl { class EventLog; } + +namespace apl { namespace xml { + +class PhysicalLayerManagerXML : public PhysicalLayerManager +{ + public: + PhysicalLayerManagerXML(Logger*); + PhysicalLayerManagerXML(Logger*, const APLXML_Base::PhysicalLayerList_t*, FilterLevel aLevel); + virtual ~PhysicalLayerManagerXML() {} + + void AddList(const APLXML_Base::PhysicalLayerList_t*, FilterLevel aLevel); + + private: + + template + void AddStandalones(const std::vector& arVector, FilterLevel aLevel); + + template + void AddPhysLayer(const std::string& aName, FilterLevel aLevel, const T* apConfig); +}; + +}} + +#endif + diff --git a/APLXML/PhysicalLayerXMLFactory.h b/APLXML/PhysicalLayerXMLFactory.h index 6efce7a2..6dd7faae 100644 --- a/APLXML/PhysicalLayerXMLFactory.h +++ b/APLXML/PhysicalLayerXMLFactory.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,43 +6,43 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __PHYSICAL_LAYER_XML_FACTORY_H_ -#define __PHYSICAL_LAYER_XML_FACTORY_H_ - -#include -#include -#include - -namespace apl { namespace xml { - -class PhysicalLayerXMLFactory -{ - public: - - //these 3 return functor factories - static IPhysicalLayerAsyncFactory GetFactoryAsync(const APLXML_Base::PhysicalLayerDescriptor_t* apCfg); - - /* These factories should take the regular configuration types */ - static IPhysicalLayerAsyncFactory GetAsync(const APLXML_Base::Serial_t* apCfg); - static IPhysicalLayerAsyncFactory GetAsync(const APLXML_Base::TCPClient_t* apCfg); - static IPhysicalLayerAsyncFactory GetAsync(const APLXML_Base::TCPServer_t* apCfg); -}; - -int BaudToInt(APLXML_Base::BaudRateEnum aBaud); -ParityType EnumToParity(APLXML_Base::ParityEnum aParity); -SerialSettings GetSerialSettings(const APLXML_Base::Serial_t* apCfg); -FlowType EnumToFlow(APLXML_Base::FlowControlEnum); - -}} - -#endif +// +#ifndef __PHYSICAL_LAYER_XML_FACTORY_H_ +#define __PHYSICAL_LAYER_XML_FACTORY_H_ + +#include +#include +#include + +namespace apl { namespace xml { + +class PhysicalLayerXMLFactory +{ + public: + + //these 3 return functor factories + static IPhysicalLayerAsyncFactory GetFactoryAsync(const APLXML_Base::PhysicalLayerDescriptor_t* apCfg); + + /* These factories should take the regular configuration types */ + static IPhysicalLayerAsyncFactory GetAsync(const APLXML_Base::Serial_t* apCfg); + static IPhysicalLayerAsyncFactory GetAsync(const APLXML_Base::TCPClient_t* apCfg); + static IPhysicalLayerAsyncFactory GetAsync(const APLXML_Base::TCPServer_t* apCfg); +}; + +int BaudToInt(APLXML_Base::BaudRateEnum aBaud); +ParityType EnumToParity(APLXML_Base::ParityEnum aParity); +SerialSettings GetSerialSettings(const APLXML_Base::Serial_t* apCfg); +FlowType EnumToFlow(APLXML_Base::FlowControlEnum); + +}} + +#endif diff --git a/APLXML/SingleNodeSaver.h b/APLXML/SingleNodeSaver.h index 1b09b576..1792a805 100644 --- a/APLXML/SingleNodeSaver.h +++ b/APLXML/SingleNodeSaver.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _SINGLE_NODE_SAVER_H_ @@ -37,7 +37,7 @@ namespace apl{ SingleNodeSaver(std::string aFileName, Logger* apLogger) :Loggable(apLogger), mFileName(aFileName) { } - + protected: bool _LoadNode(RootNode&); bool _SaveNode(RootNode&); diff --git a/APLXML/XMLConversion.cpp b/APLXML/XMLConversion.cpp index be5709ea..62f20165 100644 --- a/APLXML/XMLConversion.cpp +++ b/APLXML/XMLConversion.cpp @@ -16,25 +16,25 @@ // specific language governing permissions and limitations // under the License. // -#include "XMLConversion.h" - -using namespace APLXML_Base; - -namespace apl { namespace xml { - - FilterLevel Convert(APLXML_Base::LogLevelEnum aEnum) - { - switch(aEnum) - { - case(APLXML_Base::LOG_DEBUG): return LEV_DEBUG; - case(APLXML_Base::LOG_COMM): return LEV_COMM; - case(APLXML_Base::LOG_INTERPRET): return LEV_INTERPRET; - case(APLXML_Base::LOG_INFO): return LEV_INFO; - case(APLXML_Base::LOG_WARNING): return LEV_WARNING; - case(APLXML_Base::LOG_ERROR): return LEV_ERROR; - case(APLXML_Base::LOG_EVENT): return LEV_EVENT; - default: return LEV_WARNING; - } - } - -}} +#include "XMLConversion.h" + +using namespace APLXML_Base; + +namespace apl { namespace xml { + + FilterLevel Convert(APLXML_Base::LogLevelEnum aEnum) + { + switch(aEnum) + { + case(APLXML_Base::LOG_DEBUG): return LEV_DEBUG; + case(APLXML_Base::LOG_COMM): return LEV_COMM; + case(APLXML_Base::LOG_INTERPRET): return LEV_INTERPRET; + case(APLXML_Base::LOG_INFO): return LEV_INFO; + case(APLXML_Base::LOG_WARNING): return LEV_WARNING; + case(APLXML_Base::LOG_ERROR): return LEV_ERROR; + case(APLXML_Base::LOG_EVENT): return LEV_EVENT; + default: return LEV_WARNING; + } + } + +}} diff --git a/APLXML/XMLConversion.h b/APLXML/XMLConversion.h index 067b4a5f..5b8ca7c5 100644 --- a/APLXML/XMLConversion.h +++ b/APLXML/XMLConversion.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,25 +6,25 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __XML_CONVERSION_H_ -#define __XML_CONVERSION_H_ - -#include -#include - -namespace apl { namespace xml { - - FilterLevel Convert(APLXML_Base::LogLevelEnum aEnum); -}} - -#endif +// +#ifndef __XML_CONVERSION_H_ +#define __XML_CONVERSION_H_ + +#include +#include + +namespace apl { namespace xml { + + FilterLevel Convert(APLXML_Base::LogLevelEnum aEnum); +}} + +#endif diff --git a/APLXML/XML_APL.h b/APLXML/XML_APL.h index 527619b2..bc384fff 100644 --- a/APLXML/XML_APL.h +++ b/APLXML/XML_APL.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __XML_APL_CONFIGURE_H_ #define __XML_APL_CONFIGURE_H_ @@ -26,11 +26,11 @@ namespace apl { namespace xml { class XML_APL { public: - + static APLXML_Base::TCPServer_t* AddTCPServer(APLXML_Base::PhysicalLayerList_t& arList, const std::string& arDevice, int aPort); static APLXML_Base::TCPClient_t* AddTCPClient(APLXML_Base::PhysicalLayerList_t& arList, const std::string& arDevice, const std::string& arServer, int aPort); static APLXML_Base::Serial_t* AddSerial(APLXML_Base::PhysicalLayerList_t& arList, const std::string& arName, const std::string& arDevice); - + }; }} diff --git a/APLXML/rake.project.rb b/APLXML/rake.project.rb index 089d844b..308490e5 100644 --- a/APLXML/rake.project.rb +++ b/APLXML/rake.project.rb @@ -16,8 +16,8 @@ # specific language governing permissions and limitations # under the License. # - -$options = { -:target => 'libpsixml.a', -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES] -} + +$options = { +:target => 'libpsixml.a', +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES] +} diff --git a/APLXML/tinybinding.cpp b/APLXML/tinybinding.cpp index f4480e9d..7087e935 100644 --- a/APLXML/tinybinding.cpp +++ b/APLXML/tinybinding.cpp @@ -16,94 +16,94 @@ // specific language governing permissions and limitations // under the License. // -#include "tinybinding.h" - -#include - -using namespace std; -using namespace apl; - - -IXMLDataBound::IXMLDataBound():valid(false) -{ - -} - -IXMLDataBound::~IXMLDataBound(){ - -} -bool IXMLDataBound::msExceptOnFailure = true; - -const char * IXMLDataBound::GetValue(const char * aNodeName, TiXmlNode* apNode, TiXmlNode* apParent){ - if(apNode != NULL){ - TiXmlElement* node = apNode->ToElement(); - if(node != NULL){ - return node->GetText(); - } - } - std::ostringstream oss; - oss << "ERROR: Missing node: " << aNodeName << " at " << apParent->Row() << ":" << apParent->Column(); - if(msExceptOnFailure){ - throw apl::Exception(LOCATION, oss.str()); - }else{ - std::cout << oss.str() << std::endl; - return ""; - } -} - -void loadXmlInto(const std::string& arFileName, IXMLDataBound* sps) -{ - TiXmlDocument doc(arFileName); - - if(!doc.LoadFile()) - { - std::ostringstream oss; - oss << "Load file failed on: " << arFileName << " - " << doc.ErrorDesc() << " at " << doc.ErrorRow() << ":"<< doc.ErrorCol(); - throw Exception("loadXmlInto", oss.str(), IXMLDataBound::ERR_XML_NO_FILE); - } - if(!doc.Type() == TiXmlNode::DOCUMENT) - throw Exception("loadXmlInto","Document is not of type TiXmlNode::DOCUMENT"); - - TiXmlNode* node = doc.FirstChild(); - TiXmlNode* lastChild = doc.LastChild(); - while(node->Type() != TiXmlNode::ELEMENT && node != lastChild){ - node = node->NextSibling(); - } - sps->fromXml(node); -}; - -void WriteXmlToFile(IXMLDataBound* aXml, std::string aFileName) -{ - TiXmlDocument doc; - aXml->toXml(&doc, true, true); - if(!doc.SaveFile(aFileName)) throw Exception(LOCATION, "Unspecified error while saving"); -} - - - -template <> -void collectedType::toXml(TiXmlNode* pParent, bool /*aCreateNode*/, bool /*aIgnoreValid*/){ - //no idea why we need typename here but caused link error under - //gcc. fix: http://gcc.gnu.org/ml/gcc-help/2004-10/msg00179.html - std::vector< string *>::iterator iter = collection.begin(); - while(iter != collection.end()){ - string* item = (*iter); - TiXmlElement* pEm = new TiXmlElement(name); - TiXmlText* pText = new TiXmlText(ToString_string(*item)); - pEm->LinkEndChild(pText); - pParent->LinkEndChild(pEm); - //item->toXml(pParent, aCreateNode); - iter++; - }; -}; - -template <> -void collectedType::fromXml(TiXmlNode* pNode){ - TiXmlElement* node=pNode->FirstChildElement(name); - for( ; node != 0 ; node=node->NextSiblingElement(name)) - { - string* item = new string(); - *item = FromString_string(pNode, GetValue(name.c_str(), node, pNode)); - collection.push_back(item); - } -}; +#include "tinybinding.h" + +#include + +using namespace std; +using namespace apl; + + +IXMLDataBound::IXMLDataBound():valid(false) +{ + +} + +IXMLDataBound::~IXMLDataBound(){ + +} +bool IXMLDataBound::msExceptOnFailure = true; + +const char * IXMLDataBound::GetValue(const char * aNodeName, TiXmlNode* apNode, TiXmlNode* apParent){ + if(apNode != NULL){ + TiXmlElement* node = apNode->ToElement(); + if(node != NULL){ + return node->GetText(); + } + } + std::ostringstream oss; + oss << "ERROR: Missing node: " << aNodeName << " at " << apParent->Row() << ":" << apParent->Column(); + if(msExceptOnFailure){ + throw apl::Exception(LOCATION, oss.str()); + }else{ + std::cout << oss.str() << std::endl; + return ""; + } +} + +void loadXmlInto(const std::string& arFileName, IXMLDataBound* sps) +{ + TiXmlDocument doc(arFileName); + + if(!doc.LoadFile()) + { + std::ostringstream oss; + oss << "Load file failed on: " << arFileName << " - " << doc.ErrorDesc() << " at " << doc.ErrorRow() << ":"<< doc.ErrorCol(); + throw Exception("loadXmlInto", oss.str(), IXMLDataBound::ERR_XML_NO_FILE); + } + if(!doc.Type() == TiXmlNode::DOCUMENT) + throw Exception("loadXmlInto","Document is not of type TiXmlNode::DOCUMENT"); + + TiXmlNode* node = doc.FirstChild(); + TiXmlNode* lastChild = doc.LastChild(); + while(node->Type() != TiXmlNode::ELEMENT && node != lastChild){ + node = node->NextSibling(); + } + sps->fromXml(node); +}; + +void WriteXmlToFile(IXMLDataBound* aXml, std::string aFileName) +{ + TiXmlDocument doc; + aXml->toXml(&doc, true, true); + if(!doc.SaveFile(aFileName)) throw Exception(LOCATION, "Unspecified error while saving"); +} + + + +template <> +void collectedType::toXml(TiXmlNode* pParent, bool /*aCreateNode*/, bool /*aIgnoreValid*/){ + //no idea why we need typename here but caused link error under + //gcc. fix: http://gcc.gnu.org/ml/gcc-help/2004-10/msg00179.html + std::vector< string *>::iterator iter = collection.begin(); + while(iter != collection.end()){ + string* item = (*iter); + TiXmlElement* pEm = new TiXmlElement(name); + TiXmlText* pText = new TiXmlText(ToString_string(*item)); + pEm->LinkEndChild(pText); + pParent->LinkEndChild(pEm); + //item->toXml(pParent, aCreateNode); + iter++; + }; +}; + +template <> +void collectedType::fromXml(TiXmlNode* pNode){ + TiXmlElement* node=pNode->FirstChildElement(name); + for( ; node != 0 ; node=node->NextSiblingElement(name)) + { + string* item = new string(); + *item = FromString_string(pNode, GetValue(name.c_str(), node, pNode)); + collection.push_back(item); + } +}; diff --git a/APLXML/tinybinding.h b/APLXML/tinybinding.h index 2e7e1735..cc554c15 100644 --- a/APLXML/tinybinding.h +++ b/APLXML/tinybinding.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _TINY_BINDING_H_ #define _TINY_BINDING_H_ @@ -60,7 +60,7 @@ class IXMLDataBound{ inline static bool FromString_bool(TiXmlNode* apParent, const char * aStr); inline static std::string FromString_string(TiXmlNode* apParent, const char * aStr); inline static float FromString_float(TiXmlNode* apParent, const char * aStr); - + inline static std::string ToString_int(int aValue); inline static std::string ToString_double(double aValue); inline static std::string ToString_bool(bool aValue); @@ -93,7 +93,7 @@ class IXMLDataBound{ return aDefault; } } - + template std::string IXMLDataBound::ToString_T(T aValue){ std::ostringstream oss; @@ -118,7 +118,7 @@ class IXMLDataBound{ inline float IXMLDataBound::FromString_float(TiXmlNode* apParent, const char * aStr){ return FromString_T(apParent, aStr, "float", 0); } - + inline std::string IXMLDataBound::ToString_int(int aValue){return ToString_T(aValue);} inline std::string IXMLDataBound::ToString_double(double aValue){return ToString_T(aValue);} inline std::string IXMLDataBound::ToString_bool(bool aValue){return ToString_T(aValue);} diff --git a/CSToCppXMLBinder/Bind.cs b/CSToCppXMLBinder/Bind.cs index 0aab2ee7..d92af3f0 100755 --- a/CSToCppXMLBinder/Bind.cs +++ b/CSToCppXMLBinder/Bind.cs @@ -1,34 +1,34 @@ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; -using System.Xml.Serialization; -using System.Collections.Specialized; - -namespace CSToCppXMLBinder -{ - class Bind - { - static void Main(string[] args) - { - if (args.Length != 4) - { - Console.Error.WriteLine("Command line should be:\n\t\tBind.exe [NameSpace] [Assembly] [output]\n\nEx: Bind PSiXML.Common Bindings.netmodule mappings.ini"); - return; - } - try - { - string xml_support_dir = args[3]; - - Assembly asm = Assembly.LoadFrom(Environment.CurrentDirectory+"\\"+args[1]); - CppBinder.BindAssembly(args[2], args[0], asm, xml_support_dir); - Console.WriteLine("Success!"); - } - catch (Exception e) - { - Console.Error.WriteLine(e.ToString()); - } - } - } -} + +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Xml.Serialization; +using System.Collections.Specialized; + +namespace CSToCppXMLBinder +{ + class Bind + { + static void Main(string[] args) + { + if (args.Length != 4) + { + Console.Error.WriteLine("Command line should be:\n\t\tBind.exe [NameSpace] [Assembly] [output]\n\nEx: Bind PSiXML.Common Bindings.netmodule mappings.ini"); + return; + } + try + { + string xml_support_dir = args[3]; + + Assembly asm = Assembly.LoadFrom(Environment.CurrentDirectory+"\\"+args[1]); + CppBinder.BindAssembly(args[2], args[0], asm, xml_support_dir); + Console.WriteLine("Success!"); + } + catch (Exception e) + { + Console.Error.WriteLine(e.ToString()); + } + } + } +} diff --git a/CSToCppXMLBinder/CSToCppXMLBinder.csproj b/CSToCppXMLBinder/CSToCppXMLBinder.csproj index 62bea6a4..da4abb78 100755 --- a/CSToCppXMLBinder/CSToCppXMLBinder.csproj +++ b/CSToCppXMLBinder/CSToCppXMLBinder.csproj @@ -1,50 +1,50 @@ - - - Debug - AnyCPU - 8.0.50727 - 2.0 - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0} - Exe - Properties - CSToCppXMLBinder - CSToCppXMLBinder - - - true - full - false - bin\debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0} + Exe + Properties + CSToCppXMLBinder + CSToCppXMLBinder + + + true + full + false + bin\debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSToCppXMLBinder/CppBinder.cs b/CSToCppXMLBinder/CppBinder.cs index e924acae..9cac25ca 100755 --- a/CSToCppXMLBinder/CppBinder.cs +++ b/CSToCppXMLBinder/CppBinder.cs @@ -162,7 +162,7 @@ private static void CreateOutputFiles(StreamWriter header, StreamWriter cpp, Fil foreach (string include in info.includes.Keys) { - Console.WriteLine("include: " + include); + Console.WriteLine("include: " + include); string dir = xml_support_dir; Console.WriteLine("include: " + include + " -> " + dir); header.WriteLine("#include <"+dir+"/" + include + ".h>"); diff --git a/ConfigurationBuilder/ReBuildCSharpFromSchema.bat b/ConfigurationBuilder/ReBuildCSharpFromSchema.bat index 9735af9b..ec66e189 100755 --- a/ConfigurationBuilder/ReBuildCSharpFromSchema.bat +++ b/ConfigurationBuilder/ReBuildCSharpFromSchema.bat @@ -1,17 +1,17 @@ -%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\SlaveTestSet.xsd" /d "/y:APLXML.STS|APLXML.DNP|APLXML.Base" /n:ignored "/z:%CD%\APLXML.STS.cs|%CD%\APLXML.DNP.cs|%CD%\APLXML.Base.cs" -%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\MasterTestSet.xsd" /d "/y:APLXML.DNP|APLXML.Base|APLXML.MTS" /n:ignored "/z:%CD%\APLXML.DNP.cs|%CD%\APLXML.Base.cs|%CD%\APLXML.MTS.cs" -%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\DNP.xsd" /d /y:"APLXML.DNP|APLXML.Base" /n:ignored "/z:%CD%\APLXML.DNP.cs|%CD%\APLXML.Base.cs" -%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\APL.xsd" /d /n:"APLXML.Base" - -call "%VS80COMNTOOLS%vsvars32.bat" -csc /t:module /out:Bindings.netmodule APLXML.DNP.cs APLXML.Base.cs APLXML.MTS.cs APLXML.STS.cs -al /t:lib /out:Bindings.assembly Bindings.netmodule -CSToCppXMLBinder.exe APLXML.Base Bindings.assembly ../XMLBindings XMLBindings -CSToCppXMLBinder.exe APLXML.DNP Bindings.assembly ../XMLBindings XMLBindings -CSToCppXMLBinder.exe APLXML.MTS Bindings.assembly ../XMLBindings XMLBindings -CSToCppXMLBinder.exe APLXML.STS Bindings.assembly ../XMLBindings XMLBindings - - -del Bindings.assembly -del Bindings.netmodule -pause +%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\SlaveTestSet.xsd" /d "/y:APLXML.STS|APLXML.DNP|APLXML.Base" /n:ignored "/z:%CD%\APLXML.STS.cs|%CD%\APLXML.DNP.cs|%CD%\APLXML.Base.cs" +%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\MasterTestSet.xsd" /d "/y:APLXML.DNP|APLXML.Base|APLXML.MTS" /n:ignored "/z:%CD%\APLXML.DNP.cs|%CD%\APLXML.Base.cs|%CD%\APLXML.MTS.cs" +%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\DNP.xsd" /d /y:"APLXML.DNP|APLXML.Base" /n:ignored "/z:%CD%\APLXML.DNP.cs|%CD%\APLXML.Base.cs" +%TOOLS_HOME%\XSDObjectGenerator\xsdobjectgen.exe "%CD%\APL.xsd" /d /n:"APLXML.Base" + +call "%VS80COMNTOOLS%vsvars32.bat" +csc /t:module /out:Bindings.netmodule APLXML.DNP.cs APLXML.Base.cs APLXML.MTS.cs APLXML.STS.cs +al /t:lib /out:Bindings.assembly Bindings.netmodule +CSToCppXMLBinder.exe APLXML.Base Bindings.assembly ../XMLBindings XMLBindings +CSToCppXMLBinder.exe APLXML.DNP Bindings.assembly ../XMLBindings XMLBindings +CSToCppXMLBinder.exe APLXML.MTS Bindings.assembly ../XMLBindings XMLBindings +CSToCppXMLBinder.exe APLXML.STS Bindings.assembly ../XMLBindings XMLBindings + + +del Bindings.assembly +del Bindings.netmodule +pause diff --git a/DNP.sln b/DNP.sln index 1e597723..bdb9cdd4 100755 --- a/DNP.sln +++ b/DNP.sln @@ -1,194 +1,194 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSToCppXMLBinder", "CSToCppXMLBinder\CSToCppXMLBinder.csproj", "{F5DDA7D5-B5CC-47DF-923B-55049170C0D0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3", "DNP3\DNP3.vcproj", "{E053E7ED-F462-4DE0-8D69-6D97045FFB25}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3Test", "DNP3Test\DNP3Test.vcproj", "{893D4C53-0729-480D-8F40-75E7139224DF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSet", "TestSet\TestSet.vcproj", "{DE526D6F-CE9C-47E4-8783-12344FDBF581}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3XML", "DNP3XML\DNP3XML.vcproj", "{547D1F36-8A34-4C48-B16D-9C3D60EFA505}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml", "tinyxml\tinyxml.vcproj", "{220D8EB8-6C0C-416C-8BBB-F554431C29CD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Terminal", "Terminal\Terminal.vcproj", "{FB9D36B0-102F-4E11-BF45-C80A3709D098}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalTest", "TerminalTest\TerminalTest.vcproj", "{6AB7896D-E692-4075-9396-9B1C7AE6F704}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APL", "APL\APL.vcproj", "{761218B0-F2B7-42DA-9C9B-413FA34886DF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APLTestTools", "APLTestTools\APLTestTools.vcproj", "{41D4B22B-F06E-4230-9AA8-3BFF096CC710}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APLTest", "TestAPL\TestAPL.vcproj", "{9BCA9E3F-3974-4B32-883D-9115160E4051}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XMLBindings", "XMLBindings\XMLBindings.vcproj", "{F1EB4FCC-3299-4574-AEA2-19B61F35966D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APLXML", "APLXML\APLXML.vcproj", "{91323793-8551-4484-83DC-21AC9C18BD2E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3Java", "DNP3Java\DNP3Java.vcproj", "{ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}" -EndProject -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "TestSetInstaller", "TestSetInstaller\TestSetInstaller.vdproj", "{9FAD9888-9441-4ACF-8750-90AFEA9F938A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Win32.ActiveCfg = Debug|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Any CPU.Build.0 = Release|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Win32.ActiveCfg = Release|Any CPU - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Win32.ActiveCfg = Debug|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Win32.Build.0 = Debug|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Any CPU.ActiveCfg = Release|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Mixed Platforms.Build.0 = Release|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Win32.ActiveCfg = Release|Win32 - {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Win32.Build.0 = Release|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Win32.ActiveCfg = Debug|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Win32.Build.0 = Debug|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Any CPU.ActiveCfg = Release|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Mixed Platforms.Build.0 = Release|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Win32.ActiveCfg = Release|Win32 - {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Win32.Build.0 = Release|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Win32.ActiveCfg = Debug|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Win32.Build.0 = Debug|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Any CPU.ActiveCfg = Release|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Mixed Platforms.Build.0 = Release|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Win32.ActiveCfg = Release|Win32 - {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Win32.Build.0 = Release|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Win32.ActiveCfg = Debug|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Win32.Build.0 = Debug|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Any CPU.ActiveCfg = Release|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Mixed Platforms.Build.0 = Release|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Win32.ActiveCfg = Release|Win32 - {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Win32.Build.0 = Release|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Win32.ActiveCfg = Debug|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Win32.Build.0 = Debug|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Any CPU.ActiveCfg = Release|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Mixed Platforms.Build.0 = Release|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Win32.ActiveCfg = Release|Win32 - {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Win32.Build.0 = Release|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Win32.ActiveCfg = Debug|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Win32.Build.0 = Debug|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Any CPU.ActiveCfg = Release|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Mixed Platforms.Build.0 = Release|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Win32.ActiveCfg = Release|Win32 - {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Win32.Build.0 = Release|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Win32.ActiveCfg = Debug|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Win32.Build.0 = Debug|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Any CPU.ActiveCfg = Release|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Win32.ActiveCfg = Release|Win32 - {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Win32.Build.0 = Release|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Win32.ActiveCfg = Debug|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Win32.Build.0 = Debug|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Any CPU.ActiveCfg = Release|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Mixed Platforms.Build.0 = Release|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Win32.ActiveCfg = Release|Win32 - {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Win32.Build.0 = Release|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Win32.ActiveCfg = Debug|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Win32.Build.0 = Debug|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Any CPU.ActiveCfg = Release|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Mixed Platforms.Build.0 = Release|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Win32.ActiveCfg = Release|Win32 - {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Win32.Build.0 = Release|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Win32.ActiveCfg = Debug|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Win32.Build.0 = Debug|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Any CPU.ActiveCfg = Release|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Mixed Platforms.Build.0 = Release|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Win32.ActiveCfg = Release|Win32 - {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Win32.Build.0 = Release|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Win32.ActiveCfg = Debug|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Win32.Build.0 = Debug|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Any CPU.ActiveCfg = Release|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Mixed Platforms.Build.0 = Release|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Win32.ActiveCfg = Release|Win32 - {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Win32.Build.0 = Release|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Win32.Build.0 = Debug|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Any CPU.ActiveCfg = Release|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Mixed Platforms.Build.0 = Release|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Win32.ActiveCfg = Release|Win32 - {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Win32.Build.0 = Release|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Win32.ActiveCfg = Debug|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Win32.Build.0 = Debug|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Any CPU.ActiveCfg = Release|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Mixed Platforms.Build.0 = Release|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Win32.ActiveCfg = Release|Win32 - {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Win32.Build.0 = Release|Win32 - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Debug|Any CPU.ActiveCfg = Debug - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Debug|Mixed Platforms.ActiveCfg = Debug - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Debug|Win32.ActiveCfg = Debug - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Any CPU.ActiveCfg = Release - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Mixed Platforms.ActiveCfg = Release - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Mixed Platforms.Build.0 = Release - {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Win32.ActiveCfg = Release - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSToCppXMLBinder", "CSToCppXMLBinder\CSToCppXMLBinder.csproj", "{F5DDA7D5-B5CC-47DF-923B-55049170C0D0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3", "DNP3\DNP3.vcproj", "{E053E7ED-F462-4DE0-8D69-6D97045FFB25}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3Test", "DNP3Test\DNP3Test.vcproj", "{893D4C53-0729-480D-8F40-75E7139224DF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSet", "TestSet\TestSet.vcproj", "{DE526D6F-CE9C-47E4-8783-12344FDBF581}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3XML", "DNP3XML\DNP3XML.vcproj", "{547D1F36-8A34-4C48-B16D-9C3D60EFA505}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml", "tinyxml\tinyxml.vcproj", "{220D8EB8-6C0C-416C-8BBB-F554431C29CD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Terminal", "Terminal\Terminal.vcproj", "{FB9D36B0-102F-4E11-BF45-C80A3709D098}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalTest", "TerminalTest\TerminalTest.vcproj", "{6AB7896D-E692-4075-9396-9B1C7AE6F704}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APL", "APL\APL.vcproj", "{761218B0-F2B7-42DA-9C9B-413FA34886DF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APLTestTools", "APLTestTools\APLTestTools.vcproj", "{41D4B22B-F06E-4230-9AA8-3BFF096CC710}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APLTest", "TestAPL\TestAPL.vcproj", "{9BCA9E3F-3974-4B32-883D-9115160E4051}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XMLBindings", "XMLBindings\XMLBindings.vcproj", "{F1EB4FCC-3299-4574-AEA2-19B61F35966D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APLXML", "APLXML\APLXML.vcproj", "{91323793-8551-4484-83DC-21AC9C18BD2E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNP3Java", "DNP3Java\DNP3Java.vcproj", "{ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}" +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "TestSetInstaller", "TestSetInstaller\TestSetInstaller.vdproj", "{9FAD9888-9441-4ACF-8750-90AFEA9F938A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Debug|Win32.ActiveCfg = Debug|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Any CPU.Build.0 = Release|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F5DDA7D5-B5CC-47DF-923B-55049170C0D0}.Release|Win32.ActiveCfg = Release|Any CPU + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Win32.ActiveCfg = Debug|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Debug|Win32.Build.0 = Debug|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Any CPU.ActiveCfg = Release|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Mixed Platforms.Build.0 = Release|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Win32.ActiveCfg = Release|Win32 + {E053E7ED-F462-4DE0-8D69-6D97045FFB25}.Release|Win32.Build.0 = Release|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Win32.ActiveCfg = Debug|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Debug|Win32.Build.0 = Debug|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Any CPU.ActiveCfg = Release|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Mixed Platforms.Build.0 = Release|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Win32.ActiveCfg = Release|Win32 + {893D4C53-0729-480D-8F40-75E7139224DF}.Release|Win32.Build.0 = Release|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Win32.ActiveCfg = Debug|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Debug|Win32.Build.0 = Debug|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Any CPU.ActiveCfg = Release|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Mixed Platforms.Build.0 = Release|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Win32.ActiveCfg = Release|Win32 + {DE526D6F-CE9C-47E4-8783-12344FDBF581}.Release|Win32.Build.0 = Release|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Win32.ActiveCfg = Debug|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Debug|Win32.Build.0 = Debug|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Any CPU.ActiveCfg = Release|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Mixed Platforms.Build.0 = Release|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Win32.ActiveCfg = Release|Win32 + {547D1F36-8A34-4C48-B16D-9C3D60EFA505}.Release|Win32.Build.0 = Release|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Win32.ActiveCfg = Debug|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Debug|Win32.Build.0 = Debug|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Any CPU.ActiveCfg = Release|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Mixed Platforms.Build.0 = Release|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Win32.ActiveCfg = Release|Win32 + {220D8EB8-6C0C-416C-8BBB-F554431C29CD}.Release|Win32.Build.0 = Release|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Win32.ActiveCfg = Debug|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Debug|Win32.Build.0 = Debug|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Any CPU.ActiveCfg = Release|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Mixed Platforms.Build.0 = Release|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Win32.ActiveCfg = Release|Win32 + {FB9D36B0-102F-4E11-BF45-C80A3709D098}.Release|Win32.Build.0 = Release|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Win32.ActiveCfg = Debug|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Debug|Win32.Build.0 = Debug|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Any CPU.ActiveCfg = Release|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Win32.ActiveCfg = Release|Win32 + {6AB7896D-E692-4075-9396-9B1C7AE6F704}.Release|Win32.Build.0 = Release|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Win32.ActiveCfg = Debug|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Debug|Win32.Build.0 = Debug|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Any CPU.ActiveCfg = Release|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Mixed Platforms.Build.0 = Release|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Win32.ActiveCfg = Release|Win32 + {761218B0-F2B7-42DA-9C9B-413FA34886DF}.Release|Win32.Build.0 = Release|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Win32.ActiveCfg = Debug|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Debug|Win32.Build.0 = Debug|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Any CPU.ActiveCfg = Release|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Mixed Platforms.Build.0 = Release|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Win32.ActiveCfg = Release|Win32 + {41D4B22B-F06E-4230-9AA8-3BFF096CC710}.Release|Win32.Build.0 = Release|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Win32.ActiveCfg = Debug|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Debug|Win32.Build.0 = Debug|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Any CPU.ActiveCfg = Release|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Mixed Platforms.Build.0 = Release|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Win32.ActiveCfg = Release|Win32 + {9BCA9E3F-3974-4B32-883D-9115160E4051}.Release|Win32.Build.0 = Release|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Win32.ActiveCfg = Debug|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Debug|Win32.Build.0 = Debug|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Any CPU.ActiveCfg = Release|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Mixed Platforms.Build.0 = Release|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Win32.ActiveCfg = Release|Win32 + {F1EB4FCC-3299-4574-AEA2-19B61F35966D}.Release|Win32.Build.0 = Release|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Win32.ActiveCfg = Debug|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Debug|Win32.Build.0 = Debug|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Any CPU.ActiveCfg = Release|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Mixed Platforms.Build.0 = Release|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Win32.ActiveCfg = Release|Win32 + {91323793-8551-4484-83DC-21AC9C18BD2E}.Release|Win32.Build.0 = Release|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Win32.ActiveCfg = Debug|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Debug|Win32.Build.0 = Debug|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Any CPU.ActiveCfg = Release|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Mixed Platforms.Build.0 = Release|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Win32.ActiveCfg = Release|Win32 + {ADDD6B3A-FFAE-4534-B27B-2795CEE8D2AD}.Release|Win32.Build.0 = Release|Win32 + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Debug|Any CPU.ActiveCfg = Debug + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Debug|Mixed Platforms.ActiveCfg = Debug + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Debug|Win32.ActiveCfg = Debug + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Any CPU.ActiveCfg = Release + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Mixed Platforms.ActiveCfg = Release + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Mixed Platforms.Build.0 = Release + {9FAD9888-9441-4ACF-8750-90AFEA9F938A}.Release|Win32.ActiveCfg = Release + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/DNP3/APDU.h b/DNP3/APDU.h index f20e2176..e2917dba 100644 --- a/DNP3/APDU.h +++ b/DNP3/APDU.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __APDU_H_ #define __APDU_H_ @@ -37,17 +37,17 @@ namespace apl { namespace dnp { - - /** + + /** Class for reading and writing APDUs. Interpret method and read iterators form the read interface, Set method and object write iterators form the write interface. */ class APDU { - + public: - + APDU(size_t aFragSize = DEFAULT_FRAG_SIZE); /// Parse the buffer. Throws exception if malformed data are encountered @@ -55,10 +55,10 @@ namespace apl { namespace dnp { /// Parse the header only. Throws exception if header is malformed void InterpretHeader(); - + /// @return The current size of the fragment in bytes size_t Size() const { return mFragmentSize; } - + /// @return pointer to the buffer const apl::byte_t* GetBuffer() const { return mBuffer; } @@ -70,7 +70,7 @@ namespace apl { namespace dnp { /// Reset and write new data into the buff void Write(const apl::byte_t* apStart, size_t aLength); - + /* Getter functions */ FunctionCodes GetFunction() const; @@ -85,7 +85,7 @@ namespace apl { namespace dnp { void SetControl(bool aFIR, bool aFIN, bool aCON = false, bool aUNS = false, int aSEQ = 0) { AppControlField f(aFIR, aFIN, aCON, aUNS, aSEQ); - this->SetControl(f); + this->SetControl(f); } void Set(FunctionCodes aCode, bool aFIR = true, bool aFIN = true, bool aCON = false, bool aUNS = false, int aSEQ = 0) @@ -96,9 +96,9 @@ namespace apl { namespace dnp { } void SetIIN(const IINField& arIIN); // throws an exception if FUNC != RSP or UNSOL - + HeaderReadIterator BeginRead() const; // returns an iterator to the first header - + /* Write iterators */ ObjectWriteIterator WriteContiguous(const FixedObject* apObj, size_t aStart, size_t aStop, QualifierCode aCode = QC_UNDEFINED); @@ -109,15 +109,15 @@ namespace apl { namespace dnp { IndexedWriteIterator WriteIndexed(const VariableByVariationObject* apObj, size_t aSize, size_t aIndex); IndexedWriteIterator WriteIndexed(const VariableByVariationObject* apObj, size_t aSize, QualifierCode aCode); - - + + // Placeholder writes do not need an iterator bool DoPlaceholderWrite(ObjectBase* apObj); static bool HasData(FunctionCodes aCode); std::string ToString() const; - + bool operator==(const APDU& rhs); bool operator!=(const APDU& rhs) { return !(*this == rhs); } @@ -130,11 +130,11 @@ namespace apl { namespace dnp { IndexedWriteIterator WriteCountHeader(size_t aObjectSize, size_t aPrefixSize, byte_t aGrp, byte_t aVar, size_t aCount, QualifierCode aQual); void WriteContiguousHeader(IObjectHeader* apHdr, byte_t* apPos, size_t aStart, size_t aStop); - + // Interpreted Information bool mIsInterpreted; IAppHeader* mpAppHeader; /// uses a singleton so auto copy is safe - std::vector mObjectHeaders; + std::vector mObjectHeaders; CopyableBuffer mBuffer; /// This makes it dynamically sizable without the need for a special copy constructor. size_t mFragmentSize; /// Number of bytes written to the buffer @@ -143,7 +143,7 @@ namespace apl { namespace dnp { QualifierCode GetIndexedQualifier(size_t aMaxIndex, size_t aCount); ICountHeader* GetCountHeader(QualifierCode aCode); - + ////////////////////////////////////////////////////////////// // Private Functions for Interpreting Frames ////////////////////////////////////////////////////////////// @@ -151,18 +151,18 @@ namespace apl { namespace dnp { IObjectHeader* GetObjectHeader(QualifierCode aCode); size_t ReadObjectHeader(size_t aOffset, size_t aRemainder); - + size_t GetPrefixSizeAndValidate(QualifierCode aCode, ObjectTypes aType); size_t GetNumObjects(const IObjectHeader* apHeader, const apl::byte_t* pStart); std::string GetSizeString(size_t aSize) const - { + { std::ostringstream oss; oss << "Insufficient data for object header: " << aSize; return oss.str(); } }; - + }} #endif diff --git a/DNP3/APDUConstants.h b/DNP3/APDUConstants.h index ce53f1c3..f7b4821a 100644 --- a/DNP3/APDUConstants.h +++ b/DNP3/APDUConstants.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,23 +6,23 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __APDU_CONSTANTS_H_ #define __APDU_CONSTANTS_H_ #include -namespace apl { namespace dnp { +namespace apl { namespace dnp { enum AppControlMasks { @@ -133,7 +133,7 @@ namespace apl { namespace dnp { QC_1B_START_STOP = 0x00, QC_2B_START_STOP = 0x01, QC_4B_START_STOP = 0x02, - + QC_ALL_OBJ = 0x06, QC_1B_CNT = 0x07, @@ -157,7 +157,7 @@ namespace apl { namespace dnp { bool IsConfirm(FunctionCodes aCode); std::string ToString(FunctionCodes aCode); - + }} diff --git a/DNP3/AppChannelStates.cpp b/DNP3/AppChannelStates.cpp index 356adf17..a448ff7f 100644 --- a/DNP3/AppChannelStates.cpp +++ b/DNP3/AppChannelStates.cpp @@ -16,245 +16,245 @@ // specific language governing permissions and limitations // under the License. // -#include "AppChannelStates.h" - -#include -#include -#include -#include -#include - -#include "AppLayerChannel.h" -#include "APDU.h" - -namespace apl { namespace dnp { - - // ---- Default behaviors for the states ---- - - void ACS_Base::Send(AppLayerChannel*, APDU&, size_t) - { this->ThrowInvalidState("Send"); } - - void ACS_Base::Cancel(AppLayerChannel*) - { this->ThrowInvalidState("Cancel"); } - - void ACS_Base::OnSendSuccess(AppLayerChannel*) - { this->ThrowInvalidState("OnSendSuccess"); } - - void ACS_Base::OnSendFailure(AppLayerChannel*) - { this->ThrowInvalidState("OnSendFailure"); } - - void ACS_Base::OnConfirm(AppLayerChannel* c, int aSeq) - { - ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, - "Unexpected confirm with sequence: " << aSeq, ALERR_UNEXPECTED_CONFIRM); - } - - void ACS_Base::OnResponse(AppLayerChannel* c, APDU& arAPDU) - { - LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, - "Unexpected response with sequence: " << arAPDU.GetControl().SEQ); - } - - void ACS_Base::OnTimeout(AppLayerChannel*) - { this->ThrowInvalidState("OnTimeout"); } - - void ACS_Base::ThrowInvalidState(const std::string& arMethod) - { - std::ostringstream oss; - oss << "State: " << this->Name() << " Method: " << arMethod; - throw InvalidStateException(LOCATION, oss.str()); - } - - void ACS_Base::ProcessResponse(AppLayerChannel* c, APDU& arAPDU, bool aExpectFIR) - { - AppControlField acf = arAPDU.GetControl(); - - if(acf.SEQ == c->Sequence()) { - if(acf.FIR == aExpectFIR) { - c->CancelTimer(); - - if(acf.FIN) { - c->ChangeState(ACS_Idle::Inst()); - c->DoFinalResponse(arAPDU); - } - else { - c->IncrSequence(); - c->ChangeState(ACS_WaitForFinalResponse::Inst()); - c->StartTimer(); - c->DoPartialResponse(arAPDU); - } - } - else { - ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Unexpected fir bit " << acf.FIR, ALERR_BAD_FIR_FIN); - } - } - else { - ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Bad sequence number " << acf.SEQ, ALERR_BAD_SEQUENCE); - } - } - - /// ---- ACS_IDle ---- - - ACS_Idle ACS_Idle::mInstance; - - void ACS_Idle::Send(AppLayerChannel* c, APDU& arAPDU, size_t aNumRetry) - { - AppControlField acf = arAPDU.GetControl(); - FunctionCodes func = arAPDU.GetFunction(); - acf.SEQ = (acf.FIR && func == FC_RESPONSE) ? c->Sequence() : c->IncrSequence(); - arAPDU.SetControl(acf); - c->ChangeState(NextState(c, arAPDU.GetFunction(), acf.CON)); - c->SetRetry(aNumRetry); - c->QueueSend(arAPDU); - } - - ACS_Base* ACS_Idle::NextState(AppLayerChannel* c, FunctionCodes aFunc, bool aConfirm) - { - switch(aFunc) - { - case(FC_CONFIRM): - throw ArgumentException(LOCATION, "Confirms are automatic only"); - case(FC_RESPONSE): - if(c->Sequence() < 0) - throw InvalidStateException(LOCATION, "Can't respond until we've received a request"); - - case(FC_UNSOLICITED_RESPONSE): - if(aConfirm) return ACS_SendConfirmed::Inst(); - else return ACS_Send::Inst(); - - case(FC_DIRECT_OPERATE_NO_ACK): - if(aConfirm) throw ArgumentException(LOCATION, "DO no ACK can't be confirmed"); - return ACS_Send::Inst(); - - default: // it's a request with an expected response - if(aConfirm) throw ArgumentException(LOCATION, "Confirmation not allowed for requests"); - return ACS_SendExpectResponse::Inst(); - } - } - - // ---- ACS_SendBase ---- - - void ACS_SendBase::OnSendFailure(AppLayerChannel* c) - { - if(!c->Retry(this)) { //if we can't retry, then go back to idle - c->ChangeState(ACS_Idle::Inst()); - c->DoFailure(); - } - } - - void ACS_SendBase::Cancel(AppLayerChannel* c) - { - c->ChangeState(ACS_SendCanceled::Inst()); - } - - // ---- ACS_SendCanceled ---- - - ACS_SendCanceled ACS_SendCanceled::mInstance; - - void ACS_SendCanceled::OnSendSuccess(AppLayerChannel* c) - { - c->ChangeState(ACS_Idle::Inst()); - c->DoFailure(); - } - - void ACS_SendCanceled::OnSendFailure(AppLayerChannel* c) - { - c->ChangeState(ACS_Idle::Inst()); - c->DoFailure(); - } - - // ---- ACS_Send ---- - - ACS_Send ACS_Send::mInstance; - - void ACS_Send::OnSendSuccess(AppLayerChannel* c) - { - c->ChangeState(ACS_Idle::Inst()); - c->DoSendSuccess(); - } - - // ---- ACS_SendConfirmed ---- - - ACS_SendConfirmed ACS_SendConfirmed::mInstance; - - void ACS_SendConfirmed::OnSendSuccess(AppLayerChannel* c) - { - c->ChangeState(ACS_WaitForConfirm::Inst()); - c->StartTimer(); - } - - // ---- ACS_SendExpectResponse ---- - - ACS_SendExpectResponse ACS_SendExpectResponse::mInstance; - - void ACS_SendExpectResponse::OnSendSuccess(AppLayerChannel* c) - { - c->ChangeState(ACS_WaitForFirstResponse::Inst()); - c->StartTimer(); - } - - // ---- ACS_WaitForConfirm ---- - - ACS_WaitForConfirm ACS_WaitForConfirm::mInstance; - - void ACS_WaitForConfirm::Cancel(AppLayerChannel* c) - { - c->ChangeState(ACS_Idle::Inst()); - c->CancelTimer(); - c->DoFailure(); - } - - void ACS_WaitForConfirm::OnConfirm(AppLayerChannel* c, int aSeq) - { - // does the confirm sequence match what we expect? - if(c->Sequence() == aSeq) { - c->CancelTimer(); - c->ChangeState(ACS_Idle::Inst()); - c->DoSendSuccess(); - } - else { - ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, - "Unexpected confirm w/ sequence " << aSeq, ALERR_UNEXPECTED_CONFIRM); - } - - } - - void ACS_WaitForConfirm::OnTimeout(AppLayerChannel* c) - { - LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Timeout while waiting for confirm"); - if(!c->Retry(ACS_SendConfirmed::Inst())) { - c->ChangeState(ACS_Idle::Inst()); - c->DoFailure(); - } - } - - // ---- ACS_WaitForResponseBase ---- - - void ACS_WaitForResponseBase::OnTimeout(AppLayerChannel* c) - { - LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Timeout while waiting for response"); - if(!c->Retry(ACS_SendExpectResponse::Inst())) { - c->ChangeState(ACS_Idle::Inst()); - c->DoFailure(); - } - } - -// ---- ACS_WaitForFirstResponse ---- - -ACS_WaitForFirstResponse ACS_WaitForFirstResponse::mInstance; - -void ACS_WaitForFirstResponse::OnResponse(AppLayerChannel* c, APDU& arAPDU) -{ - this->ProcessResponse(c, arAPDU, true); -} - -// ---- ATS_WaitForFinalResponse ---- - -ACS_WaitForFinalResponse ACS_WaitForFinalResponse::mInstance; - -void ACS_WaitForFinalResponse::OnResponse(AppLayerChannel* c, APDU& arAPDU) -{ - this->ProcessResponse(c, arAPDU, false); -} - -}} +#include "AppChannelStates.h" + +#include +#include +#include +#include +#include + +#include "AppLayerChannel.h" +#include "APDU.h" + +namespace apl { namespace dnp { + + // ---- Default behaviors for the states ---- + + void ACS_Base::Send(AppLayerChannel*, APDU&, size_t) + { this->ThrowInvalidState("Send"); } + + void ACS_Base::Cancel(AppLayerChannel*) + { this->ThrowInvalidState("Cancel"); } + + void ACS_Base::OnSendSuccess(AppLayerChannel*) + { this->ThrowInvalidState("OnSendSuccess"); } + + void ACS_Base::OnSendFailure(AppLayerChannel*) + { this->ThrowInvalidState("OnSendFailure"); } + + void ACS_Base::OnConfirm(AppLayerChannel* c, int aSeq) + { + ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, + "Unexpected confirm with sequence: " << aSeq, ALERR_UNEXPECTED_CONFIRM); + } + + void ACS_Base::OnResponse(AppLayerChannel* c, APDU& arAPDU) + { + LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, + "Unexpected response with sequence: " << arAPDU.GetControl().SEQ); + } + + void ACS_Base::OnTimeout(AppLayerChannel*) + { this->ThrowInvalidState("OnTimeout"); } + + void ACS_Base::ThrowInvalidState(const std::string& arMethod) + { + std::ostringstream oss; + oss << "State: " << this->Name() << " Method: " << arMethod; + throw InvalidStateException(LOCATION, oss.str()); + } + + void ACS_Base::ProcessResponse(AppLayerChannel* c, APDU& arAPDU, bool aExpectFIR) + { + AppControlField acf = arAPDU.GetControl(); + + if(acf.SEQ == c->Sequence()) { + if(acf.FIR == aExpectFIR) { + c->CancelTimer(); + + if(acf.FIN) { + c->ChangeState(ACS_Idle::Inst()); + c->DoFinalResponse(arAPDU); + } + else { + c->IncrSequence(); + c->ChangeState(ACS_WaitForFinalResponse::Inst()); + c->StartTimer(); + c->DoPartialResponse(arAPDU); + } + } + else { + ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Unexpected fir bit " << acf.FIR, ALERR_BAD_FIR_FIN); + } + } + else { + ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Bad sequence number " << acf.SEQ, ALERR_BAD_SEQUENCE); + } + } + + /// ---- ACS_IDle ---- + + ACS_Idle ACS_Idle::mInstance; + + void ACS_Idle::Send(AppLayerChannel* c, APDU& arAPDU, size_t aNumRetry) + { + AppControlField acf = arAPDU.GetControl(); + FunctionCodes func = arAPDU.GetFunction(); + acf.SEQ = (acf.FIR && func == FC_RESPONSE) ? c->Sequence() : c->IncrSequence(); + arAPDU.SetControl(acf); + c->ChangeState(NextState(c, arAPDU.GetFunction(), acf.CON)); + c->SetRetry(aNumRetry); + c->QueueSend(arAPDU); + } + + ACS_Base* ACS_Idle::NextState(AppLayerChannel* c, FunctionCodes aFunc, bool aConfirm) + { + switch(aFunc) + { + case(FC_CONFIRM): + throw ArgumentException(LOCATION, "Confirms are automatic only"); + case(FC_RESPONSE): + if(c->Sequence() < 0) + throw InvalidStateException(LOCATION, "Can't respond until we've received a request"); + + case(FC_UNSOLICITED_RESPONSE): + if(aConfirm) return ACS_SendConfirmed::Inst(); + else return ACS_Send::Inst(); + + case(FC_DIRECT_OPERATE_NO_ACK): + if(aConfirm) throw ArgumentException(LOCATION, "DO no ACK can't be confirmed"); + return ACS_Send::Inst(); + + default: // it's a request with an expected response + if(aConfirm) throw ArgumentException(LOCATION, "Confirmation not allowed for requests"); + return ACS_SendExpectResponse::Inst(); + } + } + + // ---- ACS_SendBase ---- + + void ACS_SendBase::OnSendFailure(AppLayerChannel* c) + { + if(!c->Retry(this)) { //if we can't retry, then go back to idle + c->ChangeState(ACS_Idle::Inst()); + c->DoFailure(); + } + } + + void ACS_SendBase::Cancel(AppLayerChannel* c) + { + c->ChangeState(ACS_SendCanceled::Inst()); + } + + // ---- ACS_SendCanceled ---- + + ACS_SendCanceled ACS_SendCanceled::mInstance; + + void ACS_SendCanceled::OnSendSuccess(AppLayerChannel* c) + { + c->ChangeState(ACS_Idle::Inst()); + c->DoFailure(); + } + + void ACS_SendCanceled::OnSendFailure(AppLayerChannel* c) + { + c->ChangeState(ACS_Idle::Inst()); + c->DoFailure(); + } + + // ---- ACS_Send ---- + + ACS_Send ACS_Send::mInstance; + + void ACS_Send::OnSendSuccess(AppLayerChannel* c) + { + c->ChangeState(ACS_Idle::Inst()); + c->DoSendSuccess(); + } + + // ---- ACS_SendConfirmed ---- + + ACS_SendConfirmed ACS_SendConfirmed::mInstance; + + void ACS_SendConfirmed::OnSendSuccess(AppLayerChannel* c) + { + c->ChangeState(ACS_WaitForConfirm::Inst()); + c->StartTimer(); + } + + // ---- ACS_SendExpectResponse ---- + + ACS_SendExpectResponse ACS_SendExpectResponse::mInstance; + + void ACS_SendExpectResponse::OnSendSuccess(AppLayerChannel* c) + { + c->ChangeState(ACS_WaitForFirstResponse::Inst()); + c->StartTimer(); + } + + // ---- ACS_WaitForConfirm ---- + + ACS_WaitForConfirm ACS_WaitForConfirm::mInstance; + + void ACS_WaitForConfirm::Cancel(AppLayerChannel* c) + { + c->ChangeState(ACS_Idle::Inst()); + c->CancelTimer(); + c->DoFailure(); + } + + void ACS_WaitForConfirm::OnConfirm(AppLayerChannel* c, int aSeq) + { + // does the confirm sequence match what we expect? + if(c->Sequence() == aSeq) { + c->CancelTimer(); + c->ChangeState(ACS_Idle::Inst()); + c->DoSendSuccess(); + } + else { + ERROR_LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, + "Unexpected confirm w/ sequence " << aSeq, ALERR_UNEXPECTED_CONFIRM); + } + + } + + void ACS_WaitForConfirm::OnTimeout(AppLayerChannel* c) + { + LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Timeout while waiting for confirm"); + if(!c->Retry(ACS_SendConfirmed::Inst())) { + c->ChangeState(ACS_Idle::Inst()); + c->DoFailure(); + } + } + + // ---- ACS_WaitForResponseBase ---- + + void ACS_WaitForResponseBase::OnTimeout(AppLayerChannel* c) + { + LOGGER_BLOCK(c->GetLogger(), LEV_WARNING, "Timeout while waiting for response"); + if(!c->Retry(ACS_SendExpectResponse::Inst())) { + c->ChangeState(ACS_Idle::Inst()); + c->DoFailure(); + } + } + +// ---- ACS_WaitForFirstResponse ---- + +ACS_WaitForFirstResponse ACS_WaitForFirstResponse::mInstance; + +void ACS_WaitForFirstResponse::OnResponse(AppLayerChannel* c, APDU& arAPDU) +{ + this->ProcessResponse(c, arAPDU, true); +} + +// ---- ATS_WaitForFinalResponse ---- + +ACS_WaitForFinalResponse ACS_WaitForFinalResponse::mInstance; + +void ACS_WaitForFinalResponse::OnResponse(AppLayerChannel* c, APDU& arAPDU) +{ + this->ProcessResponse(c, arAPDU, false); +} + +}} diff --git a/DNP3/AppChannelStates.h b/DNP3/AppChannelStates.h index 86ca124f..d8f17c9d 100644 --- a/DNP3/AppChannelStates.h +++ b/DNP3/AppChannelStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __APP_CHANNEL_STATES_H_ #define __APP_CHANNEL_STATES_H_ @@ -32,21 +32,21 @@ class APDU; /** Defines interface that concrete states must implement/override - AppChannelState(ACS)_Base -*/ +*/ class ACS_Base { public: - virtual void Send(AppLayerChannel*, APDU&, size_t aNumRetry); + virtual void Send(AppLayerChannel*, APDU&, size_t aNumRetry); virtual void Cancel(AppLayerChannel*); //cancel the outbound transaction - // external events + // external events virtual void OnSendSuccess(AppLayerChannel*); virtual void OnSendFailure(AppLayerChannel*); virtual void OnConfirm(AppLayerChannel*, int aSequence); virtual void OnResponse(AppLayerChannel*, APDU&); - virtual void OnTimeout(AppLayerChannel*); - + virtual void OnTimeout(AppLayerChannel*); + virtual std::string Name() const = 0; virtual bool AcceptsResponse() { return false; } @@ -55,7 +55,7 @@ class ACS_Base void ThrowInvalidState(const std::string& arMethod); void ProcessResponse(AppLayerChannel*, APDU&, bool aExpectFIR); - + }; class ACS_Idle : public ACS_Base @@ -72,30 +72,30 @@ class ACS_SendBase : public ACS_Base { public: - void OnSendFailure(AppLayerChannel*); + void OnSendFailure(AppLayerChannel*); void Cancel(AppLayerChannel* c); }; class ACS_Send : public ACS_SendBase { MACRO_NAME_SINGLETON_INSTANCE(ACS_Send) - - void OnSendSuccess(AppLayerChannel* c); + + void OnSendSuccess(AppLayerChannel* c); }; class ACS_SendConfirmed : public ACS_SendBase { MACRO_NAME_SINGLETON_INSTANCE(ACS_SendConfirmed) - - void OnSendSuccess(AppLayerChannel*); + + void OnSendSuccess(AppLayerChannel*); }; class ACS_SendExpectResponse : public ACS_SendBase { MACRO_STATE_SINGLETON_INSTANCE(ACS_SendExpectResponse); - - void OnSendSuccess(AppLayerChannel*); - + + void OnSendSuccess(AppLayerChannel*); + }; class ACS_SendCanceled : public ACS_Base @@ -103,7 +103,7 @@ class ACS_SendCanceled : public ACS_Base MACRO_STATE_SINGLETON_INSTANCE(ACS_SendCanceled); void Cancel(AppLayerChannel*) {} //do nothing if we're canceled and we cancel again - void OnSendSuccess(AppLayerChannel*); + void OnSendSuccess(AppLayerChannel*); void OnSendFailure(AppLayerChannel*); }; @@ -112,8 +112,8 @@ class ACS_WaitForConfirm : public ACS_Base MACRO_NAME_SINGLETON_INSTANCE(ACS_WaitForConfirm) void Cancel(AppLayerChannel*); - void OnConfirm(AppLayerChannel*, int aSequence); - void OnTimeout(AppLayerChannel*); + void OnConfirm(AppLayerChannel*, int aSequence); + void OnTimeout(AppLayerChannel*); }; class ACS_WaitForResponseBase : public ACS_Base diff --git a/DNP3/AppConfig.h b/DNP3/AppConfig.h index f838ceff..4e559f80 100644 --- a/DNP3/AppConfig.h +++ b/DNP3/AppConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,48 +6,48 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __APP_CONFIG_H_ -#define __APP_CONFIG_H_ - - -#include "DNPConstants.h" - -namespace apl { namespace dnp { - -/** Configuration structure for the dnp3 application layer -*/ -struct AppConfig -{ - /// Default constructor - AppConfig() : RspTimeout(5000), NumRetry(0), FragSize(DEFAULT_FRAG_SIZE) {} - - AppConfig(millis_t aRspTimeout, size_t aNumRetry = 0, size_t aFragSize = DEFAULT_FRAG_SIZE) : - RspTimeout(aRspTimeout), - NumRetry(aNumRetry), - FragSize(aFragSize) - {} - - /// The response/confirm timeout in millisec - millis_t RspTimeout; - - /// Number of retries performed for applicable frames - size_t NumRetry; - - /// The maximum size of received application layer fragments - size_t FragSize; - -}; - -}} - -#endif +// +#ifndef __APP_CONFIG_H_ +#define __APP_CONFIG_H_ + + +#include "DNPConstants.h" + +namespace apl { namespace dnp { + +/** Configuration structure for the dnp3 application layer +*/ +struct AppConfig +{ + /// Default constructor + AppConfig() : RspTimeout(5000), NumRetry(0), FragSize(DEFAULT_FRAG_SIZE) {} + + AppConfig(millis_t aRspTimeout, size_t aNumRetry = 0, size_t aFragSize = DEFAULT_FRAG_SIZE) : + RspTimeout(aRspTimeout), + NumRetry(aNumRetry), + FragSize(aFragSize) + {} + + /// The response/confirm timeout in millisec + millis_t RspTimeout; + + /// Number of retries performed for applicable frames + size_t NumRetry; + + /// The maximum size of received application layer fragments + size_t FragSize; + +}; + +}} + +#endif diff --git a/DNP3/AppHeader.cpp b/DNP3/AppHeader.cpp index 963437ec..dfb46e0b 100644 --- a/DNP3/AppHeader.cpp +++ b/DNP3/AppHeader.cpp @@ -16,150 +16,150 @@ // specific language governing permissions and limitations // under the License. // -#include "AppHeader.h" - - -#include -#include - -#include - -using namespace std; - -#define MACRO_FUNC_CASE(func) case(func): return func; - -namespace apl { namespace dnp { - - RequestHeader RequestHeader::mInstance; - ResponseHeader ResponseHeader::mInstance; - - FunctionCodes IntToFunction(int aFunction) - { - switch(aFunction) - { - MACRO_FUNC_CASE(FC_CONFIRM) - MACRO_FUNC_CASE(FC_READ) - MACRO_FUNC_CASE(FC_WRITE) - MACRO_FUNC_CASE(FC_SELECT) - MACRO_FUNC_CASE(FC_OPERATE) - MACRO_FUNC_CASE(FC_DIRECT_OPERATE) - MACRO_FUNC_CASE(FC_DIRECT_OPERATE_NO_ACK) - - MACRO_FUNC_CASE(FC_FREEZE) - MACRO_FUNC_CASE(FC_FREEZE_NO_ACK) - MACRO_FUNC_CASE(FC_FREEZE_CLEAR) - MACRO_FUNC_CASE(FC_FREEZE_CLEAR_NO_ACK) - MACRO_FUNC_CASE(FC_FREEZE_AT_TIME) - MACRO_FUNC_CASE(FC_FREEZE_AT_TIME_NO_ACK) - - MACRO_FUNC_CASE(FC_COLD_RESTART) - MACRO_FUNC_CASE(FC_WARM_RESTART) - MACRO_FUNC_CASE(FC_INITIALIZE_DATA) - MACRO_FUNC_CASE(FC_INITIALIZE_APPLICATION) - MACRO_FUNC_CASE(FC_START_APPLICATION) - MACRO_FUNC_CASE(FC_STOP_APPLICATION) - MACRO_FUNC_CASE(FC_SAVE_CONFIGURATION) - MACRO_FUNC_CASE(FC_ENABLE_UNSOLICITED) - MACRO_FUNC_CASE(FC_DISABLE_UNSOLICITED) - MACRO_FUNC_CASE(FC_ASSIGN_CLASS) - MACRO_FUNC_CASE(FC_DELAY_MEASURE) - MACRO_FUNC_CASE(FC_RECORD_TIME) - - MACRO_FUNC_CASE(FC_FILE_OPEN) - MACRO_FUNC_CASE(FC_FILE_CLOSE) - MACRO_FUNC_CASE(FC_FILE_DELETE) - MACRO_FUNC_CASE(FC_FILE_INFO) - MACRO_FUNC_CASE(FC_FILE_AUTHENTICATE) - MACRO_FUNC_CASE(FC_FILE_ABORT) - - MACRO_FUNC_CASE(FC_RESPONSE) - MACRO_FUNC_CASE(FC_UNSOLICITED_RESPONSE) - - default: - return FC_UNKNOWN; - } - } - - bool IINField::operator==(const IINField& arRHS) const - { - return (mLSB == arRHS.mLSB) && (mMSB == arRHS.mMSB); - } - -#define MACRO_IIN_TO_STRING(field) if(Get##field()) oss << " "#field; - - std::string IINField::ToString() const - { - ostringstream oss; - oss << " IIN: (LSB: " << ByteToHex(GetLSB()); - - MACRO_IIN_TO_STRING(AllStations) - MACRO_IIN_TO_STRING(Class1Events) - MACRO_IIN_TO_STRING(Class2Events) - MACRO_IIN_TO_STRING(Class3Events) - MACRO_IIN_TO_STRING(NeedTime) - MACRO_IIN_TO_STRING(LocalControl) - MACRO_IIN_TO_STRING(DeviceTrouble) - MACRO_IIN_TO_STRING(DeviceRestart) - - oss << ") (MSB: " << ByteToHex(GetMSB()); - - MACRO_IIN_TO_STRING(FuncNotSupported) - MACRO_IIN_TO_STRING(ObjectUnknown) - MACRO_IIN_TO_STRING(ParameterError) - MACRO_IIN_TO_STRING(EventBufferOverflow) - MACRO_IIN_TO_STRING(AlreadyExecuting) - MACRO_IIN_TO_STRING(ConfigurationCorrupt) - MACRO_IIN_TO_STRING(Reserved1) - MACRO_IIN_TO_STRING(Reserved2) - oss << ")"; - - return oss.str(); - } - - void IAppHeader::SetControl(apl::byte_t* apStart, const AppControlField& arControl) const - { - (*apStart) = 0; - if(arControl.FIR) (*apStart) |= ACM_FIR; - if(arControl.FIN) (*apStart) |= ACM_FIN; - if(arControl.CON) (*apStart) |= ACM_CON; - if(arControl.UNS) (*apStart) |= ACM_UNS; - - (*apStart) |= (arControl.SEQ % 16); - } - - AppControlField IAppHeader::GetControl(const byte_t* apStart) const - { - AppControlField f; - - f.FIR = ((*apStart) & ACM_FIR) != 0; - f.FIN = ((*apStart) & ACM_FIN) != 0; - f.CON = ((*apStart) & ACM_CON) != 0; - f.UNS = ((*apStart) & ACM_UNS) != 0; - f.SEQ = (*apStart) & ACM_SEQ; - - return f; - } - - - - IINField ResponseHeader::GetIIN(const byte_t* apStart) const - { - IINField f; - - const byte_t* pByte = apStart+2; //start w/ LSB - - f.SetLSB(*pByte); - f.SetMSB(*(++pByte)); - - return f; - } - - void ResponseHeader::SetIIN(apl::byte_t* apStart, const IINField& arIIN) const - { - byte_t* pByte = apStart+2; //start w/ LSB - - *pByte = arIIN.GetLSB(); - *(++pByte) = arIIN.GetMSB(); - } - -}} +#include "AppHeader.h" + + +#include +#include + +#include + +using namespace std; + +#define MACRO_FUNC_CASE(func) case(func): return func; + +namespace apl { namespace dnp { + + RequestHeader RequestHeader::mInstance; + ResponseHeader ResponseHeader::mInstance; + + FunctionCodes IntToFunction(int aFunction) + { + switch(aFunction) + { + MACRO_FUNC_CASE(FC_CONFIRM) + MACRO_FUNC_CASE(FC_READ) + MACRO_FUNC_CASE(FC_WRITE) + MACRO_FUNC_CASE(FC_SELECT) + MACRO_FUNC_CASE(FC_OPERATE) + MACRO_FUNC_CASE(FC_DIRECT_OPERATE) + MACRO_FUNC_CASE(FC_DIRECT_OPERATE_NO_ACK) + + MACRO_FUNC_CASE(FC_FREEZE) + MACRO_FUNC_CASE(FC_FREEZE_NO_ACK) + MACRO_FUNC_CASE(FC_FREEZE_CLEAR) + MACRO_FUNC_CASE(FC_FREEZE_CLEAR_NO_ACK) + MACRO_FUNC_CASE(FC_FREEZE_AT_TIME) + MACRO_FUNC_CASE(FC_FREEZE_AT_TIME_NO_ACK) + + MACRO_FUNC_CASE(FC_COLD_RESTART) + MACRO_FUNC_CASE(FC_WARM_RESTART) + MACRO_FUNC_CASE(FC_INITIALIZE_DATA) + MACRO_FUNC_CASE(FC_INITIALIZE_APPLICATION) + MACRO_FUNC_CASE(FC_START_APPLICATION) + MACRO_FUNC_CASE(FC_STOP_APPLICATION) + MACRO_FUNC_CASE(FC_SAVE_CONFIGURATION) + MACRO_FUNC_CASE(FC_ENABLE_UNSOLICITED) + MACRO_FUNC_CASE(FC_DISABLE_UNSOLICITED) + MACRO_FUNC_CASE(FC_ASSIGN_CLASS) + MACRO_FUNC_CASE(FC_DELAY_MEASURE) + MACRO_FUNC_CASE(FC_RECORD_TIME) + + MACRO_FUNC_CASE(FC_FILE_OPEN) + MACRO_FUNC_CASE(FC_FILE_CLOSE) + MACRO_FUNC_CASE(FC_FILE_DELETE) + MACRO_FUNC_CASE(FC_FILE_INFO) + MACRO_FUNC_CASE(FC_FILE_AUTHENTICATE) + MACRO_FUNC_CASE(FC_FILE_ABORT) + + MACRO_FUNC_CASE(FC_RESPONSE) + MACRO_FUNC_CASE(FC_UNSOLICITED_RESPONSE) + + default: + return FC_UNKNOWN; + } + } + + bool IINField::operator==(const IINField& arRHS) const + { + return (mLSB == arRHS.mLSB) && (mMSB == arRHS.mMSB); + } + +#define MACRO_IIN_TO_STRING(field) if(Get##field()) oss << " "#field; + + std::string IINField::ToString() const + { + ostringstream oss; + oss << " IIN: (LSB: " << ByteToHex(GetLSB()); + + MACRO_IIN_TO_STRING(AllStations) + MACRO_IIN_TO_STRING(Class1Events) + MACRO_IIN_TO_STRING(Class2Events) + MACRO_IIN_TO_STRING(Class3Events) + MACRO_IIN_TO_STRING(NeedTime) + MACRO_IIN_TO_STRING(LocalControl) + MACRO_IIN_TO_STRING(DeviceTrouble) + MACRO_IIN_TO_STRING(DeviceRestart) + + oss << ") (MSB: " << ByteToHex(GetMSB()); + + MACRO_IIN_TO_STRING(FuncNotSupported) + MACRO_IIN_TO_STRING(ObjectUnknown) + MACRO_IIN_TO_STRING(ParameterError) + MACRO_IIN_TO_STRING(EventBufferOverflow) + MACRO_IIN_TO_STRING(AlreadyExecuting) + MACRO_IIN_TO_STRING(ConfigurationCorrupt) + MACRO_IIN_TO_STRING(Reserved1) + MACRO_IIN_TO_STRING(Reserved2) + oss << ")"; + + return oss.str(); + } + + void IAppHeader::SetControl(apl::byte_t* apStart, const AppControlField& arControl) const + { + (*apStart) = 0; + if(arControl.FIR) (*apStart) |= ACM_FIR; + if(arControl.FIN) (*apStart) |= ACM_FIN; + if(arControl.CON) (*apStart) |= ACM_CON; + if(arControl.UNS) (*apStart) |= ACM_UNS; + + (*apStart) |= (arControl.SEQ % 16); + } + + AppControlField IAppHeader::GetControl(const byte_t* apStart) const + { + AppControlField f; + + f.FIR = ((*apStart) & ACM_FIR) != 0; + f.FIN = ((*apStart) & ACM_FIN) != 0; + f.CON = ((*apStart) & ACM_CON) != 0; + f.UNS = ((*apStart) & ACM_UNS) != 0; + f.SEQ = (*apStart) & ACM_SEQ; + + return f; + } + + + + IINField ResponseHeader::GetIIN(const byte_t* apStart) const + { + IINField f; + + const byte_t* pByte = apStart+2; //start w/ LSB + + f.SetLSB(*pByte); + f.SetMSB(*(++pByte)); + + return f; + } + + void ResponseHeader::SetIIN(apl::byte_t* apStart, const IINField& arIIN) const + { + byte_t* pByte = apStart+2; //start w/ LSB + + *pByte = arIIN.GetLSB(); + *(++pByte) = arIIN.GetMSB(); + } + +}} diff --git a/DNP3/AppHeader.h b/DNP3/AppHeader.h index a23588e4..50de63d6 100644 --- a/DNP3/AppHeader.h +++ b/DNP3/AppHeader.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __APP_HEADER_H_ #define __APP_HEADER_H_ @@ -35,7 +35,7 @@ namespace apl { namespace dnp { struct AppControlField { AppControlField(){}; - AppControlField(bool aFIR, bool aFIN, bool aCON, bool aUNS, int aSEQ = 0) : + AppControlField(bool aFIR, bool aFIN, bool aCON, bool aUNS, int aSEQ = 0) : FIR(aFIR), FIN(aFIN), CON(aCON), @@ -57,7 +57,7 @@ namespace apl { namespace dnp { IINField(apl::byte_t aLSB = 0, apl::byte_t aMSB = 0) : mLSB(aLSB), mMSB(aMSB) { - + } #define MACRO_GET_BIT(value, mask) const { return (mask&value) != 0; } @@ -71,7 +71,7 @@ namespace apl { namespace dnp { bool GetLocalControl() MACRO_GET_BIT(mLSB, IIN_LSB_LOCAL_CONTROL) bool GetDeviceTrouble() MACRO_GET_BIT(mLSB, IIN_LSB_DEVICE_TROUBLE) bool GetDeviceRestart() MACRO_GET_BIT(mLSB, IIN_LSB_DEVICE_RESTART) - + // MSB bool GetFuncNotSupported() MACRO_GET_BIT(mMSB, IIN_MSB_FUNC_NOT_SUPPORTED) bool GetObjectUnknown() MACRO_GET_BIT(mMSB, IIN_MSB_OBJECT_UNKNOWN) @@ -109,10 +109,10 @@ namespace apl { namespace dnp { apl::byte_t GetMSB() const { return mMSB; } void SetLSB(apl::byte_t aLSB) { mLSB = aLSB; } void SetMSB(apl::byte_t aMSB) { mMSB = aMSB; } - - void Zero() + + void Zero() { mLSB = mMSB = 0; } - + void BitwiseOR(const IINField& arIIN) { mLSB |= arIIN.mLSB; mMSB |= arIIN.mMSB; } @@ -162,7 +162,7 @@ namespace apl { namespace dnp { void SetIIN(apl::byte_t* apStart, const IINField& arIIN) const; IINField GetIIN(const apl::byte_t* apStart) const; }; - + }} #endif diff --git a/DNP3/AppLayerChannel.cpp b/DNP3/AppLayerChannel.cpp index 5d0e3f81..05701c84 100644 --- a/DNP3/AppLayerChannel.cpp +++ b/DNP3/AppLayerChannel.cpp @@ -16,129 +16,129 @@ // specific language governing permissions and limitations // under the License. // -#include "AppLayerChannel.h" - -#include -#include - -#include "AsyncAppLayer.h" -#include "AppChannelStates.h" - -#include - -namespace apl { namespace dnp { - -AppLayerChannel::AppLayerChannel(const std::string& arName, Logger* apLogger, AsyncAppLayer* apAppLayer, ITimerSource* apTimerSrc, millis_t aTimeout) : -Loggable(apLogger), -mpAppLayer(apAppLayer), -mpSendAPDU(NULL), -mNumRetry(0), -mpTimerSrc(apTimerSrc), -mpTimer(NULL), -M_TIMEOUT(aTimeout), -M_NAME(arName) -{ - this->Reset(); -} - -void AppLayerChannel::Reset() -{ - mpState = ACS_Idle::Inst(); - mConfirming = false; - mSequence = -1; - if(mpTimer) { - mpTimer->Cancel(); - mpTimer = NULL; - } -} - -// ---- Events ---- - -void AppLayerChannel::Send(APDU& arAPDU, size_t aNumRetry) -{ - mpState->Send(this, arAPDU, aNumRetry); - mpSendAPDU = &arAPDU; -} - -void AppLayerChannel::OnSendSuccess() -{ - mpState->OnSendSuccess(this); -} - -void AppLayerChannel::OnSendFailure() -{ - mpState->OnSendFailure(this); -} - -void AppLayerChannel::OnConfirm(int aSeq) -{ - mpState->OnConfirm(this, aSeq); -} - -void AppLayerChannel::Cancel() -{ - mpState->Cancel(this); -} - - -// ---- State Actions ---- - -void AppLayerChannel::QueueSend(APDU& arAPDU) -{ - mpAppLayer->QueueFrame(arAPDU); -} - -bool AppLayerChannel::Retry(ACS_Base* apState) -{ - if(mNumRetry > 0) { - --mNumRetry; - LOG_BLOCK(LEV_INFO, "App layer retry, " << mNumRetry << " remaining"); - this->ChangeState(apState); - mpAppLayer->QueueFrame(*mpSendAPDU); - return true; - } - else { - return false; - } -} - -void AppLayerChannel::DoPartialResponse(APDU& arAPDU) -{ - mpAppLayer->mpUser->OnPartialResponse(arAPDU); -} - -void AppLayerChannel::DoFinalResponse(APDU& arAPDU) -{ - mpAppLayer->mpUser->OnFinalResponse(arAPDU); -} - -void AppLayerChannel::StartTimer() -{ - if(mpTimer != NULL) throw InvalidStateException(LOCATION, ""); - mpTimer = mpTimerSrc->Start(M_TIMEOUT, boost::bind(&AppLayerChannel::Timeout, this)); -} - -void AppLayerChannel::CancelTimer() -{ - if(mpTimer == NULL) throw InvalidStateException(LOCATION, ""); - mpTimer->Cancel(); - mpTimer = NULL; -} - -void AppLayerChannel::ChangeState(ACS_Base* apState) -{ - if(apState != mpState) { - LOG_BLOCK(LEV_DEBUG, "State changed from " << mpState->Name() << " to " << apState->Name()); - mpState = apState; - } -} - -void AppLayerChannel::Timeout() -{ - mpTimer = NULL; - mpState->OnTimeout(this); -} - -}} - - +#include "AppLayerChannel.h" + +#include +#include + +#include "AsyncAppLayer.h" +#include "AppChannelStates.h" + +#include + +namespace apl { namespace dnp { + +AppLayerChannel::AppLayerChannel(const std::string& arName, Logger* apLogger, AsyncAppLayer* apAppLayer, ITimerSource* apTimerSrc, millis_t aTimeout) : +Loggable(apLogger), +mpAppLayer(apAppLayer), +mpSendAPDU(NULL), +mNumRetry(0), +mpTimerSrc(apTimerSrc), +mpTimer(NULL), +M_TIMEOUT(aTimeout), +M_NAME(arName) +{ + this->Reset(); +} + +void AppLayerChannel::Reset() +{ + mpState = ACS_Idle::Inst(); + mConfirming = false; + mSequence = -1; + if(mpTimer) { + mpTimer->Cancel(); + mpTimer = NULL; + } +} + +// ---- Events ---- + +void AppLayerChannel::Send(APDU& arAPDU, size_t aNumRetry) +{ + mpState->Send(this, arAPDU, aNumRetry); + mpSendAPDU = &arAPDU; +} + +void AppLayerChannel::OnSendSuccess() +{ + mpState->OnSendSuccess(this); +} + +void AppLayerChannel::OnSendFailure() +{ + mpState->OnSendFailure(this); +} + +void AppLayerChannel::OnConfirm(int aSeq) +{ + mpState->OnConfirm(this, aSeq); +} + +void AppLayerChannel::Cancel() +{ + mpState->Cancel(this); +} + + +// ---- State Actions ---- + +void AppLayerChannel::QueueSend(APDU& arAPDU) +{ + mpAppLayer->QueueFrame(arAPDU); +} + +bool AppLayerChannel::Retry(ACS_Base* apState) +{ + if(mNumRetry > 0) { + --mNumRetry; + LOG_BLOCK(LEV_INFO, "App layer retry, " << mNumRetry << " remaining"); + this->ChangeState(apState); + mpAppLayer->QueueFrame(*mpSendAPDU); + return true; + } + else { + return false; + } +} + +void AppLayerChannel::DoPartialResponse(APDU& arAPDU) +{ + mpAppLayer->mpUser->OnPartialResponse(arAPDU); +} + +void AppLayerChannel::DoFinalResponse(APDU& arAPDU) +{ + mpAppLayer->mpUser->OnFinalResponse(arAPDU); +} + +void AppLayerChannel::StartTimer() +{ + if(mpTimer != NULL) throw InvalidStateException(LOCATION, ""); + mpTimer = mpTimerSrc->Start(M_TIMEOUT, boost::bind(&AppLayerChannel::Timeout, this)); +} + +void AppLayerChannel::CancelTimer() +{ + if(mpTimer == NULL) throw InvalidStateException(LOCATION, ""); + mpTimer->Cancel(); + mpTimer = NULL; +} + +void AppLayerChannel::ChangeState(ACS_Base* apState) +{ + if(apState != mpState) { + LOG_BLOCK(LEV_DEBUG, "State changed from " << mpState->Name() << " to " << apState->Name()); + mpState = apState; + } +} + +void AppLayerChannel::Timeout() +{ + mpTimer = NULL; + mpState->OnTimeout(this); +} + +}} + + diff --git a/DNP3/AppLayerChannel.h b/DNP3/AppLayerChannel.h index 4514e1dc..a8056490 100644 --- a/DNP3/AppLayerChannel.h +++ b/DNP3/AppLayerChannel.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,109 +6,109 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __APP_LAYER_CHANNEL_H_ -#define __APP_LAYER_CHANNEL_H_ - -#include -#include - -namespace apl { - class Logger; - class ITimerSource; - class ITimer; -} - -namespace apl { namespace dnp { - -class AsyncAppLayer; -class ACS_Base; -class APDU; -struct AppControlField; - -/** The application layer contains two virtual channels, one for - solicited and unsolicited communication. Each channel has a sequence - number and some state associated with wether it is sending, waiting - for a response, etc -*/ -class AppLayerChannel : public Loggable -{ - friend class ACS_Base; - friend class ACS_Idle; - friend class ACS_Send; - friend class ACS_SendBase; - friend class ACS_SendConfirmed; - friend class ACS_SendExpectResponse; - friend class ACS_SendCanceled; - friend class ACS_WaitForConfirm; - friend class ACS_WaitForResponseBase; - friend class ACS_WaitForFirstResponse; - friend class ACS_WaitForFinalResponse; - - public: - AppLayerChannel(const std::string& arName, Logger*, AsyncAppLayer*, ITimerSource*, millis_t aTimeout); - virtual ~AppLayerChannel(){} - - /// Resets the channel to the initial state - void Reset(); - - /// send, wether a response is expected is implicit based on func code - void Send(APDU&, size_t aNumRetry); - void Cancel(); - - // Events - void OnSendSuccess(); - void OnSendFailure(); - void OnConfirm(int aSeq); - - protected: - - // functions for the states to access - int Sequence() { return mSequence; } - int IncrSequence() { return mSequence = NextSeq(mSequence); } - void QueueSend(APDU&); - void ChangeState(ACS_Base*); - void SetRetry(size_t aNumRetry) { mNumRetry = aNumRetry; } - bool Retry(ACS_Base*); - - virtual void DoSendSuccess() = 0; - virtual void DoFailure() = 0; - - void DoPartialResponse(APDU& arAPDU); - void DoFinalResponse(APDU& arAPDU); - - void StartTimer(); - void CancelTimer(); - Logger* GetLogger() { return mpLogger; } - - AsyncAppLayer* mpAppLayer; - int mSequence; /// Rotating sequence number for the channel - ACS_Base* mpState; - - static int NextSeq(int s) { return (s+1)%16; } - - private: - - void Timeout(); - - APDU* mpSendAPDU; - size_t mNumRetry; - ITimerSource* mpTimerSrc; - ITimer* mpTimer; - bool mConfirming; - const millis_t M_TIMEOUT; - const std::string M_NAME; -}; - -}} - -#endif +// +#ifndef __APP_LAYER_CHANNEL_H_ +#define __APP_LAYER_CHANNEL_H_ + +#include +#include + +namespace apl { + class Logger; + class ITimerSource; + class ITimer; +} + +namespace apl { namespace dnp { + +class AsyncAppLayer; +class ACS_Base; +class APDU; +struct AppControlField; + +/** The application layer contains two virtual channels, one for + solicited and unsolicited communication. Each channel has a sequence + number and some state associated with wether it is sending, waiting + for a response, etc +*/ +class AppLayerChannel : public Loggable +{ + friend class ACS_Base; + friend class ACS_Idle; + friend class ACS_Send; + friend class ACS_SendBase; + friend class ACS_SendConfirmed; + friend class ACS_SendExpectResponse; + friend class ACS_SendCanceled; + friend class ACS_WaitForConfirm; + friend class ACS_WaitForResponseBase; + friend class ACS_WaitForFirstResponse; + friend class ACS_WaitForFinalResponse; + + public: + AppLayerChannel(const std::string& arName, Logger*, AsyncAppLayer*, ITimerSource*, millis_t aTimeout); + virtual ~AppLayerChannel(){} + + /// Resets the channel to the initial state + void Reset(); + + /// send, wether a response is expected is implicit based on func code + void Send(APDU&, size_t aNumRetry); + void Cancel(); + + // Events + void OnSendSuccess(); + void OnSendFailure(); + void OnConfirm(int aSeq); + + protected: + + // functions for the states to access + int Sequence() { return mSequence; } + int IncrSequence() { return mSequence = NextSeq(mSequence); } + void QueueSend(APDU&); + void ChangeState(ACS_Base*); + void SetRetry(size_t aNumRetry) { mNumRetry = aNumRetry; } + bool Retry(ACS_Base*); + + virtual void DoSendSuccess() = 0; + virtual void DoFailure() = 0; + + void DoPartialResponse(APDU& arAPDU); + void DoFinalResponse(APDU& arAPDU); + + void StartTimer(); + void CancelTimer(); + Logger* GetLogger() { return mpLogger; } + + AsyncAppLayer* mpAppLayer; + int mSequence; /// Rotating sequence number for the channel + ACS_Base* mpState; + + static int NextSeq(int s) { return (s+1)%16; } + + private: + + void Timeout(); + + APDU* mpSendAPDU; + size_t mNumRetry; + ITimerSource* mpTimerSrc; + ITimer* mpTimer; + bool mConfirming; + const millis_t M_TIMEOUT; + const std::string M_NAME; +}; + +}} + +#endif diff --git a/DNP3/AsyncAppInterfaces.h b/DNP3/AsyncAppInterfaces.h index 93ee7b7b..16491d5b 100644 --- a/DNP3/AsyncAppInterfaces.h +++ b/DNP3/AsyncAppInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_APP_INTERFACES_H_ #define __ASYNC_APP_INTERFACES_H_ @@ -33,16 +33,16 @@ class APDU; SEQUENCE #. */ class IAsyncAppLayer -{ +{ public: /** Start a response transaction with optional confirmation. The incrementing of the sequence number is controlled by the FIR bit. If FIR is not set, the sequence is incremented. - + A callback to one of the following is guaranteed: - + OnFailure() - The transaction failed, either because the send failed or the confirmation timed out. @@ -53,14 +53,14 @@ class IAsyncAppLayer */ virtual void SendResponse(APDU&) = 0; - /** Start an unsolicited transaction with optional confirmation and retries. This + /** Start an unsolicited transaction with optional confirmation and retries. This sequence is almost identical to a response transaction. FIR and FIN must both be set for unsolcited responses since they cannot be multifragmented. - + A callback to one of the following is gauranteed: - + OnFailure() - The transaction failed, either because the send failed or the confirmation timed out. @@ -73,9 +73,9 @@ class IAsyncAppLayer /** Start a send transaction with optional confirmation and retries, that should result in a resposne. - + Callbacks are as follows: - + OnFailure() - The transaction failed, either because the send failed or the confirmation timed out. @@ -83,7 +83,7 @@ class IAsyncAppLayer OnPartialResponse(APDU) - A non-FIN response was received. The client should process the response and continue waiting for: - + - More partial responses - A failure - A final response @@ -125,20 +125,20 @@ class IAsyncAppUser virtual void OnSolFailure() = 0; /// A transaction has failed for some reason virtual bool IsMaster() = 0; /// controls which types of messages are sent upwards - + /// A non-final response has been received virtual void OnPartialResponse(const APDU&); /// A final response has been received - virtual void OnFinalResponse(const APDU&); + virtual void OnFinalResponse(const APDU&); /// Process unsolicited data - virtual void OnUnsolResponse(const APDU&); + virtual void OnUnsolResponse(const APDU&); /// Process request fragment virtual void OnRequest(const APDU&, SequenceInfo); // Unknown Object virtual void OnUnknownObject(); }; - + }} //end ns #endif diff --git a/DNP3/AsyncAppLayer.h b/DNP3/AsyncAppLayer.h index abd3e8ed..138e528b 100644 --- a/DNP3/AsyncAppLayer.h +++ b/DNP3/AsyncAppLayer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_APP_LAYER_H_ #define __ASYNC_APP_LAYER_H_ @@ -28,8 +28,8 @@ #include "SolicitedChannel.h" #include "UnsolicitedChannel.h" -namespace apl -{ +namespace apl +{ class ITimerSource; class ITimer; } @@ -38,7 +38,7 @@ namespace apl { namespace dnp { class AppTransactionStateBase; -/** +/** Implements the sequencing/confirm/response logic for the DNP3 application layer. Allows for canceling response transactions, as dictated by the spec. @@ -64,7 +64,7 @@ class AsyncAppLayer : public IUpperLayer, public IAsyncAppLayer void CancelResponse(); private: - + ///////////////////////////// // External Events ///////////////////////////// @@ -89,7 +89,7 @@ class AsyncAppLayer : public IUpperLayer, public IAsyncAppLayer void OnUnsolResponse(const AppControlField&, APDU&); void OnConfirm(const AppControlField&, APDU&); void OnRequest(const AppControlField&, APDU&); - + ///////////////////////////// // State ///////////////////////////// @@ -98,27 +98,27 @@ class AsyncAppLayer : public IUpperLayer, public IAsyncAppLayer APDU mIncoming; /// Fragment used to parse all incoming requests APDU mConfirm; /// Fragment used to do confirms - + bool mSending; /// State of send operation to the lower layer bool mConfirmSending; SendQueue mSendQueue; /// Buffer of send operations - + IAsyncAppUser* mpUser; /// Interface for dispatching callbacks SolicitedChannel mSolicited; /// Channel used for solicited communications UnsolicitedChannel mUnsolicited; /// Channel used for unsolicited communications size_t mNumRetry; - + ///////////////////////////// // Helpers ///////////////////////////// - + void QueueConfirm(bool aUns, int aSeq); - void QueueFrame(const APDU& arAPDU); + void QueueFrame(const APDU& arAPDU); void CheckForSend(); size_t GetRetries(FunctionCodes aCode); - + void Validate(const AppControlField& arCtrl, bool aMaster, bool aRequireFIRFIN, bool aAllowCON, bool aUNS); }; diff --git a/DNP3/AsyncDatabase.h b/DNP3/AsyncDatabase.h index 4a6ff575..ec228fc7 100644 --- a/DNP3/AsyncDatabase.h +++ b/DNP3/AsyncDatabase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_DATABASE_H_ #define __ASYNC_DATABASE_H_ @@ -35,7 +35,7 @@ #undef max #endif -namespace apl { +namespace apl { class INotifier; class EventLog; } @@ -43,8 +43,8 @@ class EventLog; namespace apl { namespace dnp { struct DeviceTemplate; - - /** + + /** Manages the static data model of a DNP3 slave. Dual-interface to update data points and read current values. Passes data updates to an associated event buffer for event generation/management. @@ -56,12 +56,12 @@ namespace apl { namespace dnp { AsyncDatabase(Logger* apLogger); virtual ~AsyncDatabase(); - + /* Configuration functions */ void Configure(const DeviceTemplate& arTmp); void Configure(apl::DataTypes aType, size_t aNumPoints, bool aStartOnline = false); - + size_t NumType(apl::DataTypes aType); size_t MaxIndex(DataTypes aType); void SetDeadband(apl::DataTypes, size_t aIndex, double aDeadband); @@ -78,7 +78,7 @@ namespace apl { namespace dnp { void Begin(ControlIterator& arIter) { arIter = mControlStatusVec.begin(); } void Begin(SetpointIterator& arIter) { arIter = mSetpointStatusVec.begin(); } - + private: // ITransactable functions, no lock on this structure. @@ -133,14 +133,14 @@ namespace apl { namespace dnp { template inline void AsyncDatabase::SetAllOnline( std::vector< PointInfo >& arVector ) { - for(size_t i=0; i inline void AsyncDatabase::AssignIndices( std::vector< PointInfo >& arVector ) { - for(size_t i=0; i= arVec.size()) throw apl::IndexOutOfBoundsException(LOCATION); T& value = arVec[aIndex].mValue; - + if(value.ShouldGenerateEvent(arValue, arVec[aIndex].mDeadband, arVec[aIndex].mLastEventValue)) { value = arValue; diff --git a/DNP3/AsyncDatabaseInterfaces.h b/DNP3/AsyncDatabaseInterfaces.h index 2d658013..0a9ffd65 100644 --- a/DNP3/AsyncDatabaseInterfaces.h +++ b/DNP3/AsyncDatabaseInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_DATABASE_INTERFACES_H_ #define __ASYNC_DATABASE_INTERFACES_H_ @@ -24,13 +24,13 @@ #include #include -namespace apl { +namespace apl { class INotifier; } namespace apl{ namespace dnp { -/// @section desc Used by the database +/// @section desc Used by the database class IAsyncEventBuffer { public: @@ -39,10 +39,10 @@ class IAsyncEventBuffer /// @return true if the event buffer accepts the event, false otherwise virtual void Update(const Binary& arEvent, PointClass aClass, size_t aIndex) = 0; - + /// @return true if the event buffer accepts the event, false otherwise virtual void Update(const Analog& arEvent, PointClass aClass, size_t aIndex) = 0; - + /// @return true if the event buffer accepts the event, false otherwise virtual void Update(const Counter& arEvent, PointClass aClass, size_t aIndex) = 0; diff --git a/DNP3/AsyncEventBufferBase.h b/DNP3/AsyncEventBufferBase.h index ecf34a9e..aa946836 100644 --- a/DNP3/AsyncEventBufferBase.h +++ b/DNP3/AsyncEventBufferBase.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_EVENT_BUFFER_BASE_H_ #define __ASYNC_EVENT_BUFFER_BASE_H_ @@ -25,12 +25,12 @@ namespace apl { namespace dnp { - + /** Base class for the AsyncEventBuffer classes (with templating and - virtual function for Update to alter event storage behavior) - + virtual function for Update to alter event storage behavior) + Single-threaded for asynchronous/event-based model. - */ + */ template class AsyncEventBufferBase { @@ -48,7 +48,7 @@ namespace apl { namespace dnp { */ void Update(const typename EventType::MeasType& arVal, PointClass aClass, size_t aIndex); - bool HasClassData(PointClass aClass) { return mCounter.GetNum(aClass) > 0; } + bool HasClassData(PointClass aClass) { return mCounter.GetNum(aClass) > 0; } /** @param aClass PointClass to select (i.e. PC_CLASS_1, 2, 3) into the selection buffer @@ -64,7 +64,7 @@ namespace apl { namespace dnp { */ size_t Deselect(); - + /** Clear events flagged with mWritten = true from the selection buffer @@ -73,18 +73,18 @@ namespace apl { namespace dnp { size_t ClearWrittenEvents(); typename EvtItr< EventType >::Type Begin(); - + size_t NumSelected() { return mSelectedEvents.size(); } size_t NumUnselected() { return mEventSet.size(); } size_t Size() { return mSelectedEvents.size() + mEventSet.size(); } - + bool IsOverflown(); - + protected: bool IsFull() { return NumUnselected() >= M_MAX_EVENTS; } - + void Update(EventType& arEvent, bool aNewValue); /** @@ -97,7 +97,7 @@ namespace apl { namespace dnp { virtual void _Update(const EventType& arEvent); ClassCounter mCounter; /// counter for class events - const size_t M_MAX_EVENTS; /// max number of events to accept before setting overflow + const size_t M_MAX_EVENTS; /// max number of events to accept before setting overflow size_t mSequence; /// used to track the insertion order of events into the buffer bool mIsOverflown; /// flag that tracks when an overflow occurs bool mDropFirst; /// on overflow, do we drop the first or last element? @@ -117,20 +117,20 @@ namespace apl { namespace dnp { mIsOverflown(false), mDropFirst(aDropFirst) { - + } template void AsyncEventBufferBase :: Update(const typename EventType::MeasType& arVal, PointClass aClass, size_t aIndex) - { - EventType evt(arVal, aClass, aIndex); + { + EventType evt(arVal, aClass, aIndex); this->Update(evt, true); - + if(this->NumUnselected() > M_MAX_EVENTS) { //we've overflown and we've got to drop an event mIsOverflown = true; if(mDropFirst) mEventSet.erase(mEventSet.begin()); else mEventSet.erase((++mEventSet.rbegin()).base()); - } + } } template @@ -138,7 +138,7 @@ namespace apl { namespace dnp { { // prevents numerical overflow of the increasing sequence number if(this->Size() == 0) mSequence = 0; - + if(aNewValue) arEvent.mSequence = mSequence++; this->_Update(arEvent); // call the overridable NVII function @@ -169,21 +169,21 @@ namespace apl { namespace dnp { { // if the buffer previously overflowed, but is no longer full, reset the flag if(mIsOverflown && this->Size() < M_MAX_EVENTS) mIsOverflown = false; - + return mIsOverflown; } - + template size_t AsyncEventBufferBase :: ClearWrittenEvents() { typename std::vector::iterator itr = this->mSelectedEvents.begin(); - + size_t num = 0; while(itr != this->mSelectedEvents.end() && itr->mWritten) { ++itr; ++num; } - + this->mSelectedEvents.erase(this->mSelectedEvents.begin(), itr); return num; } @@ -196,15 +196,15 @@ namespace apl { namespace dnp { template size_t AsyncEventBufferBase :: Select(PointClass aClass, size_t aMaxEvent) - { + { typename SetType::Type::iterator i = mEventSet.begin(); size_t count = 0; while( i != mEventSet.end() && count < aMaxEvent) { - if( ( i->mClass & aClass) != 0 ) - { + if( ( i->mClass & aClass) != 0 ) + { mCounter.DecrCount(i->mClass); mSelectedEvents.push_back(*i); mEventSet.erase(i++); @@ -213,7 +213,7 @@ namespace apl { namespace dnp { } else ++i; } - + return count; } diff --git a/DNP3/AsyncEventBuffers.h b/DNP3/AsyncEventBuffers.h index 8e441845..423ea82c 100644 --- a/DNP3/AsyncEventBuffers.h +++ b/DNP3/AsyncEventBuffers.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_EVENT_BUFFERS_H_ #define __ASYNC_EVENT_BUFFERS_H_ @@ -32,7 +32,7 @@ namespace apl { namespace dnp { /** Event buffer that only stores one event per Index: - + Note: EventType must have the public property mIndex. */ template @@ -63,36 +63,36 @@ namespace apl { namespace dnp { AsyncInsertionOrderedEventBuffer(size_t aMaxEvents); }; - + template AsyncSingleEventBuffer :: AsyncSingleEventBuffer(size_t aMaxEvents) : AsyncEventBufferBase< EventType, IndexSet< EventType > >(aMaxEvents) {} template - AsyncTimeOrderedEventBuffer :: AsyncTimeOrderedEventBuffer(size_t aMaxEvents) : + AsyncTimeOrderedEventBuffer :: AsyncTimeOrderedEventBuffer(size_t aMaxEvents) : AsyncEventBufferBase >(aMaxEvents) {} template - AsyncInsertionOrderedEventBuffer :: AsyncInsertionOrderedEventBuffer(size_t aMaxEvents) : + AsyncInsertionOrderedEventBuffer :: AsyncInsertionOrderedEventBuffer(size_t aMaxEvents) : AsyncEventBufferBase >(aMaxEvents) {} - + template void AsyncSingleEventBuffer :: _Update(const EventType& arEvent) - { + { typename IndexSet< EventType >::Type::iterator i = this->mEventSet.find(arEvent); - if(i != this->mEventSet.end() ) - { - if(arEvent.mValue.GetTime() >= i->mValue.GetTime()) + if(i != this->mEventSet.end() ) + { + if(arEvent.mValue.GetTime() >= i->mValue.GetTime()) { this->mEventSet.erase(i); this->mEventSet.insert(arEvent); //new event } } - else + else { this->mEventSet.insert(arEvent); //new event this->mCounter.IncrCount(arEvent.mClass); diff --git a/DNP3/AsyncLinkLayer.h b/DNP3/AsyncLinkLayer.h index e00a3d8a..f4c57957 100644 --- a/DNP3/AsyncLinkLayer.h +++ b/DNP3/AsyncLinkLayer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_LINK_LAYER_H_ #define __ASYNC_LINK_LAYER_H_ @@ -36,7 +36,7 @@ namespace apl { namespace dnp { /// @section desc Implements the contextual state of DNP3 Data Link Layer class AsyncLinkLayer : public ILowerLayer, public ILinkContext - { + { public: AsyncLinkLayer(apl::Logger*, ITimerSource*, const LinkConfig& arConfig); @@ -45,7 +45,7 @@ namespace apl { namespace dnp { // ILinkContext interface void OnLowerLayerUp(); - void OnLowerLayerDown(); + void OnLowerLayerDown(); // IFrameSink interface void Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); @@ -63,10 +63,10 @@ namespace apl { namespace dnp { void ChangeState(SecStateBase*); Logger* GetLogger() { return mpLogger; } - + void DoDataUp(const byte_t* apData, size_t aLength) { if(mpUpperLayer) mpUpperLayer->OnReceive(apData, aLength); } - + void DoSendSuccess() { if(mpUpperLayer) mpUpperLayer->OnSendSuccess(); } @@ -83,7 +83,7 @@ namespace apl { namespace dnp { // Helpers for sending frames void SendAck(); - void SendLinkStatus(); + void SendLinkStatus(); void SendResetLinks(); void SendUnconfirmedUserData(const byte_t* apData, size_t aLength); void SendDelayedUserData(bool aFCB); @@ -116,10 +116,10 @@ namespace apl { namespace dnp { bool mNextReadFCB; bool mNextWriteFCB; - bool mIsOnline; + bool mIsOnline; bool Validate(bool aIsMaster, uint_16_t aSrc, uint_16_t aDest); - + /* Events - NVII delegates from ILayerDown and Events produced internally */ void _Send(const apl::byte_t*, size_t); diff --git a/DNP3/AsyncLinkLayerRouter.h b/DNP3/AsyncLinkLayerRouter.h index a2e90f09..75bca00f 100644 --- a/DNP3/AsyncLinkLayerRouter.h +++ b/DNP3/AsyncLinkLayerRouter.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_LINK_LAYER_ROUTER_H_ #define __ASYNC_LINK_LAYER_ROUTER_H_ @@ -42,10 +42,10 @@ namespace apl { namespace dnp { /// of DNP 3 Data Link Layer. AsyncPhysLayerMonitor inherits /// from IHandlerAsync, which inherits from IUpperLayer class AsyncLinkLayerRouter : public AsyncPhysLayerMonitor, public IFrameSink, public ILinkRouter - { + { public: - AsyncLinkLayerRouter(apl::Logger*, IPhysicalLayerAsync*, ITimerSource*, millis_t aOpenRetry); + AsyncLinkLayerRouter(apl::Logger*, IPhysicalLayerAsync*, ITimerSource*, millis_t aOpenRetry); /// Ties the lower part of the link layer to the upper part void AddContext(ILinkContext*, uint_16_t aAddress); @@ -75,7 +75,7 @@ namespace apl { namespace dnp { ILinkContext* GetContext(uint_16_t aDest); void CheckForSend(); - + typedef std::map AddressMap; typedef std::deque TransmitQueue; diff --git a/DNP3/AsyncMaster.h b/DNP3/AsyncMaster.h index a1a76e7e..f81f1ff8 100644 --- a/DNP3/AsyncMaster.h +++ b/DNP3/AsyncMaster.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_MASTER_H_ #define __ASYNC_MASTER_H_ @@ -74,7 +74,7 @@ class AsyncMaster : public Loggable, public IAsyncAppUser//, public ICommandAcce typedef boost::function CommandFormatter; typedef boost::function CommandValidator; typedef boost::function DelayValidator; - + public: AsyncMaster(Logger*, MasterConfig aCfg, IAsyncAppLayer*, IDataObserver*, AsyncTaskGroup*, ITimerSource*, ITimeSource* apTimeSrc = TimeSource::Inst()); @@ -92,7 +92,7 @@ class AsyncMaster : public Loggable, public IAsyncAppUser//, public ICommandAcce void ExecuteCommand(); /* Implement IAsyncAppUser - callbacks from the app layer */ - + void OnLowerLayerUp(); void OnLowerLayerDown(); @@ -105,12 +105,12 @@ class AsyncMaster : public Loggable, public IAsyncAppUser//, public ICommandAcce // override the response functions void OnPartialResponse(const APDU&); void OnFinalResponse(const APDU&); - void OnUnsolResponse(const APDU&); + void OnUnsolResponse(const APDU&); bool IsMaster() { return true; } private: - + IINField mLastIIN; /// last IIN received from the outstation void ProcessIIN(const IINField& arIIN); /// Analyze IIN bits and react accordingly @@ -120,12 +120,12 @@ class AsyncMaster : public Loggable, public IAsyncAppUser//, public ICommandAcce void CompleteCommandTask(CommandStatus aStatus); /// finalize the execution of the command task void ProcessDataResponse(const APDU&); /// Read data output of solicited or unsolicited response and publish - + PostingNotifierSource mNotifierSource; /// way to get special notifiers for the command queue / vto CommandQueue mCommandQueue; /// Threadsafe queue for buffering command requests AMS_Base* mpState; /// Pointer to active state, start in TLS_Closed ITaskCompletion* mpTask; /// Pointer to active task, NULL if no task - + APDU mRequest; /// APDU that gets reused for requests IAsyncAppLayer* mpAppLayer; /// lower application layer @@ -144,7 +144,7 @@ class AsyncMaster : public Loggable, public IAsyncAppUser//, public ICommandAcce DelayValidator mDelayValidator; bool ValidateDelayMeas(const APDU&, boost::posix_time::ptime aStart, millis_t& arDelay); - + CopyableBuffer FormatSetpoint(const Setpoint& arCmd, CommandObject*, size_t aIndex, bool aIsSelect); CopyableBuffer FormatBinaryOutput(const BinaryOutput& arCmd, size_t aIndex, bool aIsSelect); @@ -159,7 +159,7 @@ CommandStatus AsyncMaster::ValidateCommandResponse(const APDU& arAPDU, CommandOb if(hdr.Count() == 1) { int grp = hdr->GetGroup(); - int var = hdr->GetVariation(); + int var = hdr->GetVariation(); if(grp == apObj->GetGroup() && var == apObj->GetVariation()) { @@ -169,7 +169,7 @@ CommandStatus AsyncMaster::ValidateCommandResponse(const APDU& arAPDU, CommandOb //compare what was written to what was received T cmd = apObj->Read(*obj); if(arData == apObj->GetValueBytes(*obj)) return cmd.mStatus; - else return CS_FORMAT_ERROR; + else return CS_FORMAT_ERROR; } } } diff --git a/DNP3/AsyncMasterStack.cpp b/DNP3/AsyncMasterStack.cpp index d5c5f7e4..c93c458e 100644 --- a/DNP3/AsyncMasterStack.cpp +++ b/DNP3/AsyncMasterStack.cpp @@ -16,24 +16,24 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncMasterStack.h" - -#include - -namespace apl { namespace dnp { - -AsyncMasterStack::AsyncMasterStack( - -Logger* apLogger, -ITimerSource* apTimerSrc, -IDataObserver* apPublisher, -AsyncTaskGroup* apTaskGroup, -const MasterStackConfig& arCfg) : - -AsyncStack(apLogger, apTimerSrc, arCfg.app, arCfg.link), -mMaster(apLogger->GetSubLogger("master"), arCfg.master, &mApplication, apPublisher, apTaskGroup, apTimerSrc) -{ - mApplication.SetUser(&mMaster); -} - -}} +#include "AsyncMasterStack.h" + +#include + +namespace apl { namespace dnp { + +AsyncMasterStack::AsyncMasterStack( + +Logger* apLogger, +ITimerSource* apTimerSrc, +IDataObserver* apPublisher, +AsyncTaskGroup* apTaskGroup, +const MasterStackConfig& arCfg) : + +AsyncStack(apLogger, apTimerSrc, arCfg.app, arCfg.link), +mMaster(apLogger->GetSubLogger("master"), arCfg.master, &mApplication, apPublisher, apTaskGroup, apTimerSrc) +{ + mApplication.SetUser(&mMaster); +} + +}} diff --git a/DNP3/AsyncMasterStack.h b/DNP3/AsyncMasterStack.h index 241e1e85..206236f5 100644 --- a/DNP3/AsyncMasterStack.h +++ b/DNP3/AsyncMasterStack.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,40 +6,40 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_MASTER_STACK_H_ -#define __ASYNC_MASTER_STACK_H_ - -#include "AsyncStack.h" -#include "AsyncMaster.h" -#include "MasterStackConfig.h" - -namespace apl { namespace dnp { - -/** @section desc A stack object for a master */ -class AsyncMasterStack : public AsyncStack -{ - public: - - AsyncMasterStack( - Logger*, - ITimerSource* apTimerSrc, - IDataObserver* apPublisher, - AsyncTaskGroup* apTaskGroup, - const MasterStackConfig& arCfg); - - AsyncMaster mMaster; -}; - -}} - -#endif +// +#ifndef __ASYNC_MASTER_STACK_H_ +#define __ASYNC_MASTER_STACK_H_ + +#include "AsyncStack.h" +#include "AsyncMaster.h" +#include "MasterStackConfig.h" + +namespace apl { namespace dnp { + +/** @section desc A stack object for a master */ +class AsyncMasterStack : public AsyncStack +{ + public: + + AsyncMasterStack( + Logger*, + ITimerSource* apTimerSrc, + IDataObserver* apPublisher, + AsyncTaskGroup* apTaskGroup, + const MasterStackConfig& arCfg); + + AsyncMaster mMaster; +}; + +}} + +#endif diff --git a/DNP3/AsyncMasterStates.h b/DNP3/AsyncMasterStates.h index c425421e..02829225 100644 --- a/DNP3/AsyncMasterStates.h +++ b/DNP3/AsyncMasterStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_MASTER_STATES_H_ #define __ASYNC_MASTER_STATES_H_ @@ -26,9 +26,9 @@ #include "ObjectInterfaces.h" -namespace apl +namespace apl { - class ITaskCompletion; + class ITaskCompletion; class Logger; class BinaryOutput; class Setpoint; @@ -50,7 +50,7 @@ class AMS_Base virtual void EventPoll(AsyncMaster*, ITaskCompletion* apTask, int aClassMask); virtual void ChangeUnsol(AsyncMaster*, ITaskCompletion* apTask, bool aEnable, int aClassMask); virtual void SyncTime(AsyncMaster*, ITaskCompletion* apTask); - virtual void Execute(AsyncMaster*, const BinaryOutput&, size_t); + virtual void Execute(AsyncMaster*, const BinaryOutput&, size_t); virtual void Execute(AsyncMaster*, const Setpoint&, size_t); /* Events from application layer */ @@ -63,7 +63,7 @@ class AMS_Base virtual void OnPartialResponse(AsyncMaster*, const APDU&); virtual void OnFinalResponse(AsyncMaster*, const APDU&); - virtual void OnUnsolResponse(AsyncMaster*, const APDU&); + virtual void OnUnsolResponse(AsyncMaster*, const APDU&); virtual std::string Name() const = 0; @@ -107,7 +107,7 @@ class AMS_Closed : public AMS_Base class AMS_OpenBase : public AMS_Base { public: - void OnUnsolResponse(AsyncMaster*, const APDU&); + void OnUnsolResponse(AsyncMaster*, const APDU&); }; /* AMS_Idle */ diff --git a/DNP3/AsyncPort.cpp b/DNP3/AsyncPort.cpp index a5188fc5..3f6e64ef 100644 --- a/DNP3/AsyncPort.cpp +++ b/DNP3/AsyncPort.cpp @@ -16,82 +16,82 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncPort.h" - -#include "AsyncStack.h" -#include -#include - -#include -#include -#include - -namespace apl { namespace dnp { - -AsyncPort::AsyncPort(const std::string& arName, Logger* apLogger, AsyncTaskGroup* apGroup, ITimerSource* apTimerSrc, IPhysicalLayerAsync* apPhys, millis_t aOpenDelay) : -Loggable(apLogger->GetSubLogger("port")), -mName(arName), -mRouter(apLogger, apPhys, apTimerSrc, aOpenDelay), -mpGroup(apGroup), -mpPhys(apPhys), -mRelease(false) -{ - mRouter.SetMonitor(this); -} - -//ports own their physical layers -AsyncPort::~AsyncPort() -{ - delete mpPhys; - delete mpGroup; - -} - -//Once we're sure the router is done with -void AsyncPort::Release() //do nothing right now -{ - if(mRouter.IsRunning()) mRelease = true; - else { - delete this; - } -} - -void AsyncPort::OnStateChange(IPhysMonitor::State aState) -{ - switch(aState) { - case(IPhysMonitor::Stopped): - if(mRelease) delete this; //when the router stops, delete ourselves - break; - default: - break; - } -} - -void AsyncPort::Associate(const std::string& arStackName, AsyncStack* apStack, uint_16_t aLocalAddress) -{ - LOG_BLOCK(LEV_DEBUG, "Linking stack to port: " << aLocalAddress); - mStackMap[arStackName] = StackRecord(apStack, aLocalAddress); - apStack->mLink.SetRouter(&mRouter); - mRouter.AddContext(&apStack->mLink, aLocalAddress); - if(!mRouter.IsRunning()) { - LOG_BLOCK(LEV_DEBUG, "Starting router"); - mRouter.Start(); - } -} - -void AsyncPort::Disassociate(const std::string& arStackName) -{ - StackMap::iterator i = mStackMap.find(arStackName); - StackRecord r = i->second; - LOG_BLOCK(LEV_DEBUG, "Unlinking stack from port: " << r.mLocalAddress); - mRouter.RemoveContext(r.mLocalAddress); // decouple the stack from the router and tell the stack to go offline if the it was previously online - delete r.pStack; // delete the stack - if(mRouter.IsRunning() && mRouter.NumContext() == 0) { - LOG_BLOCK(LEV_DEBUG, "Stopping router"); - mRouter.Stop(); - } - mStackMap.erase(i); -} - - -}} +#include "AsyncPort.h" + +#include "AsyncStack.h" +#include +#include + +#include +#include +#include + +namespace apl { namespace dnp { + +AsyncPort::AsyncPort(const std::string& arName, Logger* apLogger, AsyncTaskGroup* apGroup, ITimerSource* apTimerSrc, IPhysicalLayerAsync* apPhys, millis_t aOpenDelay) : +Loggable(apLogger->GetSubLogger("port")), +mName(arName), +mRouter(apLogger, apPhys, apTimerSrc, aOpenDelay), +mpGroup(apGroup), +mpPhys(apPhys), +mRelease(false) +{ + mRouter.SetMonitor(this); +} + +//ports own their physical layers +AsyncPort::~AsyncPort() +{ + delete mpPhys; + delete mpGroup; + +} + +//Once we're sure the router is done with +void AsyncPort::Release() //do nothing right now +{ + if(mRouter.IsRunning()) mRelease = true; + else { + delete this; + } +} + +void AsyncPort::OnStateChange(IPhysMonitor::State aState) +{ + switch(aState) { + case(IPhysMonitor::Stopped): + if(mRelease) delete this; //when the router stops, delete ourselves + break; + default: + break; + } +} + +void AsyncPort::Associate(const std::string& arStackName, AsyncStack* apStack, uint_16_t aLocalAddress) +{ + LOG_BLOCK(LEV_DEBUG, "Linking stack to port: " << aLocalAddress); + mStackMap[arStackName] = StackRecord(apStack, aLocalAddress); + apStack->mLink.SetRouter(&mRouter); + mRouter.AddContext(&apStack->mLink, aLocalAddress); + if(!mRouter.IsRunning()) { + LOG_BLOCK(LEV_DEBUG, "Starting router"); + mRouter.Start(); + } +} + +void AsyncPort::Disassociate(const std::string& arStackName) +{ + StackMap::iterator i = mStackMap.find(arStackName); + StackRecord r = i->second; + LOG_BLOCK(LEV_DEBUG, "Unlinking stack from port: " << r.mLocalAddress); + mRouter.RemoveContext(r.mLocalAddress); // decouple the stack from the router and tell the stack to go offline if the it was previously online + delete r.pStack; // delete the stack + if(mRouter.IsRunning() && mRouter.NumContext() == 0) { + LOG_BLOCK(LEV_DEBUG, "Stopping router"); + mRouter.Stop(); + } + mStackMap.erase(i); +} + + +}} diff --git a/DNP3/AsyncPort.h b/DNP3/AsyncPort.h index 473b8c97..32268817 100644 --- a/DNP3/AsyncPort.h +++ b/DNP3/AsyncPort.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_PORT_H_ #define __ASYNC_PORT_H_ @@ -53,19 +53,19 @@ class AsyncPort : public Loggable, public IPhysMonitor StackRecord() : pStack(NULL), mLocalAddress(0) {} - StackRecord(AsyncStack* apStack, uint_16_t aLocalAddress) : + StackRecord(AsyncStack* apStack, uint_16_t aLocalAddress) : pStack(apStack) , mLocalAddress(aLocalAddress) {} - + AsyncStack* pStack; uint_16_t mLocalAddress; }; - + public: AsyncPort(const std::string& arName, Logger*, AsyncTaskGroup*, ITimerSource* apTimerSrc, IPhysicalLayerAsync*, millis_t aOpenDelay); ~AsyncPort(); - - + + AsyncTaskGroup* GetGroup() { return mpGroup; } void Associate(const std::string& arStackName, AsyncStack* apStack, uint_16_t aLocalAddress); void Disassociate(const std::string& arStackName); @@ -76,20 +76,20 @@ class AsyncPort : public Loggable, public IPhysMonitor //Events from the router void OnStateChange(IPhysMonitor::State); - + private: - + std::string mName; AsyncLinkLayerRouter mRouter; - AsyncTaskGroup* mpGroup; + AsyncTaskGroup* mpGroup; IPhysicalLayerAsync* mpPhys; bool mRelease; private: - + typedef std::map StackMap; StackMap mStackMap; - + }; }} diff --git a/DNP3/AsyncResponseContext.cpp b/DNP3/AsyncResponseContext.cpp index 00895127..67d30cee 100644 --- a/DNP3/AsyncResponseContext.cpp +++ b/DNP3/AsyncResponseContext.cpp @@ -16,398 +16,398 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncResponseContext.h" - -#include "Objects.h" -#include "DNPConstants.h" -#include "SlaveResponseTypes.h" -#include - -#include - -using namespace boost; - -#define MACRO_CONTINUOUS_CASE(obj,var) \ -case(MACRO_DNP_RADIX(obj,var)): { \ - /*WriteFunc::Type func = bind(DataToDNP::WriteGroup##obj##Var##var, _1, _2); \*/ \ - if(!this->IterateContiguous(iter, arAPDU)) return false; \ - break; \ -} - -namespace apl { namespace dnp { - -AsyncResponseContext::AsyncResponseContext(Logger* apLogger, AsyncDatabase* apDB, SlaveResponseTypes* apRspTypes, size_t aMaxBinary, size_t aMaxAnalog, size_t aMaxCounter) : -Loggable(apLogger), -mBuffer(aMaxBinary, aMaxAnalog, aMaxCounter), -mMode(UNDEFINED), - -mpDB(apDB), -mFIR(true), -mFIN(false), -mpRspTypes(apRspTypes) -{} - -void AsyncResponseContext::Reset() -{ - mFIR = true; - mMode = UNDEFINED; - mTempIIN.Zero(); - - this->mStaticBinaries.clear(); - this->mStaticAnalogs.clear(); - this->mStaticCounters.clear(); - this->mStaticControls.clear(); - this->mStaticSetpoints.clear(); - - this->mBinaryEvents.clear(); - this->mAnalogEvents.clear(); - this->mCounterEvents.clear(); - - mBuffer.Deselect(); -} - -void AsyncResponseContext::ClearWritten() -{ - mBuffer.ClearWritten(); -} - -void AsyncResponseContext::ClearAndReset() -{ - this->ClearWritten(); - this->Reset(); -} - -inline size_t GetEventCount(const HeaderInfo& arHeader) -{ - switch(arHeader.GetQualifier()) { - case QC_1B_CNT: - case QC_2B_CNT: - return arHeader.GetCount(); - default: - return std::numeric_limits::max(); - } -} - -IINField AsyncResponseContext::Configure(const APDU& arRequest) -{ - this->Reset(); - mMode = SOLICITED; - - for(HeaderReadIterator hdr = arRequest.BeginRead(); !hdr.IsEnd(); ++hdr) - { - switch(MACRO_DNP_RADIX(hdr->GetGroup(), hdr->GetVariation())) - { - // static objects, all variations - case(MACRO_DNP_RADIX(1,0)): - this->AddIntegrity(mStaticBinaries, mpRspTypes->mpStaticBinary); - break; - case(MACRO_DNP_RADIX(10,0)): - this->AddIntegrity(mStaticControls, mpRspTypes->mpStaticControlStatus); - break; - case(MACRO_DNP_RADIX(20,0)): - this->AddIntegrity(mStaticCounters, mpRspTypes->mpStaticCounter); - break; - case(MACRO_DNP_RADIX(30,0)): - this->AddIntegrity(mStaticAnalogs, mpRspTypes->mpStaticAnalog); - break; - case(MACRO_DNP_RADIX(40,0)): - this->AddIntegrity(mStaticSetpoints, mpRspTypes->mpStaticSetpointStatus); - break; - - // event objects - case(MACRO_DNP_RADIX(2,0)): - this->SelectEvents(PC_ALL_EVENTS, mpRspTypes->mpEventBinary, mBinaryEvents, GetEventCount(hdr.info())); - break; - case(MACRO_DNP_RADIX(22,0)): - this->SelectEvents(PC_ALL_EVENTS, mpRspTypes->mpEventCounter, mCounterEvents, GetEventCount(hdr.info())); - break; - case(MACRO_DNP_RADIX(32,0)): - this->SelectEvents(PC_ALL_EVENTS, mpRspTypes->mpEventAnalog, mAnalogEvents, GetEventCount(hdr.info())); - break; - - //specific objects - case(MACRO_DNP_RADIX(2,1)): - this->SelectEvents(PC_ALL_EVENTS, Group2Var1::Inst(), mBinaryEvents, GetEventCount(hdr.info())); - break; - case(MACRO_DNP_RADIX(2,2)): - this->SelectEvents(PC_ALL_EVENTS, Group2Var2::Inst(), mBinaryEvents, GetEventCount(hdr.info())); - break; - case(MACRO_DNP_RADIX(2,3)): - this->SelectEvents(PC_ALL_EVENTS, Group2Var3::Inst(), mBinaryEvents, GetEventCount(hdr.info())); - break; - - - // Class Objects - case(MACRO_DNP_RADIX(60,1)): - this->AddIntegrityPoll(); - break; - case(MACRO_DNP_RADIX(60,2)): - this->SelectEvents(PC_CLASS_1, GetEventCount(hdr.info())); - break; - case(MACRO_DNP_RADIX(60,3)): - this->SelectEvents(PC_CLASS_2, GetEventCount(hdr.info())); - break; - case(MACRO_DNP_RADIX(60,4)): - this->SelectEvents(PC_CLASS_3, GetEventCount(hdr.info())); - break; - default: - LOG_BLOCK(LEV_WARNING, "READ for obj " << hdr->GetGroup() << " var " << hdr->GetVariation() << " not supported."); - this->mTempIIN.SetFuncNotSupported(true); - break; - } - } - - return mTempIIN; -} - -void AsyncResponseContext::SelectEvents(PointClass aClass, size_t aNum) -{ - size_t remain = aNum; - - if(mBuffer.IsOverflow()) - mTempIIN.SetEventBufferOverflow(true); - - remain -= this->SelectEvents(aClass, mpRspTypes->mpEventBinary, mBinaryEvents, remain); - remain -= this->SelectEvents(aClass, mpRspTypes->mpEventAnalog, mAnalogEvents, remain); - remain -= this->SelectEvents(aClass, mpRspTypes->mpEventCounter, mCounterEvents, remain); -} - -void AsyncResponseContext::LoadResponse(APDU& arAPDU) -{ - //delay the setting of FIR/FIN until we know if it will be multifragmented or not - arAPDU.Set(FC_RESPONSE); - - bool events = false; - - bool wrote_all = this->LoadEventData(arAPDU, events); - - if(wrote_all) wrote_all = LoadStaticData(arAPDU); - - FinalizeResponse(arAPDU, events, wrote_all); -} - -bool AsyncResponseContext::SelectUnsol(ClassMask m) -{ - if(m.class1) this->SelectEvents(PC_CLASS_1); - if(m.class2) this->SelectEvents(PC_CLASS_2); - if(m.class3) this->SelectEvents(PC_CLASS_3); - - return mBuffer.NumSelected() > 0; -} - -bool AsyncResponseContext::HasEvents(ClassMask m) -{ - if(m.class1 && mBuffer.HasClassData(PC_CLASS_1)) return true; - if(m.class2 && mBuffer.HasClassData(PC_CLASS_2)) return true; - if(m.class3 && mBuffer.HasClassData(PC_CLASS_3)) return true; - - return false; -} - -bool AsyncResponseContext::LoadUnsol(APDU& arAPDU, const IINField& arIIN, ClassMask m) -{ - this->SelectUnsol(m); - - arAPDU.Set(FC_UNSOLICITED_RESPONSE, true, true, true, true); - bool events = false; - this->LoadEventData(arAPDU, events); - return events; -} - -bool AsyncResponseContext::LoadStaticData(APDU& arAPDU) -{ - if(!this->LoadStaticBinaries(arAPDU)) return false; - if(!this->LoadStaticCounters(arAPDU)) return false; - if(!this->LoadStaticAnalogs(arAPDU)) return false; - if(!this->LoadStaticControlStatii(arAPDU)) return false; - if(!this->LoadStaticSetpointStatii(arAPDU)) return false; - - return true; -} - -bool AsyncResponseContext::LoadEventData(APDU& arAPDU, bool& arEventsLoaded) -{ - if(!this->LoadEvents(arAPDU, mBinaryEvents, arEventsLoaded)) return false; - if(!this->LoadEvents(arAPDU, mAnalogEvents, arEventsLoaded)) return false; - if(!this->LoadEvents(arAPDU, mCounterEvents, arEventsLoaded)) return false; - - return true; -} - -bool AsyncResponseContext::IsEmpty() -{ - return this->IsStaticEmpty() && this->IsEventEmpty(); -} - -bool AsyncResponseContext::IsStaticEmpty() -{ - return this->mStaticBinaries.empty() && this->mStaticCounters.empty() && - this->mStaticAnalogs.empty() && this->mStaticControls.empty() && - this->mStaticSetpoints.empty(); -} - -bool AsyncResponseContext::IsEventEmpty() -{ - // are there unwritten events in the selection buffer? - return mBuffer.NumSelected() == 0; -} - -void AsyncResponseContext::FinalizeResponse(APDU& arAPDU, bool aHasEventData, bool aFIN) -{ - mFIN = aFIN; - bool confirm = !aFIN || aHasEventData; - arAPDU.SetControl(mFIR, mFIN, confirm); - mFIR = false; -} - -bool AsyncResponseContext::LoadStaticBinaries(APDU& arAPDU) -{ - while(!mStaticBinaries.empty()) - { - IterRecord& iter = this->mStaticBinaries.front(); - int grp = iter.pObject->GetGroup(); - int var = iter.pObject->GetVariation(); - - switch(MACRO_DNP_RADIX(grp, var)) - { - //special case for the bitfield - /*case(MACRO_DNP_RADIX(1,1)): - { - WriteFunc::Type func = bind(&Group1Var1::Write, Group1Var1::Inst(), _1, iter.first->mIndex, _3, _2); - if(!this->IterateContiguous(iter, arAPDU, func)) return false; - break; - }*/ - - MACRO_CONTINUOUS_CASE(1,2); - - default: - break; - } - - this->mStaticBinaries.pop_front(); - } - - return true; -} - -bool AsyncResponseContext::LoadStaticAnalogs(APDU& arAPDU) -{ - while(!mStaticAnalogs.empty()) - { - IterRecord& iter = this->mStaticAnalogs.front(); - int grp = iter.pObject->GetGroup(); - int var = iter.pObject->GetVariation(); - - switch(MACRO_DNP_RADIX(grp, var)) - { - MACRO_CONTINUOUS_CASE(30,1); - MACRO_CONTINUOUS_CASE(30,2); - MACRO_CONTINUOUS_CASE(30,3); - MACRO_CONTINUOUS_CASE(30,4); - MACRO_CONTINUOUS_CASE(30,5); - MACRO_CONTINUOUS_CASE(30,6); - - default: - break; - } - - this->mStaticAnalogs.pop_front(); - } - - return true; -} - -bool AsyncResponseContext::LoadStaticCounters(APDU& arAPDU) -{ - while(!mStaticCounters.empty()) - { - IterRecord& iter = this->mStaticCounters.front(); - int grp = iter.pObject->GetGroup(); - int var = iter.pObject->GetVariation(); - - // Delta counters omitted - switch(MACRO_DNP_RADIX(grp, var)) - { - MACRO_CONTINUOUS_CASE(20,1); - MACRO_CONTINUOUS_CASE(20,2); - MACRO_CONTINUOUS_CASE(20,5); - MACRO_CONTINUOUS_CASE(20,6); - - default: - break; - } - - this->mStaticCounters.pop_front(); - } - - return true; -} - -bool AsyncResponseContext::LoadStaticControlStatii(APDU& arAPDU) -{ - while(!mStaticControls.empty()) - { - IterRecord& iter = this->mStaticControls.front(); - int grp = iter.pObject->GetGroup(); - int var = iter.pObject->GetVariation(); - - switch(MACRO_DNP_RADIX(grp, var)) - { - MACRO_CONTINUOUS_CASE(10,2); - - default: - break; - } - - this->mStaticControls.pop_front(); - } - - return true; -} - -/* -bool AsyncResponseContext::WriteCTO(const TimeStamp_t& arTime, APDU& arAPDU) -{ - Group51Var1* pObj = Group51Var1::Inst(); - ObjectWriteIterator owi = arAPDU.WriteContiguous(pObj, 0, 0); - if(owi.IsEnd()) return false; - pObj->mTime.Set(*owi, arTime); - return true; -}*/ - -bool AsyncResponseContext::LoadStaticSetpointStatii(APDU& arAPDU) -{ - while(!mStaticSetpoints.empty()) - { - IterRecord& iter = this->mStaticSetpoints.front(); - int grp = iter.pObject->GetGroup(); - int var = iter.pObject->GetVariation(); - - switch(MACRO_DNP_RADIX(grp, var)) - { - MACRO_CONTINUOUS_CASE(40,1); - MACRO_CONTINUOUS_CASE(40,2); - MACRO_CONTINUOUS_CASE(40,3); - MACRO_CONTINUOUS_CASE(40,4); - - default: - break; - } - - this->mStaticSetpoints.pop_front(); - } - - return true; -} - -void AsyncResponseContext::AddIntegrityPoll() -{ - this->AddIntegrity(mStaticBinaries, mpRspTypes->mpStaticBinary); - this->AddIntegrity(mStaticAnalogs, mpRspTypes->mpStaticAnalog); - this->AddIntegrity(mStaticCounters, mpRspTypes->mpStaticCounter); - this->AddIntegrity(mStaticControls, mpRspTypes->mpStaticControlStatus); - this->AddIntegrity(mStaticSetpoints, mpRspTypes->mpStaticSetpointStatus); -} - -}} - +#include "AsyncResponseContext.h" + +#include "Objects.h" +#include "DNPConstants.h" +#include "SlaveResponseTypes.h" +#include + +#include + +using namespace boost; + +#define MACRO_CONTINUOUS_CASE(obj,var) \ +case(MACRO_DNP_RADIX(obj,var)): { \ + /*WriteFunc::Type func = bind(DataToDNP::WriteGroup##obj##Var##var, _1, _2); \*/ \ + if(!this->IterateContiguous(iter, arAPDU)) return false; \ + break; \ +} + +namespace apl { namespace dnp { + +AsyncResponseContext::AsyncResponseContext(Logger* apLogger, AsyncDatabase* apDB, SlaveResponseTypes* apRspTypes, size_t aMaxBinary, size_t aMaxAnalog, size_t aMaxCounter) : +Loggable(apLogger), +mBuffer(aMaxBinary, aMaxAnalog, aMaxCounter), +mMode(UNDEFINED), + +mpDB(apDB), +mFIR(true), +mFIN(false), +mpRspTypes(apRspTypes) +{} + +void AsyncResponseContext::Reset() +{ + mFIR = true; + mMode = UNDEFINED; + mTempIIN.Zero(); + + this->mStaticBinaries.clear(); + this->mStaticAnalogs.clear(); + this->mStaticCounters.clear(); + this->mStaticControls.clear(); + this->mStaticSetpoints.clear(); + + this->mBinaryEvents.clear(); + this->mAnalogEvents.clear(); + this->mCounterEvents.clear(); + + mBuffer.Deselect(); +} + +void AsyncResponseContext::ClearWritten() +{ + mBuffer.ClearWritten(); +} + +void AsyncResponseContext::ClearAndReset() +{ + this->ClearWritten(); + this->Reset(); +} + +inline size_t GetEventCount(const HeaderInfo& arHeader) +{ + switch(arHeader.GetQualifier()) { + case QC_1B_CNT: + case QC_2B_CNT: + return arHeader.GetCount(); + default: + return std::numeric_limits::max(); + } +} + +IINField AsyncResponseContext::Configure(const APDU& arRequest) +{ + this->Reset(); + mMode = SOLICITED; + + for(HeaderReadIterator hdr = arRequest.BeginRead(); !hdr.IsEnd(); ++hdr) + { + switch(MACRO_DNP_RADIX(hdr->GetGroup(), hdr->GetVariation())) + { + // static objects, all variations + case(MACRO_DNP_RADIX(1,0)): + this->AddIntegrity(mStaticBinaries, mpRspTypes->mpStaticBinary); + break; + case(MACRO_DNP_RADIX(10,0)): + this->AddIntegrity(mStaticControls, mpRspTypes->mpStaticControlStatus); + break; + case(MACRO_DNP_RADIX(20,0)): + this->AddIntegrity(mStaticCounters, mpRspTypes->mpStaticCounter); + break; + case(MACRO_DNP_RADIX(30,0)): + this->AddIntegrity(mStaticAnalogs, mpRspTypes->mpStaticAnalog); + break; + case(MACRO_DNP_RADIX(40,0)): + this->AddIntegrity(mStaticSetpoints, mpRspTypes->mpStaticSetpointStatus); + break; + + // event objects + case(MACRO_DNP_RADIX(2,0)): + this->SelectEvents(PC_ALL_EVENTS, mpRspTypes->mpEventBinary, mBinaryEvents, GetEventCount(hdr.info())); + break; + case(MACRO_DNP_RADIX(22,0)): + this->SelectEvents(PC_ALL_EVENTS, mpRspTypes->mpEventCounter, mCounterEvents, GetEventCount(hdr.info())); + break; + case(MACRO_DNP_RADIX(32,0)): + this->SelectEvents(PC_ALL_EVENTS, mpRspTypes->mpEventAnalog, mAnalogEvents, GetEventCount(hdr.info())); + break; + + //specific objects + case(MACRO_DNP_RADIX(2,1)): + this->SelectEvents(PC_ALL_EVENTS, Group2Var1::Inst(), mBinaryEvents, GetEventCount(hdr.info())); + break; + case(MACRO_DNP_RADIX(2,2)): + this->SelectEvents(PC_ALL_EVENTS, Group2Var2::Inst(), mBinaryEvents, GetEventCount(hdr.info())); + break; + case(MACRO_DNP_RADIX(2,3)): + this->SelectEvents(PC_ALL_EVENTS, Group2Var3::Inst(), mBinaryEvents, GetEventCount(hdr.info())); + break; + + + // Class Objects + case(MACRO_DNP_RADIX(60,1)): + this->AddIntegrityPoll(); + break; + case(MACRO_DNP_RADIX(60,2)): + this->SelectEvents(PC_CLASS_1, GetEventCount(hdr.info())); + break; + case(MACRO_DNP_RADIX(60,3)): + this->SelectEvents(PC_CLASS_2, GetEventCount(hdr.info())); + break; + case(MACRO_DNP_RADIX(60,4)): + this->SelectEvents(PC_CLASS_3, GetEventCount(hdr.info())); + break; + default: + LOG_BLOCK(LEV_WARNING, "READ for obj " << hdr->GetGroup() << " var " << hdr->GetVariation() << " not supported."); + this->mTempIIN.SetFuncNotSupported(true); + break; + } + } + + return mTempIIN; +} + +void AsyncResponseContext::SelectEvents(PointClass aClass, size_t aNum) +{ + size_t remain = aNum; + + if(mBuffer.IsOverflow()) + mTempIIN.SetEventBufferOverflow(true); + + remain -= this->SelectEvents(aClass, mpRspTypes->mpEventBinary, mBinaryEvents, remain); + remain -= this->SelectEvents(aClass, mpRspTypes->mpEventAnalog, mAnalogEvents, remain); + remain -= this->SelectEvents(aClass, mpRspTypes->mpEventCounter, mCounterEvents, remain); +} + +void AsyncResponseContext::LoadResponse(APDU& arAPDU) +{ + //delay the setting of FIR/FIN until we know if it will be multifragmented or not + arAPDU.Set(FC_RESPONSE); + + bool events = false; + + bool wrote_all = this->LoadEventData(arAPDU, events); + + if(wrote_all) wrote_all = LoadStaticData(arAPDU); + + FinalizeResponse(arAPDU, events, wrote_all); +} + +bool AsyncResponseContext::SelectUnsol(ClassMask m) +{ + if(m.class1) this->SelectEvents(PC_CLASS_1); + if(m.class2) this->SelectEvents(PC_CLASS_2); + if(m.class3) this->SelectEvents(PC_CLASS_3); + + return mBuffer.NumSelected() > 0; +} + +bool AsyncResponseContext::HasEvents(ClassMask m) +{ + if(m.class1 && mBuffer.HasClassData(PC_CLASS_1)) return true; + if(m.class2 && mBuffer.HasClassData(PC_CLASS_2)) return true; + if(m.class3 && mBuffer.HasClassData(PC_CLASS_3)) return true; + + return false; +} + +bool AsyncResponseContext::LoadUnsol(APDU& arAPDU, const IINField& arIIN, ClassMask m) +{ + this->SelectUnsol(m); + + arAPDU.Set(FC_UNSOLICITED_RESPONSE, true, true, true, true); + bool events = false; + this->LoadEventData(arAPDU, events); + return events; +} + +bool AsyncResponseContext::LoadStaticData(APDU& arAPDU) +{ + if(!this->LoadStaticBinaries(arAPDU)) return false; + if(!this->LoadStaticCounters(arAPDU)) return false; + if(!this->LoadStaticAnalogs(arAPDU)) return false; + if(!this->LoadStaticControlStatii(arAPDU)) return false; + if(!this->LoadStaticSetpointStatii(arAPDU)) return false; + + return true; +} + +bool AsyncResponseContext::LoadEventData(APDU& arAPDU, bool& arEventsLoaded) +{ + if(!this->LoadEvents(arAPDU, mBinaryEvents, arEventsLoaded)) return false; + if(!this->LoadEvents(arAPDU, mAnalogEvents, arEventsLoaded)) return false; + if(!this->LoadEvents(arAPDU, mCounterEvents, arEventsLoaded)) return false; + + return true; +} + +bool AsyncResponseContext::IsEmpty() +{ + return this->IsStaticEmpty() && this->IsEventEmpty(); +} + +bool AsyncResponseContext::IsStaticEmpty() +{ + return this->mStaticBinaries.empty() && this->mStaticCounters.empty() && + this->mStaticAnalogs.empty() && this->mStaticControls.empty() && + this->mStaticSetpoints.empty(); +} + +bool AsyncResponseContext::IsEventEmpty() +{ + // are there unwritten events in the selection buffer? + return mBuffer.NumSelected() == 0; +} + +void AsyncResponseContext::FinalizeResponse(APDU& arAPDU, bool aHasEventData, bool aFIN) +{ + mFIN = aFIN; + bool confirm = !aFIN || aHasEventData; + arAPDU.SetControl(mFIR, mFIN, confirm); + mFIR = false; +} + +bool AsyncResponseContext::LoadStaticBinaries(APDU& arAPDU) +{ + while(!mStaticBinaries.empty()) + { + IterRecord& iter = this->mStaticBinaries.front(); + int grp = iter.pObject->GetGroup(); + int var = iter.pObject->GetVariation(); + + switch(MACRO_DNP_RADIX(grp, var)) + { + //special case for the bitfield + /*case(MACRO_DNP_RADIX(1,1)): + { + WriteFunc::Type func = bind(&Group1Var1::Write, Group1Var1::Inst(), _1, iter.first->mIndex, _3, _2); + if(!this->IterateContiguous(iter, arAPDU, func)) return false; + break; + }*/ + + MACRO_CONTINUOUS_CASE(1,2); + + default: + break; + } + + this->mStaticBinaries.pop_front(); + } + + return true; +} + +bool AsyncResponseContext::LoadStaticAnalogs(APDU& arAPDU) +{ + while(!mStaticAnalogs.empty()) + { + IterRecord& iter = this->mStaticAnalogs.front(); + int grp = iter.pObject->GetGroup(); + int var = iter.pObject->GetVariation(); + + switch(MACRO_DNP_RADIX(grp, var)) + { + MACRO_CONTINUOUS_CASE(30,1); + MACRO_CONTINUOUS_CASE(30,2); + MACRO_CONTINUOUS_CASE(30,3); + MACRO_CONTINUOUS_CASE(30,4); + MACRO_CONTINUOUS_CASE(30,5); + MACRO_CONTINUOUS_CASE(30,6); + + default: + break; + } + + this->mStaticAnalogs.pop_front(); + } + + return true; +} + +bool AsyncResponseContext::LoadStaticCounters(APDU& arAPDU) +{ + while(!mStaticCounters.empty()) + { + IterRecord& iter = this->mStaticCounters.front(); + int grp = iter.pObject->GetGroup(); + int var = iter.pObject->GetVariation(); + + // Delta counters omitted + switch(MACRO_DNP_RADIX(grp, var)) + { + MACRO_CONTINUOUS_CASE(20,1); + MACRO_CONTINUOUS_CASE(20,2); + MACRO_CONTINUOUS_CASE(20,5); + MACRO_CONTINUOUS_CASE(20,6); + + default: + break; + } + + this->mStaticCounters.pop_front(); + } + + return true; +} + +bool AsyncResponseContext::LoadStaticControlStatii(APDU& arAPDU) +{ + while(!mStaticControls.empty()) + { + IterRecord& iter = this->mStaticControls.front(); + int grp = iter.pObject->GetGroup(); + int var = iter.pObject->GetVariation(); + + switch(MACRO_DNP_RADIX(grp, var)) + { + MACRO_CONTINUOUS_CASE(10,2); + + default: + break; + } + + this->mStaticControls.pop_front(); + } + + return true; +} + +/* +bool AsyncResponseContext::WriteCTO(const TimeStamp_t& arTime, APDU& arAPDU) +{ + Group51Var1* pObj = Group51Var1::Inst(); + ObjectWriteIterator owi = arAPDU.WriteContiguous(pObj, 0, 0); + if(owi.IsEnd()) return false; + pObj->mTime.Set(*owi, arTime); + return true; +}*/ + +bool AsyncResponseContext::LoadStaticSetpointStatii(APDU& arAPDU) +{ + while(!mStaticSetpoints.empty()) + { + IterRecord& iter = this->mStaticSetpoints.front(); + int grp = iter.pObject->GetGroup(); + int var = iter.pObject->GetVariation(); + + switch(MACRO_DNP_RADIX(grp, var)) + { + MACRO_CONTINUOUS_CASE(40,1); + MACRO_CONTINUOUS_CASE(40,2); + MACRO_CONTINUOUS_CASE(40,3); + MACRO_CONTINUOUS_CASE(40,4); + + default: + break; + } + + this->mStaticSetpoints.pop_front(); + } + + return true; +} + +void AsyncResponseContext::AddIntegrityPoll() +{ + this->AddIntegrity(mStaticBinaries, mpRspTypes->mpStaticBinary); + this->AddIntegrity(mStaticAnalogs, mpRspTypes->mpStaticAnalog); + this->AddIntegrity(mStaticCounters, mpRspTypes->mpStaticCounter); + this->AddIntegrity(mStaticControls, mpRspTypes->mpStaticControlStatus); + this->AddIntegrity(mStaticSetpoints, mpRspTypes->mpStaticSetpointStatus); +} + +}} + diff --git a/DNP3/AsyncResponseContext.h b/DNP3/AsyncResponseContext.h index 39fa5ddc..5f40b299 100644 --- a/DNP3/AsyncResponseContext.h +++ b/DNP3/AsyncResponseContext.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_RESPONSE_CONTEXT_H_ #define __ASYNC_RESPONSE_CONTEXT_H_ @@ -47,7 +47,7 @@ struct WriteFunc /** Builds and tracks the state of responses. Interprets FC_READ requests or can be prompted for an unsolicited response fragment. - Coordinates the AsyncDatabase and AsyncSlaveEventBuffer. + Coordinates the AsyncDatabase and AsyncSlaveEventBuffer. */ class AsyncResponseContext : public Loggable { @@ -63,7 +63,7 @@ class AsyncResponseContext : public Loggable Mode GetMode() { return mMode; } IAsyncEventBuffer* GetBuffer() { return &mBuffer; } - + /// Setup the response context with a new read request IINField Configure(const APDU& arRequest); @@ -76,7 +76,7 @@ class AsyncResponseContext : public Loggable current state of the event buffer */ bool LoadUnsol(APDU&, const IINField& arIIN, ClassMask aMask); - + /// @return TRUE is all of the response data has already been written bool IsComplete() { return IsEmpty(); } @@ -88,22 +88,22 @@ class AsyncResponseContext : public Loggable /// Clear written events and reset the state of the object void ClearAndReset(); - + private: - + // configure the state for unsol, return true of events exist bool SelectUnsol(ClassMask aMask); - + AsyncSlaveEventBuffer mBuffer; - Mode mMode; + Mode mMode; /// @return TRUE if all of the data has been written bool LoadStaticData(APDU&); - + /** @param arEventsLoaded Set to true if events were written to the APDU @param arAPDU Events are loaded into this fragment @return TRUE if all of the data has been written @@ -119,8 +119,8 @@ class AsyncResponseContext : public Loggable void AddIntegrityPoll(); //bool WriteCTO(const TimeStamp_t& arTime, APDU& arAPDU); - - AsyncDatabase* mpDB; /// Pointer to the database for static data + + AsyncDatabase* mpDB; /// Pointer to the database for static data bool mFIR; bool mFIN; SlaveResponseTypes* mpRspTypes; @@ -131,7 +131,7 @@ class AsyncResponseContext : public Loggable struct IterRecord { IterRecord() : pObject(NULL) {} - + typename StaticIter::Type first; /// Begining of iteration typename StaticIter::Type last; /// Last element of iteration StreamObject* pObject; /// Type to use to write @@ -144,10 +144,10 @@ class AsyncResponseContext : public Loggable pObj(apObj), count(aCount) {} - + const StreamObject* pObj; /// Type to use to write size_t count; /// Number of events to read - + }; typedef std::deque< IterRecord > BinaryIterQueue; @@ -159,7 +159,7 @@ class AsyncResponseContext : public Loggable typedef std::deque< EventRequest > BinaryEventQueue; typedef std::deque< EventRequest > AnalogEventQueue; typedef std::deque< EventRequest > CounterEventQueue; - + //these queues track what static point ranges were requested so that we can split the response over multiple fragments BinaryIterQueue mStaticBinaries; AnalogIterQueue mStaticAnalogs; @@ -196,7 +196,7 @@ class AsyncResponseContext : public Loggable template bool IterateContiguous(IterRecord& arIters, APDU& arAPDU); - // T is the event type + // T is the event type template size_t IterateIndexed(EventRequest& arIters, typename EvtItr< EventInfo >::Type& arIter, APDU& arAPDU); @@ -243,16 +243,16 @@ bool AsyncResponseContext::LoadEvents(APDU& arAPDU, std::deque< EventRequest EventRequest& r = arQueue.front(); // how many were requested if(r.count > remain) r.count = remain; - + size_t written = r.pObj->UseCTO() ? this->IterateCTO(r.pObj, r.count, itr, arAPDU) : this->IterateIndexed(r, itr, arAPDU); remain -= written; if(written > 0) arEventsLoaded = true; // at least 1 event was loaded - - if(written == r.count) arQueue.pop_front(); // all events written, we're done with this request - else { //incomplete write + + if(written == r.count) arQueue.pop_front(); // all events written, we're done with this request + else { //incomplete write r.count -= written; - return false; + return false; } } @@ -267,16 +267,16 @@ bool AsyncResponseContext::IterateContiguous(IterRecord& arIters, APDU& arAPD size_t stop = arIters.last->mIndex; ObjectWriteIterator owi = arAPDU.WriteContiguous(arIters.pObject, start, stop); - + for(size_t i=start; i<=stop; ++i) - { + { if(owi.IsEnd()) return false; // out of space in the fragment - arWriter(*owi, arIters.first->mValue, i); + arWriter(*owi, arIters.first->mValue, i); ++arIters.first; //increment the iterators ++owi; } - return true; + return true; }*/ template @@ -285,13 +285,13 @@ bool AsyncResponseContext::IterateContiguous(IterRecord& arIters, APDU& arAPD size_t start = arIters.first->mIndex; size_t stop = arIters.last->mIndex; StreamObject* pObj = arIters.pObject; - + ObjectWriteIterator owi = arAPDU.WriteContiguous(arIters.pObject, start, stop); - + for(size_t i=start; i<=stop; ++i) - { - if(owi.IsEnd()) return false; // out of space in the fragment - pObj->Write(*owi, arIters.first->mValue); + { + if(owi.IsEnd()) return false; // out of space in the fragment + pObj->Write(*owi, arIters.first->mValue); ++arIters.first; //increment the iterators ++owi; } @@ -306,11 +306,11 @@ bool AsyncResponseContext::IterateContiguous(IterRecord& arIters, APDU& arAPD template size_t AsyncResponseContext::IterateIndexed(EventRequest& arRequest, typename EvtItr< EventInfo >::Type& arIter, APDU& arAPDU) { - size_t max_index = mpDB->MaxIndex(T::MeasEnum); + size_t max_index = mpDB->MaxIndex(T::MeasEnum); IndexedWriteIterator write = arAPDU.WriteIndexed(arRequest.pObj, arRequest.count, max_index); - + for(size_t i = 0; i < arRequest.count; ++i) - { + { if(write.IsEnd()) return i; //that's all we can get into this fragment write.SetIndex(arIter->mIndex); @@ -354,12 +354,12 @@ size_t AsyncResponseContext::IterateCTO(const StreamObject* apObj, size_t aCo // predetermine how many results you're going to be able to fit given the time differences size_t num = this->CalcPossibleCTO(arIter, aCount); IndexedWriteIterator write = arAPDU.WriteIndexed(apObj, num, max_index); //start the object write - + for(size_t i = 0; i < num; ++i) - { + { if(write.IsEnd()) return i; // that's all we can get into this fragment - T tmp = arIter->mValue; // make a copy and adjust the time + T tmp = arIter->mValue; // make a copy and adjust the time tmp.SetTime(tmp.GetTime()-start); write.SetIndex(arIter->mIndex); diff --git a/DNP3/AsyncSlave.h b/DNP3/AsyncSlave.h index 613a7857..d8124f71 100644 --- a/DNP3/AsyncSlave.h +++ b/DNP3/AsyncSlave.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_SLAVE_H_ #define __ASYNC_SLAVE_H_ @@ -45,11 +45,11 @@ namespace apl { namespace dnp { class AS_Base; -/** @section desc DNP3 outstation. +/** @section desc DNP3 outstation. Manages a state machine that handles events from the user layer and the application layer to provide DNP outstation services. - ResponseContext and AsyncSlaveEventBuffer objects manage data/event responses to master requests, and the IDNPCommandMaster + ResponseContext and AsyncSlaveEventBuffer objects manage data/event responses to master requests, and the IDNPCommandMaster implementation verifies control/setpoint behavior and passes valid commands to the user code. SlaveConfig structure represents the slave behavioral configuration, the AsyncDatabase is in charge of the data model itself. @@ -87,11 +87,11 @@ class AsyncSlave : public Loggable, public IAsyncAppUser void OnUnsolFailure(); void OnSolFailure(); - + // Only have to override OnRequest since we're a slave void OnRequest(const APDU&, SequenceInfo); void OnUnknownObject(); - + /////////////////////////////////// // End - External events /////////////////////////////////// @@ -101,12 +101,12 @@ class AsyncSlave : public Loggable, public IAsyncAppUser IDataObserver* GetDataObserver() { return &mChangeBuffer; } private: - + ChangeBuffer mChangeBuffer; /// how client code gives us updates PostingNotifierSource mNotifierSource; /// way to get special notifiers for the change queue / vto IAsyncAppLayer* mpAppLayer; /// lower application layer ITimerSource* mpTimerSrc; /// used for post and timers - AsyncDatabase* mpDatabase; /// holds static data + AsyncDatabase* mpDatabase; /// holds static data IDNPCommandMaster* mpCmdMaster; /// how commands are selected/operated int mSequence; /// control sequence CommandResponseQueue mRspQueue; /// how command responses are received @@ -115,7 +115,7 @@ class AsyncSlave : public Loggable, public IAsyncAppUser SlaveResponseTypes mRspTypes; /// converts the group/var in the config to dnp singletons ITimer* mpUnsolTimer; /// timer for sending unsol responsess - + IINField mIIN; /// IIN bits that persist between requests (i.e. NeedsTime/Restart/Etc) IINField mRspIIN; /// Transient IIN bits that get merged before a response is issued APDU mResponse; /// APDU used to form responses @@ -129,14 +129,14 @@ class AsyncSlave : public Loggable, public IAsyncAppUser ITimeManager* mpTime; - // Flags that tell us that some action has been Deferred + // Flags that tell us that some action has been Deferred // until the slave is in a state capable of handling it. - + bool mDeferredUpdate; /// Indicates that a data update has been Deferred bool mDeferredRequest; /// Indicates that a request has been Deferred bool mDeferredUnsol; /// Indicates that the unsol timer expired, but the event was Deferred bool mDeferredUnknown; - + bool mStartupNullUnsol; /// Tracks whether the device has completed the NULL unsol startup message void OnDataUpdate(); /// internal event dispatched when user code commits an update to mChangeBuffer @@ -154,15 +154,15 @@ class AsyncSlave : public Loggable, public IAsyncAppUser void HandleOperate(const APDU& arRequest, SequenceInfo aSeqInfo); void HandleDirectOperate(const APDU& arRequest, SequenceInfo aSeqInfo); void HandleEnableUnsolicited(const APDU& arRequest, bool aIsEnable); - void HandleUnknown(); - - + void HandleUnknown(); + + void ConfigureDelayMeasurement(const APDU& arRequest); void CreateResponseContext(const APDU& arRequest); // Helpers - size_t FlushUpdates(); + size_t FlushUpdates(); void FlushDeferredEvents(); void StartUnsolTimer(millis_t aTimeout); @@ -218,7 +218,7 @@ void AsyncSlave::RespondToCommands(const StreamObject* apObj, ObjectReadItera template CommandStatus AsyncSlave::Select(T& arCmd, size_t aIndex, const HeaderInfo& aHdr, SequenceInfo aSeqInfo, int aAPDUSequence) -{ +{ CommandStatus res = mpCmdMaster->Select(CommandRequestInfo(arCmd, aHdr.GetObjectType(), aHdr.GetVariation(), aHdr.GetQualifier(), aSeqInfo, aAPDUSequence), aIndex) ? CS_SUCCESS : CS_NOT_SUPPORTED; LOG_BLOCK(LEV_INFO, "Selecting " << arCmd.ToString() << " Index: " << aIndex << " Result: " << ToString(res)); if ( res == CS_NOT_SUPPORTED ) diff --git a/DNP3/AsyncSlaveEventBuffer.h b/DNP3/AsyncSlaveEventBuffer.h index 23233e39..ddb67af2 100644 --- a/DNP3/AsyncSlaveEventBuffer.h +++ b/DNP3/AsyncSlaveEventBuffer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_SLAVE_EVENT_BUFFER_H_ #define __ASYNC_SLAVE_EVENT_BUFFER_H_ @@ -27,8 +27,8 @@ namespace apl { namespace dnp { - /** Manager for DNP3 data events composed of per-type event buffer implementations. Events are selected based on - classification (data type, class) and then read using an iterator system. The behavior is transactional such that + /** Manager for DNP3 data events composed of per-type event buffer implementations. Events are selected based on + classification (data type, class) and then read using an iterator system. The behavior is transactional such that failed deliveries put events back into the buffer. All selections can be limited by a desired event count. @@ -54,14 +54,14 @@ class AsyncSlaveEventBuffer : public IAsyncEventBuffer bool IsOverflow(); bool HasClassData(PointClass aClass); bool HasEventData(); - + size_t Select(DataTypes aType, PointClass aClass, size_t aMaxEvent = std::numeric_limits::max()); size_t Select(PointClass aClass, size_t aMaxEvent = std::numeric_limits::max()); - + /// Put all selected events back into the event buffer void Deselect(); void ClearWritten(); - + private: AsyncTimeOrderedEventBuffer mBinaryEvents; /// Multiple events for the same time, ordered by time of occurrence diff --git a/DNP3/AsyncSlaveStack.h b/DNP3/AsyncSlaveStack.h index 1f5c1c24..7d5736ec 100644 --- a/DNP3/AsyncSlaveStack.h +++ b/DNP3/AsyncSlaveStack.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,51 +6,51 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_SLAVE_STACK_H_ -#define __ASYNC_SLAVE_STACK_H_ - -#include "AsyncStack.h" -#include "AsyncSlave.h" -#include "AsyncDatabase.h" -#include "DNPCommandMaster.h" -#include "SlaveStackConfig.h" -#include - -namespace apl { namespace dnp { - -/** @section desc A stack object for a master */ -class AsyncSlaveStack : public AsyncStack -{ - public: - - /** - @param apLogger Logger used by the stack - @param apTimerSrc Timer source used by the slave for asynchronous eventing - @param apCmdAcceptor Command acceptor interface used for dispatching commands to the outside world - @param arCfg Configuration struct that holds parameters for the stack - */ - AsyncSlaveStack( - Logger* apLogger, - ITimerSource* apTimerSrc, - ICommandAcceptor* apCmdAcceptor, - const SlaveStackConfig& arCfg); - - TimeSourceSystemOffset mTimeSource; - AsyncDatabase mDB; /// The database holds static event data and forwards to an event buffer - DNPCommandMaster mCmdMaster; /// Controls the execution of commands - AsyncSlave mSlave; /// The dnp3 outstation class -}; - -}} - -#endif +// +#ifndef __ASYNC_SLAVE_STACK_H_ +#define __ASYNC_SLAVE_STACK_H_ + +#include "AsyncStack.h" +#include "AsyncSlave.h" +#include "AsyncDatabase.h" +#include "DNPCommandMaster.h" +#include "SlaveStackConfig.h" +#include + +namespace apl { namespace dnp { + +/** @section desc A stack object for a master */ +class AsyncSlaveStack : public AsyncStack +{ + public: + + /** + @param apLogger Logger used by the stack + @param apTimerSrc Timer source used by the slave for asynchronous eventing + @param apCmdAcceptor Command acceptor interface used for dispatching commands to the outside world + @param arCfg Configuration struct that holds parameters for the stack + */ + AsyncSlaveStack( + Logger* apLogger, + ITimerSource* apTimerSrc, + ICommandAcceptor* apCmdAcceptor, + const SlaveStackConfig& arCfg); + + TimeSourceSystemOffset mTimeSource; + AsyncDatabase mDB; /// The database holds static event data and forwards to an event buffer + DNPCommandMaster mCmdMaster; /// Controls the execution of commands + AsyncSlave mSlave; /// The dnp3 outstation class +}; + +}} + +#endif diff --git a/DNP3/AsyncSlaveStates.h b/DNP3/AsyncSlaveStates.h index 2f51b796..0821ac8b 100644 --- a/DNP3/AsyncSlaveStates.h +++ b/DNP3/AsyncSlaveStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_SLAVE_STATES_H_ #define __ASYNC_SLAVE_STATES_H_ @@ -25,9 +25,9 @@ #include #include -namespace apl +namespace apl { - class ITaskCompletion; + class ITaskCompletion; class Logger; class BinaryOutput; class Setpoint; @@ -38,7 +38,7 @@ namespace apl { namespace dnp { class AsyncSlave; class APDU; -/** @section desc +/** @section desc Base class for all slave transaction states */ class AS_Base @@ -87,8 +87,8 @@ class AS_Base void ChangeState(AsyncSlave*, AS_Base*); }; -/** @section desc -The application layer has not informed the slave yet that it is up +/** @section desc +The application layer has not informed the slave yet that it is up */ class AS_Closed : public AS_Base { @@ -106,14 +106,14 @@ class AS_OpenBase : public AS_Base void OnLowerLayerDown(AsyncSlave*); }; -/** @section desc -The app layer is online, but the slave is not doing or waiting on anything +/** @section desc +The app layer is online, but the slave is not doing or waiting on anything */ class AS_Idle : public AS_OpenBase { MACRO_STATE_SINGLETON_INSTANCE(AS_Idle); - void OnRequest(AsyncSlave*, const APDU&, SequenceInfo); + void OnRequest(AsyncSlave*, const APDU&, SequenceInfo); void OnDataUpdate(AsyncSlave*); void OnUnsolExpiration(AsyncSlave*); void OnUnknown(AsyncSlave*); @@ -125,7 +125,7 @@ class AS_Idle : public AS_OpenBase }; -/** @section desc +/** @section desc The slave is waiting for a response to complete */ class AS_WaitForRspSuccess : public AS_OpenBase @@ -137,7 +137,7 @@ class AS_WaitForRspSuccess : public AS_OpenBase void OnSolSendSuccess(AsyncSlave*); }; -/** @section desc +/** @section desc The slave is waiting for an unsolicited response to complete */ class AS_WaitForUnsolSuccess : public AS_OpenBase @@ -146,10 +146,10 @@ class AS_WaitForUnsolSuccess : public AS_OpenBase void OnRequest(AsyncSlave*, const APDU&, SequenceInfo); void OnUnsolFailure(AsyncSlave*); - void OnUnsolSendSuccess(AsyncSlave*); + void OnUnsolSendSuccess(AsyncSlave*); }; -/** @section desc +/** @section desc The slave is waiting for an unsolicited response and a solicited response to complete */ class AS_WaitForSolUnsolSuccess : public AS_OpenBase @@ -160,7 +160,7 @@ class AS_WaitForSolUnsolSuccess : public AS_OpenBase void OnSolFailure(AsyncSlave*); void OnSolSendSuccess(AsyncSlave*); void OnUnsolFailure(AsyncSlave*); - void OnUnsolSendSuccess(AsyncSlave*); + void OnUnsolSendSuccess(AsyncSlave*); }; diff --git a/DNP3/AsyncStack.cpp b/DNP3/AsyncStack.cpp index 7b409be2..3fe08e31 100644 --- a/DNP3/AsyncStack.cpp +++ b/DNP3/AsyncStack.cpp @@ -16,20 +16,20 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncStack.h" - -#include - -namespace apl { namespace dnp { - -AsyncStack::AsyncStack(Logger* apLogger, ITimerSource* apTimerSrc, AppConfig aAppCfg, LinkConfig aCfg) : -mLink(apLogger->GetSubLogger("link"), apTimerSrc, aCfg), -mTransport(apLogger->GetSubLogger("transport")), -mApplication(apLogger->GetSubLogger("app"), apTimerSrc, aAppCfg) -{ - mLink.SetUpperLayer(&mTransport); - mTransport.SetUpperLayer(&mApplication); -} - -}} - +#include "AsyncStack.h" + +#include + +namespace apl { namespace dnp { + +AsyncStack::AsyncStack(Logger* apLogger, ITimerSource* apTimerSrc, AppConfig aAppCfg, LinkConfig aCfg) : +mLink(apLogger->GetSubLogger("link"), apTimerSrc, aCfg), +mTransport(apLogger->GetSubLogger("transport")), +mApplication(apLogger->GetSubLogger("app"), apTimerSrc, aAppCfg) +{ + mLink.SetUpperLayer(&mTransport); + mTransport.SetUpperLayer(&mApplication); +} + +}} + diff --git a/DNP3/AsyncStack.h b/DNP3/AsyncStack.h index 5ad0e856..abed474e 100644 --- a/DNP3/AsyncStack.h +++ b/DNP3/AsyncStack.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,41 +6,41 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_STACK_H_ -#define __ASYNC_STACK_H_ - -#include "AsyncLinkLayer.h" -#include "AsyncTransportLayer.h" -#include "AsyncAppLayer.h" - -namespace apl { -class Logger; -class ITimerSource; -} - -namespace apl { namespace dnp { - -class AsyncStack -{ - public: - AsyncStack(Logger*, ITimerSource* apTimerSrc, AppConfig aAppCfg, LinkConfig aCfg); - virtual ~AsyncStack() {} - - AsyncLinkLayer mLink; - AsyncTransportLayer mTransport; - AsyncAppLayer mApplication; -}; - -}} - -#endif +// +#ifndef __ASYNC_STACK_H_ +#define __ASYNC_STACK_H_ + +#include "AsyncLinkLayer.h" +#include "AsyncTransportLayer.h" +#include "AsyncAppLayer.h" + +namespace apl { +class Logger; +class ITimerSource; +} + +namespace apl { namespace dnp { + +class AsyncStack +{ + public: + AsyncStack(Logger*, ITimerSource* apTimerSrc, AppConfig aAppCfg, LinkConfig aCfg); + virtual ~AsyncStack() {} + + AsyncLinkLayer mLink; + AsyncTransportLayer mTransport; + AsyncAppLayer mApplication; +}; + +}} + +#endif diff --git a/DNP3/AsyncStackManager.cpp b/DNP3/AsyncStackManager.cpp index 66c64b29..7e7cdc13 100644 --- a/DNP3/AsyncStackManager.cpp +++ b/DNP3/AsyncStackManager.cpp @@ -16,226 +16,226 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "AsyncStackManager.h" -#include "AsyncPort.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -using namespace std; - -namespace apl { namespace dnp { - -AsyncStackManager::AsyncStackManager(Logger* apLogger, bool aAutoRun) : -Loggable(apLogger), -mRunASIO(aAutoRun), -mRunning(false), -mService(), -mTimerSrc(mService.Get()), -mMgr(apLogger->GetSubLogger("ports", LEV_WARNING), false), // the false here is important!!! -mScheduler(&mTimerSrc), // it means that any layer we retrieve from the manager, we will delete -mThread(this) -{ - -} - -AsyncStackManager::~AsyncStackManager() -{ - this->Stop(); // tell every port to stop, join on the thread - this->Run(); // run out the io_service, to make sure all the deletes are called, if the io_service wasn't running -} - -std::vector AsyncStackManager::GetStackNames() { return GetKeys(mStackToPort); } -std::vector AsyncStackManager::GetPortNames() { return GetKeys(mPortToPort); } - -void AsyncStackManager::AddTCPClient(const std::string& arName, PhysLayerSettings aSettings, const std::string& arAddr, uint_16_t aPort) -{ - mMgr.AddTCPClient(arName, aSettings, arAddr, aPort); -} - -void AsyncStackManager::AddTCPServer(const std::string& arName, PhysLayerSettings aSettings, uint_16_t aPort) -{ - mMgr.AddTCPServer(arName, aSettings, aPort); -} - -void AsyncStackManager::AddSerial(const std::string& arName, PhysLayerSettings aSettings, SerialSettings aSerial) -{ - mMgr.AddSerial(arName, aSettings, aSerial); -} - -ICommandAcceptor* AsyncStackManager::AddMaster( const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, IDataObserver* apPublisher, - const MasterStackConfig& arCfg) -{ - AsyncPort* pPort = this->AllocatePort(arPortName); - Logger* pLogger = mpLogger->GetSubLogger(arStackName, aLevel); - AsyncMasterStack* pMaster = new AsyncMasterStack(pLogger, &mTimerSrc, apPublisher, pPort->GetGroup(), arCfg); - this->OnAddStack(arStackName, pMaster, pPort, arCfg.link.LocalAddr); - return pMaster->mMaster.GetCmdAcceptor(); -} - -IDataObserver* AsyncStackManager::AddSlave( const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, ICommandAcceptor* apCmdAcceptor, - const SlaveStackConfig& arCfg) -{ - AsyncPort* pPort = this->AllocatePort(arPortName); - Logger* pLogger = mpLogger->GetSubLogger(arStackName, aLevel); - AsyncSlaveStack* pSlave = new AsyncSlaveStack(pLogger, &mTimerSrc, apCmdAcceptor, arCfg); - this->OnAddStack(arStackName, pSlave, pPort, arCfg.link.LocalAddr); - return pSlave->mSlave.GetDataObserver(); -} - -/// Remove a port and all associated stacks -void AsyncStackManager::RemovePort(const std::string& arPortName) -{ - AsyncPort* pPort = this->GetPort(arPortName); - vector stacks = this->StacksOnPort(arPortName); - BOOST_FOREACH(string s, stacks) { this->SeverStack(pPort, s); } - mPortToPort.erase(arPortName); - - mScheduler.Sever(pPort->GetGroup()); // this tells the scheduler that we'll delete the group - mTimerSrc.Post(boost::bind(&AsyncPort::Release, pPort)); - - // remove the physical layer from the list - // The ports own the layers themselves, so deleting the port will delete the layer - mMgr.Remove(arPortName); - - this->CheckForJoin(); -} - -std::vector AsyncStackManager::StacksOnPort(const std::string& arPortName) -{ - std::vector ret; - for(PortMap::iterator i = this->mStackToPort.begin(); i!=mStackToPort.end(); ++i) { - if(i->second->Name() == arPortName) ret.push_back(i->first); - } - return ret; -} - -void AsyncStackManager::RemoveStack(const std::string& arStackName) -{ - AsyncPort* pPort = this->GetPortByStackName(arStackName); - this->SeverStack(pPort, arStackName); - this->CheckForJoin(); -} - -void AsyncStackManager::SeverStack(AsyncPort* apPort, const std::string& arStackName) -{ - mTimerSrc.Post(boost::bind(&AsyncPort::Disassociate, apPort, arStackName)); - mStackToPort.erase(arStackName); -} - -AsyncPort* AsyncStackManager::GetPortByStackName(const std::string& arStackName) -{ - PortMap::iterator i = mStackToPort.find(arStackName); - if(i == mStackToPort.end()) throw ArgumentException(LOCATION, "Unknown stack"); - return i->second; -} - -void AsyncStackManager::Stop() -{ - LOG_BLOCK(LEV_DEBUG, "enter stop"); - vector ports = this->GetPortNames(); - BOOST_FOREACH(string s, ports) { - LOG_BLOCK(LEV_DEBUG, "Removing port: " << s); - this->RemovePort(s); - LOG_BLOCK(LEV_DEBUG, "Done removing Port: " << s); - } - if(mRunning) { - LOG_BLOCK(LEV_DEBUG, "Joining on io_service thread"); - mThread.WaitForStop(); - mRunning = false; - LOG_BLOCK(LEV_DEBUG, "Done joining"); - } - LOG_BLOCK(LEV_DEBUG, "exit stop"); -} - -void AsyncStackManager::Start() -{ - if(this->NumStacks() > 0 && !mRunning) { - mRunning = true; - mThread.Start(); - } -} - -AsyncPort* AsyncStackManager::AllocatePort(const std::string& arName) -{ - AsyncPort* pPort = this->GetPortPointer(arName); - if(pPort == NULL) { - PhysLayerSettings s = mMgr.GetSettings(arName); - IPhysicalLayerAsync* pPhys = mMgr.GetLayer(arName, mService.Get()); - pPort = this->CreatePort(arName, pPhys, mpLogger->GetSubLogger(arName, s.LogLevel), s.RetryTimeout); - } - return pPort; -} - -AsyncPort* AsyncStackManager::GetPort(const std::string& arName) -{ - AsyncPort* pPort = this->GetPortPointer(arName); - if(pPort == NULL) throw ArgumentException(LOCATION, "Port doesn't exist"); - return pPort; -} - - -AsyncPort* AsyncStackManager::CreatePort(const std::string& arName, IPhysicalLayerAsync* apPhys, Logger* apLogger, millis_t aOpenDelay) -{ - if(GetPortPointer(arName) != NULL) throw ArgumentException(LOCATION, "Port already exists"); - AsyncPort* pPort = new AsyncPort(arName, apLogger, mScheduler.NewGroup(), &mTimerSrc, apPhys, aOpenDelay); - mPortToPort[arName] = pPort; - return pPort; -} - -AsyncPort* AsyncStackManager::GetPortPointer(const std::string& arName) -{ - PortMap::iterator i = mPortToPort.find(arName); - return (i==mPortToPort.end()) ? NULL : i->second; -} - -void AsyncStackManager::Run() -{ - size_t num = 0; - - do { - try { - num = mService.Get()->run(); - } - catch(const std::exception& ex) { - std::cout << "Unhandled exception: " << ex.what() << std::endl; - } - } - while(num > 0); - - mService.Get()->reset(); -} - -void AsyncStackManager::OnAddStack(const std::string& arStackName, AsyncStack* apStack, AsyncPort* apPort, uint_16_t aAddress) -{ - // marshall the linking to the io_service - mStackToPort[arStackName] = apPort; //map the stack to a portname - mTimerSrc.Post(boost::bind(&AsyncPort::Associate, apPort, arStackName, apStack, aAddress)); - if(!mRunning && mRunASIO) { - mRunning = true; - mThread.Start(); - } -} - -void AsyncStackManager::CheckForJoin() -{ - if(mRunning && this->NumStacks() == 0) { - LOG_BLOCK(LEV_DEBUG, "Check For join: joining on io_service thread"); - mThread.WaitForStop(); //join on the thread, ASIO will exit when there's no more work to be done - mRunning = false; - LOG_BLOCK(LEV_DEBUG, "Check For join: complete"); - } -} - - -}} +#include +#include "AsyncStackManager.h" +#include "AsyncPort.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +using namespace std; + +namespace apl { namespace dnp { + +AsyncStackManager::AsyncStackManager(Logger* apLogger, bool aAutoRun) : +Loggable(apLogger), +mRunASIO(aAutoRun), +mRunning(false), +mService(), +mTimerSrc(mService.Get()), +mMgr(apLogger->GetSubLogger("ports", LEV_WARNING), false), // the false here is important!!! +mScheduler(&mTimerSrc), // it means that any layer we retrieve from the manager, we will delete +mThread(this) +{ + +} + +AsyncStackManager::~AsyncStackManager() +{ + this->Stop(); // tell every port to stop, join on the thread + this->Run(); // run out the io_service, to make sure all the deletes are called, if the io_service wasn't running +} + +std::vector AsyncStackManager::GetStackNames() { return GetKeys(mStackToPort); } +std::vector AsyncStackManager::GetPortNames() { return GetKeys(mPortToPort); } + +void AsyncStackManager::AddTCPClient(const std::string& arName, PhysLayerSettings aSettings, const std::string& arAddr, uint_16_t aPort) +{ + mMgr.AddTCPClient(arName, aSettings, arAddr, aPort); +} + +void AsyncStackManager::AddTCPServer(const std::string& arName, PhysLayerSettings aSettings, uint_16_t aPort) +{ + mMgr.AddTCPServer(arName, aSettings, aPort); +} + +void AsyncStackManager::AddSerial(const std::string& arName, PhysLayerSettings aSettings, SerialSettings aSerial) +{ + mMgr.AddSerial(arName, aSettings, aSerial); +} + +ICommandAcceptor* AsyncStackManager::AddMaster( const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, IDataObserver* apPublisher, + const MasterStackConfig& arCfg) +{ + AsyncPort* pPort = this->AllocatePort(arPortName); + Logger* pLogger = mpLogger->GetSubLogger(arStackName, aLevel); + AsyncMasterStack* pMaster = new AsyncMasterStack(pLogger, &mTimerSrc, apPublisher, pPort->GetGroup(), arCfg); + this->OnAddStack(arStackName, pMaster, pPort, arCfg.link.LocalAddr); + return pMaster->mMaster.GetCmdAcceptor(); +} + +IDataObserver* AsyncStackManager::AddSlave( const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, ICommandAcceptor* apCmdAcceptor, + const SlaveStackConfig& arCfg) +{ + AsyncPort* pPort = this->AllocatePort(arPortName); + Logger* pLogger = mpLogger->GetSubLogger(arStackName, aLevel); + AsyncSlaveStack* pSlave = new AsyncSlaveStack(pLogger, &mTimerSrc, apCmdAcceptor, arCfg); + this->OnAddStack(arStackName, pSlave, pPort, arCfg.link.LocalAddr); + return pSlave->mSlave.GetDataObserver(); +} + +/// Remove a port and all associated stacks +void AsyncStackManager::RemovePort(const std::string& arPortName) +{ + AsyncPort* pPort = this->GetPort(arPortName); + vector stacks = this->StacksOnPort(arPortName); + BOOST_FOREACH(string s, stacks) { this->SeverStack(pPort, s); } + mPortToPort.erase(arPortName); + + mScheduler.Sever(pPort->GetGroup()); // this tells the scheduler that we'll delete the group + mTimerSrc.Post(boost::bind(&AsyncPort::Release, pPort)); + + // remove the physical layer from the list + // The ports own the layers themselves, so deleting the port will delete the layer + mMgr.Remove(arPortName); + + this->CheckForJoin(); +} + +std::vector AsyncStackManager::StacksOnPort(const std::string& arPortName) +{ + std::vector ret; + for(PortMap::iterator i = this->mStackToPort.begin(); i!=mStackToPort.end(); ++i) { + if(i->second->Name() == arPortName) ret.push_back(i->first); + } + return ret; +} + +void AsyncStackManager::RemoveStack(const std::string& arStackName) +{ + AsyncPort* pPort = this->GetPortByStackName(arStackName); + this->SeverStack(pPort, arStackName); + this->CheckForJoin(); +} + +void AsyncStackManager::SeverStack(AsyncPort* apPort, const std::string& arStackName) +{ + mTimerSrc.Post(boost::bind(&AsyncPort::Disassociate, apPort, arStackName)); + mStackToPort.erase(arStackName); +} + +AsyncPort* AsyncStackManager::GetPortByStackName(const std::string& arStackName) +{ + PortMap::iterator i = mStackToPort.find(arStackName); + if(i == mStackToPort.end()) throw ArgumentException(LOCATION, "Unknown stack"); + return i->second; +} + +void AsyncStackManager::Stop() +{ + LOG_BLOCK(LEV_DEBUG, "enter stop"); + vector ports = this->GetPortNames(); + BOOST_FOREACH(string s, ports) { + LOG_BLOCK(LEV_DEBUG, "Removing port: " << s); + this->RemovePort(s); + LOG_BLOCK(LEV_DEBUG, "Done removing Port: " << s); + } + if(mRunning) { + LOG_BLOCK(LEV_DEBUG, "Joining on io_service thread"); + mThread.WaitForStop(); + mRunning = false; + LOG_BLOCK(LEV_DEBUG, "Done joining"); + } + LOG_BLOCK(LEV_DEBUG, "exit stop"); +} + +void AsyncStackManager::Start() +{ + if(this->NumStacks() > 0 && !mRunning) { + mRunning = true; + mThread.Start(); + } +} + +AsyncPort* AsyncStackManager::AllocatePort(const std::string& arName) +{ + AsyncPort* pPort = this->GetPortPointer(arName); + if(pPort == NULL) { + PhysLayerSettings s = mMgr.GetSettings(arName); + IPhysicalLayerAsync* pPhys = mMgr.GetLayer(arName, mService.Get()); + pPort = this->CreatePort(arName, pPhys, mpLogger->GetSubLogger(arName, s.LogLevel), s.RetryTimeout); + } + return pPort; +} + +AsyncPort* AsyncStackManager::GetPort(const std::string& arName) +{ + AsyncPort* pPort = this->GetPortPointer(arName); + if(pPort == NULL) throw ArgumentException(LOCATION, "Port doesn't exist"); + return pPort; +} + + +AsyncPort* AsyncStackManager::CreatePort(const std::string& arName, IPhysicalLayerAsync* apPhys, Logger* apLogger, millis_t aOpenDelay) +{ + if(GetPortPointer(arName) != NULL) throw ArgumentException(LOCATION, "Port already exists"); + AsyncPort* pPort = new AsyncPort(arName, apLogger, mScheduler.NewGroup(), &mTimerSrc, apPhys, aOpenDelay); + mPortToPort[arName] = pPort; + return pPort; +} + +AsyncPort* AsyncStackManager::GetPortPointer(const std::string& arName) +{ + PortMap::iterator i = mPortToPort.find(arName); + return (i==mPortToPort.end()) ? NULL : i->second; +} + +void AsyncStackManager::Run() +{ + size_t num = 0; + + do { + try { + num = mService.Get()->run(); + } + catch(const std::exception& ex) { + std::cout << "Unhandled exception: " << ex.what() << std::endl; + } + } + while(num > 0); + + mService.Get()->reset(); +} + +void AsyncStackManager::OnAddStack(const std::string& arStackName, AsyncStack* apStack, AsyncPort* apPort, uint_16_t aAddress) +{ + // marshall the linking to the io_service + mStackToPort[arStackName] = apPort; //map the stack to a portname + mTimerSrc.Post(boost::bind(&AsyncPort::Associate, apPort, arStackName, apStack, aAddress)); + if(!mRunning && mRunASIO) { + mRunning = true; + mThread.Start(); + } +} + +void AsyncStackManager::CheckForJoin() +{ + if(mRunning && this->NumStacks() == 0) { + LOG_BLOCK(LEV_DEBUG, "Check For join: joining on io_service thread"); + mThread.WaitForStop(); //join on the thread, ASIO will exit when there's no more work to be done + mRunning = false; + LOG_BLOCK(LEV_DEBUG, "Check For join: complete"); + } +} + + +}} diff --git a/DNP3/AsyncStackManager.h b/DNP3/AsyncStackManager.h index 9582fcb0..7a1f252b 100644 --- a/DNP3/AsyncStackManager.h +++ b/DNP3/AsyncStackManager.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_STACK_MANAGER_H_ #define __ASYNC_STACK_MANAGER_H_ @@ -59,7 +59,7 @@ class AsyncStackManager : private Threadable, private Loggable public: /** @param apLogger - Logger to use for all other loggers - @param aAutoRun - Stacks begin execution immediately after being added + @param aAutoRun - Stacks begin execution immediately after being added */ AsyncStackManager(Logger* apLogger, bool aAutoRun = false); ~AsyncStackManager(); @@ -68,16 +68,16 @@ class AsyncStackManager : private Threadable, private Loggable /// Adds a TCPClient port, excepts if the port already exists void AddTCPClient(const std::string& arName, PhysLayerSettings, const std::string& arAddr, uint_16_t aPort); - + /// Adds a TCPServer port, excepts if the port already exists void AddTCPServer(const std::string& arName, PhysLayerSettings, uint_16_t aPort); - + /// Adds a Serial port, excepts if the port already exists void AddSerial(const std::string& arName, PhysLayerSettings, SerialSettings); /** Adds a master stack - Stack will automatically start running if Start() has been called or aAutoRun == true - + @param arPortName Unique name of the port to with which to associate the stack. Will except if port doesn't exist @param arStackName Unique name of the stack. Will except if the name already exists @param aLevel Log filter level to use @@ -85,15 +85,15 @@ class AsyncStackManager : private Threadable, private Loggable @param arCfg Configuration data for the master stack @return Threadsafe interface to use for dispatching commands to the master. */ - ICommandAcceptor* AddMaster(const std::string& arPortName, + ICommandAcceptor* AddMaster(const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, - IDataObserver* apPublisher, + IDataObserver* apPublisher, const MasterStackConfig& arCfg); /** Adds a slave stack - Stack will automatically start running if Start() has been called or aAutoRun == true - + @param arPortName Unique name of the port to with which to associate the stack. Will except if port doesn't exist @param arStackName Unique name of the stack. Will except if the name already exists @param aLevel Log filter level to use @@ -101,7 +101,7 @@ class AsyncStackManager : private Threadable, private Loggable @param arCfg Configuration data for the slave stack @return Threadsafe interface to use for writing new measurement values to the slave */ - IDataObserver* AddSlave(const std::string& arPortName, + IDataObserver* AddSlave(const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, ICommandAcceptor* apCmdAcceptor, @@ -118,21 +118,21 @@ class AsyncStackManager : private Threadable, private Loggable /// @return a vector of all the port names std::vector GetPortNames(); - + /// Start the thead if it isn't running void Start(); /// Stop the thread, doesn't delete anything until the stack manager destructs void Stop(); - + private: - + AsyncPort* AllocatePort(const std::string& arName); AsyncPort* CreatePort(const std::string& arName, IPhysicalLayerAsync* apPhys, Logger* apLogger, millis_t aOpenDelay); AsyncPort* GetPort(const std::string& arName); AsyncPort* GetPortByStackName(const std::string& arStackName); AsyncPort* GetPortPointer(const std::string& arName); - + void Run(); /// Remove a stack @@ -140,24 +140,24 @@ class AsyncStackManager : private Threadable, private Loggable void OnAddStack(const std::string& arStackName, AsyncStack* apStack, AsyncPort* apPort, uint_16_t aAddress); void CheckForJoin(); - + bool mRunASIO; - bool mRunning; + bool mRunning; size_t NumStacks() { return mStackToPort.size(); } std::vector StacksOnPort(const std::string& arPortName); - + protected: IOService mService; - TimerSourceASIO mTimerSrc; + TimerSourceASIO mTimerSrc; private: PhysicalLayerManager mMgr; AsyncTaskScheduler mScheduler; - Thread mThread; + Thread mThread; typedef std::map PortMap; - PortMap mStackToPort; /// maps a stack name a port instance + PortMap mStackToPort; /// maps a stack name a port instance PortMap mPortToPort; /// maps a port name to a port instance typedef std::map mPortCount; /// how many stacks per port diff --git a/DNP3/AsyncTransportLayer.h b/DNP3/AsyncTransportLayer.h index 30fadfb8..ad3cc432 100644 --- a/DNP3/AsyncTransportLayer.h +++ b/DNP3/AsyncTransportLayer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_TRANSPORT_LAYER_H_ #define __ASYNC_TRANSPORT_LAYER_H_ @@ -52,11 +52,11 @@ namespace apl { namespace dnp { void TransmitTPDU(const byte_t* apData, size_t aNumBytes); void ReceiveAPDU(const byte_t* apData, size_t aNumBytes); void ReceiveTPDU(const byte_t* apData, size_t aNumBytes); - - bool ContinueSend(); /// return true if - void SignalSendSuccess(); + + bool ContinueSend(); /// return true if + void SignalSendSuccess(); void SignalSendFailure(); - + /* Events - NVII delegates from ILayerUp/ILayerDown and Events produced internally */ static std::string ToString(byte_t aHeader); @@ -70,7 +70,7 @@ namespace apl { namespace dnp { void _OnSendSuccess(); void _OnSendFailure(); void _OnLowerLayerShutdown(); - + /* Members and Helpers */ TLS_Base* mpState; diff --git a/DNP3/BufferSetTypes.h b/DNP3/BufferSetTypes.h index 6815b224..2cb84f7d 100644 --- a/DNP3/BufferSetTypes.h +++ b/DNP3/BufferSetTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __BUFFER_SET_TYPES_H_ #define __BUFFER_SET_TYPES_H_ @@ -29,11 +29,11 @@ namespace apl { namespace dnp { // C++ doesn't allow templated typedefs, but this technique simulates this behavior - + /// Set that forces data exclusivity by index template - struct IndexSet - { + struct IndexSet + { struct LessThanByIndex { // Const to fix VS compilation bug @@ -45,14 +45,14 @@ namespace apl { namespace dnp { /// Multiset that orders data by order by timestamp, multi-entries allowed template - struct TimeMultiSet + struct TimeMultiSet { struct LessThanByTime { bool operator()(const T& a, const T& b) const { return a.mValue.GetTime() < b.mValue.GetTime(); } }; - + typedef std::multiset Type; }; @@ -67,7 +67,7 @@ namespace apl { namespace dnp { bool operator()(const T& a, const T& b) const { return a.mLastEventValue < b.mLastEventValue; } }; - + typedef std::multiset Type; }; @@ -82,11 +82,11 @@ namespace apl { namespace dnp { bool operator()(const T& a, const T& b) const { return a.mSequence < b.mSequence; } }; - + typedef std::set Type; }; - + }} //end NS #endif diff --git a/DNP3/CTOHistory.h b/DNP3/CTOHistory.h index b0dc8c36..cbe566ce 100644 --- a/DNP3/CTOHistory.h +++ b/DNP3/CTOHistory.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __CTO_HISTORY_H_ #define __CTO_HISTORY_H_ @@ -24,15 +24,15 @@ namespace apl { namespace dnp { class CTOHistory { public: - CTOHistory() : + CTOHistory() : mCTO(-1), mHeaderNum(0), mTimeHeaderNum(0) { - + } - void Reset() + void Reset() { mCTO = TimeStamp_t(-1); mHeaderNum = 0; @@ -40,7 +40,7 @@ class CTOHistory } void NextHeader() { ++mHeaderNum; } - + void SetCTO(TimeStamp_t& arTime) { mCTO = arTime; @@ -62,7 +62,7 @@ class CTOHistory TimeStamp_t mCTO; size_t mHeaderNum; size_t mTimeHeaderNum; - + }; }} diff --git a/DNP3/ClassCounter.h b/DNP3/ClassCounter.h index 93acf34b..4c31a01f 100644 --- a/DNP3/ClassCounter.h +++ b/DNP3/ClassCounter.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __CLASS_COUNTER_H_ #define __CLASS_COUNTER_H_ @@ -58,7 +58,7 @@ class ClassCounter size_t GetNumAllClass() { return mNumClass1 + mNumClass2 + mNumClass3; } void IncrCount(dnp::PointClass aClass); - void DecrCount(dnp::PointClass aClass); + void DecrCount(dnp::PointClass aClass); private: diff --git a/DNP3/ClassMask.h b/DNP3/ClassMask.h index cf619298..d998ad8a 100644 --- a/DNP3/ClassMask.h +++ b/DNP3/ClassMask.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,53 +6,53 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __CLASS_MASK_H_ -#define __CLASS_MASK_H_ - -#include "PointClass.h" - -namespace apl { namespace dnp { - -struct ClassMask -{ - ClassMask(bool c1, bool c2, bool c3) : - class1(c1), - class2(c2), - class3(c3) - {} - - ClassMask() : - class1(false), - class2(false), - class3(false) - {} - - bool class1; - bool class2; - bool class3; - - static int GetMask(bool c1, bool c2, bool c3) - { - int m = 0; - if(c1) m |= PC_CLASS_1; - if(c2) m |= PC_CLASS_2; - if(c3) m |= PC_CLASS_3; - return m; - } - - bool IsEnabled() { return class1 || class2 || class3; } -}; - -}} - -#endif +// +#ifndef __CLASS_MASK_H_ +#define __CLASS_MASK_H_ + +#include "PointClass.h" + +namespace apl { namespace dnp { + +struct ClassMask +{ + ClassMask(bool c1, bool c2, bool c3) : + class1(c1), + class2(c2), + class3(c3) + {} + + ClassMask() : + class1(false), + class2(false), + class3(false) + {} + + bool class1; + bool class2; + bool class3; + + static int GetMask(bool c1, bool c2, bool c3) + { + int m = 0; + if(c1) m |= PC_CLASS_1; + if(c2) m |= PC_CLASS_2; + if(c3) m |= PC_CLASS_3; + return m; + } + + bool IsEnabled() { return class1 || class2 || class3; } +}; + +}} + +#endif diff --git a/DNP3/DNP3.vcproj b/DNP3/DNP3.vcproj index 6837cf14..7b44c0c2 100755 --- a/DNP3/DNP3.vcproj +++ b/DNP3/DNP3.vcproj @@ -1,691 +1,691 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DNP3/DNPCommandMaster.h b/DNP3/DNPCommandMaster.h index 5bc7113e..7bdbd7ce 100644 --- a/DNP3/DNPCommandMaster.h +++ b/DNP3/DNPCommandMaster.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_COMMAND_MASTER_H_ #define __DNP_COMMAND_MASTER_H_ @@ -38,7 +38,7 @@ namespace apl { namespace dnp { struct CommandRequestInfo { CommandRequestInfo() : group(0), var(0), qual(QC_UNDEFINED), seqInfo(SI_OTHER), seqAPDU(-1) {} - CommandRequestInfo(const T& aCmd, int aGroup, int aVar, QualifierCode aQual, SequenceInfo aSeqInfo, int aSeqAPDU) + CommandRequestInfo(const T& aCmd, int aGroup, int aVar, QualifierCode aQual, SequenceInfo aSeqInfo, int aSeqAPDU) : cmd(aCmd), group(aGroup), var(aVar), qual(aQual), seqInfo(aSeqInfo), seqAPDU(aSeqAPDU) {} T cmd; @@ -75,7 +75,7 @@ namespace apl { namespace dnp { Handles DNP3 control/setpoint behavior, using a DeviceTemplate for start-up characterization of binary and analog outputs. Keeps a map to match operates to previous selects, with a separate control path for direct operates. If command requests are validated they are passed to the user code through ICommandAcceptor, which responds with success/failure. - + */ class DNPCommandMaster: public IDNPCommandMaster, public apl::IResponseAcceptor { @@ -84,8 +84,8 @@ namespace apl { namespace dnp { struct CommandInfo { CommandInfo():mSelectTime(0){} - size_t mRemoteIndex; - apl::ICommandAcceptor* mpAcceptor; + size_t mRemoteIndex; + apl::ICommandAcceptor* mpAcceptor; CommandModes mMode; apl::TimeStamp_t mSelectTime; bool mIsSelected; @@ -141,7 +141,7 @@ namespace apl { namespace dnp { CommandModes mCommandMode; }; - + template void DNPCommandMaster::BindCommand(std::map >& aMap, apl::CommandTypes aType, size_t aLocalIndex, size_t aRemoteIndex, CommandModes aMode, millis_t aSelectTimeoutMS, apl::ICommandAcceptor* apAcceptor) { @@ -172,12 +172,12 @@ namespace apl { namespace dnp { CommandInfo& info = i->second; if(info.mMode == CM_DO_ONLY) return false; - + info.mSelectTime = TimeStamp::GetTimeStamp(); info.mIsSelected = true; info.mSelectSequence = aCmd.seqAPDU; info.mRequest = aCmd; - + return true; } } @@ -207,7 +207,7 @@ namespace apl { namespace dnp { info.mIsSelected = false; return CS_NO_SELECT; } - + info.mIsSelected = false; info.mpAcceptor->AcceptCommand(arType.cmd, info.mRemoteIndex, aSequence, this); return CS_SUCCESS; @@ -231,7 +231,7 @@ namespace apl { namespace dnp { if(info.mMode == CM_SBO_ONLY) return CS_NOT_SUPPORTED; - + info.mIsSelected = false; info.mpAcceptor->AcceptCommand(arType.cmd, info.mRemoteIndex, aSequence, this); return CS_SUCCESS; @@ -239,7 +239,7 @@ namespace apl { namespace dnp { } - + }} #endif diff --git a/DNP3/DNPConstants.h b/DNP3/DNPConstants.h index 10a887d0..c4a835a6 100644 --- a/DNP3/DNPConstants.h +++ b/DNP3/DNPConstants.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_CONSTANTS_H_ #define __DNP_CONSTANTS_H_ @@ -79,17 +79,17 @@ namespace apl { namespace dnp { /* TRANSPORT Layer */ TLERR_NEW_FIR, - TLERR_MESSAGE_WITHOUT_FIR, + TLERR_MESSAGE_WITHOUT_FIR, TLERR_NO_PAYLOAD, - TLERR_BAD_SEQUENCE, - TLERR_BAD_LENGTH, + TLERR_BAD_SEQUENCE, + TLERR_BAD_LENGTH, TLERR_BUFFER_FULL, TLERR_TIMEOUT, //used in linkframeparser DLERR_CRC, // CRC failure in header or data payload DLERR_INVALID_LENGTH, // length parameter outside range [0,255] - DLERR_UNEXPECTED_DATA, // length > 5 for non-user data func code + DLERR_UNEXPECTED_DATA, // length > 5 for non-user data func code DLERR_NO_DATA, // length == 5 but func code indicates data DLERR_UNKNOWN_FUNC, // unknown function code DLERR_UNEXPECTED_FCV, // FCV bit set unexpectedly, ie set on wrong func code @@ -117,7 +117,7 @@ namespace apl { namespace dnp { }; - + }} #endif diff --git a/DNP3/DNPCrc.h b/DNP3/DNPCrc.h index 8768ee7f..0b392f98 100644 --- a/DNP3/DNPCrc.h +++ b/DNP3/DNPCrc.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_CRC_H_ #define __DNP_CRC_H_ diff --git a/DNP3/DNPDatabaseTypes.h b/DNP3/DNPDatabaseTypes.h index afb1c2f1..c1f13c34 100644 --- a/DNP3/DNPDatabaseTypes.h +++ b/DNP3/DNPDatabaseTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_DATABASE_TYPES_H_ #define __DNP_DATABASE_TYPES_H_ @@ -38,18 +38,18 @@ The common base class allows some common operations to be performed on static an template struct PointInfoBase { - PointInfoBase(const T& arValue, PointClass aClass, size_t aIndex) : + PointInfoBase(const T& arValue, PointClass aClass, size_t aIndex) : mValue(arValue), mClass(aClass), mIndex(aIndex) {} - + PointInfoBase() : mClass(PC_CLASS_0) {} T mValue; /// current measurment (i.e. Binary, Analog, etc) PointClass mClass; /// class of the point (PC_CLASS<0-3>) size_t mIndex; /// index of the measurement - + typedef T MeasType; }; @@ -59,17 +59,17 @@ and a last event value to the base class. */ template struct PointInfo : public PointInfoBase -{ - PointInfo(const T& arVal, PointClass aClass, size_t aIndex) : +{ + PointInfo(const T& arVal, PointClass aClass, size_t aIndex) : PointInfoBase(arVal, aClass, aIndex), - mDeadband(0), + mDeadband(0), mLastEventValue(0) {} - + PointInfo() : mDeadband(0), mLastEventValue(0) {} double mDeadband; /// deadband associated with measurement (optional) - typename T::ValueType mLastEventValue; /// the last value that was reported + typename T::ValueType mLastEventValue; /// the last value that was reported }; template @@ -92,8 +92,8 @@ typedef StaticIter::Type ControlIterator; typedef StaticIter::Type SetpointIterator; - -}} //end namespace + +}} //end namespace #endif diff --git a/DNP3/DNPExceptions.h b/DNP3/DNPExceptions.h index a2e7b3ee..b5d6c93e 100644 --- a/DNP3/DNPExceptions.h +++ b/DNP3/DNPExceptions.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_EXCEPTIONS_H_ #define __DNP_EXCEPTIONS_H_ @@ -27,8 +27,8 @@ namespace apl { namespace dnp { class ParameterException : public apl::Exception { public: - ParameterException(const std::string& aSource, const std::string& aMessage, int aErrorCode = -1) throw() : - Exception(aSource, aMessage, aErrorCode) {} + ParameterException(const std::string& aSource, const std::string& aMessage, int aErrorCode = -1) throw() : + Exception(aSource, aMessage, aErrorCode) {} }; class NotSupportedException : public apl::Exception diff --git a/DNP3/DNPFromStream.h b/DNP3/DNPFromStream.h index 2367cf58..d2b5c924 100644 --- a/DNP3/DNPFromStream.h +++ b/DNP3/DNPFromStream.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_FROM_STREAM_H_ #define __DNP_FROM_STREAM_H_ @@ -44,7 +44,7 @@ namespace apl { namespace dnp { class DNPFromStream { public: - + template static Setpoint ReadSetpoint(const apl::byte_t*, const T*); @@ -68,7 +68,7 @@ namespace apl { namespace dnp { static typename T::DataType ReadBinaryQVT(const apl::byte_t* apPos, const T* apObj); template - static typename T::DataType ReadQVT(const apl::byte_t* apPos, const T* apObj); + static typename T::DataType ReadQVT(const apl::byte_t* apPos, const T* apObj); }; template diff --git a/DNP3/DNPToStream.h b/DNP3/DNPToStream.h index 8ab3f457..0ea0b872 100644 --- a/DNP3/DNPToStream.h +++ b/DNP3/DNPToStream.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_TO_STREAM_H_ #define __DNP_TO_STREAM_H_ @@ -36,7 +36,7 @@ namespace apl { namespace dnp { class DNPToStream { public: - + // Templates for writing to stream template static void WriteQ(apl::byte_t* apPos, const T* apObj, const U& arObj); @@ -46,10 +46,10 @@ namespace apl { namespace dnp { template static void WriteQT(apl::byte_t* apPos, const T* apObj, const U& arObj); - + template static void WriteCheckRangeQV(apl::byte_t* apPos, const T* apObj, const U& arObj); - + template static void WriteV(apl::byte_t* apPos, const T* apObj, const U& arObj); @@ -62,14 +62,14 @@ namespace apl { namespace dnp { template class Conversion - { + { public: static U Convert(T aVal) { return aVal; } //try implicit casting }; //this partial specialization allows us to change how doubles are converted template - class Conversion + class Conversion { public: static U Convert(double aVal) { @@ -95,13 +95,13 @@ namespace apl { namespace dnp { void DNPToStream::WriteCheckRangeQV(apl::byte_t* apPos, const T* apObj, const U& arObj) { apl::byte_t qual = arObj.GetQuality(); - + typename U::Type val = arObj.GetValue(); - if(val > apObj->mValue.Max()) + if(val > apObj->mValue.Max()) { val = apObj->mValue.Max(); qual |= apObj->mValue.OverRangeMask(); } - if(val < apObj->mValue.Min()) + if(val < apObj->mValue.Min()) { val = apObj->mValue.Min(); qual |= apObj->mValue.OverRangeMask(); } - + apObj->mFlag.Set(apPos, qual); apObj->mValue.Set(apPos, Conversion::Convert(val)); } @@ -111,11 +111,11 @@ namespace apl { namespace dnp { void DNPToStream::WriteV(apl::byte_t* apPos, const T* apObj, const U& arObj) { typename U::Type val = arObj.GetValue(); - if(val > apObj->mValue.Max()) + if(val > apObj->mValue.Max()) { val = apObj->mValue.Max(); } - if(val < apObj->mValue.Min()) + if(val < apObj->mValue.Min()) { val = apObj->mValue.Min(); } - + apObj->mValue.Set(apPos, Conversion::Convert(val)); } @@ -133,14 +133,14 @@ namespace apl { namespace dnp { WriteQV(apPos, apObj, arObj); apObj->mTime.Set(apPos, arObj.GetTime()); } - + template inline void DNPToStream::WriteCheckRangeQVT(apl::byte_t* apPos, const T* apObj, const U& arObj) { WriteCheckRangeQV(apPos, apObj, arObj); apObj->mTime.Set(apPos, arObj.GetTime()); } - + }} #ifdef APL_PLATFORM_WIN diff --git a/DNP3/DeviceTemplate.cpp b/DNP3/DeviceTemplate.cpp index 3c58d6fe..f0f452f3 100644 --- a/DNP3/DeviceTemplate.cpp +++ b/DNP3/DeviceTemplate.cpp @@ -16,30 +16,30 @@ // specific language governing permissions and limitations // under the License. // -#include "DeviceTemplate.h" - - -namespace apl { namespace dnp { - - - DeviceTemplate::DeviceTemplate( size_t aNumBinary, - size_t aNumAnalog, - size_t aNumCounter, - size_t aNumControlStatus, - size_t aNumSetpointStatus, - size_t aNumControls, - size_t aNumSetpoints) - : mStartOnline(false) - { - this->mBinary.resize(aNumBinary); this->InitNames("Binary", mBinary); - this->mAnalog.resize(aNumAnalog); this->InitNames("Analog", mAnalog); - this->mCounter.resize(aNumCounter); this->InitNames("Counter", mCounter); - this->mControlStatus.resize(aNumControlStatus); this->InitNames("ControlStatus", mControlStatus); - this->mSetpointStatus.resize(aNumSetpointStatus); this->InitNames("SetpointStatus", mSetpointStatus); - this->mControls.resize(aNumControls); this->InitNames("Control", mControls); - this->mSetpoints.resize(aNumSetpoints); this->InitNames("Setpoint", mSetpoints);; - } - -}} - - +#include "DeviceTemplate.h" + + +namespace apl { namespace dnp { + + + DeviceTemplate::DeviceTemplate( size_t aNumBinary, + size_t aNumAnalog, + size_t aNumCounter, + size_t aNumControlStatus, + size_t aNumSetpointStatus, + size_t aNumControls, + size_t aNumSetpoints) + : mStartOnline(false) + { + this->mBinary.resize(aNumBinary); this->InitNames("Binary", mBinary); + this->mAnalog.resize(aNumAnalog); this->InitNames("Analog", mAnalog); + this->mCounter.resize(aNumCounter); this->InitNames("Counter", mCounter); + this->mControlStatus.resize(aNumControlStatus); this->InitNames("ControlStatus", mControlStatus); + this->mSetpointStatus.resize(aNumSetpointStatus); this->InitNames("SetpointStatus", mSetpointStatus); + this->mControls.resize(aNumControls); this->InitNames("Control", mControls); + this->mSetpoints.resize(aNumSetpoints); this->InitNames("Setpoint", mSetpoints);; + } + +}} + + diff --git a/DNP3/DeviceTemplate.h b/DNP3/DeviceTemplate.h index d9ff1687..a447f6a4 100644 --- a/DNP3/DeviceTemplate.h +++ b/DNP3/DeviceTemplate.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,71 +6,71 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __DEVICE_TEMPLATE_H_ -#define __DEVICE_TEMPLATE_H_ - -#include -#include - -#include "DeviceTemplateTypes.h" - -namespace apl { namespace dnp { - -/** Configuration structure that defines: - 1) the default layout of the database - 2) how controls are handled - - The indices of the points are implicit based on their - position within the vectors below. -*/ -struct DeviceTemplate -{ - DeviceTemplate( size_t aNumBinary = 0, - size_t aNumAnalog = 0, - size_t aNumCounter = 0, - size_t aNumControlStatus = 0, - size_t aNumSetpointStatus = 0, - size_t aNumSetpoints = 0, - size_t aNumControls = 0); - - //Measurements - std::vector mBinary; /// list of binary point properties - std::vector mCounter; /// list of counter point properties - std::vector mAnalog; /// list of analog point properties - std::vector mControlStatus; /// list of control status point properties - std::vector mSetpointStatus; /// list of control status point properties - - //Controls - std::vector mControls; /// list of binary output properties - std::vector mSetpoints; /// list of analog output properties - - bool mStartOnline; - - private: - - /// Helper function for setting up default names - template - void InitNames(const std::string& arName, std::vector& arVec) - { - for(size_t i=0; i +#include + +#include "DeviceTemplateTypes.h" + +namespace apl { namespace dnp { + +/** Configuration structure that defines: + 1) the default layout of the database + 2) how controls are handled + + The indices of the points are implicit based on their + position within the vectors below. +*/ +struct DeviceTemplate +{ + DeviceTemplate( size_t aNumBinary = 0, + size_t aNumAnalog = 0, + size_t aNumCounter = 0, + size_t aNumControlStatus = 0, + size_t aNumSetpointStatus = 0, + size_t aNumSetpoints = 0, + size_t aNumControls = 0); + + //Measurements + std::vector mBinary; /// list of binary point properties + std::vector mCounter; /// list of counter point properties + std::vector mAnalog; /// list of analog point properties + std::vector mControlStatus; /// list of control status point properties + std::vector mSetpointStatus; /// list of control status point properties + + //Controls + std::vector mControls; /// list of binary output properties + std::vector mSetpoints; /// list of analog output properties + + bool mStartOnline; + + private: + + /// Helper function for setting up default names + template + void InitNames(const std::string& arName, std::vector& arVec) + { + for(size_t i=0; i - -#include -#include -#include "PointClass.h" - -namespace apl { namespace dnp { - -/// base class - all point types have a name -struct PointRecord -{ - PointRecord(const std::string& arName) : Name(arName) {} - PointRecord() {} - - std::string Name; -}; - -/// Event point records also have a class -struct EventPointRecord : public PointRecord -{ - EventPointRecord(const std::string& arName, PointClass aPointClass) : - PointRecord(arName), - EventClass(aPointClass) - {} - - EventPointRecord() : EventClass(PC_CLASS_1) {} - - /// when the point changes, it will generate an event unless EventClass == PC_CLASS_0 - PointClass EventClass; -}; - -/// Adds a deadband parameter -struct DeadbandPointRecord : public EventPointRecord -{ - DeadbandPointRecord(const std::string& arName, PointClass aPointClass, double aDeadband) : - EventPointRecord(arName, aPointClass), - Deadband(aDeadband) - {} - - DeadbandPointRecord() : Deadband(0) {} - - /// Points can change value within the deadband and not trigger events - double Deadband; -}; - -/// Todo - Add properties that determine how controls are handled - i.e. DO/SBO/etc -struct ControlRecord : public PointRecord -{ - ControlRecord(const std::string& arName = "", CommandModes aMode = CM_SBO_ONLY, millis_t aSelectTimeoutMS = 5000) : - PointRecord(arName), - CommandMode(aMode), - SelectTimeoutMS(aSelectTimeoutMS) - {} - - apl::CommandModes CommandMode; - millis_t SelectTimeoutMS; -}; - - -}} - -#endif +// +#ifndef __DEVICE_TEMPLATE_TYPES_H_ +#define __DEVICE_TEMPLATE_TYPES_H_ + +#include + +#include +#include +#include "PointClass.h" + +namespace apl { namespace dnp { + +/// base class - all point types have a name +struct PointRecord +{ + PointRecord(const std::string& arName) : Name(arName) {} + PointRecord() {} + + std::string Name; +}; + +/// Event point records also have a class +struct EventPointRecord : public PointRecord +{ + EventPointRecord(const std::string& arName, PointClass aPointClass) : + PointRecord(arName), + EventClass(aPointClass) + {} + + EventPointRecord() : EventClass(PC_CLASS_1) {} + + /// when the point changes, it will generate an event unless EventClass == PC_CLASS_0 + PointClass EventClass; +}; + +/// Adds a deadband parameter +struct DeadbandPointRecord : public EventPointRecord +{ + DeadbandPointRecord(const std::string& arName, PointClass aPointClass, double aDeadband) : + EventPointRecord(arName, aPointClass), + Deadband(aDeadband) + {} + + DeadbandPointRecord() : Deadband(0) {} + + /// Points can change value within the deadband and not trigger events + double Deadband; +}; + +/// Todo - Add properties that determine how controls are handled - i.e. DO/SBO/etc +struct ControlRecord : public PointRecord +{ + ControlRecord(const std::string& arName = "", CommandModes aMode = CM_SBO_ONLY, millis_t aSelectTimeoutMS = 5000) : + PointRecord(arName), + CommandMode(aMode), + SelectTimeoutMS(aSelectTimeoutMS) + {} + + apl::CommandModes CommandMode; + millis_t SelectTimeoutMS; +}; + + +}} + +#endif diff --git a/DNP3/EventTypes.h b/DNP3/EventTypes.h index ec783408..fa8e0e8c 100644 --- a/DNP3/EventTypes.h +++ b/DNP3/EventTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __EVENT_TYPES_H_ #define __EVENT_TYPES_H_ @@ -30,13 +30,13 @@ flag to the data member. */ template struct EventInfo : public PointInfoBase -{ - EventInfo(const T& arValue, PointClass aClass, size_t aIndex) : +{ + EventInfo(const T& arValue, PointClass aClass, size_t aIndex) : PointInfoBase(arValue, aClass, aIndex), mSequence(0), - mWritten(false) + mWritten(false) {} - + EventInfo() : mSequence(0), mWritten(false) {} size_t mSequence; /// sequence number used by the event buffers to record insertion order @@ -49,15 +49,15 @@ typedef EventInfo CounterEvent; template struct EvtItr -{ +{ typedef typename std::vector< EventType >::iterator Type; }; typedef EvtItr::Type BinaryEventIter; typedef EvtItr::Type AnalogEventIter; typedef EvtItr::Type CounterEventIter; - -}} //end namespace + +}} //end namespace #endif diff --git a/DNP3/HeaderReadIterator.h b/DNP3/HeaderReadIterator.h index bb09040f..0dea650f 100644 --- a/DNP3/HeaderReadIterator.h +++ b/DNP3/HeaderReadIterator.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __HEADER_READ_ITERATOR_H_ #define __HEADER_READ_ITERATOR_H_ @@ -31,12 +31,12 @@ class IObjectHeader; -namespace apl { namespace dnp { +namespace apl { namespace dnp { class ObjectReadIterator; - + class HeaderInfo - { + { public: HeaderInfo(const ObjectHeaderField& arData, size_t aCount, size_t aPrefixSize, IObjectHeader* apHeader, ObjectBase* apObject, size_t aPos) : @@ -63,7 +63,7 @@ namespace apl { namespace dnp { const ObjectBase* GetBaseObject() const { return mpObjectBase; } const IObjectHeader* GetHeader() const { return mpHeader; } size_t GetPosition() const { return mPos; } - + private: size_t mPos; @@ -76,11 +76,11 @@ namespace apl { namespace dnp { /// An interator that clients can use to loop over the object headers in an APDU class HeaderReadIterator - { + { friend class APDU; - + public: - + const HeaderInfo* operator->() const; const apl::byte_t* operator*() const; const HeaderReadIterator& operator++(); @@ -90,14 +90,14 @@ namespace apl { namespace dnp { ObjectReadIterator BeginRead(); size_t Count() { return mpHeaders->size(); } bool IsEnd() { return mIndex >= mpHeaders->size(); } - + private: - + HeaderReadIterator(const std::vector* apHeaders, const byte_t* apBuffer, bool aHasData); const std::vector* mpHeaders; const byte_t* mpBuffer; bool mHasData; - size_t mIndex; + size_t mIndex; }; inline const HeaderInfo& HeaderReadIterator::info() const @@ -122,15 +122,15 @@ namespace apl { namespace dnp { } inline const HeaderReadIterator& HeaderReadIterator::operator++() - { + { if(mIndex >= mpHeaders->size()) { throw apl::Exception(LOCATION, "", ALERR_ITERATOR_OUT_OF_BOUNDS); } - ++mIndex; + ++mIndex; return (*this); } inline const HeaderReadIterator HeaderReadIterator::operator++(int) - { + { if(mIndex >= mpHeaders->size()) { throw apl::Exception(LOCATION, "", ALERR_ITERATOR_OUT_OF_BOUNDS); } HeaderReadIterator tmp(*this); diff --git a/DNP3/IFrameSink.h b/DNP3/IFrameSink.h index 49f85e70..4b8c6930 100644 --- a/DNP3/IFrameSink.h +++ b/DNP3/IFrameSink.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,49 +6,49 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_FRAME_SINK_H_ -#define __I_FRAME_SINK_H_ - -#include -#include - -namespace apl { namespace dnp { - -/// @section DESCRIPTION Interface that receives parsed FT3 frame information -class IFrameSink -{ - public: - - virtual ~IFrameSink() {} - - // Sec to Pri - - virtual void Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; - virtual void Nack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; - virtual void LinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; - virtual void NotSupported (bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; - - - // Pri to Sec - - virtual void TestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) = 0; - virtual void ResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) = 0; - virtual void RequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) = 0; - virtual void ConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) = 0; - virtual void UnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) = 0; -}; - -}} - -#endif - +// +#ifndef __I_FRAME_SINK_H_ +#define __I_FRAME_SINK_H_ + +#include +#include + +namespace apl { namespace dnp { + +/// @section DESCRIPTION Interface that receives parsed FT3 frame information +class IFrameSink +{ + public: + + virtual ~IFrameSink() {} + + // Sec to Pri + + virtual void Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; + virtual void Nack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; + virtual void LinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; + virtual void NotSupported (bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) = 0; + + + // Pri to Sec + + virtual void TestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) = 0; + virtual void ResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) = 0; + virtual void RequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) = 0; + virtual void ConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) = 0; + virtual void UnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) = 0; +}; + +}} + +#endif + diff --git a/DNP3/ILinkContext.h b/DNP3/ILinkContext.h index 7753b89b..32789b04 100644 --- a/DNP3/ILinkContext.h +++ b/DNP3/ILinkContext.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,35 +6,35 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_LINK_CONTEXT_H_ -#define __I_LINK_CONTEXT_H_ - -#include "IFrameSink.h" - -namespace apl { namespace dnp { - -/// @section DESCRIPTION Interface from the link router to the link layer -class ILinkContext : public IFrameSink -{ - public: - - virtual ~ILinkContext() {} - - virtual void OnLowerLayerUp() = 0; - virtual void OnLowerLayerDown() = 0; -}; - -}} - -#endif - +// +#ifndef __I_LINK_CONTEXT_H_ +#define __I_LINK_CONTEXT_H_ + +#include "IFrameSink.h" + +namespace apl { namespace dnp { + +/// @section DESCRIPTION Interface from the link router to the link layer +class ILinkContext : public IFrameSink +{ + public: + + virtual ~ILinkContext() {} + + virtual void OnLowerLayerUp() = 0; + virtual void OnLowerLayerDown() = 0; +}; + +}} + +#endif + diff --git a/DNP3/ILinkRouter.h b/DNP3/ILinkRouter.h index 2d64631a..4df0b4ca 100644 --- a/DNP3/ILinkRouter.h +++ b/DNP3/ILinkRouter.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,34 +6,34 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __I_LINK_ROUTER_H_ -#define __I_LINK_ROUTER_H_ - -namespace apl { namespace dnp { - -class LinkFrame; - -/// @section DESCRIPTION Interface from the link layer to the link router -class ILinkRouter -{ - public: - - virtual ~ILinkRouter() {} - - virtual void Transmit(const LinkFrame&) = 0; -}; - -}} - -#endif - +// +#ifndef __I_LINK_ROUTER_H_ +#define __I_LINK_ROUTER_H_ + +namespace apl { namespace dnp { + +class LinkFrame; + +/// @section DESCRIPTION Interface from the link layer to the link router +class ILinkRouter +{ + public: + + virtual ~ILinkRouter() {} + + virtual void Transmit(const LinkFrame&) = 0; +}; + +}} + +#endif + diff --git a/DNP3/IndexedWriteIterator.h b/DNP3/IndexedWriteIterator.h index d9fa37ec..1661a209 100644 --- a/DNP3/IndexedWriteIterator.h +++ b/DNP3/IndexedWriteIterator.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __INDEXED_WRITE_ITERATOR_H_ #define __INDEXED_WRITE_ITERATOR_H_ @@ -37,11 +37,11 @@ namespace apl { namespace dnp { public: IndexedWriteIterator(); - + const IndexedWriteIterator& operator++(); const IndexedWriteIterator operator++(int); apl::byte_t* operator*() const; - + void SetIndex(size_t aIndex); bool IsEnd() { return mIndex >= mCount; } size_t Count() { return mCount; } @@ -66,7 +66,7 @@ namespace apl { namespace dnp { size_t mIndex; size_t mCount; size_t mObjectSize; - bool mIndexSet; + bool mIndexSet; }; }} diff --git a/DNP3/LinkConfig.h b/DNP3/LinkConfig.h index 4bb56ac3..47ffca32 100644 --- a/DNP3/LinkConfig.h +++ b/DNP3/LinkConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,79 +6,79 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __LINK_CONFIG_H_ -#define __LINK_CONFIG_H_ - -#include - -namespace apl { namespace dnp { - -/** - Configuration for the dnp3 link layer -*/ -struct LinkConfig -{ - LinkConfig( - bool aIsMaster, - bool aUseConfirms, - size_t aNumRetry, - uint_16_t aLocalAddr, - uint_16_t aRemoteAddr, - millis_t aTimeout) : - - IsMaster(aIsMaster), - UseConfirms(aUseConfirms), - NumRetry(aNumRetry), - LocalAddr(aLocalAddr), - RemoteAddr(aRemoteAddr), - Timeout(aTimeout) - {} - - LinkConfig( - bool aIsMaster, - bool aUseConfirms) : - - IsMaster(aIsMaster), - UseConfirms(aUseConfirms), - NumRetry(0), - LocalAddr(aIsMaster ? 1 : 1024), - RemoteAddr(aIsMaster ? 1024 : 1), - Timeout(1000) - {} - - /// The master/slave bit set on all messages - bool IsMaster; - - /// If true, the link layer will send data requesting confirmation - bool UseConfirms; - - /// The number of retry attempts the link will attempt after the initial try - size_t NumRetry; - - /// dnp3 address of the local device - uint_16_t LocalAddr; - - /// dnp3 address of the remote device - uint_16_t RemoteAddr; - - /// the response timeout in milliseconds for confirmed requests - millis_t Timeout; - - private: - - LinkConfig() {} -}; - -}} - -#endif +// +#ifndef __LINK_CONFIG_H_ +#define __LINK_CONFIG_H_ + +#include + +namespace apl { namespace dnp { + +/** + Configuration for the dnp3 link layer +*/ +struct LinkConfig +{ + LinkConfig( + bool aIsMaster, + bool aUseConfirms, + size_t aNumRetry, + uint_16_t aLocalAddr, + uint_16_t aRemoteAddr, + millis_t aTimeout) : + + IsMaster(aIsMaster), + UseConfirms(aUseConfirms), + NumRetry(aNumRetry), + LocalAddr(aLocalAddr), + RemoteAddr(aRemoteAddr), + Timeout(aTimeout) + {} + + LinkConfig( + bool aIsMaster, + bool aUseConfirms) : + + IsMaster(aIsMaster), + UseConfirms(aUseConfirms), + NumRetry(0), + LocalAddr(aIsMaster ? 1 : 1024), + RemoteAddr(aIsMaster ? 1024 : 1), + Timeout(1000) + {} + + /// The master/slave bit set on all messages + bool IsMaster; + + /// If true, the link layer will send data requesting confirmation + bool UseConfirms; + + /// The number of retry attempts the link will attempt after the initial try + size_t NumRetry; + + /// dnp3 address of the local device + uint_16_t LocalAddr; + + /// dnp3 address of the remote device + uint_16_t RemoteAddr; + + /// the response timeout in milliseconds for confirmed requests + millis_t Timeout; + + private: + + LinkConfig() {} +}; + +}} + +#endif diff --git a/DNP3/LinkFrame.cpp b/DNP3/LinkFrame.cpp index 4cb20366..e1fcce62 100644 --- a/DNP3/LinkFrame.cpp +++ b/DNP3/LinkFrame.cpp @@ -16,194 +16,194 @@ // specific language governing permissions and limitations // under the License. // -#include "LinkFrame.h" - -#include "DNPCrc.h" - -#include -#include -#include - -using namespace std; - -namespace apl { namespace dnp { - -LinkFrame::LinkFrame() : -mIsComplete(false), -mSize(0) -{ - -} - -LinkFrame::~LinkFrame() -{ - -} - -ostream& operator<<(ostream& output, const LinkFrame& f) { - output << f.ToString(); - return output; // for multiple << operators. -} - -bool LinkFrame::operator==(const LinkFrame& arRHS) const -{ - if(!this->IsComplete() || !arRHS.IsComplete()) return false; - - if(this->GetSize() != arRHS.GetSize()) return false; - - for(size_t i=0; iGetSize(); ++i) - if(this->GetBuffer()[i] != arRHS.GetBuffer()[i]) return false; - - return true; -} - -size_t LinkFrame::ReadUserData(byte_t* apBuffer) const -{ - assert(this->mIsComplete); - size_t user_bytes = mHeader.GetLength() - LS_MIN_LENGTH; - ReadUserData(mpBuffer+LS_HEADER_SIZE, apBuffer, user_bytes); - return user_bytes; -} - -void LinkFrame::ReadUserData(const byte_t* apSrc, byte_t* apDest, size_t aLength) -{ - if(aLength == 0) return; //base case of recursion - size_t max = LS_DATA_BLOCK_SIZE; - size_t num = (aLength <= max) ? aLength : max; - size_t num_with_crc = num + 2; - memcpy(apDest, apSrc, num); - ReadUserData(apSrc+num_with_crc, apDest+num, aLength-num); //tail recursive -} - -bool LinkFrame::ValidateHeaderCRC() const -{ - return UInt16LE::Read(mpBuffer+LI_CRC) == DNPCrc::CalcCrc(mpBuffer, LI_CRC); -} - -bool LinkFrame::ValidateBodyCRC() const -{ - return ValidateBodyCRC(mpBuffer+LS_HEADER_SIZE, mHeader.GetLength()-LS_MIN_LENGTH); -} - -bool LinkFrame::ValidateBodyCRC(const byte_t* apBody, size_t aLength) -{ - if(aLength == 0) return true; //base case of recursion - size_t max = LS_DATA_BLOCK_SIZE ; - size_t num = (aLength <= max) ? aLength : max; - if(!DNPCrc::IsCorrectCRC(apBody,num)) return false; - else return ValidateBodyCRC(apBody+num+2, aLength-num); //tail recursive -} - -size_t LinkFrame::CalcFrameSize(size_t aDataLength) -{ - assert(aDataLength <= LS_MAX_USER_DATA_SIZE); - - size_t ret = LS_HEADER_SIZE; - - if(aDataLength > 0) { - size_t mod16 = aDataLength%LS_DATA_BLOCK_SIZE; - ret += (aDataLength/LS_DATA_BLOCK_SIZE)*LS_DATA_PLUS_CRC_SIZE; //complete blocks - if(mod16) ret += mod16 + LS_CRC_SIZE; //possible partial block - } - - return ret; -} - -//////////////////////////////////////////////////////////////////////// -// -// Outgoing frame formatting functions for Sec to Pri transactions -// -//////////////////////////////////////////////////////////////////////// - -void LinkFrame::FormatAck(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_ACK, aDest, aSrc); -} - -void LinkFrame::FormatNack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_NACK, aDest, aSrc); -} - -void LinkFrame::FormatLinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_LINK_STATUS, aDest, aSrc); -} - -void LinkFrame::FormatNotSupported(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_NOT_SUPPORTED, aDest, aSrc); -} - -//////////////////////////////////////////////////////////////////////// -// -// Outgoing frame formatting functions for Pri to Sec transactions -// -//////////////////////////////////////////////////////////////////////// - -void LinkFrame::FormatResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, false, false, FC_PRI_RESET_LINK_STATES, aDest, aSrc); -} - -void LinkFrame::FormatRequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, false, false, FC_PRI_REQUEST_LINK_STATUS, aDest, aSrc); -} - -void LinkFrame::FormatTestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) -{ - this->FormatHeader(0, aIsMaster, aFcb, true, FC_PRI_TEST_LINK_STATES, aDest, aSrc); -} - -void LinkFrame::FormatConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) -{ - assert(aDataLength > 0); - assert(aDataLength <= 250); - this->FormatHeader(aDataLength, aIsMaster, aFcb, true, FC_PRI_CONFIRMED_USER_DATA, aDest, aSrc); - WriteUserData(apData, mpBuffer + LS_HEADER_SIZE, aDataLength); -} - -void LinkFrame::FormatUnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const byte_t* apData, size_t aDataLength) -{ - assert(aDataLength > 0); - assert(aDataLength <= 250); - this->FormatHeader(aDataLength, aIsMaster, false, false, FC_PRI_UNCONFIRMED_USER_DATA, aDest, aSrc); - WriteUserData(apData, mpBuffer + LS_HEADER_SIZE, aDataLength); -} - -void LinkFrame::ChangeFCB(bool aFCB) -{ - if(mHeader.IsFcbSet() != aFCB) { - mHeader.ChangeFCB(aFCB); - mHeader.Write(mpBuffer); - } - -} - -void LinkFrame::FormatHeader(size_t aDataLength, bool aIsMaster, bool aFcb, bool aFcvDfc, FuncCodes aFuncCode, uint_16_t aDest, uint_16_t aSrc) -{ - mSize = this->CalcFrameSize(aDataLength); - - mHeader.Set(static_cast(aDataLength+LS_MIN_LENGTH), aSrc, aDest, aIsMaster, aFcvDfc, aFcb, aFuncCode); - mHeader.Write(mpBuffer); - - mIsComplete = true; -} - -void LinkFrame::WriteUserData(const apl::byte_t* apSrc, byte_t* apDest, size_t aLength) -{ - if(aLength == 0) return; - size_t max = LS_DATA_BLOCK_SIZE; - size_t num = aLength > max ? max : aLength; - memcpy(apDest, apSrc, num); - DNPCrc::AddCrc(apDest, num); - WriteUserData(apSrc+num, apDest+num+2, aLength-num); //tail recursive -} - -std::string LinkFrame::ToString() const -{ - return mHeader.ToString(); -} - -}} //end namespace +#include "LinkFrame.h" + +#include "DNPCrc.h" + +#include +#include +#include + +using namespace std; + +namespace apl { namespace dnp { + +LinkFrame::LinkFrame() : +mIsComplete(false), +mSize(0) +{ + +} + +LinkFrame::~LinkFrame() +{ + +} + +ostream& operator<<(ostream& output, const LinkFrame& f) { + output << f.ToString(); + return output; // for multiple << operators. +} + +bool LinkFrame::operator==(const LinkFrame& arRHS) const +{ + if(!this->IsComplete() || !arRHS.IsComplete()) return false; + + if(this->GetSize() != arRHS.GetSize()) return false; + + for(size_t i=0; iGetSize(); ++i) + if(this->GetBuffer()[i] != arRHS.GetBuffer()[i]) return false; + + return true; +} + +size_t LinkFrame::ReadUserData(byte_t* apBuffer) const +{ + assert(this->mIsComplete); + size_t user_bytes = mHeader.GetLength() - LS_MIN_LENGTH; + ReadUserData(mpBuffer+LS_HEADER_SIZE, apBuffer, user_bytes); + return user_bytes; +} + +void LinkFrame::ReadUserData(const byte_t* apSrc, byte_t* apDest, size_t aLength) +{ + if(aLength == 0) return; //base case of recursion + size_t max = LS_DATA_BLOCK_SIZE; + size_t num = (aLength <= max) ? aLength : max; + size_t num_with_crc = num + 2; + memcpy(apDest, apSrc, num); + ReadUserData(apSrc+num_with_crc, apDest+num, aLength-num); //tail recursive +} + +bool LinkFrame::ValidateHeaderCRC() const +{ + return UInt16LE::Read(mpBuffer+LI_CRC) == DNPCrc::CalcCrc(mpBuffer, LI_CRC); +} + +bool LinkFrame::ValidateBodyCRC() const +{ + return ValidateBodyCRC(mpBuffer+LS_HEADER_SIZE, mHeader.GetLength()-LS_MIN_LENGTH); +} + +bool LinkFrame::ValidateBodyCRC(const byte_t* apBody, size_t aLength) +{ + if(aLength == 0) return true; //base case of recursion + size_t max = LS_DATA_BLOCK_SIZE ; + size_t num = (aLength <= max) ? aLength : max; + if(!DNPCrc::IsCorrectCRC(apBody,num)) return false; + else return ValidateBodyCRC(apBody+num+2, aLength-num); //tail recursive +} + +size_t LinkFrame::CalcFrameSize(size_t aDataLength) +{ + assert(aDataLength <= LS_MAX_USER_DATA_SIZE); + + size_t ret = LS_HEADER_SIZE; + + if(aDataLength > 0) { + size_t mod16 = aDataLength%LS_DATA_BLOCK_SIZE; + ret += (aDataLength/LS_DATA_BLOCK_SIZE)*LS_DATA_PLUS_CRC_SIZE; //complete blocks + if(mod16) ret += mod16 + LS_CRC_SIZE; //possible partial block + } + + return ret; +} + +//////////////////////////////////////////////////////////////////////// +// +// Outgoing frame formatting functions for Sec to Pri transactions +// +//////////////////////////////////////////////////////////////////////// + +void LinkFrame::FormatAck(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_ACK, aDest, aSrc); +} + +void LinkFrame::FormatNack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_NACK, aDest, aSrc); +} + +void LinkFrame::FormatLinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_LINK_STATUS, aDest, aSrc); +} + +void LinkFrame::FormatNotSupported(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, false, aIsRcvBuffFull, FC_SEC_NOT_SUPPORTED, aDest, aSrc); +} + +//////////////////////////////////////////////////////////////////////// +// +// Outgoing frame formatting functions for Pri to Sec transactions +// +//////////////////////////////////////////////////////////////////////// + +void LinkFrame::FormatResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, false, false, FC_PRI_RESET_LINK_STATES, aDest, aSrc); +} + +void LinkFrame::FormatRequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, false, false, FC_PRI_REQUEST_LINK_STATUS, aDest, aSrc); +} + +void LinkFrame::FormatTestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) +{ + this->FormatHeader(0, aIsMaster, aFcb, true, FC_PRI_TEST_LINK_STATES, aDest, aSrc); +} + +void LinkFrame::FormatConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) +{ + assert(aDataLength > 0); + assert(aDataLength <= 250); + this->FormatHeader(aDataLength, aIsMaster, aFcb, true, FC_PRI_CONFIRMED_USER_DATA, aDest, aSrc); + WriteUserData(apData, mpBuffer + LS_HEADER_SIZE, aDataLength); +} + +void LinkFrame::FormatUnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const byte_t* apData, size_t aDataLength) +{ + assert(aDataLength > 0); + assert(aDataLength <= 250); + this->FormatHeader(aDataLength, aIsMaster, false, false, FC_PRI_UNCONFIRMED_USER_DATA, aDest, aSrc); + WriteUserData(apData, mpBuffer + LS_HEADER_SIZE, aDataLength); +} + +void LinkFrame::ChangeFCB(bool aFCB) +{ + if(mHeader.IsFcbSet() != aFCB) { + mHeader.ChangeFCB(aFCB); + mHeader.Write(mpBuffer); + } + +} + +void LinkFrame::FormatHeader(size_t aDataLength, bool aIsMaster, bool aFcb, bool aFcvDfc, FuncCodes aFuncCode, uint_16_t aDest, uint_16_t aSrc) +{ + mSize = this->CalcFrameSize(aDataLength); + + mHeader.Set(static_cast(aDataLength+LS_MIN_LENGTH), aSrc, aDest, aIsMaster, aFcvDfc, aFcb, aFuncCode); + mHeader.Write(mpBuffer); + + mIsComplete = true; +} + +void LinkFrame::WriteUserData(const apl::byte_t* apSrc, byte_t* apDest, size_t aLength) +{ + if(aLength == 0) return; + size_t max = LS_DATA_BLOCK_SIZE; + size_t num = aLength > max ? max : aLength; + memcpy(apDest, apSrc, num); + DNPCrc::AddCrc(apDest, num); + WriteUserData(apSrc+num, apDest+num+2, aLength-num); //tail recursive +} + +std::string LinkFrame::ToString() const +{ + return mHeader.ToString(); +} + +}} //end namespace diff --git a/DNP3/LinkFrame.h b/DNP3/LinkFrame.h index ed005fce..6fbe88c4 100644 --- a/DNP3/LinkFrame.h +++ b/DNP3/LinkFrame.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LINK_FRAME_H_ #define __LINK_FRAME_H_ @@ -39,17 +39,17 @@ class LinkFrame LinkFrame(); ~LinkFrame(); - + /* implement pure virtual functions from base class */ apl::byte_t* GetBuffer() { return mpBuffer; } const apl::byte_t* GetBuffer() const { return mpBuffer; } size_t GetSize() const { return mSize; } - bool IsComplete() const { return mIsComplete; } + bool IsComplete() const { return mIsComplete; } bool ValidateHeaderCRC() const; bool ValidateBodyCRC() const; - + // Helpers for extracting data inline bool Valid_0564() const { return mpBuffer[LI_START_05] == 0x05 && mpBuffer[LI_START_64] == 0x64; } @@ -103,22 +103,22 @@ class LinkFrame @return True if the body CRC is correct */ static bool ValidateBodyCRC(const byte_t* apBody, size_t aLength); - /** Reads data from src to dest removing 2 byte CRC checks every 16 data bytes + /** Reads data from src to dest removing 2 byte CRC checks every 16 data bytes @param apSrc Source buffer with crc checks. Must begin at data, not header @param apDest Destination buffer to which the data is extracted - @param aLength Length of user data to read to the dest buffer. The source buffer must be larger b/c of crc bytes. + @param aLength Length of user data to read to the dest buffer. The source buffer must be larger b/c of crc bytes. */ static void ReadUserData(const byte_t* apSrc, byte_t* apDest, size_t aLength); - + private: - /** Writes data from src to dest interlacing 2 byte CRC checks every 16 data bytes + /** Writes data from src to dest interlacing 2 byte CRC checks every 16 data bytes @param apSrc Source buffer full of user data @param apDest Destination buffer where the data + CRC is written @param aLength Number of user data bytes */ static void WriteUserData(const byte_t* apSrc, byte_t* apDest, size_t aLength); - + /** Write 10 header bytes to to buffer including 0x0564, all fields, and CRC */ void FormatHeader(size_t aDataLength, bool aIsMaster, bool aFcb, bool aFcvDfc, FuncCodes aCode, uint_16_t aDest, uint_16_t aSrc); diff --git a/DNP3/LinkHeader.cpp b/DNP3/LinkHeader.cpp index 93c89aae..57e99758 100644 --- a/DNP3/LinkHeader.cpp +++ b/DNP3/LinkHeader.cpp @@ -16,100 +16,100 @@ // specific language governing permissions and limitations // under the License. // -#include "LinkHeader.h" - -#include -#include "DNPCrc.h" - -#include - -using namespace std; - -namespace apl { namespace dnp { - -LinkHeader::LinkHeader(){} - -LinkHeader::LinkHeader(byte_t aLen, uint_16_t aSrc, uint_16_t aDest, bool aMaster, bool aFcvDfc, bool aFcb, FuncCodes aCode) : -length(aLen), -src(aSrc), -dest(aDest), -ctrl(ControlByte(aMaster, aFcb, aFcvDfc, aCode)) -{ - -} - -LinkHeader::LinkHeader(const byte_t* apBuff) -{ - this->Read(apBuff); -} - -void LinkHeader::Set(byte_t aLen, uint_16_t aSrc, uint_16_t aDest, bool aFromMaster, bool aFcvDfc, bool aFcb, FuncCodes aCode) -{ - length = aLen; - src = aSrc; - dest = aDest; - ctrl = ControlByte(aFromMaster, aFcb, aFcvDfc, aCode); -} - -void LinkHeader::ChangeFCB(bool aFCB) -{ - if(aFCB) ctrl |= MASK_FCB; - else ctrl &= ~MASK_FCB; -} - -byte_t LinkHeader::ControlByte(bool aIsMaster, bool aFcb, bool aFcvDfc, FuncCodes aFunc) -{ - byte_t ret = aFunc; - - if(aIsMaster) ret |= MASK_DIR; - if(aFcb) ret |= MASK_FCB; - if(aFcvDfc) ret |= MASK_FCV; - - return ret; -} - -void LinkHeader::Read(const byte_t* apBuff) -{ - length = apBuff[LI_LENGTH]; - dest = UInt16LE::Read(apBuff + LI_DESTINATION); - src = UInt16LE::Read(apBuff + LI_SOURCE); - ctrl = apBuff[LI_CONTROL]; -} - -void LinkHeader::Write(byte_t* apBuff) const -{ - apBuff[LI_START_05] = 0x05; - apBuff[LI_START_64]= 0x64; - - apBuff[LI_LENGTH] = length; - UInt16LE::Write(apBuff+LI_DESTINATION, dest); - UInt16LE::Write(apBuff+LI_SOURCE, src); - apBuff[LI_CONTROL] = ctrl; - - DNPCrc::AddCrc(apBuff, LI_CRC); -} - -std::string LinkHeader::ToString() const -{ - ostringstream oss; - oss << "DL " << this->GetSrc() << " to " << this->GetDest(); - oss << " : " << FuncCodeToString(this->GetFuncEnum()); - oss << " PayloadSize: " << (this->GetLength() - 5); - oss << ((this->IsFromMaster())?" From Master":" From Outstation"); - if(this->IsPriToSec()) - { - oss << " Pri->Sec"; - oss << " FCB=" << this->IsFcbSet() << " FCV=" << this->IsFcvDfcSet(); - } - else - { - oss << " Sec->Pri"; - if(this->IsFcbSet()) oss << " ERROR: FCB not Blank!!"; - oss << " DFC=" << this->IsFcvDfcSet(); - } - - return oss.str(); -} - -}} - +#include "LinkHeader.h" + +#include +#include "DNPCrc.h" + +#include + +using namespace std; + +namespace apl { namespace dnp { + +LinkHeader::LinkHeader(){} + +LinkHeader::LinkHeader(byte_t aLen, uint_16_t aSrc, uint_16_t aDest, bool aMaster, bool aFcvDfc, bool aFcb, FuncCodes aCode) : +length(aLen), +src(aSrc), +dest(aDest), +ctrl(ControlByte(aMaster, aFcb, aFcvDfc, aCode)) +{ + +} + +LinkHeader::LinkHeader(const byte_t* apBuff) +{ + this->Read(apBuff); +} + +void LinkHeader::Set(byte_t aLen, uint_16_t aSrc, uint_16_t aDest, bool aFromMaster, bool aFcvDfc, bool aFcb, FuncCodes aCode) +{ + length = aLen; + src = aSrc; + dest = aDest; + ctrl = ControlByte(aFromMaster, aFcb, aFcvDfc, aCode); +} + +void LinkHeader::ChangeFCB(bool aFCB) +{ + if(aFCB) ctrl |= MASK_FCB; + else ctrl &= ~MASK_FCB; +} + +byte_t LinkHeader::ControlByte(bool aIsMaster, bool aFcb, bool aFcvDfc, FuncCodes aFunc) +{ + byte_t ret = aFunc; + + if(aIsMaster) ret |= MASK_DIR; + if(aFcb) ret |= MASK_FCB; + if(aFcvDfc) ret |= MASK_FCV; + + return ret; +} + +void LinkHeader::Read(const byte_t* apBuff) +{ + length = apBuff[LI_LENGTH]; + dest = UInt16LE::Read(apBuff + LI_DESTINATION); + src = UInt16LE::Read(apBuff + LI_SOURCE); + ctrl = apBuff[LI_CONTROL]; +} + +void LinkHeader::Write(byte_t* apBuff) const +{ + apBuff[LI_START_05] = 0x05; + apBuff[LI_START_64]= 0x64; + + apBuff[LI_LENGTH] = length; + UInt16LE::Write(apBuff+LI_DESTINATION, dest); + UInt16LE::Write(apBuff+LI_SOURCE, src); + apBuff[LI_CONTROL] = ctrl; + + DNPCrc::AddCrc(apBuff, LI_CRC); +} + +std::string LinkHeader::ToString() const +{ + ostringstream oss; + oss << "DL " << this->GetSrc() << " to " << this->GetDest(); + oss << " : " << FuncCodeToString(this->GetFuncEnum()); + oss << " PayloadSize: " << (this->GetLength() - 5); + oss << ((this->IsFromMaster())?" From Master":" From Outstation"); + if(this->IsPriToSec()) + { + oss << " Pri->Sec"; + oss << " FCB=" << this->IsFcbSet() << " FCV=" << this->IsFcvDfcSet(); + } + else + { + oss << " Sec->Pri"; + if(this->IsFcbSet()) oss << " ERROR: FCB not Blank!!"; + oss << " DFC=" << this->IsFcvDfcSet(); + } + + return oss.str(); +} + +}} + diff --git a/DNP3/LinkHeader.h b/DNP3/LinkHeader.h index 170a00f2..345b238c 100644 --- a/DNP3/LinkHeader.h +++ b/DNP3/LinkHeader.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LINK_HEADER_H_ #define __LINK_HEADER_H_ @@ -27,7 +27,7 @@ namespace apl { namespace dnp { /// Class for dealing with all aspects of FT3 Frame headers struct LinkHeader { - LinkHeader(); + LinkHeader(); LinkHeader(byte_t aLen, uint_16_t aSrc, uint_16_t aDest, bool aFromMaster, bool aFcvDfc, bool aFcb, FuncCodes aCode); diff --git a/DNP3/LinkLayerConstants.h b/DNP3/LinkLayerConstants.h index c4c68365..a4ec4a56 100644 --- a/DNP3/LinkLayerConstants.h +++ b/DNP3/LinkLayerConstants.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LINK_LAYER_CONSTANTS_ #define __LINK_LAYER_CONSTANTS_ @@ -53,10 +53,10 @@ namespace apl { namespace dnp { /** These func codes are a little different then those defined in the specification for the following reason. For simplicity the PRM bit is included to make the Pri-To-Sec and Sec-To-Pri codes non-overlapping - This is much simplier and for all intents and purposes you don't have to deal with the PRM bit anymore. - + This is much simplier and for all intents and purposes you don't have to deal with the PRM bit anymore. + No implementation of function code 1: - + 2004-03-29_DNP3_Doc_Library.pdf: Page 526. DNP3 does not define any action associated with the Data Link Layer Reset User Process request function code. Support of this function is not required. Function code 1 is now obsolete. @@ -64,8 +64,8 @@ namespace apl { namespace dnp { enum FuncCodes { // Pri-To-Sec functions, add 0x40 to each to for the PRM bit - FC_PRI_RESET_LINK_STATES = 0x40, - FC_PRI_TEST_LINK_STATES = 0x42, + FC_PRI_RESET_LINK_STATES = 0x40, + FC_PRI_TEST_LINK_STATES = 0x42, FC_PRI_CONFIRMED_USER_DATA = 0x43, FC_PRI_UNCONFIRMED_USER_DATA = 0x44, FC_PRI_REQUEST_LINK_STATUS = 0x49, @@ -82,7 +82,7 @@ namespace apl { namespace dnp { /** @param aByte Any byte @return Returns FC_INVALID if byte is not a valid function code */ FuncCodes ByteToFuncCode(byte_t aByte); - + /** @param aCode Any function code @return Returns string representation */ std::string FuncCodeToString(FuncCodes aCode); @@ -95,7 +95,7 @@ namespace apl { namespace dnp { MASK_FCB = 0x20, MASK_FCV = 0x10, MASK_FUNC = 0x0F, - MASK_FUNC_OR_PRM = MASK_PRM|MASK_FUNC + MASK_FUNC_OR_PRM = MASK_PRM|MASK_FUNC }; }} diff --git a/DNP3/LinkLayerReceiver.cpp b/DNP3/LinkLayerReceiver.cpp index d393098f..caade66c 100644 --- a/DNP3/LinkLayerReceiver.cpp +++ b/DNP3/LinkLayerReceiver.cpp @@ -1,254 +1,254 @@ -// -// Licensed to Green Energy Corp (www.greenenergycorp.com) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. Green Enery Corp licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// -#include -#include -#include - -#include "DNPCrc.h" -#include "LinkReceiverStates.h" -#include "IFrameSink.h" - -namespace apl { namespace dnp { - -const byte_t LinkLayerReceiver::M_SYNC_PATTERN[2] = {0x05, 0x64}; - -LinkLayerReceiver::LinkLayerReceiver(Logger* apLogger, IFrameSink* apSink) : -Loggable(apLogger), -mFrameSize(0), -mpSink(apSink), -mpState(LRS_Sync::Inst()), -mBuffer(BUFFER_SIZE), -mCrcFailures(apLogger, "crc_failure") -{ - -} - -void LinkLayerReceiver::OnRead(size_t aNumBytes) -{ - // This is a serious condition if it occurs - // It indicates a possible buffer over run - assert(aNumBytes <= mBuffer.NumWriteBytes()); - mBuffer.AdvanceWrite(aNumBytes); - - // this might push frame data to the sink and will free - // space in the buffer - while(mpState->Parse(this)); - - //anytime we have a partially incomplete frame, shift the buffer - mBuffer.Shift(); -} - -void LinkLayerReceiver::PushFrame() -{ - switch(mHeader.GetFuncEnum()) { - case(FC_PRI_RESET_LINK_STATES): - mpSink->ResetLinkStates(mHeader.IsFromMaster(), mHeader.GetDest(), mHeader.GetSrc()); - break; - case(FC_PRI_TEST_LINK_STATES): - mpSink->TestLinkStatus(mHeader.IsFromMaster(), mHeader.IsFcbSet(), mHeader.GetDest(), mHeader.GetSrc()); - break; - case(FC_PRI_CONFIRMED_USER_DATA): - mpSink->ConfirmedUserData(mHeader.IsFromMaster(), mHeader.IsFcbSet(), mHeader.GetDest(), mHeader.GetSrc(), - mpUserData, TransferUserData()); - break; - case(FC_PRI_UNCONFIRMED_USER_DATA): - mpSink->UnconfirmedUserData(mHeader.IsFromMaster(), mHeader.GetDest(), mHeader.GetSrc(), - mpUserData, TransferUserData()); - break; - case(FC_PRI_REQUEST_LINK_STATUS): - mpSink->RequestLinkStatus(mHeader.IsFromMaster(), mHeader.GetDest(), mHeader.GetSrc()); - break; - case(FC_SEC_ACK): - mpSink->Ack(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); - break; - case(FC_SEC_NACK): - mpSink->Nack(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); - break; - case(FC_SEC_LINK_STATUS): - mpSink->LinkStatus(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); - break; - case(FC_SEC_NOT_SUPPORTED): - mpSink->NotSupported(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); - break; - default: - break; - } - - mBuffer.AdvanceRead(mFrameSize); -} - -size_t LinkLayerReceiver::TransferUserData() -{ - size_t len = mHeader.GetLength() - LS_MIN_LENGTH; - LinkFrame::ReadUserData(mBuffer.ReadBuff()+LS_HEADER_SIZE, mpUserData, len); - return len; -} - -bool LinkLayerReceiver::ReadHeader() -{ - mHeader.Read(mBuffer.ReadBuff()); - return this->ValidateHeader(); -} - -bool LinkLayerReceiver::ValidateBody() -{ - size_t len = mHeader.GetLength() - LS_MIN_LENGTH; - if(LinkFrame::ValidateBodyCRC(mBuffer.ReadBuff()+LS_HEADER_SIZE, len)) return true; - else - { - mCrcFailures.Increment(); - ERROR_BLOCK(LEV_ERROR, "CRC failure in body", DLERR_CRC); - return false; - } -} - -bool LinkLayerReceiver::ValidateHeader() -{ - //first thing to do is check the CRC - if(!DNPCrc::IsCorrectCRC(mBuffer.ReadBuff(),LI_CRC)) { - mCrcFailures.Increment(); - ERROR_BLOCK(LEV_ERROR, "CRC failure in header", DLERR_CRC); - return false; - } - - if(!mHeader.ValidLength()) { - ERROR_BLOCK(LEV_ERROR, "LENGTH out of range [5,255]: " << static_cast(mHeader.GetLength()), DLERR_INVALID_LENGTH); - return false; - } - - LOG_BLOCK(LEV_INTERPRET, "<~ " << mHeader.ToString()); - - // some combinations of these header parameters are invalid - // check for them here - - //Now make sure that the function code is known and that the FCV is appropriate - if(!this->ValidateFunctionCode()) return false; - - byte_t user_data_length = mHeader.GetLength() - LS_MIN_LENGTH; - mFrameSize = LinkFrame::CalcFrameSize(user_data_length); - FuncCodes func = mHeader.GetFuncEnum(); - - // make sure that the presence/absence of user data - // matches the function code - if(func == FC_PRI_CONFIRMED_USER_DATA || func == FC_PRI_UNCONFIRMED_USER_DATA) { - if(user_data_length > 0) { - //mFrameSize = LinkFrame::CalcFrameSize(user_data_length); - } - else { - ERROR_BLOCK(LEV_ERROR, "User data packet received with zero payload. FUNCTION: " << func, DLERR_NO_DATA); - return false; - } - } - else - { - if(user_data_length > 0) { - ERROR_BLOCK(LEV_ERROR, "Unexpected LENGTH in frame: " << static_cast(user_data_length) << " with FUNCTION: " << func, DLERR_UNEXPECTED_DATA); - return false; - } - - } - - if(user_data_length > 0) { - if(func == FC_PRI_CONFIRMED_USER_DATA || func == FC_PRI_UNCONFIRMED_USER_DATA) { - - } - else { - ERROR_BLOCK(LEV_ERROR, "Unexpected LENGTH in frame: " << static_cast(user_data_length) << " with FUNCTION: " << func, DLERR_UNEXPECTED_DATA); - return false; - } - } - else { - if(func == FC_PRI_CONFIRMED_USER_DATA || func == FC_PRI_UNCONFIRMED_USER_DATA) { - ERROR_BLOCK(LEV_ERROR, "User data packet received with zero payload. FUNCTION: " << func, DLERR_NO_DATA); - return false; - } - } - - return true; -} - -void LinkLayerReceiver::FailFrame() { - // All you have to do is advance the reader by one, when the resync happens the data will disappear - mBuffer.AdvanceRead(1); -} - -bool LinkLayerReceiver::ValidateFunctionCode() -{ - //Now make sure that the function code is known and that the FCV is appropriate - if(mHeader.IsPriToSec()) - { - bool fcv_set = false; - - switch(mHeader.GetFuncEnum()) - { - case(FC_PRI_CONFIRMED_USER_DATA): - case(FC_PRI_TEST_LINK_STATES): - fcv_set = true; - break; - case(FC_PRI_REQUEST_LINK_STATUS): - case(FC_PRI_RESET_LINK_STATES): - case(FC_PRI_UNCONFIRMED_USER_DATA): - break; - default: - { - ERROR_BLOCK(LEV_WARNING, "Unknown PriToSec FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNKNOWN_FUNC); - return false; - } - } - - //now check the fcv - if(fcv_set != mHeader.IsFcvDfcSet()) - { - ERROR_BLOCK(LEV_WARNING, "Bad FCV for FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNEXPECTED_FCV); - return false; - } - - //if fcv isn't expected to be set, fcb can be either 1 or 0, doesn't matter - - } - else // SecToPri - just validate the function codes and that FCB is 0 - { - switch(mHeader.GetFuncEnum()) - { - case(FC_SEC_ACK): - case(FC_SEC_NACK): - case(FC_SEC_LINK_STATUS): - case(FC_SEC_NOT_SUPPORTED): - break; - default: - { - ERROR_BLOCK(LEV_ERROR, "Unknown SecToPri FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNKNOWN_FUNC); - return false; - } - } - - //now check the fcb, it should always be zero - if(mHeader.IsFcbSet()) - { - ERROR_BLOCK(LEV_ERROR, "FCB set for SecToPri FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNEXPECTED_FCB); - return false; - } - } - - return true; //valid! -} - - - -}} +// +// Licensed to Green Energy Corp (www.greenenergycorp.com) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. Green Enery Corp licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +#include +#include +#include + +#include "DNPCrc.h" +#include "LinkReceiverStates.h" +#include "IFrameSink.h" + +namespace apl { namespace dnp { + +const byte_t LinkLayerReceiver::M_SYNC_PATTERN[2] = {0x05, 0x64}; + +LinkLayerReceiver::LinkLayerReceiver(Logger* apLogger, IFrameSink* apSink) : +Loggable(apLogger), +mFrameSize(0), +mpSink(apSink), +mpState(LRS_Sync::Inst()), +mBuffer(BUFFER_SIZE), +mCrcFailures(apLogger, "crc_failure") +{ + +} + +void LinkLayerReceiver::OnRead(size_t aNumBytes) +{ + // This is a serious condition if it occurs + // It indicates a possible buffer over run + assert(aNumBytes <= mBuffer.NumWriteBytes()); + mBuffer.AdvanceWrite(aNumBytes); + + // this might push frame data to the sink and will free + // space in the buffer + while(mpState->Parse(this)); + + //anytime we have a partially incomplete frame, shift the buffer + mBuffer.Shift(); +} + +void LinkLayerReceiver::PushFrame() +{ + switch(mHeader.GetFuncEnum()) { + case(FC_PRI_RESET_LINK_STATES): + mpSink->ResetLinkStates(mHeader.IsFromMaster(), mHeader.GetDest(), mHeader.GetSrc()); + break; + case(FC_PRI_TEST_LINK_STATES): + mpSink->TestLinkStatus(mHeader.IsFromMaster(), mHeader.IsFcbSet(), mHeader.GetDest(), mHeader.GetSrc()); + break; + case(FC_PRI_CONFIRMED_USER_DATA): + mpSink->ConfirmedUserData(mHeader.IsFromMaster(), mHeader.IsFcbSet(), mHeader.GetDest(), mHeader.GetSrc(), + mpUserData, TransferUserData()); + break; + case(FC_PRI_UNCONFIRMED_USER_DATA): + mpSink->UnconfirmedUserData(mHeader.IsFromMaster(), mHeader.GetDest(), mHeader.GetSrc(), + mpUserData, TransferUserData()); + break; + case(FC_PRI_REQUEST_LINK_STATUS): + mpSink->RequestLinkStatus(mHeader.IsFromMaster(), mHeader.GetDest(), mHeader.GetSrc()); + break; + case(FC_SEC_ACK): + mpSink->Ack(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); + break; + case(FC_SEC_NACK): + mpSink->Nack(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); + break; + case(FC_SEC_LINK_STATUS): + mpSink->LinkStatus(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); + break; + case(FC_SEC_NOT_SUPPORTED): + mpSink->NotSupported(mHeader.IsFromMaster(), mHeader.IsFcvDfcSet(), mHeader.GetDest(), mHeader.GetSrc()); + break; + default: + break; + } + + mBuffer.AdvanceRead(mFrameSize); +} + +size_t LinkLayerReceiver::TransferUserData() +{ + size_t len = mHeader.GetLength() - LS_MIN_LENGTH; + LinkFrame::ReadUserData(mBuffer.ReadBuff()+LS_HEADER_SIZE, mpUserData, len); + return len; +} + +bool LinkLayerReceiver::ReadHeader() +{ + mHeader.Read(mBuffer.ReadBuff()); + return this->ValidateHeader(); +} + +bool LinkLayerReceiver::ValidateBody() +{ + size_t len = mHeader.GetLength() - LS_MIN_LENGTH; + if(LinkFrame::ValidateBodyCRC(mBuffer.ReadBuff()+LS_HEADER_SIZE, len)) return true; + else + { + mCrcFailures.Increment(); + ERROR_BLOCK(LEV_ERROR, "CRC failure in body", DLERR_CRC); + return false; + } +} + +bool LinkLayerReceiver::ValidateHeader() +{ + //first thing to do is check the CRC + if(!DNPCrc::IsCorrectCRC(mBuffer.ReadBuff(),LI_CRC)) { + mCrcFailures.Increment(); + ERROR_BLOCK(LEV_ERROR, "CRC failure in header", DLERR_CRC); + return false; + } + + if(!mHeader.ValidLength()) { + ERROR_BLOCK(LEV_ERROR, "LENGTH out of range [5,255]: " << static_cast(mHeader.GetLength()), DLERR_INVALID_LENGTH); + return false; + } + + LOG_BLOCK(LEV_INTERPRET, "<~ " << mHeader.ToString()); + + // some combinations of these header parameters are invalid + // check for them here + + //Now make sure that the function code is known and that the FCV is appropriate + if(!this->ValidateFunctionCode()) return false; + + byte_t user_data_length = mHeader.GetLength() - LS_MIN_LENGTH; + mFrameSize = LinkFrame::CalcFrameSize(user_data_length); + FuncCodes func = mHeader.GetFuncEnum(); + + // make sure that the presence/absence of user data + // matches the function code + if(func == FC_PRI_CONFIRMED_USER_DATA || func == FC_PRI_UNCONFIRMED_USER_DATA) { + if(user_data_length > 0) { + //mFrameSize = LinkFrame::CalcFrameSize(user_data_length); + } + else { + ERROR_BLOCK(LEV_ERROR, "User data packet received with zero payload. FUNCTION: " << func, DLERR_NO_DATA); + return false; + } + } + else + { + if(user_data_length > 0) { + ERROR_BLOCK(LEV_ERROR, "Unexpected LENGTH in frame: " << static_cast(user_data_length) << " with FUNCTION: " << func, DLERR_UNEXPECTED_DATA); + return false; + } + + } + + if(user_data_length > 0) { + if(func == FC_PRI_CONFIRMED_USER_DATA || func == FC_PRI_UNCONFIRMED_USER_DATA) { + + } + else { + ERROR_BLOCK(LEV_ERROR, "Unexpected LENGTH in frame: " << static_cast(user_data_length) << " with FUNCTION: " << func, DLERR_UNEXPECTED_DATA); + return false; + } + } + else { + if(func == FC_PRI_CONFIRMED_USER_DATA || func == FC_PRI_UNCONFIRMED_USER_DATA) { + ERROR_BLOCK(LEV_ERROR, "User data packet received with zero payload. FUNCTION: " << func, DLERR_NO_DATA); + return false; + } + } + + return true; +} + +void LinkLayerReceiver::FailFrame() { + // All you have to do is advance the reader by one, when the resync happens the data will disappear + mBuffer.AdvanceRead(1); +} + +bool LinkLayerReceiver::ValidateFunctionCode() +{ + //Now make sure that the function code is known and that the FCV is appropriate + if(mHeader.IsPriToSec()) + { + bool fcv_set = false; + + switch(mHeader.GetFuncEnum()) + { + case(FC_PRI_CONFIRMED_USER_DATA): + case(FC_PRI_TEST_LINK_STATES): + fcv_set = true; + break; + case(FC_PRI_REQUEST_LINK_STATUS): + case(FC_PRI_RESET_LINK_STATES): + case(FC_PRI_UNCONFIRMED_USER_DATA): + break; + default: + { + ERROR_BLOCK(LEV_WARNING, "Unknown PriToSec FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNKNOWN_FUNC); + return false; + } + } + + //now check the fcv + if(fcv_set != mHeader.IsFcvDfcSet()) + { + ERROR_BLOCK(LEV_WARNING, "Bad FCV for FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNEXPECTED_FCV); + return false; + } + + //if fcv isn't expected to be set, fcb can be either 1 or 0, doesn't matter + + } + else // SecToPri - just validate the function codes and that FCB is 0 + { + switch(mHeader.GetFuncEnum()) + { + case(FC_SEC_ACK): + case(FC_SEC_NACK): + case(FC_SEC_LINK_STATUS): + case(FC_SEC_NOT_SUPPORTED): + break; + default: + { + ERROR_BLOCK(LEV_ERROR, "Unknown SecToPri FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNKNOWN_FUNC); + return false; + } + } + + //now check the fcb, it should always be zero + if(mHeader.IsFcbSet()) + { + ERROR_BLOCK(LEV_ERROR, "FCB set for SecToPri FUNCTION: " << mHeader.GetFuncEnum(), DLERR_UNEXPECTED_FCB); + return false; + } + } + + return true; //valid! +} + + + +}} diff --git a/DNP3/LinkLayerReceiver.h b/DNP3/LinkLayerReceiver.h index 8a2d65ee..13acfbed 100644 --- a/DNP3/LinkLayerReceiver.h +++ b/DNP3/LinkLayerReceiver.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LINK_LAYER_RECEIVER_H_ #define __LINK_LAYER_RECEIVER_H_ @@ -91,7 +91,7 @@ class LinkLayerReceiver : public Loggable LRS_Base* mpState; /// Buffer to which user data is extracted, this is necessary since CRC checks are interlaced - byte_t mpUserData[LS_MAX_USER_DATA_SIZE]; + byte_t mpUserData[LS_MAX_USER_DATA_SIZE]; ShiftableBuffer mBuffer; ///Buffer used to cache frames data as it arrives LogCounter mCrcFailures; }; diff --git a/DNP3/LinkReceiverStates.cpp b/DNP3/LinkReceiverStates.cpp index 7fba34da..33217238 100644 --- a/DNP3/LinkReceiverStates.cpp +++ b/DNP3/LinkReceiverStates.cpp @@ -16,77 +16,77 @@ // specific language governing permissions and limitations // under the License. // -#include "LinkReceiverStates.h" - -#include -#include "LinkLayerReceiver.h" -#include -#include "DNPCrc.h" -#include - - -namespace apl { namespace dnp { - -///////////////////////////////////////////////////// -// Base class -///////////////////////////////////////////////////// - -bool LRS_Base::Parse(LinkLayerReceiver*) -{ - throw InvalidStateException(LOCATION, this->Name()); -} - -///////////////////////////////////////////////////// -// Inherited States -///////////////////////////////////////////////////// - -LRS_Sync LRS_Sync::mInstance; - -bool LRS_Sync::Parse(LinkLayerReceiver* c) -{ - if(c->NumReadBytes() < 2) return false; - else { - if(c->Sync0564()) c->ChangeState(LRS_Header::Inst()); - return true; - } -} - -LRS_Header LRS_Header::mInstance; - -bool LRS_Header::Parse(LinkLayerReceiver* c) -{ - if(c->NumReadBytes() < 10) return false; - else { - if(c->ReadHeader()) { - c->ChangeState(LRS_Body::Inst()); - } - else { - c->FailFrame(); - c->ChangeState(LRS_Sync::Inst()); - } - return true; - } -} - -LRS_Body LRS_Body::mInstance; - -bool LRS_Body::Parse(LinkLayerReceiver* c) -{ - if(c->NumReadBytes() < c->mFrameSize) return false; - else { - if(c->ValidateBody()) { - c->PushFrame(); - c->ChangeState(LRS_Sync::Inst()); - } - else { - c->FailFrame(); - c->ChangeState(LRS_Sync::Inst()); - } - return true; - } -} - - - - -}} +#include "LinkReceiverStates.h" + +#include +#include "LinkLayerReceiver.h" +#include +#include "DNPCrc.h" +#include + + +namespace apl { namespace dnp { + +///////////////////////////////////////////////////// +// Base class +///////////////////////////////////////////////////// + +bool LRS_Base::Parse(LinkLayerReceiver*) +{ + throw InvalidStateException(LOCATION, this->Name()); +} + +///////////////////////////////////////////////////// +// Inherited States +///////////////////////////////////////////////////// + +LRS_Sync LRS_Sync::mInstance; + +bool LRS_Sync::Parse(LinkLayerReceiver* c) +{ + if(c->NumReadBytes() < 2) return false; + else { + if(c->Sync0564()) c->ChangeState(LRS_Header::Inst()); + return true; + } +} + +LRS_Header LRS_Header::mInstance; + +bool LRS_Header::Parse(LinkLayerReceiver* c) +{ + if(c->NumReadBytes() < 10) return false; + else { + if(c->ReadHeader()) { + c->ChangeState(LRS_Body::Inst()); + } + else { + c->FailFrame(); + c->ChangeState(LRS_Sync::Inst()); + } + return true; + } +} + +LRS_Body LRS_Body::mInstance; + +bool LRS_Body::Parse(LinkLayerReceiver* c) +{ + if(c->NumReadBytes() < c->mFrameSize) return false; + else { + if(c->ValidateBody()) { + c->PushFrame(); + c->ChangeState(LRS_Sync::Inst()); + } + else { + c->FailFrame(); + c->ChangeState(LRS_Sync::Inst()); + } + return true; + } +} + + + + +}} diff --git a/DNP3/LinkReceiverStates.h b/DNP3/LinkReceiverStates.h index 1a56b820..e9103fd4 100644 --- a/DNP3/LinkReceiverStates.h +++ b/DNP3/LinkReceiverStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __LINK_RECEIVER_STATES_H_ #define __LINK_RECEIVER_STATES_H_ @@ -33,7 +33,7 @@ class LRS_Base : private Uncopyable public: virtual ~LRS_Base(){} - + /** Perform a bit of work towards reading a frame. @return True if the function can be called again to make further progress */ virtual bool Parse(LinkLayerReceiver*); diff --git a/DNP3/MasterConfig.h b/DNP3/MasterConfig.h index cff8c72a..c2cade51 100644 --- a/DNP3/MasterConfig.h +++ b/DNP3/MasterConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,79 +6,79 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MASTER_CONFIG_H_ -#define __MASTER_CONFIG_H_ - -#include "DNPConstants.h" -#include "PointClass.h" -#include "MasterConfigTypes.h" - -#include - -namespace apl { namespace dnp { - -/** -Configuration information for the dnp3 master -*/ -struct MasterConfig -{ - /// Default constructor - MasterConfig() : - FragSize(DEFAULT_FRAG_SIZE), - AllowTimeSync(true), - DoUnsolOnStartup(false), - EnableUnsol(true), - UnsolClassMask(PC_ALL_EVENTS), - IntegrityRate(5000), - TaskRetryRate(5000) - {} - - /** Adds a periodic exception scan to the configuration - - @param aClassMask Bitwise mask representing the classes to scan - @param aPeriod Period of the scan in milliseconds - */ - void AddExceptionScan(int aClassMask, millis_t aPeriod) - { - ExceptionScan ex = { aClassMask, aPeriod }; - mScans.push_back(ex); - } - - /// Maximum fragment size to use for requests - size_t FragSize; - - /// If true, the master will do time syncs when it sees the time IIN bit from the slave - bool AllowTimeSync; - - /// If true, the master will enable/disable unsol on startup - bool DoUnsolOnStartup; - - /// If DoUnsolOnStartup == true, the master will use this bit to decide wether to enable (true) or disable (false) - bool EnableUnsol; - - /// Bitwise mask used determine which classes are enabled/disabled for unsol - int UnsolClassMask; - - /// Period for integrity scans (class 0), -1 for non periodic - millis_t IntegrityRate; - - /// Time delay between task retries - millis_t TaskRetryRate; - - ///vector that holds exception scans - std::vector mScans; -}; - -}} - -#endif +// +#ifndef __MASTER_CONFIG_H_ +#define __MASTER_CONFIG_H_ + +#include "DNPConstants.h" +#include "PointClass.h" +#include "MasterConfigTypes.h" + +#include + +namespace apl { namespace dnp { + +/** +Configuration information for the dnp3 master +*/ +struct MasterConfig +{ + /// Default constructor + MasterConfig() : + FragSize(DEFAULT_FRAG_SIZE), + AllowTimeSync(true), + DoUnsolOnStartup(false), + EnableUnsol(true), + UnsolClassMask(PC_ALL_EVENTS), + IntegrityRate(5000), + TaskRetryRate(5000) + {} + + /** Adds a periodic exception scan to the configuration + + @param aClassMask Bitwise mask representing the classes to scan + @param aPeriod Period of the scan in milliseconds + */ + void AddExceptionScan(int aClassMask, millis_t aPeriod) + { + ExceptionScan ex = { aClassMask, aPeriod }; + mScans.push_back(ex); + } + + /// Maximum fragment size to use for requests + size_t FragSize; + + /// If true, the master will do time syncs when it sees the time IIN bit from the slave + bool AllowTimeSync; + + /// If true, the master will enable/disable unsol on startup + bool DoUnsolOnStartup; + + /// If DoUnsolOnStartup == true, the master will use this bit to decide wether to enable (true) or disable (false) + bool EnableUnsol; + + /// Bitwise mask used determine which classes are enabled/disabled for unsol + int UnsolClassMask; + + /// Period for integrity scans (class 0), -1 for non periodic + millis_t IntegrityRate; + + /// Time delay between task retries + millis_t TaskRetryRate; + + ///vector that holds exception scans + std::vector mScans; +}; + +}} + +#endif diff --git a/DNP3/MasterConfigTypes.h b/DNP3/MasterConfigTypes.h index 35dff1b4..3d9f1118 100644 --- a/DNP3/MasterConfigTypes.h +++ b/DNP3/MasterConfigTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,30 +6,30 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __EXCEPTION_SCAN_H_ -#define __EXCEPTION_SCAN_H_ - -#include - -namespace apl { namespace dnp { - -struct ExceptionScan -{ - int ClassMask; - millis_t ScanRate; -}; - -}} - -#endif - +// +#ifndef __EXCEPTION_SCAN_H_ +#define __EXCEPTION_SCAN_H_ + +#include + +namespace apl { namespace dnp { + +struct ExceptionScan +{ + int ClassMask; + millis_t ScanRate; +}; + +}} + +#endif + diff --git a/DNP3/MasterStackConfig.h b/DNP3/MasterStackConfig.h index cd74883f..9a3dbdcd 100644 --- a/DNP3/MasterStackConfig.h +++ b/DNP3/MasterStackConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,40 +6,40 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MASTER_STACK_CONFIG_H_ -#define __MASTER_STACK_CONFIG_H_ - -#include "MasterConfig.h" -#include "AppConfig.h" -#include "LinkConfig.h" - -namespace apl { namespace dnp { - -/** A composite configuration struct that contains all the config - information for a dnp3 master stack -*/ -struct MasterStackConfig -{ - MasterStackConfig() : - link(true, false) - {} - - MasterConfig master; /// Master config - AppConfig app; /// Application layer config - LinkConfig link; /// Link layer config -}; - -}} - -#endif - +// +#ifndef __MASTER_STACK_CONFIG_H_ +#define __MASTER_STACK_CONFIG_H_ + +#include "MasterConfig.h" +#include "AppConfig.h" +#include "LinkConfig.h" + +namespace apl { namespace dnp { + +/** A composite configuration struct that contains all the config + information for a dnp3 master stack +*/ +struct MasterStackConfig +{ + MasterStackConfig() : + link(true, false) + {} + + MasterConfig master; /// Master config + AppConfig app; /// Application layer config + LinkConfig link; /// Link layer config +}; + +}} + +#endif + diff --git a/DNP3/ObjectHeader.cpp b/DNP3/ObjectHeader.cpp index 6ddb0afa..dad19997 100644 --- a/DNP3/ObjectHeader.cpp +++ b/DNP3/ObjectHeader.cpp @@ -16,60 +16,60 @@ // specific language governing permissions and limitations // under the License. // -#include "ObjectHeader.h" - - -#include - -using namespace apl; - -namespace apl { namespace dnp { - - AllObjectsHeader AllObjectsHeader::mInstance; - -#define MACRO_CASE_DEFINE(enm) case(enm): return enm; - - QualifierCode IObjectHeader::ByteToQualifierCode(byte_t aCode) - { - switch(aCode) - { - MACRO_CASE_DEFINE(QC_1B_START_STOP) - MACRO_CASE_DEFINE(QC_2B_START_STOP) - MACRO_CASE_DEFINE(QC_4B_START_STOP) - - MACRO_CASE_DEFINE(QC_ALL_OBJ) - - MACRO_CASE_DEFINE(QC_1B_CNT) - MACRO_CASE_DEFINE(QC_2B_CNT) - MACRO_CASE_DEFINE(QC_4B_CNT) - - MACRO_CASE_DEFINE(QC_1B_CNT_1B_INDEX) - MACRO_CASE_DEFINE(QC_2B_CNT_2B_INDEX) - MACRO_CASE_DEFINE(QC_4B_CNT_4B_INDEX) - - MACRO_CASE_DEFINE(QC_1B_VCNT_1B_SIZE) - MACRO_CASE_DEFINE(QC_1B_VCNT_2B_SIZE) - MACRO_CASE_DEFINE(QC_1B_VCNT_4B_SIZE) - - default: - return QC_UNDEFINED; - } - } - - - void IObjectHeader::Get(const byte_t* apStart, ObjectHeaderField& arData) const - { - arData.Group = *(apStart); - arData.Variation = *(++apStart); - arData.Qualifier = IObjectHeader::ByteToQualifierCode(*(++apStart)); - } - - void IObjectHeader::Set(apl::byte_t* apStart, byte_t aGrp, byte_t aVar, QualifierCode aQual) const - { - *(apStart) = aGrp; - *(++apStart) = aVar; - *(++apStart) = aQual; - } - - -}} +#include "ObjectHeader.h" + + +#include + +using namespace apl; + +namespace apl { namespace dnp { + + AllObjectsHeader AllObjectsHeader::mInstance; + +#define MACRO_CASE_DEFINE(enm) case(enm): return enm; + + QualifierCode IObjectHeader::ByteToQualifierCode(byte_t aCode) + { + switch(aCode) + { + MACRO_CASE_DEFINE(QC_1B_START_STOP) + MACRO_CASE_DEFINE(QC_2B_START_STOP) + MACRO_CASE_DEFINE(QC_4B_START_STOP) + + MACRO_CASE_DEFINE(QC_ALL_OBJ) + + MACRO_CASE_DEFINE(QC_1B_CNT) + MACRO_CASE_DEFINE(QC_2B_CNT) + MACRO_CASE_DEFINE(QC_4B_CNT) + + MACRO_CASE_DEFINE(QC_1B_CNT_1B_INDEX) + MACRO_CASE_DEFINE(QC_2B_CNT_2B_INDEX) + MACRO_CASE_DEFINE(QC_4B_CNT_4B_INDEX) + + MACRO_CASE_DEFINE(QC_1B_VCNT_1B_SIZE) + MACRO_CASE_DEFINE(QC_1B_VCNT_2B_SIZE) + MACRO_CASE_DEFINE(QC_1B_VCNT_4B_SIZE) + + default: + return QC_UNDEFINED; + } + } + + + void IObjectHeader::Get(const byte_t* apStart, ObjectHeaderField& arData) const + { + arData.Group = *(apStart); + arData.Variation = *(++apStart); + arData.Qualifier = IObjectHeader::ByteToQualifierCode(*(++apStart)); + } + + void IObjectHeader::Set(apl::byte_t* apStart, byte_t aGrp, byte_t aVar, QualifierCode aQual) const + { + *(apStart) = aGrp; + *(++apStart) = aVar; + *(++apStart) = aQual; + } + + +}} diff --git a/DNP3/ObjectHeader.h b/DNP3/ObjectHeader.h index c6b6a3c6..917bec5c 100644 --- a/DNP3/ObjectHeader.h +++ b/DNP3/ObjectHeader.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __OBJECT_HEADER_H_ #define __OBJECT_HEADER_H_ @@ -47,7 +47,7 @@ namespace apl { namespace dnp { struct ObjectHeaderField { ObjectHeaderField(){}; - ObjectHeaderField(apl::byte_t aGroup, apl::byte_t aVariation, QualifierCode aQualifier) : + ObjectHeaderField(apl::byte_t aGroup, apl::byte_t aVariation, QualifierCode aQualifier) : Group(aGroup), Variation(aVariation), Qualifier(aQualifier) @@ -75,7 +75,7 @@ namespace apl { namespace dnp { virtual ~IObjectHeader(){} virtual size_t GetSize() const = 0; // depends on the subtype, default size is 3 virtual ObjectHeaderTypes GetType() const = 0; - + void Get(const apl::byte_t* apStart, ObjectHeaderField& arData) const; void Set(apl::byte_t* apStart, byte_t aGrp, byte_t aVar, QualifierCode aQual) const; @@ -114,26 +114,26 @@ namespace apl { namespace dnp { class RangedHeader : public IRangeHeader { MACRO_SINGLETON_INSTANCE(RangedHeader) - + size_t GetSize() const { return Size; } ObjectHeaderTypes GetType() const { return U; } void GetRange(const apl::byte_t* apStart, RangeInfo& arInfo) const - { + { arInfo.Start = T::Read(apStart+3); arInfo.Stop = T::Read(apStart+3+T::Size); } void SetRange(apl::byte_t* apStart, const RangeInfo& arInfo) const - { + { if(arInfo.Start > arInfo.Stop) throw ArgumentException(LOCATION, "stop > start"); if(arInfo.Stop > T::Max) throw ArgumentException(LOCATION, "stop > max"); - + T::Write(apStart+3, static_cast(arInfo.Start)); T::Write(apStart+3+T::Size, static_cast(arInfo.Stop)); } - static size_t MaxRange() + static size_t MaxRange() { return T::Max; } const static size_t Size = 3+2*T::Size; @@ -155,7 +155,7 @@ namespace apl { namespace dnp { void SetCount(apl::byte_t* apStart, size_t aCount) const { - if(aCount > T::Max) throw ArgumentException(LOCATION); + if(aCount > T::Max) throw ArgumentException(LOCATION); T::Write(apStart+3, static_cast(aCount)); } @@ -172,7 +172,7 @@ namespace apl { namespace dnp { typedef RangedHeader Ranged2OctetHeader; typedef RangedHeader Ranged4OctetHeader; typedef RangedHeader Ranged8OctetHeader; - + typedef CountHeader Count1OctetHeader; typedef CountHeader Count2OctetHeader; typedef CountHeader Count4OctetHeader; diff --git a/DNP3/ObjectInterfaces.h b/DNP3/ObjectInterfaces.h index c293811d..cac39652 100644 --- a/DNP3/ObjectInterfaces.h +++ b/DNP3/ObjectInterfaces.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __OBJECT_INTERFACES_H_ #define __OBJECT_INTERFACES_H_ @@ -26,18 +26,18 @@ #include #include -namespace apl { +namespace apl { class VTOData; class CopyableBuffer; } /* Object hierarchy - - - ___ PlaceHolderObject + + + ___ PlaceHolderObject | -- FixedObject --- StreamObject - | | + | | ObjectBase -|--- IndexedObject -----| | |-- BitFieldObject |___ VariableObject | diff --git a/DNP3/ObjectReadIterator.h b/DNP3/ObjectReadIterator.h index b31042ea..40cc16ad 100644 --- a/DNP3/ObjectReadIterator.h +++ b/DNP3/ObjectReadIterator.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __OBJECT_READ_ITERATOR_H_ #define __OBJECT_READ_ITERATOR_H_ @@ -30,9 +30,9 @@ class IObjectHeader; namespace apl { namespace dnp { - + class ObjectInfo - { + { friend class ObjectReadIterator; public: @@ -43,10 +43,10 @@ namespace apl { namespace dnp { private: size_t mIndex; // the objects device-based index - size_t mStart; // used in conjunction with bitfield objects only, + size_t mStart; // used in conjunction with bitfield objects only, // returns the device-based index of the first object in the collection - }; - + }; + /** Traverses APDU buffer for object data. */ @@ -58,7 +58,7 @@ namespace apl { namespace dnp { bool HasData() { return mHasData; } const ObjectInfo* operator->() const; const apl::byte_t* operator*() const; - + const ObjectReadIterator& operator++(); //prefix version const ObjectReadIterator operator++(int); //postfix version const HeaderInfo& Header() { return mHeaderInfo; } @@ -69,13 +69,13 @@ namespace apl { namespace dnp { private: ObjectReadIterator(const HeaderInfo& arInfo, const byte_t* apBuffer, bool aHasData); HeaderInfo mHeaderInfo; - size_t mCurrentObjectNum; + size_t mCurrentObjectNum; ObjectInfo mInfo; const apl::byte_t* mpPrefixPos; const apl::byte_t* mpPosition; const byte_t* mpBuffer; bool mHasData; - + void SetObjectInfo(); @@ -86,9 +86,9 @@ namespace apl { namespace dnp { }; inline const ObjectInfo* ObjectReadIterator::operator->() const - { + { if(this->IsEnd()) throw apl::Exception(LOCATION, "", ALERR_ITERATOR_OUT_OF_BOUNDS); - return &mInfo; + return &mInfo; } inline const apl::byte_t* ObjectReadIterator::operator*() const @@ -99,7 +99,7 @@ namespace apl { namespace dnp { } inline const ObjectReadIterator& ObjectReadIterator::operator++() - { + { if(this->IsEnd()) throw apl::Exception(LOCATION, "", ALERR_ITERATOR_OUT_OF_BOUNDS); ++mCurrentObjectNum; @@ -117,7 +117,7 @@ namespace apl { namespace dnp { } inline const ObjectReadIterator ObjectReadIterator::operator++(int) - { + { ObjectReadIterator tmp(*this); ++(*this); return tmp; diff --git a/DNP3/ObjectWriteIterator.h b/DNP3/ObjectWriteIterator.h index 67924364..d81f642d 100644 --- a/DNP3/ObjectWriteIterator.h +++ b/DNP3/ObjectWriteIterator.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __OBJECT_WRITE_ITERATOR_H_ #define __OBJECT_WRITE_ITERATOR_H_ @@ -29,7 +29,7 @@ #include namespace apl { namespace dnp { - + /** Buffer iterator to write objects with continuous indices. */ @@ -45,19 +45,19 @@ namespace apl { namespace dnp { const ObjectWriteIterator& operator++(); const ObjectWriteIterator operator++(int); bool IsEnd() const { return mIndex > mStop; }; - + apl::byte_t* operator*() const; private: ObjectWriteIterator(apl::byte_t* apPos, size_t aStart, size_t aStop, size_t aObjectSize); - + apl::byte_t* mpPos; - + size_t mIndex; size_t mStart; size_t mStop; - size_t mObjectSize; + size_t mObjectSize; }; inline apl::byte_t* ObjectWriteIterator::operator*() const diff --git a/DNP3/Objects.cpp b/DNP3/Objects.cpp index 5afb697e..37f8a47b 100644 --- a/DNP3/Objects.cpp +++ b/DNP3/Objects.cpp @@ -16,365 +16,365 @@ // specific language governing permissions and limitations // under the License. // -#include "Objects.h" - -#include -#include -#include - -#include "DNPToStream.h" -#include "DNPFromStream.h" - -#define MACRO_STATIC_INSTANCE(group, var) Group##group##Var##var Group##group##Var##var::mInstance; - -namespace apl { namespace dnp { - - MACRO_STATIC_INSTANCE(1,0) - MACRO_STATIC_INSTANCE(1,1) - MACRO_STATIC_INSTANCE(1,2) - MACRO_STATIC_INSTANCE(2,0) - MACRO_STATIC_INSTANCE(2,1) - MACRO_STATIC_INSTANCE(2,2) - MACRO_STATIC_INSTANCE(2,3) - - MACRO_STATIC_INSTANCE(10,0) - MACRO_STATIC_INSTANCE(10,1) - MACRO_STATIC_INSTANCE(10,2) - - MACRO_STATIC_INSTANCE(12,1) - MACRO_STATIC_INSTANCE(12,2) - MACRO_STATIC_INSTANCE(12,3) - - - MACRO_STATIC_INSTANCE(20,0) - MACRO_STATIC_INSTANCE(20,1) - MACRO_STATIC_INSTANCE(20,2) - MACRO_STATIC_INSTANCE(20,3) - MACRO_STATIC_INSTANCE(20,4) - MACRO_STATIC_INSTANCE(20,5) - MACRO_STATIC_INSTANCE(20,6) - MACRO_STATIC_INSTANCE(20,7) - MACRO_STATIC_INSTANCE(20,8) - - MACRO_STATIC_INSTANCE(21,0) - MACRO_STATIC_INSTANCE(21,1) - MACRO_STATIC_INSTANCE(21,2) - MACRO_STATIC_INSTANCE(21,3) - MACRO_STATIC_INSTANCE(21,4) - MACRO_STATIC_INSTANCE(21,5) - MACRO_STATIC_INSTANCE(21,6) - MACRO_STATIC_INSTANCE(21,7) - MACRO_STATIC_INSTANCE(21,8) - MACRO_STATIC_INSTANCE(21,9) - MACRO_STATIC_INSTANCE(21,10) - MACRO_STATIC_INSTANCE(21,11) - MACRO_STATIC_INSTANCE(21,12) - - MACRO_STATIC_INSTANCE(22,0) - MACRO_STATIC_INSTANCE(22,1) - MACRO_STATIC_INSTANCE(22,2) - MACRO_STATIC_INSTANCE(22,3) - MACRO_STATIC_INSTANCE(22,4) - MACRO_STATIC_INSTANCE(22,5) - MACRO_STATIC_INSTANCE(22,6) - MACRO_STATIC_INSTANCE(22,7) - MACRO_STATIC_INSTANCE(22,8) - - MACRO_STATIC_INSTANCE(23,0) - MACRO_STATIC_INSTANCE(23,1) - MACRO_STATIC_INSTANCE(23,2) - MACRO_STATIC_INSTANCE(23,3) - MACRO_STATIC_INSTANCE(23,4) - MACRO_STATIC_INSTANCE(23,5) - MACRO_STATIC_INSTANCE(23,6) - MACRO_STATIC_INSTANCE(23,7) - MACRO_STATIC_INSTANCE(23,8) - - MACRO_STATIC_INSTANCE(30,0) - MACRO_STATIC_INSTANCE(30,1) - MACRO_STATIC_INSTANCE(30,2) - MACRO_STATIC_INSTANCE(30,3) - MACRO_STATIC_INSTANCE(30,4) - MACRO_STATIC_INSTANCE(30,5) - MACRO_STATIC_INSTANCE(30,6) - - MACRO_STATIC_INSTANCE(31,0) - MACRO_STATIC_INSTANCE(31,1) - MACRO_STATIC_INSTANCE(31,2) - MACRO_STATIC_INSTANCE(31,3) - MACRO_STATIC_INSTANCE(31,4) - MACRO_STATIC_INSTANCE(31,5) - MACRO_STATIC_INSTANCE(31,6) - - MACRO_STATIC_INSTANCE(32,0) - MACRO_STATIC_INSTANCE(32,1) - MACRO_STATIC_INSTANCE(32,2) - MACRO_STATIC_INSTANCE(32,3) - MACRO_STATIC_INSTANCE(32,4) - MACRO_STATIC_INSTANCE(32,5) - MACRO_STATIC_INSTANCE(32,6) - MACRO_STATIC_INSTANCE(32,7) - MACRO_STATIC_INSTANCE(32,8) - - MACRO_STATIC_INSTANCE(33,0) - MACRO_STATIC_INSTANCE(33,1) - MACRO_STATIC_INSTANCE(33,2) - MACRO_STATIC_INSTANCE(33,3) - MACRO_STATIC_INSTANCE(33,4) - MACRO_STATIC_INSTANCE(33,5) - MACRO_STATIC_INSTANCE(33,6) - MACRO_STATIC_INSTANCE(33,7) - MACRO_STATIC_INSTANCE(33,8) - - MACRO_STATIC_INSTANCE(40,0) - MACRO_STATIC_INSTANCE(40,1) - MACRO_STATIC_INSTANCE(40,2) - MACRO_STATIC_INSTANCE(40,3) - MACRO_STATIC_INSTANCE(40,4) - - MACRO_STATIC_INSTANCE(41,1) - MACRO_STATIC_INSTANCE(41,2) - MACRO_STATIC_INSTANCE(41,3) - MACRO_STATIC_INSTANCE(41,4) - - MACRO_STATIC_INSTANCE(50,1) - MACRO_STATIC_INSTANCE(50,2) - MACRO_STATIC_INSTANCE(51,1) - MACRO_STATIC_INSTANCE(51,2) - MACRO_STATIC_INSTANCE(52,1) - MACRO_STATIC_INSTANCE(52,2) - - MACRO_STATIC_INSTANCE(60,1) - MACRO_STATIC_INSTANCE(60,2) - MACRO_STATIC_INSTANCE(60,3) - MACRO_STATIC_INSTANCE(60,4) - - - MACRO_STATIC_INSTANCE(80,1) - - MACRO_STATIC_INSTANCE(110,0) - MACRO_STATIC_INSTANCE(111,0) - MACRO_STATIC_INSTANCE(112,0) - MACRO_STATIC_INSTANCE(113,0) - - ////////////////////////////////////////////// - // Binary Input Types - ////////////////////////////////////////////// - - void Group1Var2::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQ(p, Group1Var2::Inst(), v); } - void Group2Var1::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQ(p, Group2Var1::Inst(), v); } - void Group2Var2::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQT(p, Group2Var2::Inst(), v); } - void Group2Var3::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQT(p, Group2Var3::Inst(), v); } - - Binary Group1Var2::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQV(p, Group1Var2::Inst()); } - Binary Group2Var1::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQV(p, Group2Var1::Inst()); } - Binary Group2Var2::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQV(p, Group2Var2::Inst()); } - Binary Group2Var3::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQVT(p, Group2Var3::Inst()); } - - - ////////////////////////////////////////////// - // Binary Output Status - ////////////////////////////////////////////// - - ControlStatus Group10Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQ(apPos, Group10Var2::Inst()); } - void Group10Var2::Write(apl::byte_t* apPos, const ControlStatus& arObj) const { DNPToStream::WriteQ(apPos, Group10Var2::Inst(), arObj); } - - ////////////////////////////////////////////// - // Binary Output Types - ////////////////////////////////////////////// - - void Group12Var1::Write(apl::byte_t* apPos, const BinaryOutput& arControl) const - { - mCode.Set(apPos, arControl.mRawCode); - mCount.Set(apPos, arControl.mCount); - mOffTime.Set(apPos, arControl.mOffTimeMS); - mOnTime.Set(apPos, arControl.mOnTimeMS); - mStatus.Set(apPos, arControl.mStatus); - } - - BinaryOutput Group12Var1::Read(const apl::byte_t* apPos) const - { - BinaryOutput b; - b.mRawCode = mCode.Get(apPos); - b.mCount = mCount.Get(apPos); - b.mOffTimeMS = mOffTime.Get(apPos); - b.mOnTimeMS = mOnTime.Get(apPos); - b.mStatus = ByteToCommandStatus(mStatus.Get(apPos)); - return b; - } - - apl::CopyableBuffer Group12Var1::GetValueBytes(const apl::byte_t* apPos) const - { - return CopyableBuffer(apPos, 10); //first 10 bytes, everything but the status - } - - ////////////////////////////////////////////// - // Counter Types - ////////////////////////////////////////////// - - Counter Group20Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var1::Inst()); } - Counter Group20Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var2::Inst()); } - Counter Group20Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var3::Inst()); } - Counter Group20Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var4::Inst()); } - Counter Group20Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var5::Inst()); } - Counter Group20Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var6::Inst()); } - Counter Group20Var7::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var7::Inst()); } - Counter Group20Var8::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var8::Inst()); } - - void Group20Var1::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var1::Inst(), v); } - void Group20Var2::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var2::Inst(), v); } - void Group20Var3::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var3::Inst(), v); } - void Group20Var4::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var4::Inst(), v); } - void Group20Var5::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var5::Inst(), v); } - void Group20Var6::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var6::Inst(), v); } - void Group20Var7::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var7::Inst(), v); } - void Group20Var8::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var8::Inst(), v); } - - Counter Group22Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var1::Inst()); } - Counter Group22Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var2::Inst()); } - Counter Group22Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var3::Inst()); } - Counter Group22Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var4::Inst()); } - Counter Group22Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var5::Inst()); } - Counter Group22Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var6::Inst()); } - Counter Group22Var7::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var7::Inst()); } - Counter Group22Var8::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var8::Inst()); } - - void Group22Var1::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var1::Inst(), v); } - void Group22Var2::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var2::Inst(), v); } - void Group22Var3::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var3::Inst(), v); } - void Group22Var4::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var4::Inst(), v); } - void Group22Var5::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var5::Inst(), v); } - void Group22Var6::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var6::Inst(), v); } - void Group22Var7::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var7::Inst(), v); } - void Group22Var8::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var8::Inst(), v); } - - - ////////////////////////////////////////////// - // Analog Input Types - ////////////////////////////////////////////// - void Group30Var1::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var1::Inst(), v); } - void Group30Var2::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var2::Inst(), v); } - void Group30Var3::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteV(p, Group30Var3::Inst(), v); } - void Group30Var4::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteV(p, Group30Var4::Inst(), v); } - void Group30Var5::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var5::Inst(), v); } - void Group30Var6::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var6::Inst(), v); } - - Analog Group30Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var1::Inst()); } - Analog Group30Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var2::Inst()); } - Analog Group30Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group30Var3::Inst()); } - Analog Group30Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group30Var4::Inst()); } - Analog Group30Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var5::Inst()); } - Analog Group30Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var6::Inst()); } - - void Group32Var1::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group32Var1::Inst(), v); } - void Group32Var2::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group32Var2::Inst(), v); } - void Group32Var3::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQVT(p, Group32Var3::Inst(), v); } - void Group32Var4::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQVT(p, Group32Var4::Inst(), v); } - void Group32Var5::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQV(p, Group32Var5::Inst(), v); } - void Group32Var6::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQV(p, Group32Var6::Inst(), v); } - void Group32Var7::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQVT(p, Group32Var7::Inst(), v); } - void Group32Var8::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQVT(p, Group32Var8::Inst(), v); } - - Analog Group32Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var1::Inst()); } - Analog Group32Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var2::Inst()); } - Analog Group32Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var3::Inst()); } - Analog Group32Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var4::Inst()); } - Analog Group32Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var5::Inst()); } - Analog Group32Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var6::Inst()); } - Analog Group32Var7::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var7::Inst()); } - Analog Group32Var8::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var8::Inst()); } - - ////////////////////////////////////////////// - // Analog Output Status - ////////////////////////////////////////////// - - SetpointStatus Group40Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var1::Inst()); } - SetpointStatus Group40Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var2::Inst()); } - SetpointStatus Group40Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var3::Inst()); } - SetpointStatus Group40Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var4::Inst()); } - - void Group40Var1::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var1::Inst(), arObj); } - void Group40Var2::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var2::Inst(), arObj); } - void Group40Var3::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var3::Inst(), arObj); } - void Group40Var4::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var4::Inst(), arObj); } - - ////////////////////////////////////////////// - // Setpoint Types - ////////////////////////////////////////////// - - void Group41Var1::Write(apl::byte_t* apBuff, const Setpoint& arVal) const - { - this->mValue.Set(apBuff, arVal.GetIntValue()); - this->mStatus.Set(apBuff, arVal.mStatus); - } - - Setpoint Group41Var1::Read(const apl::byte_t* apBuff) const - { - Setpoint s(static_cast(this->mValue.Get(apBuff))); - s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); - s.SetEncodingType(SPET_INT32); - return s; - } - - apl::CopyableBuffer Group41Var1::GetValueBytes(const apl::byte_t* apBuff) const - { - return CopyableBuffer(apBuff, 4); - } - - void Group41Var2::Write(apl::byte_t* apBuff, const Setpoint& arVal) const - { - this->mValue.Set(apBuff, static_cast(arVal.GetIntValue())); - this->mStatus.Set(apBuff, arVal.mStatus); - } - - Setpoint Group41Var2::Read(const apl::byte_t* apBuff) const - { - Setpoint s(static_cast(this->mValue.Get(apBuff))); - s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); - s.SetEncodingType(SPET_INT16); - return s; - } - - apl::CopyableBuffer Group41Var2::GetValueBytes(const apl::byte_t* apBuff) const - { - return CopyableBuffer(apBuff, 2); - } - - void Group41Var3::Write(apl::byte_t* apBuff, const Setpoint& arVal) const - { - this->mValue.Set(apBuff, static_cast(arVal.GetValue())); - this->mStatus.Set(apBuff, arVal.mStatus); - } - - Setpoint Group41Var3::Read(const apl::byte_t* apBuff) const - { - Setpoint s(this->mValue.Get(apBuff)); - s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); - s.SetEncodingType(SPET_FLOAT); - return s; - } - - apl::CopyableBuffer Group41Var3::GetValueBytes(const apl::byte_t* apBuff) const - { - return CopyableBuffer(apBuff, 4); - } - - void Group41Var4::Write(apl::byte_t* apBuff, const Setpoint& arVal) const - { - this->mValue.Set(apBuff, arVal.GetValue()); - this->mStatus.Set(apBuff, arVal.mStatus); - } - - Setpoint Group41Var4::Read(const apl::byte_t* apBuff) const - { - Setpoint s(this->mValue.Get(apBuff)); - s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); - s.SetEncodingType(SPET_DOUBLE); - return s; - } - - apl::CopyableBuffer Group41Var4::GetValueBytes(const apl::byte_t* apBuff) const - { - return CopyableBuffer(apBuff, 8); - } -}} +#include "Objects.h" + +#include +#include +#include + +#include "DNPToStream.h" +#include "DNPFromStream.h" + +#define MACRO_STATIC_INSTANCE(group, var) Group##group##Var##var Group##group##Var##var::mInstance; + +namespace apl { namespace dnp { + + MACRO_STATIC_INSTANCE(1,0) + MACRO_STATIC_INSTANCE(1,1) + MACRO_STATIC_INSTANCE(1,2) + MACRO_STATIC_INSTANCE(2,0) + MACRO_STATIC_INSTANCE(2,1) + MACRO_STATIC_INSTANCE(2,2) + MACRO_STATIC_INSTANCE(2,3) + + MACRO_STATIC_INSTANCE(10,0) + MACRO_STATIC_INSTANCE(10,1) + MACRO_STATIC_INSTANCE(10,2) + + MACRO_STATIC_INSTANCE(12,1) + MACRO_STATIC_INSTANCE(12,2) + MACRO_STATIC_INSTANCE(12,3) + + + MACRO_STATIC_INSTANCE(20,0) + MACRO_STATIC_INSTANCE(20,1) + MACRO_STATIC_INSTANCE(20,2) + MACRO_STATIC_INSTANCE(20,3) + MACRO_STATIC_INSTANCE(20,4) + MACRO_STATIC_INSTANCE(20,5) + MACRO_STATIC_INSTANCE(20,6) + MACRO_STATIC_INSTANCE(20,7) + MACRO_STATIC_INSTANCE(20,8) + + MACRO_STATIC_INSTANCE(21,0) + MACRO_STATIC_INSTANCE(21,1) + MACRO_STATIC_INSTANCE(21,2) + MACRO_STATIC_INSTANCE(21,3) + MACRO_STATIC_INSTANCE(21,4) + MACRO_STATIC_INSTANCE(21,5) + MACRO_STATIC_INSTANCE(21,6) + MACRO_STATIC_INSTANCE(21,7) + MACRO_STATIC_INSTANCE(21,8) + MACRO_STATIC_INSTANCE(21,9) + MACRO_STATIC_INSTANCE(21,10) + MACRO_STATIC_INSTANCE(21,11) + MACRO_STATIC_INSTANCE(21,12) + + MACRO_STATIC_INSTANCE(22,0) + MACRO_STATIC_INSTANCE(22,1) + MACRO_STATIC_INSTANCE(22,2) + MACRO_STATIC_INSTANCE(22,3) + MACRO_STATIC_INSTANCE(22,4) + MACRO_STATIC_INSTANCE(22,5) + MACRO_STATIC_INSTANCE(22,6) + MACRO_STATIC_INSTANCE(22,7) + MACRO_STATIC_INSTANCE(22,8) + + MACRO_STATIC_INSTANCE(23,0) + MACRO_STATIC_INSTANCE(23,1) + MACRO_STATIC_INSTANCE(23,2) + MACRO_STATIC_INSTANCE(23,3) + MACRO_STATIC_INSTANCE(23,4) + MACRO_STATIC_INSTANCE(23,5) + MACRO_STATIC_INSTANCE(23,6) + MACRO_STATIC_INSTANCE(23,7) + MACRO_STATIC_INSTANCE(23,8) + + MACRO_STATIC_INSTANCE(30,0) + MACRO_STATIC_INSTANCE(30,1) + MACRO_STATIC_INSTANCE(30,2) + MACRO_STATIC_INSTANCE(30,3) + MACRO_STATIC_INSTANCE(30,4) + MACRO_STATIC_INSTANCE(30,5) + MACRO_STATIC_INSTANCE(30,6) + + MACRO_STATIC_INSTANCE(31,0) + MACRO_STATIC_INSTANCE(31,1) + MACRO_STATIC_INSTANCE(31,2) + MACRO_STATIC_INSTANCE(31,3) + MACRO_STATIC_INSTANCE(31,4) + MACRO_STATIC_INSTANCE(31,5) + MACRO_STATIC_INSTANCE(31,6) + + MACRO_STATIC_INSTANCE(32,0) + MACRO_STATIC_INSTANCE(32,1) + MACRO_STATIC_INSTANCE(32,2) + MACRO_STATIC_INSTANCE(32,3) + MACRO_STATIC_INSTANCE(32,4) + MACRO_STATIC_INSTANCE(32,5) + MACRO_STATIC_INSTANCE(32,6) + MACRO_STATIC_INSTANCE(32,7) + MACRO_STATIC_INSTANCE(32,8) + + MACRO_STATIC_INSTANCE(33,0) + MACRO_STATIC_INSTANCE(33,1) + MACRO_STATIC_INSTANCE(33,2) + MACRO_STATIC_INSTANCE(33,3) + MACRO_STATIC_INSTANCE(33,4) + MACRO_STATIC_INSTANCE(33,5) + MACRO_STATIC_INSTANCE(33,6) + MACRO_STATIC_INSTANCE(33,7) + MACRO_STATIC_INSTANCE(33,8) + + MACRO_STATIC_INSTANCE(40,0) + MACRO_STATIC_INSTANCE(40,1) + MACRO_STATIC_INSTANCE(40,2) + MACRO_STATIC_INSTANCE(40,3) + MACRO_STATIC_INSTANCE(40,4) + + MACRO_STATIC_INSTANCE(41,1) + MACRO_STATIC_INSTANCE(41,2) + MACRO_STATIC_INSTANCE(41,3) + MACRO_STATIC_INSTANCE(41,4) + + MACRO_STATIC_INSTANCE(50,1) + MACRO_STATIC_INSTANCE(50,2) + MACRO_STATIC_INSTANCE(51,1) + MACRO_STATIC_INSTANCE(51,2) + MACRO_STATIC_INSTANCE(52,1) + MACRO_STATIC_INSTANCE(52,2) + + MACRO_STATIC_INSTANCE(60,1) + MACRO_STATIC_INSTANCE(60,2) + MACRO_STATIC_INSTANCE(60,3) + MACRO_STATIC_INSTANCE(60,4) + + + MACRO_STATIC_INSTANCE(80,1) + + MACRO_STATIC_INSTANCE(110,0) + MACRO_STATIC_INSTANCE(111,0) + MACRO_STATIC_INSTANCE(112,0) + MACRO_STATIC_INSTANCE(113,0) + + ////////////////////////////////////////////// + // Binary Input Types + ////////////////////////////////////////////// + + void Group1Var2::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQ(p, Group1Var2::Inst(), v); } + void Group2Var1::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQ(p, Group2Var1::Inst(), v); } + void Group2Var2::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQT(p, Group2Var2::Inst(), v); } + void Group2Var3::Write(apl::byte_t* p, const apl::Binary& v) const { DNPToStream::WriteQT(p, Group2Var3::Inst(), v); } + + Binary Group1Var2::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQV(p, Group1Var2::Inst()); } + Binary Group2Var1::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQV(p, Group2Var1::Inst()); } + Binary Group2Var2::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQV(p, Group2Var2::Inst()); } + Binary Group2Var3::Read(const apl::byte_t* p) const { return DNPFromStream::ReadBinaryQVT(p, Group2Var3::Inst()); } + + + ////////////////////////////////////////////// + // Binary Output Status + ////////////////////////////////////////////// + + ControlStatus Group10Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQ(apPos, Group10Var2::Inst()); } + void Group10Var2::Write(apl::byte_t* apPos, const ControlStatus& arObj) const { DNPToStream::WriteQ(apPos, Group10Var2::Inst(), arObj); } + + ////////////////////////////////////////////// + // Binary Output Types + ////////////////////////////////////////////// + + void Group12Var1::Write(apl::byte_t* apPos, const BinaryOutput& arControl) const + { + mCode.Set(apPos, arControl.mRawCode); + mCount.Set(apPos, arControl.mCount); + mOffTime.Set(apPos, arControl.mOffTimeMS); + mOnTime.Set(apPos, arControl.mOnTimeMS); + mStatus.Set(apPos, arControl.mStatus); + } + + BinaryOutput Group12Var1::Read(const apl::byte_t* apPos) const + { + BinaryOutput b; + b.mRawCode = mCode.Get(apPos); + b.mCount = mCount.Get(apPos); + b.mOffTimeMS = mOffTime.Get(apPos); + b.mOnTimeMS = mOnTime.Get(apPos); + b.mStatus = ByteToCommandStatus(mStatus.Get(apPos)); + return b; + } + + apl::CopyableBuffer Group12Var1::GetValueBytes(const apl::byte_t* apPos) const + { + return CopyableBuffer(apPos, 10); //first 10 bytes, everything but the status + } + + ////////////////////////////////////////////// + // Counter Types + ////////////////////////////////////////////// + + Counter Group20Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var1::Inst()); } + Counter Group20Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var2::Inst()); } + Counter Group20Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var3::Inst()); } + Counter Group20Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group20Var4::Inst()); } + Counter Group20Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var5::Inst()); } + Counter Group20Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var6::Inst()); } + Counter Group20Var7::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var7::Inst()); } + Counter Group20Var8::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group20Var8::Inst()); } + + void Group20Var1::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var1::Inst(), v); } + void Group20Var2::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var2::Inst(), v); } + void Group20Var3::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var3::Inst(), v); } + void Group20Var4::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group20Var4::Inst(), v); } + void Group20Var5::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var5::Inst(), v); } + void Group20Var6::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var6::Inst(), v); } + void Group20Var7::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var7::Inst(), v); } + void Group20Var8::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteV(apPos, Group20Var8::Inst(), v); } + + Counter Group22Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var1::Inst()); } + Counter Group22Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var2::Inst()); } + Counter Group22Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var3::Inst()); } + Counter Group22Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group22Var4::Inst()); } + Counter Group22Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var5::Inst()); } + Counter Group22Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var6::Inst()); } + Counter Group22Var7::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var7::Inst()); } + Counter Group22Var8::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group22Var8::Inst()); } + + void Group22Var1::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var1::Inst(), v); } + void Group22Var2::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var2::Inst(), v); } + void Group22Var3::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var3::Inst(), v); } + void Group22Var4::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQV(apPos, Group22Var4::Inst(), v); } + void Group22Var5::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var5::Inst(), v); } + void Group22Var6::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var6::Inst(), v); } + void Group22Var7::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var7::Inst(), v); } + void Group22Var8::Write(apl::byte_t* apPos, const apl::Counter& v) const { DNPToStream::WriteQVT(apPos, Group22Var8::Inst(), v); } + + + ////////////////////////////////////////////// + // Analog Input Types + ////////////////////////////////////////////// + void Group30Var1::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var1::Inst(), v); } + void Group30Var2::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var2::Inst(), v); } + void Group30Var3::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteV(p, Group30Var3::Inst(), v); } + void Group30Var4::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteV(p, Group30Var4::Inst(), v); } + void Group30Var5::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var5::Inst(), v); } + void Group30Var6::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group30Var6::Inst(), v); } + + Analog Group30Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var1::Inst()); } + Analog Group30Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var2::Inst()); } + Analog Group30Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group30Var3::Inst()); } + Analog Group30Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadV(apPos, Group30Var4::Inst()); } + Analog Group30Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var5::Inst()); } + Analog Group30Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group30Var6::Inst()); } + + void Group32Var1::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group32Var1::Inst(), v); } + void Group32Var2::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQV(p, Group32Var2::Inst(), v); } + void Group32Var3::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQVT(p, Group32Var3::Inst(), v); } + void Group32Var4::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteCheckRangeQVT(p, Group32Var4::Inst(), v); } + void Group32Var5::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQV(p, Group32Var5::Inst(), v); } + void Group32Var6::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQV(p, Group32Var6::Inst(), v); } + void Group32Var7::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQVT(p, Group32Var7::Inst(), v); } + void Group32Var8::Write(apl::byte_t* p, const apl::Analog& v) const { DNPToStream::WriteQVT(p, Group32Var8::Inst(), v); } + + Analog Group32Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var1::Inst()); } + Analog Group32Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var2::Inst()); } + Analog Group32Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var3::Inst()); } + Analog Group32Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var4::Inst()); } + Analog Group32Var5::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var5::Inst()); } + Analog Group32Var6::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group32Var6::Inst()); } + Analog Group32Var7::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var7::Inst()); } + Analog Group32Var8::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQVT(apPos, Group32Var8::Inst()); } + + ////////////////////////////////////////////// + // Analog Output Status + ////////////////////////////////////////////// + + SetpointStatus Group40Var1::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var1::Inst()); } + SetpointStatus Group40Var2::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var2::Inst()); } + SetpointStatus Group40Var3::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var3::Inst()); } + SetpointStatus Group40Var4::Read(const apl::byte_t* apPos) const { return DNPFromStream::ReadQV(apPos, Group40Var4::Inst()); } + + void Group40Var1::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var1::Inst(), arObj); } + void Group40Var2::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var2::Inst(), arObj); } + void Group40Var3::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var3::Inst(), arObj); } + void Group40Var4::Write(apl::byte_t* apPos, const apl::SetpointStatus& arObj) const { DNPToStream::WriteQV(apPos, Group40Var4::Inst(), arObj); } + + ////////////////////////////////////////////// + // Setpoint Types + ////////////////////////////////////////////// + + void Group41Var1::Write(apl::byte_t* apBuff, const Setpoint& arVal) const + { + this->mValue.Set(apBuff, arVal.GetIntValue()); + this->mStatus.Set(apBuff, arVal.mStatus); + } + + Setpoint Group41Var1::Read(const apl::byte_t* apBuff) const + { + Setpoint s(static_cast(this->mValue.Get(apBuff))); + s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); + s.SetEncodingType(SPET_INT32); + return s; + } + + apl::CopyableBuffer Group41Var1::GetValueBytes(const apl::byte_t* apBuff) const + { + return CopyableBuffer(apBuff, 4); + } + + void Group41Var2::Write(apl::byte_t* apBuff, const Setpoint& arVal) const + { + this->mValue.Set(apBuff, static_cast(arVal.GetIntValue())); + this->mStatus.Set(apBuff, arVal.mStatus); + } + + Setpoint Group41Var2::Read(const apl::byte_t* apBuff) const + { + Setpoint s(static_cast(this->mValue.Get(apBuff))); + s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); + s.SetEncodingType(SPET_INT16); + return s; + } + + apl::CopyableBuffer Group41Var2::GetValueBytes(const apl::byte_t* apBuff) const + { + return CopyableBuffer(apBuff, 2); + } + + void Group41Var3::Write(apl::byte_t* apBuff, const Setpoint& arVal) const + { + this->mValue.Set(apBuff, static_cast(arVal.GetValue())); + this->mStatus.Set(apBuff, arVal.mStatus); + } + + Setpoint Group41Var3::Read(const apl::byte_t* apBuff) const + { + Setpoint s(this->mValue.Get(apBuff)); + s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); + s.SetEncodingType(SPET_FLOAT); + return s; + } + + apl::CopyableBuffer Group41Var3::GetValueBytes(const apl::byte_t* apBuff) const + { + return CopyableBuffer(apBuff, 4); + } + + void Group41Var4::Write(apl::byte_t* apBuff, const Setpoint& arVal) const + { + this->mValue.Set(apBuff, arVal.GetValue()); + this->mStatus.Set(apBuff, arVal.mStatus); + } + + Setpoint Group41Var4::Read(const apl::byte_t* apBuff) const + { + Setpoint s(this->mValue.Get(apBuff)); + s.mStatus = ByteToCommandStatus(this->mStatus.Get(apBuff)); + s.SetEncodingType(SPET_DOUBLE); + return s; + } + + apl::CopyableBuffer Group41Var4::GetValueBytes(const apl::byte_t* apBuff) const + { + return CopyableBuffer(apBuff, 8); + } +}} diff --git a/DNP3/Objects.h b/DNP3/Objects.h index 73751bba..92bb66e0 100644 --- a/DNP3/Objects.h +++ b/DNP3/Objects.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __OBJECTS_H_ #define __OBJECTS_H_ @@ -58,7 +58,7 @@ #define MACRO_DECLARE_TIME(packer, position) \ Pack mTime; \ bool HasTime() const { return true; } - + #define MACRO_GROUP_VAR_FUNC(group, var)\ int GetGroup() const { return group; }\ @@ -74,10 +74,10 @@ namespace apl { class SetpointStatus; class ControlStatus; } - + namespace apl { namespace dnp { - + ////////////////////////////////////////////// // Binary Input Types @@ -100,7 +100,7 @@ namespace apl { namespace dnp { MACRO_NAME_SINGLETON_INSTANCE(Group1Var2) MACRO_GROUP_VAR_SIZE_FUNC(1, 2, 1) MACRO_DECLARE_QUALITY(UInt8,0) - MACRO_DECLARE_STREAM_TYPE(Binary) + MACRO_DECLARE_STREAM_TYPE(Binary) }; struct Group2Var0 : public PlaceHolderObject @@ -114,7 +114,7 @@ namespace apl { namespace dnp { MACRO_NAME_SINGLETON_INSTANCE(Group2Var1) MACRO_GROUP_VAR_SIZE_FUNC_WITH_EVENTS(2, 1, 1) MACRO_DECLARE_QUALITY(UInt8,0) - MACRO_DECLARE_STREAM_TYPE(Binary) + MACRO_DECLARE_STREAM_TYPE(Binary) }; struct Group2Var2 : public StreamObject @@ -129,12 +129,12 @@ namespace apl { namespace dnp { struct Group2Var3 : public StreamObject { MACRO_NAME_SINGLETON_INSTANCE(Group2Var3) - MACRO_GROUP_VAR_SIZE_FUNC_WITH_EVENTS(2, 3, 3) + MACRO_GROUP_VAR_SIZE_FUNC_WITH_EVENTS(2, 3, 3) MACRO_DECLARE_QUALITY(UInt8, 0) MACRO_DECLARE_TIME(UInt16LE, 1) MACRO_DECLARE_STREAM_TYPE(Binary) - bool UseCTO() const { return true; } + bool UseCTO() const { return true; } }; ////////////////////////////////////////////// @@ -158,7 +158,7 @@ namespace apl { namespace dnp { MACRO_NAME_SINGLETON_INSTANCE(Group10Var2) MACRO_GROUP_VAR_SIZE_FUNC(10, 2, 1) MACRO_DECLARE_QUALITY(UInt8, 0) - MACRO_DECLARE_STREAM_TYPE(ControlStatus); + MACRO_DECLARE_STREAM_TYPE(ControlStatus); }; ////////////////////////////////////////////// @@ -166,7 +166,7 @@ namespace apl { namespace dnp { ////////////////////////////////////////////// struct Group12Var1 : public CommandObject - { + { MACRO_NAME_SINGLETON_INSTANCE(Group12Var1) MACRO_GROUP_VAR_SIZE_FUNC(12, 1, 11) MACRO_DECLARE_STREAM_TYPE(BinaryOutput); @@ -191,7 +191,7 @@ namespace apl { namespace dnp { Pack mOffTime; Pack mStatus; }; - + struct Group12Var3 : public BitfieldObject { MACRO_NAME_SINGLETON_INSTANCE(Group12Var3) @@ -214,8 +214,8 @@ namespace apl { namespace dnp { MACRO_GROUP_VAR_SIZE_FUNC(20, 1, 5) MACRO_DECLARE_QUALITY(UInt8, 0); MACRO_DECLARE_VALUE(UInt32LE, 1); - MACRO_DECLARE_STREAM_TYPE(Counter); - + MACRO_DECLARE_STREAM_TYPE(Counter); + }; struct Group20Var2 : public StreamObject @@ -224,7 +224,7 @@ namespace apl { namespace dnp { MACRO_GROUP_VAR_SIZE_FUNC(20, 2, 3) MACRO_DECLARE_QUALITY(UInt8, 0); MACRO_DECLARE_VALUE(UInt16LE, 1); - MACRO_DECLARE_STREAM_TYPE(Counter); + MACRO_DECLARE_STREAM_TYPE(Counter); }; struct Group20Var3 : public StreamObject @@ -233,7 +233,7 @@ namespace apl { namespace dnp { MACRO_GROUP_VAR_SIZE_FUNC(20, 3, 5) MACRO_DECLARE_QUALITY(UInt8, 0); MACRO_DECLARE_VALUE(UInt32LE, 1); - MACRO_DECLARE_STREAM_TYPE(Counter); + MACRO_DECLARE_STREAM_TYPE(Counter); }; struct Group20Var4 : public StreamObject @@ -242,8 +242,8 @@ namespace apl { namespace dnp { MACRO_GROUP_VAR_SIZE_FUNC(20, 4, 3) MACRO_DECLARE_QUALITY(UInt8, 0); MACRO_DECLARE_VALUE(UInt16LE, 1); - MACRO_DECLARE_STREAM_TYPE(Counter); - + MACRO_DECLARE_STREAM_TYPE(Counter); + }; struct Group20Var5 : public StreamObject @@ -554,7 +554,7 @@ namespace apl { namespace dnp { ////////////////////////////////////////////// struct Group30Var0 : public PlaceHolderObject - { + { MACRO_NAME_SINGLETON_INSTANCE(Group30Var0) MACRO_GROUP_VAR_FUNC(30, 0) }; @@ -574,7 +574,7 @@ namespace apl { namespace dnp { MACRO_GROUP_VAR_SIZE_FUNC(30, 2, 3) MACRO_DECLARE_QUALITY(UInt8, 0) MACRO_DECLARE_VALUE_OVERRANGE(Int16LE, 1, AQ_OVERRANGE) - MACRO_DECLARE_STREAM_TYPE(Analog) + MACRO_DECLARE_STREAM_TYPE(Analog) }; struct Group30Var3 : public StreamObject @@ -634,7 +634,7 @@ namespace apl { namespace dnp { MACRO_NAME_SINGLETON_INSTANCE(Group31Var2) MACRO_GROUP_VAR_SIZE_FUNC(31, 2, 3) MACRO_DECLARE_QUALITY(UInt8, 0) - MACRO_DECLARE_VALUE_OVERRANGE(Int16LE, 1, AQ_OVERRANGE) + MACRO_DECLARE_VALUE_OVERRANGE(Int16LE, 1, AQ_OVERRANGE) }; struct Group31Var3 : public FixedObject @@ -642,7 +642,7 @@ namespace apl { namespace dnp { MACRO_NAME_SINGLETON_INSTANCE(Group31Var3) MACRO_GROUP_VAR_SIZE_FUNC(31, 3, 11) MACRO_DECLARE_QUALITY(UInt8, 0) - MACRO_DECLARE_VALUE_OVERRANGE(Int32LE, 1, AQ_OVERRANGE) + MACRO_DECLARE_VALUE_OVERRANGE(Int32LE, 1, AQ_OVERRANGE) MACRO_DECLARE_TIME(UInt48LE, 5) }; @@ -905,7 +905,7 @@ namespace apl { namespace dnp { Pack mStatus; MACRO_DECLARE_STREAM_TYPE(Setpoint) - apl::CopyableBuffer GetValueBytes(const apl::byte_t*) const; + apl::CopyableBuffer GetValueBytes(const apl::byte_t*) const; }; struct Group41Var2 : public CommandObject @@ -1029,7 +1029,7 @@ namespace apl { namespace dnp { struct Group110Var0 : public VariableByVariationObject { MACRO_NAME_SINGLETON_INSTANCE(Group110Var0) - MACRO_GROUP_VAR_FUNC(110, 0) + MACRO_GROUP_VAR_FUNC(110, 0) }; struct Group111Var0 : public VariableByVariationObject diff --git a/DNP3/PointClass.h b/DNP3/PointClass.h index 22188f5f..703d5532 100644 --- a/DNP3/PointClass.h +++ b/DNP3/PointClass.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __POINT_CLASS_H_ #define __POINT_CLASS_H_ diff --git a/DNP3/PriLinkLayerStates.h b/DNP3/PriLinkLayerStates.h index b43eb9e8..fd506af6 100644 --- a/DNP3/PriLinkLayerStates.h +++ b/DNP3/PriLinkLayerStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __PRI_LINK_LAYER_STATES_H_ #define __PRI_LINK_LAYER_STATES_H_ @@ -40,7 +40,7 @@ namespace apl { namespace dnp { virtual void NotSupported (AsyncLinkLayer*, bool aIsRcvBuffFull); virtual void OnTimeout(AsyncLinkLayer*); - + /*Upper layer events to handle */ virtual void SendConfirmed(AsyncLinkLayer*, const apl::byte_t*, size_t); virtual void SendUnconfirmed(AsyncLinkLayer*, const apl::byte_t*, size_t); @@ -97,7 +97,7 @@ namespace apl { namespace dnp { }; - + }} //end namepsace diff --git a/DNP3/ResponseLoader.cpp b/DNP3/ResponseLoader.cpp index a4eccfac..5b996f4c 100644 --- a/DNP3/ResponseLoader.cpp +++ b/DNP3/ResponseLoader.cpp @@ -16,96 +16,96 @@ // specific language governing permissions and limitations // under the License. // -#include "ResponseLoader.h" - -#include - -#include "HeaderReadIterator.h" -#include "Objects.h" - -namespace apl { namespace dnp { - -ResponseLoader::ResponseLoader(Logger* apLogger, TimeStamp_t aTime, IDataObserver* apPublisher) : -Loggable(apLogger), -mpPublisher(apPublisher), -mTransaction(apPublisher), -mTime(aTime) -{ - -} - -void ResponseLoader::Process(HeaderReadIterator& arIter) -{ - int grp = arIter->GetGroup(); - int var = arIter->GetVariation(); - - this->ProcessData(arIter, grp, var); - - mCTO.NextHeader(); -} - -void ResponseLoader::ProcessData(HeaderReadIterator& arIter, int aGrp, int aVar) -{ - switch(MACRO_DNP_RADIX(aGrp, aVar)) - { - // Control Status - case(MACRO_DNP_RADIX(10,2)): this->Read(arIter, Group10Var2::Inst()); break; - - // Binary - case(MACRO_DNP_RADIX(1,1)): this->ReadBitfield(arIter); break; - - case(MACRO_DNP_RADIX(1,2)): this->Read(arIter, Group1Var2::Inst()); break; - case(MACRO_DNP_RADIX(2,1)): this->Read(arIter, Group2Var1::Inst()); break; - case(MACRO_DNP_RADIX(2,2)): this->Read(arIter, Group2Var2::Inst()); break; - case(MACRO_DNP_RADIX(2,3)): this->Read(arIter, Group2Var3::Inst()); break; - - // Counters - case(MACRO_DNP_RADIX(20,1)): this->Read(arIter, Group20Var1::Inst()); break; - case(MACRO_DNP_RADIX(20,2)): this->Read(arIter, Group20Var2::Inst()); break; - case(MACRO_DNP_RADIX(20,3)): this->Read(arIter, Group20Var3::Inst()); break; - case(MACRO_DNP_RADIX(20,4)): this->Read(arIter, Group20Var4::Inst()); break; - case(MACRO_DNP_RADIX(20,5)): this->Read(arIter, Group20Var5::Inst()); break; - case(MACRO_DNP_RADIX(20,6)): this->Read(arIter, Group20Var6::Inst()); break; - case(MACRO_DNP_RADIX(20,7)): this->Read(arIter, Group20Var7::Inst()); break; - case(MACRO_DNP_RADIX(20,8)): this->Read(arIter, Group20Var8::Inst()); break; - - case(MACRO_DNP_RADIX(22,1)): this->Read(arIter, Group22Var1::Inst()); break; - case(MACRO_DNP_RADIX(22,2)): this->Read(arIter, Group22Var2::Inst()); break; - case(MACRO_DNP_RADIX(22,3)): this->Read(arIter, Group22Var3::Inst()); break; - case(MACRO_DNP_RADIX(22,4)): this->Read(arIter, Group22Var4::Inst()); break; - - // Analogs - case(MACRO_DNP_RADIX(30,1)): this->Read(arIter, Group30Var1::Inst()); break; - case(MACRO_DNP_RADIX(30,2)): this->Read(arIter, Group30Var2::Inst()); break; - case(MACRO_DNP_RADIX(30,3)): this->Read(arIter, Group30Var3::Inst()); break; - case(MACRO_DNP_RADIX(30,4)): this->Read(arIter, Group30Var4::Inst()); break; - case(MACRO_DNP_RADIX(30,5)): this->Read(arIter, Group30Var5::Inst()); break; - case(MACRO_DNP_RADIX(30,6)): this->Read(arIter, Group30Var6::Inst()); break; - - case(MACRO_DNP_RADIX(32,1)): this->Read(arIter, Group32Var1::Inst()); break; - case(MACRO_DNP_RADIX(32,2)): this->Read(arIter, Group32Var2::Inst()); break; - case(MACRO_DNP_RADIX(32,3)): this->Read(arIter, Group32Var3::Inst()); break; - case(MACRO_DNP_RADIX(32,4)): this->Read(arIter, Group32Var4::Inst()); break; - case(MACRO_DNP_RADIX(32,5)): this->Read(arIter, Group32Var5::Inst()); break; - case(MACRO_DNP_RADIX(32,6)): this->Read(arIter, Group32Var6::Inst()); break; - case(MACRO_DNP_RADIX(32,7)): this->Read(arIter, Group32Var7::Inst()); break; - case(MACRO_DNP_RADIX(32,8)): this->Read(arIter, Group32Var8::Inst()); break; - - // Setpoint Status - case(MACRO_DNP_RADIX(40,1)): this->Read(arIter, Group40Var1::Inst()); break; - case(MACRO_DNP_RADIX(40,2)): this->Read(arIter, Group40Var2::Inst()); break; - case(MACRO_DNP_RADIX(40,3)): this->Read(arIter, Group40Var3::Inst()); break; - case(MACRO_DNP_RADIX(40,4)): this->Read(arIter, Group40Var4::Inst()); break; - - // CTO - case(MACRO_DNP_RADIX(51,1)): this->ReadCTO(arIter); break; - case(MACRO_DNP_RADIX(51,2)): this->ReadCTO(arIter); break; - - default: - LOG_BLOCK(LEV_WARNING, "Group: " << aGrp << " Var: " << aVar << " does not map to a data type"); - break; - } -} - - -}} +#include "ResponseLoader.h" + +#include + +#include "HeaderReadIterator.h" +#include "Objects.h" + +namespace apl { namespace dnp { + +ResponseLoader::ResponseLoader(Logger* apLogger, TimeStamp_t aTime, IDataObserver* apPublisher) : +Loggable(apLogger), +mpPublisher(apPublisher), +mTransaction(apPublisher), +mTime(aTime) +{ + +} + +void ResponseLoader::Process(HeaderReadIterator& arIter) +{ + int grp = arIter->GetGroup(); + int var = arIter->GetVariation(); + + this->ProcessData(arIter, grp, var); + + mCTO.NextHeader(); +} + +void ResponseLoader::ProcessData(HeaderReadIterator& arIter, int aGrp, int aVar) +{ + switch(MACRO_DNP_RADIX(aGrp, aVar)) + { + // Control Status + case(MACRO_DNP_RADIX(10,2)): this->Read(arIter, Group10Var2::Inst()); break; + + // Binary + case(MACRO_DNP_RADIX(1,1)): this->ReadBitfield(arIter); break; + + case(MACRO_DNP_RADIX(1,2)): this->Read(arIter, Group1Var2::Inst()); break; + case(MACRO_DNP_RADIX(2,1)): this->Read(arIter, Group2Var1::Inst()); break; + case(MACRO_DNP_RADIX(2,2)): this->Read(arIter, Group2Var2::Inst()); break; + case(MACRO_DNP_RADIX(2,3)): this->Read(arIter, Group2Var3::Inst()); break; + + // Counters + case(MACRO_DNP_RADIX(20,1)): this->Read(arIter, Group20Var1::Inst()); break; + case(MACRO_DNP_RADIX(20,2)): this->Read(arIter, Group20Var2::Inst()); break; + case(MACRO_DNP_RADIX(20,3)): this->Read(arIter, Group20Var3::Inst()); break; + case(MACRO_DNP_RADIX(20,4)): this->Read(arIter, Group20Var4::Inst()); break; + case(MACRO_DNP_RADIX(20,5)): this->Read(arIter, Group20Var5::Inst()); break; + case(MACRO_DNP_RADIX(20,6)): this->Read(arIter, Group20Var6::Inst()); break; + case(MACRO_DNP_RADIX(20,7)): this->Read(arIter, Group20Var7::Inst()); break; + case(MACRO_DNP_RADIX(20,8)): this->Read(arIter, Group20Var8::Inst()); break; + + case(MACRO_DNP_RADIX(22,1)): this->Read(arIter, Group22Var1::Inst()); break; + case(MACRO_DNP_RADIX(22,2)): this->Read(arIter, Group22Var2::Inst()); break; + case(MACRO_DNP_RADIX(22,3)): this->Read(arIter, Group22Var3::Inst()); break; + case(MACRO_DNP_RADIX(22,4)): this->Read(arIter, Group22Var4::Inst()); break; + + // Analogs + case(MACRO_DNP_RADIX(30,1)): this->Read(arIter, Group30Var1::Inst()); break; + case(MACRO_DNP_RADIX(30,2)): this->Read(arIter, Group30Var2::Inst()); break; + case(MACRO_DNP_RADIX(30,3)): this->Read(arIter, Group30Var3::Inst()); break; + case(MACRO_DNP_RADIX(30,4)): this->Read(arIter, Group30Var4::Inst()); break; + case(MACRO_DNP_RADIX(30,5)): this->Read(arIter, Group30Var5::Inst()); break; + case(MACRO_DNP_RADIX(30,6)): this->Read(arIter, Group30Var6::Inst()); break; + + case(MACRO_DNP_RADIX(32,1)): this->Read(arIter, Group32Var1::Inst()); break; + case(MACRO_DNP_RADIX(32,2)): this->Read(arIter, Group32Var2::Inst()); break; + case(MACRO_DNP_RADIX(32,3)): this->Read(arIter, Group32Var3::Inst()); break; + case(MACRO_DNP_RADIX(32,4)): this->Read(arIter, Group32Var4::Inst()); break; + case(MACRO_DNP_RADIX(32,5)): this->Read(arIter, Group32Var5::Inst()); break; + case(MACRO_DNP_RADIX(32,6)): this->Read(arIter, Group32Var6::Inst()); break; + case(MACRO_DNP_RADIX(32,7)): this->Read(arIter, Group32Var7::Inst()); break; + case(MACRO_DNP_RADIX(32,8)): this->Read(arIter, Group32Var8::Inst()); break; + + // Setpoint Status + case(MACRO_DNP_RADIX(40,1)): this->Read(arIter, Group40Var1::Inst()); break; + case(MACRO_DNP_RADIX(40,2)): this->Read(arIter, Group40Var2::Inst()); break; + case(MACRO_DNP_RADIX(40,3)): this->Read(arIter, Group40Var3::Inst()); break; + case(MACRO_DNP_RADIX(40,4)): this->Read(arIter, Group40Var4::Inst()); break; + + // CTO + case(MACRO_DNP_RADIX(51,1)): this->ReadCTO(arIter); break; + case(MACRO_DNP_RADIX(51,2)): this->ReadCTO(arIter); break; + + default: + LOG_BLOCK(LEV_WARNING, "Group: " << aGrp << " Var: " << aVar << " does not map to a data type"); + break; + } +} + + +}} diff --git a/DNP3/ResponseLoader.h b/DNP3/ResponseLoader.h index b771868f..27620d4d 100644 --- a/DNP3/ResponseLoader.h +++ b/DNP3/ResponseLoader.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __RESPONSE_LOADER_H_ #define __RESPONSE_LOADER_H_ @@ -54,8 +54,8 @@ class ResponseLoader : Loggable template void ReadBitfield(HeaderReadIterator& arHeader); - - IDataObserver* mpPublisher; + + IDataObserver* mpPublisher; Transaction mTransaction; TimeStamp_t mTime; CTOHistory mCTO; @@ -67,7 +67,7 @@ void ResponseLoader::ReadCTO(HeaderReadIterator& arIter) ObjectReadIterator i = arIter.BeginRead(); if(i.Count() != 1) - { + { LOG_BLOCK(LEV_WARNING, "Invalid number of CTO objects"); return; } @@ -80,7 +80,7 @@ template void ResponseLoader::Read(HeaderReadIterator& arIter, StreamObject* apObj) { TimeStamp_t t(0); //base time - if(apObj->UseCTO() && !mCTO.GetCTO(t)) { + if(apObj->UseCTO() && !mCTO.GetCTO(t)) { LOG_BLOCK(LEV_ERROR, "No CTO for relative time type " << apObj->Name()); return; } @@ -91,7 +91,7 @@ void ResponseLoader::Read(HeaderReadIterator& arIter, StreamObject* apObj) { size_t index = obj->Index(); T value = apObj->Read(*obj); - + //Make sure the value has time information if(apObj->UseCTO()) value.SetTime(t+value.GetTime()); else if(!apObj->HasTime()) @@ -101,7 +101,7 @@ void ResponseLoader::Read(HeaderReadIterator& arIter, StreamObject* apObj) //Make sure the value has quality information if(!apObj->HasQuality()) value.SetQuality(T::ONLINE); - + mpPublisher->Update(value, index); } } @@ -117,7 +117,7 @@ void ResponseLoader::ReadBitfield(HeaderReadIterator& arIter) for(; !obj.IsEnd(); ++obj) { bool val = BitfieldObject::StaticRead(*obj, obj->Start(), obj->Index()); - b.SetValue(val); + b.SetValue(val); mpPublisher->Update(b, obj->Index()); } } diff --git a/DNP3/SecLinkLayerStates.h b/DNP3/SecLinkLayerStates.h index ecceb01e..874bf11d 100644 --- a/DNP3/SecLinkLayerStates.h +++ b/DNP3/SecLinkLayerStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __SEC_LINK_LAYER_STATES_H_ #define __SEC_LINK_LAYER_STATES_H_ @@ -26,25 +26,25 @@ #include "AsyncLinkLayer.h" namespace apl { namespace dnp { - + class SecStateBase { public: /* Incoming messages to secondary station */ - + void ResetLinkStates(AsyncLinkLayer*); void RequestLinkStatus(AsyncLinkLayer*); void UnconfirmedUserData(AsyncLinkLayer*, const apl::byte_t* apData, size_t aDataLength); virtual void TestLinkStatus(AsyncLinkLayer*, bool aFcb) = 0; - virtual void ConfirmedUserData(AsyncLinkLayer*, bool aFcb, const apl::byte_t* apData, size_t aDataLength) = 0; - - + virtual void ConfirmedUserData(AsyncLinkLayer*, bool aFcb, const apl::byte_t* apData, size_t aDataLength) = 0; + + //every concrete state implements this for logging purposes virtual std::string Name() const = 0; }; - + //////////////////////////////////////////////////////////////////////////////////// // Class SLLS_UnReset //////////////////////////////////////////////////////////////////////////////////// @@ -52,8 +52,8 @@ namespace apl { namespace dnp { { MACRO_STATE_SINGLETON_INSTANCE(SLLS_NotReset); - void TestLinkStatus(AsyncLinkLayer*, bool aFcb); - void ConfirmedUserData(AsyncLinkLayer*, bool aFcb, const apl::byte_t* apData, size_t aDataLength); + void TestLinkStatus(AsyncLinkLayer*, bool aFcb); + void ConfirmedUserData(AsyncLinkLayer*, bool aFcb, const apl::byte_t* apData, size_t aDataLength); }; //////////////////////////////////////////////////////////////////////////////////// @@ -66,7 +66,7 @@ namespace apl { namespace dnp { void TestLinkStatus(AsyncLinkLayer*, bool aFcb); void ConfirmedUserData(AsyncLinkLayer*, bool aFcb, const apl::byte_t* apData, size_t aDataLength); }; - + }} //end namepsace diff --git a/DNP3/SlaveConfig.h b/DNP3/SlaveConfig.h index 4c7d8fc9..800695c7 100644 --- a/DNP3/SlaveConfig.h +++ b/DNP3/SlaveConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,112 +6,112 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __SLAVE_CONFIG_H_ -#define __SLAVE_CONFIG_H_ - - -#include "ObjectInterfaces.h" -#include "ClassMask.h" -#include - -#include - -namespace apl { namespace dnp { - - /// Group/Variation pair - struct GrpVar - { - GrpVar() : Grp(-1), Var(-1) {} - GrpVar(int aGrp, int aVar) : Grp(aGrp), Var(aVar) {} - - int Grp; - int Var; - }; - - /** Configuration information for a dnp3 slave (outstation) - - Used as both input describing the startup configuration of the slave, and as configuration state of mutable properties (i.e. unsolicited responses). - - Major feature areas are unsolicited responses, time synchronization requests, event buffer limits, and the DNP3 object/variations to use by default - when the master requests class data or variation 0. - - */ - struct SlaveConfig - { - SlaveConfig(); - - - /// The maximum number of controls the slave will attempt to process from a single APDU - size_t mMaxControls; - - /// if true, fully disables unsolicited mode as if the slave didn't support it - bool mDisableUnsol; - - /// controls what unsol classes are enabled - ClassMask mUnsolMask; - - /// if true, the slave will request time synchronization on an interval - bool mAllowTimeSync; - - - /// The period of time sync interval in milliseconds - millis_t mTimeSyncPeriod; - - /// The amount of time the slave will wait before sending new unsolicited data ( <= 0 == immediate) - millis_t mUnsolPackDelay; - - /// How long the slave will wait before retrying an unsuccessful unsol response - millis_t mUnsolRetryDelay; - - - /// The maximum fragment size the slave will use for data it sends - size_t mMaxFragSize; - - /// The number of binary events the slave will buffer before overflowing - size_t mMaxBinaryEvents; - - /// The number of analog events the slave will buffer before overflowing - size_t mMaxAnalogEvents; - - /// The number of counter events the slave will buffer before overflowing - size_t mMaxCounterEvents; - - // default static response types - - /// The default group/variation to use for static binary responses - GrpVar mStaticBinary; - - /// The default group/variation to use for static analog responses - GrpVar mStaticAnalog; - - /// The default group/variation to use for static counter responses - GrpVar mStaticCounter; - - /// The default group/variation to use for static setpoint status responses - GrpVar mStaticSetpointStatus; - - // default event response types - - /// The default group/variation to use for binary event responses - GrpVar mEventBinary; - - /// The default group/variation to use for analog event responses - GrpVar mEventAnalog; - - /// The default group/variation to use for counter event responses - GrpVar mEventCounter; - }; - -}} - -#endif +// +#ifndef __SLAVE_CONFIG_H_ +#define __SLAVE_CONFIG_H_ + + +#include "ObjectInterfaces.h" +#include "ClassMask.h" +#include + +#include + +namespace apl { namespace dnp { + + /// Group/Variation pair + struct GrpVar + { + GrpVar() : Grp(-1), Var(-1) {} + GrpVar(int aGrp, int aVar) : Grp(aGrp), Var(aVar) {} + + int Grp; + int Var; + }; + + /** Configuration information for a dnp3 slave (outstation) + + Used as both input describing the startup configuration of the slave, and as configuration state of mutable properties (i.e. unsolicited responses). + + Major feature areas are unsolicited responses, time synchronization requests, event buffer limits, and the DNP3 object/variations to use by default + when the master requests class data or variation 0. + + */ + struct SlaveConfig + { + SlaveConfig(); + + + /// The maximum number of controls the slave will attempt to process from a single APDU + size_t mMaxControls; + + /// if true, fully disables unsolicited mode as if the slave didn't support it + bool mDisableUnsol; + + /// controls what unsol classes are enabled + ClassMask mUnsolMask; + + /// if true, the slave will request time synchronization on an interval + bool mAllowTimeSync; + + + /// The period of time sync interval in milliseconds + millis_t mTimeSyncPeriod; + + /// The amount of time the slave will wait before sending new unsolicited data ( <= 0 == immediate) + millis_t mUnsolPackDelay; + + /// How long the slave will wait before retrying an unsuccessful unsol response + millis_t mUnsolRetryDelay; + + + /// The maximum fragment size the slave will use for data it sends + size_t mMaxFragSize; + + /// The number of binary events the slave will buffer before overflowing + size_t mMaxBinaryEvents; + + /// The number of analog events the slave will buffer before overflowing + size_t mMaxAnalogEvents; + + /// The number of counter events the slave will buffer before overflowing + size_t mMaxCounterEvents; + + // default static response types + + /// The default group/variation to use for static binary responses + GrpVar mStaticBinary; + + /// The default group/variation to use for static analog responses + GrpVar mStaticAnalog; + + /// The default group/variation to use for static counter responses + GrpVar mStaticCounter; + + /// The default group/variation to use for static setpoint status responses + GrpVar mStaticSetpointStatus; + + // default event response types + + /// The default group/variation to use for binary event responses + GrpVar mEventBinary; + + /// The default group/variation to use for analog event responses + GrpVar mEventAnalog; + + /// The default group/variation to use for counter event responses + GrpVar mEventCounter; + }; + +}} + +#endif diff --git a/DNP3/SlaveResponseTypes.cpp b/DNP3/SlaveResponseTypes.cpp index a7adf5ca..c556fd3a 100644 --- a/DNP3/SlaveResponseTypes.cpp +++ b/DNP3/SlaveResponseTypes.cpp @@ -16,145 +16,145 @@ // specific language governing permissions and limitations // under the License. // -#include "SlaveResponseTypes.h" - -#include "SlaveConfig.h" -#include "Objects.h" - -#include - -namespace apl { namespace dnp { - - SlaveResponseTypes::SlaveResponseTypes(const SlaveConfig& arCfg) - { - mpStaticBinary = GetStaticBinary(arCfg.mStaticBinary); - mpStaticAnalog = GetStaticAnalog(arCfg.mStaticAnalog); - mpStaticCounter = GetStaticCounter(arCfg.mStaticCounter); - mpStaticControlStatus = Group10Var2::Inst(); - mpStaticSetpointStatus = GetStaticSetpointStatus(arCfg.mStaticSetpointStatus); - - mpEventBinary = GetEventBinary(arCfg.mEventBinary); - mpEventAnalog = GetEventAnalog(arCfg.mEventAnalog); - mpEventCounter = GetEventCounter(arCfg.mEventCounter); - } - - StreamObject* SlaveResponseTypes::GetStaticBinary(GrpVar gv) - { - switch(gv.Grp) { - case(1): - switch(gv.Var) { - //case(1): return Group1Var1::Inst(); - case(2): return Group1Var2::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid static binary"); - } - - StreamObject* SlaveResponseTypes::GetStaticAnalog(GrpVar gv) - { - switch(gv.Grp) { - case(30): - switch(gv.Var) { - case(1): return Group30Var1::Inst(); - case(2): return Group30Var2::Inst(); - case(3): return Group30Var3::Inst(); - case(4): return Group30Var4::Inst(); - case(5): return Group30Var5::Inst(); - case(6): return Group30Var6::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid static analog"); - } - - StreamObject* SlaveResponseTypes::GetStaticCounter(GrpVar gv) - { - switch(gv.Grp) { - case(20): - switch(gv.Var) { //delta counters are obsolete and have been omitted - //as valid slave responses - case(1): return Group20Var1::Inst(); - case(2): return Group20Var2::Inst(); - case(5): return Group20Var5::Inst(); - case(6): return Group20Var6::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid static counter"); - } - - StreamObject* SlaveResponseTypes::GetStaticSetpointStatus(GrpVar gv) - { - switch(gv.Grp) { - case(40): - switch(gv.Var) { - case(1): return Group40Var1::Inst(); - case(2): return Group40Var2::Inst(); - case(3): return Group40Var3::Inst(); - case(4): return Group40Var4::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid setpoint status"); - } - - StreamObject* SlaveResponseTypes::GetEventBinary(GrpVar gv) - { - switch(gv.Grp) { - case(2): - switch(gv.Var) { - case(1): return Group2Var1::Inst(); - case(2): return Group2Var2::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid event binary"); - } - - StreamObject* SlaveResponseTypes::GetEventAnalog(GrpVar gv) - { - switch(gv.Grp) { - case(32): - switch(gv.Var) { - case(1): return Group32Var1::Inst(); - case(2): return Group32Var2::Inst(); - case(3): return Group32Var3::Inst(); - case(4): return Group32Var4::Inst(); - case(5): return Group32Var5::Inst(); - case(6): return Group32Var6::Inst(); - case(7): return Group32Var7::Inst(); - case(8): return Group32Var8::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid event analog"); - } - - StreamObject* SlaveResponseTypes::GetEventCounter(GrpVar gv) - { - switch(gv.Grp) { - case(22): - switch(gv.Var) { //delta counters are obsolete and have been omitted - //as valid slave responses - case(1): return Group22Var1::Inst(); - case(2): return Group22Var2::Inst(); - case(5): return Group22Var5::Inst(); - case(6): return Group22Var6::Inst(); - } - break; - } - - throw ArgumentException(LOCATION, "Invalid event counter"); - } - - - -}} - +#include "SlaveResponseTypes.h" + +#include "SlaveConfig.h" +#include "Objects.h" + +#include + +namespace apl { namespace dnp { + + SlaveResponseTypes::SlaveResponseTypes(const SlaveConfig& arCfg) + { + mpStaticBinary = GetStaticBinary(arCfg.mStaticBinary); + mpStaticAnalog = GetStaticAnalog(arCfg.mStaticAnalog); + mpStaticCounter = GetStaticCounter(arCfg.mStaticCounter); + mpStaticControlStatus = Group10Var2::Inst(); + mpStaticSetpointStatus = GetStaticSetpointStatus(arCfg.mStaticSetpointStatus); + + mpEventBinary = GetEventBinary(arCfg.mEventBinary); + mpEventAnalog = GetEventAnalog(arCfg.mEventAnalog); + mpEventCounter = GetEventCounter(arCfg.mEventCounter); + } + + StreamObject* SlaveResponseTypes::GetStaticBinary(GrpVar gv) + { + switch(gv.Grp) { + case(1): + switch(gv.Var) { + //case(1): return Group1Var1::Inst(); + case(2): return Group1Var2::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid static binary"); + } + + StreamObject* SlaveResponseTypes::GetStaticAnalog(GrpVar gv) + { + switch(gv.Grp) { + case(30): + switch(gv.Var) { + case(1): return Group30Var1::Inst(); + case(2): return Group30Var2::Inst(); + case(3): return Group30Var3::Inst(); + case(4): return Group30Var4::Inst(); + case(5): return Group30Var5::Inst(); + case(6): return Group30Var6::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid static analog"); + } + + StreamObject* SlaveResponseTypes::GetStaticCounter(GrpVar gv) + { + switch(gv.Grp) { + case(20): + switch(gv.Var) { //delta counters are obsolete and have been omitted + //as valid slave responses + case(1): return Group20Var1::Inst(); + case(2): return Group20Var2::Inst(); + case(5): return Group20Var5::Inst(); + case(6): return Group20Var6::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid static counter"); + } + + StreamObject* SlaveResponseTypes::GetStaticSetpointStatus(GrpVar gv) + { + switch(gv.Grp) { + case(40): + switch(gv.Var) { + case(1): return Group40Var1::Inst(); + case(2): return Group40Var2::Inst(); + case(3): return Group40Var3::Inst(); + case(4): return Group40Var4::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid setpoint status"); + } + + StreamObject* SlaveResponseTypes::GetEventBinary(GrpVar gv) + { + switch(gv.Grp) { + case(2): + switch(gv.Var) { + case(1): return Group2Var1::Inst(); + case(2): return Group2Var2::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid event binary"); + } + + StreamObject* SlaveResponseTypes::GetEventAnalog(GrpVar gv) + { + switch(gv.Grp) { + case(32): + switch(gv.Var) { + case(1): return Group32Var1::Inst(); + case(2): return Group32Var2::Inst(); + case(3): return Group32Var3::Inst(); + case(4): return Group32Var4::Inst(); + case(5): return Group32Var5::Inst(); + case(6): return Group32Var6::Inst(); + case(7): return Group32Var7::Inst(); + case(8): return Group32Var8::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid event analog"); + } + + StreamObject* SlaveResponseTypes::GetEventCounter(GrpVar gv) + { + switch(gv.Grp) { + case(22): + switch(gv.Var) { //delta counters are obsolete and have been omitted + //as valid slave responses + case(1): return Group22Var1::Inst(); + case(2): return Group22Var2::Inst(); + case(5): return Group22Var5::Inst(); + case(6): return Group22Var6::Inst(); + } + break; + } + + throw ArgumentException(LOCATION, "Invalid event counter"); + } + + + +}} + diff --git a/DNP3/SlaveResponseTypes.h b/DNP3/SlaveResponseTypes.h index 3a0c2f09..44b69159 100644 --- a/DNP3/SlaveResponseTypes.h +++ b/DNP3/SlaveResponseTypes.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,57 +6,57 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __SLAVE_RESPONSE_TYPES_H_ -#define __SLAVE_RESPONSE_TYPES_H_ - -#include "ObjectInterfaces.h" -#include - -namespace apl { namespace dnp { - -struct SlaveConfig; -struct GrpVar; - -/** Reads a slave config object and and translates the configuration to singletons -*/ -class SlaveResponseTypes -{ - public: - SlaveResponseTypes(const SlaveConfig& arCfg); - - StreamObject* mpStaticBinary; - StreamObject* mpStaticAnalog; - StreamObject* mpStaticCounter; - StreamObject* mpStaticControlStatus; - StreamObject* mpStaticSetpointStatus; - - StreamObject* mpEventBinary; - StreamObject* mpEventAnalog; - StreamObject* mpEventCounter; - - private: - - static StreamObject* GetStaticBinary(GrpVar); - static StreamObject* GetStaticAnalog(GrpVar); - static StreamObject* GetStaticCounter(GrpVar); - static StreamObject* GetStaticSetpointStatus(GrpVar); - - static StreamObject* GetEventBinary(GrpVar); - static StreamObject* GetEventAnalog(GrpVar); - static StreamObject* GetEventCounter(GrpVar); - -}; - -}} - -#endif +// +#ifndef __SLAVE_RESPONSE_TYPES_H_ +#define __SLAVE_RESPONSE_TYPES_H_ + +#include "ObjectInterfaces.h" +#include + +namespace apl { namespace dnp { + +struct SlaveConfig; +struct GrpVar; + +/** Reads a slave config object and and translates the configuration to singletons +*/ +class SlaveResponseTypes +{ + public: + SlaveResponseTypes(const SlaveConfig& arCfg); + + StreamObject* mpStaticBinary; + StreamObject* mpStaticAnalog; + StreamObject* mpStaticCounter; + StreamObject* mpStaticControlStatus; + StreamObject* mpStaticSetpointStatus; + + StreamObject* mpEventBinary; + StreamObject* mpEventAnalog; + StreamObject* mpEventCounter; + + private: + + static StreamObject* GetStaticBinary(GrpVar); + static StreamObject* GetStaticAnalog(GrpVar); + static StreamObject* GetStaticCounter(GrpVar); + static StreamObject* GetStaticSetpointStatus(GrpVar); + + static StreamObject* GetEventBinary(GrpVar); + static StreamObject* GetEventAnalog(GrpVar); + static StreamObject* GetEventCounter(GrpVar); + +}; + +}} + +#endif diff --git a/DNP3/SlaveStackConfig.h b/DNP3/SlaveStackConfig.h index 5f53923f..2a87cbb0 100644 --- a/DNP3/SlaveStackConfig.h +++ b/DNP3/SlaveStackConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,42 +6,42 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __SLAVE_STACK_CONFIG_H_ -#define __SLAVE_STACK_CONFIG_H_ - -#include "SlaveConfig.h" -#include "DeviceTemplate.h" -#include "AppConfig.h" -#include "LinkConfig.h" - -namespace apl { namespace dnp { - -/** A composite configuration struct that contains all the config - information for a dnp3 slave stack -*/ -struct SlaveStackConfig -{ - SlaveStackConfig() : - link(false, false) - {} - - SlaveConfig slave; /// Slave config - DeviceTemplate device; /// Device template that specifies database layout, control behavior - AppConfig app; /// Application layer config - LinkConfig link; /// Link layer config -}; - -}} - -#endif - +// +#ifndef __SLAVE_STACK_CONFIG_H_ +#define __SLAVE_STACK_CONFIG_H_ + +#include "SlaveConfig.h" +#include "DeviceTemplate.h" +#include "AppConfig.h" +#include "LinkConfig.h" + +namespace apl { namespace dnp { + +/** A composite configuration struct that contains all the config + information for a dnp3 slave stack +*/ +struct SlaveStackConfig +{ + SlaveStackConfig() : + link(false, false) + {} + + SlaveConfig slave; /// Slave config + DeviceTemplate device; /// Device template that specifies database layout, control behavior + AppConfig app; /// Application layer config + LinkConfig link; /// Link layer config +}; + +}} + +#endif + diff --git a/DNP3/SolicitedChannel.cpp b/DNP3/SolicitedChannel.cpp index f1efd1af..c8c88bfd 100644 --- a/DNP3/SolicitedChannel.cpp +++ b/DNP3/SolicitedChannel.cpp @@ -16,60 +16,60 @@ // specific language governing permissions and limitations // under the License. // -#include "SolicitedChannel.h" - -#include "AsyncAppLayer.h" -#include "AppChannelStates.h" - -namespace apl { namespace dnp { - - -SolicitedChannel::SolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout) : -AppLayerChannel("Solicited", apLogger, apApp, apTimerSrc, aTimeout) -{} - -bool SolicitedChannel::AcceptsResponse() -{ return mpState->AcceptsResponse(); } - -void SolicitedChannel::DoSendSuccess() -{ - mpAppLayer->mpUser->OnSolSendSuccess(); -} - -void SolicitedChannel::DoFailure() -{ - mpAppLayer->mpUser->OnSolFailure(); -} - -void SolicitedChannel::OnResponse(APDU& arAPDU) -{ - mpState->OnResponse(this, arAPDU); -} - -void SolicitedChannel::OnRequest(APDU& arAPDU) -{ - - AppControlField acf = arAPDU.GetControl(); - - SequenceInfo seq = SI_OTHER; - if (acf.SEQ == this->Sequence()) { - seq = SI_PREV; - } - else if (acf.SEQ == NextSeq(this->Sequence())) { - seq = SI_CORRECT; - } - - mSequence = acf.SEQ; - - mpAppLayer->mpUser->OnRequest(arAPDU, seq); -} - -void SolicitedChannel::OnUnknownObjectInRequest(const AppControlField& acf) -{ - mSequence = acf.SEQ; // capture the sequence number -} - - -}} - - +#include "SolicitedChannel.h" + +#include "AsyncAppLayer.h" +#include "AppChannelStates.h" + +namespace apl { namespace dnp { + + +SolicitedChannel::SolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout) : +AppLayerChannel("Solicited", apLogger, apApp, apTimerSrc, aTimeout) +{} + +bool SolicitedChannel::AcceptsResponse() +{ return mpState->AcceptsResponse(); } + +void SolicitedChannel::DoSendSuccess() +{ + mpAppLayer->mpUser->OnSolSendSuccess(); +} + +void SolicitedChannel::DoFailure() +{ + mpAppLayer->mpUser->OnSolFailure(); +} + +void SolicitedChannel::OnResponse(APDU& arAPDU) +{ + mpState->OnResponse(this, arAPDU); +} + +void SolicitedChannel::OnRequest(APDU& arAPDU) +{ + + AppControlField acf = arAPDU.GetControl(); + + SequenceInfo seq = SI_OTHER; + if (acf.SEQ == this->Sequence()) { + seq = SI_PREV; + } + else if (acf.SEQ == NextSeq(this->Sequence())) { + seq = SI_CORRECT; + } + + mSequence = acf.SEQ; + + mpAppLayer->mpUser->OnRequest(arAPDU, seq); +} + +void SolicitedChannel::OnUnknownObjectInRequest(const AppControlField& acf) +{ + mSequence = acf.SEQ; // capture the sequence number +} + + +}} + + diff --git a/DNP3/SolicitedChannel.h b/DNP3/SolicitedChannel.h index 64b75e73..83a7f247 100644 --- a/DNP3/SolicitedChannel.h +++ b/DNP3/SolicitedChannel.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,48 +6,48 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __SOLICITED_CHANNEL_H_ -#define __SOLICITED_CHANNEL_H_ - -#include "AppLayerChannel.h" - -namespace apl { namespace dnp { - -/** The application layer contains two virtual channels, one for - solicited and unsolicited communication. Each channel has a sequence - number and some state associated with wether it is sending, waiting - for a response, etc -*/ -class SolicitedChannel : public AppLayerChannel -{ - public: - SolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout); - virtual ~SolicitedChannel(){} - - /// Called when the app layer has a problem parsing an object header - void OnUnknownObjectInRequest(const AppControlField& acf); - void OnResponse(APDU& arAPDU); - void OnRequest(APDU& arAPDU); - - bool AcceptsResponse(); - - private: - - // implement virtual memebers from AppLayerChannel - void DoSendSuccess(); - void DoFailure(); -}; - -}} - -#endif +// +#ifndef __SOLICITED_CHANNEL_H_ +#define __SOLICITED_CHANNEL_H_ + +#include "AppLayerChannel.h" + +namespace apl { namespace dnp { + +/** The application layer contains two virtual channels, one for + solicited and unsolicited communication. Each channel has a sequence + number and some state associated with wether it is sending, waiting + for a response, etc +*/ +class SolicitedChannel : public AppLayerChannel +{ + public: + SolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout); + virtual ~SolicitedChannel(){} + + /// Called when the app layer has a problem parsing an object header + void OnUnknownObjectInRequest(const AppControlField& acf); + void OnResponse(APDU& arAPDU); + void OnRequest(APDU& arAPDU); + + bool AcceptsResponse(); + + private: + + // implement virtual memebers from AppLayerChannel + void DoSendSuccess(); + void DoFailure(); +}; + +}} + +#endif diff --git a/DNP3/StackManager.cpp b/DNP3/StackManager.cpp index 5790f613..47f269c9 100644 --- a/DNP3/StackManager.cpp +++ b/DNP3/StackManager.cpp @@ -16,52 +16,52 @@ // specific language governing permissions and limitations // under the License. // -#include "StackManager.h" - -#include -#include - -namespace apl { namespace dnp { - -StackManager::StackManager(bool aAutoStart) : -mpLog(new EventLog()), -mpImpl(new AsyncStackManager(mpLog->GetLogger(LEV_WARNING, "dnp"), aAutoStart)) -{ - -} - -void StackManager::AddLogHook(ILogBase* apHook) -{ - mpLog->AddLogSubscriber(apHook); -} - -StackManager::~StackManager() { delete mpImpl; delete mpLog; } - -//used for defining ports -void StackManager::AddTCPClient(const std::string& arName, PhysLayerSettings s, const std::string& arAddr, uint_16_t aPort) -{ mpImpl->AddTCPClient(arName, s, arAddr, aPort); } - -void StackManager::AddTCPServer(const std::string& arName, PhysLayerSettings s, uint_16_t aPort) -{ mpImpl->AddTCPServer(arName, s, aPort); } - -void StackManager::AddSerial(const std::string& arName, PhysLayerSettings s, SerialSettings aSerial) -{ mpImpl->AddSerial(arName, s, aSerial); } - -ICommandAcceptor* StackManager::AddMaster(const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, - IDataObserver* apPublisher, const MasterStackConfig& arCfg) -{ return mpImpl->AddMaster(arPortName, arStackName, aLevel, apPublisher, arCfg); } - -IDataObserver* StackManager::AddSlave(const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, - ICommandAcceptor* apCmdAcceptor, const SlaveStackConfig& arCfg) -{ return mpImpl->AddSlave(arPortName, arStackName, aLevel, apCmdAcceptor, arCfg); } - - -void StackManager::Stop() { mpImpl->Stop(); } -void StackManager::Start() { mpImpl->Start(); } -void StackManager::RemovePort(const std::string& arPortName) { mpImpl->RemovePort(arPortName); } -void StackManager::RemoveStack(const std::string& arStackName) { mpImpl->RemoveStack(arStackName); } -std::vector StackManager::GetStackNames() { return mpImpl->GetStackNames(); } -std::vector StackManager::GetPortNames() { return mpImpl->GetPortNames(); } - -}} - +#include "StackManager.h" + +#include +#include + +namespace apl { namespace dnp { + +StackManager::StackManager(bool aAutoStart) : +mpLog(new EventLog()), +mpImpl(new AsyncStackManager(mpLog->GetLogger(LEV_WARNING, "dnp"), aAutoStart)) +{ + +} + +void StackManager::AddLogHook(ILogBase* apHook) +{ + mpLog->AddLogSubscriber(apHook); +} + +StackManager::~StackManager() { delete mpImpl; delete mpLog; } + +//used for defining ports +void StackManager::AddTCPClient(const std::string& arName, PhysLayerSettings s, const std::string& arAddr, uint_16_t aPort) +{ mpImpl->AddTCPClient(arName, s, arAddr, aPort); } + +void StackManager::AddTCPServer(const std::string& arName, PhysLayerSettings s, uint_16_t aPort) +{ mpImpl->AddTCPServer(arName, s, aPort); } + +void StackManager::AddSerial(const std::string& arName, PhysLayerSettings s, SerialSettings aSerial) +{ mpImpl->AddSerial(arName, s, aSerial); } + +ICommandAcceptor* StackManager::AddMaster(const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, + IDataObserver* apPublisher, const MasterStackConfig& arCfg) +{ return mpImpl->AddMaster(arPortName, arStackName, aLevel, apPublisher, arCfg); } + +IDataObserver* StackManager::AddSlave(const std::string& arPortName, const std::string& arStackName, FilterLevel aLevel, + ICommandAcceptor* apCmdAcceptor, const SlaveStackConfig& arCfg) +{ return mpImpl->AddSlave(arPortName, arStackName, aLevel, apCmdAcceptor, arCfg); } + + +void StackManager::Stop() { mpImpl->Stop(); } +void StackManager::Start() { mpImpl->Start(); } +void StackManager::RemovePort(const std::string& arPortName) { mpImpl->RemovePort(arPortName); } +void StackManager::RemoveStack(const std::string& arStackName) { mpImpl->RemoveStack(arStackName); } +std::vector StackManager::GetStackNames() { return mpImpl->GetStackNames(); } +std::vector StackManager::GetPortNames() { return mpImpl->GetPortNames(); } + +}} + diff --git a/DNP3/StackManager.h b/DNP3/StackManager.h index 30101220..fe987b4b 100644 --- a/DNP3/StackManager.h +++ b/DNP3/StackManager.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,85 +6,85 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __STACK_MANAGER_H_ -#define __STACK_MANAGER_H_ - -#include -#include -#include -#include -#include - -#include -#include - -#include - -namespace apl { - class EventLog; - class ILogBase; -} - -namespace apl { namespace dnp { - -class AsyncStackManager; - -/** Wraps the AyncStackManger using the impl pattern. This makes it suiteable - for wrapping with swig or for creating a header-only distribution - The functions do the exact same thing as their impl counterparts - */ -class StackManager -{ - public: - StackManager(bool aAutoStart); - ~StackManager(); - - void AddTCPClient(const std::string& arName, PhysLayerSettings aPhys, const std::string& arAddr, uint_16_t aPort); - void AddTCPServer(const std::string& arName, PhysLayerSettings aPhys, uint_16_t aPort); - void AddSerial(const std::string& arName, PhysLayerSettings aPhys, SerialSettings aSerial); - - ICommandAcceptor* AddMaster(const std::string& arPortName, - const std::string& arStackName, - FilterLevel aLevel, - IDataObserver* apPublisher, - const MasterStackConfig& arCfg); - - IDataObserver* AddSlave(const std::string& arPortName, - const std::string& arStackName, - FilterLevel aLevel, - ICommandAcceptor* apCmdAcceptor, - const SlaveStackConfig& arCfg); - - void RemovePort(const std::string& arPortName); - - void RemoveStack(const std::string& arStackName); - - void AddLogHook(ILogBase*); - - std::vector GetStackNames(); - - std::vector GetPortNames(); - - - void Stop(); - void Start(); - - private: - EventLog* mpLog; - AsyncStackManager* mpImpl; -}; - -}} - -#endif - +// +#ifndef __STACK_MANAGER_H_ +#define __STACK_MANAGER_H_ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace apl { + class EventLog; + class ILogBase; +} + +namespace apl { namespace dnp { + +class AsyncStackManager; + +/** Wraps the AyncStackManger using the impl pattern. This makes it suiteable + for wrapping with swig or for creating a header-only distribution + The functions do the exact same thing as their impl counterparts + */ +class StackManager +{ + public: + StackManager(bool aAutoStart); + ~StackManager(); + + void AddTCPClient(const std::string& arName, PhysLayerSettings aPhys, const std::string& arAddr, uint_16_t aPort); + void AddTCPServer(const std::string& arName, PhysLayerSettings aPhys, uint_16_t aPort); + void AddSerial(const std::string& arName, PhysLayerSettings aPhys, SerialSettings aSerial); + + ICommandAcceptor* AddMaster(const std::string& arPortName, + const std::string& arStackName, + FilterLevel aLevel, + IDataObserver* apPublisher, + const MasterStackConfig& arCfg); + + IDataObserver* AddSlave(const std::string& arPortName, + const std::string& arStackName, + FilterLevel aLevel, + ICommandAcceptor* apCmdAcceptor, + const SlaveStackConfig& arCfg); + + void RemovePort(const std::string& arPortName); + + void RemoveStack(const std::string& arStackName); + + void AddLogHook(ILogBase*); + + std::vector GetStackNames(); + + std::vector GetPortNames(); + + + void Stop(); + void Start(); + + private: + EventLog* mpLog; + AsyncStackManager* mpImpl; +}; + +}} + +#endif + diff --git a/DNP3/TLS_Base.h b/DNP3/TLS_Base.h index f724ac7c..b42902ef 100644 --- a/DNP3/TLS_Base.h +++ b/DNP3/TLS_Base.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TLS_BASE_H_ #define __TLS_BASE_H_ @@ -38,11 +38,11 @@ namespace apl { namespace dnp { public: virtual void Send(const apl::byte_t*, size_t, AsyncTransportLayer*); virtual void HandleReceive(const apl::byte_t*, size_t, AsyncTransportLayer*); - + // TPDU failure/success handlers virtual void HandleSendSuccess(AsyncTransportLayer*); virtual void HandleSendFailure(AsyncTransportLayer*); - + virtual void LowerLayerUp(AsyncTransportLayer*); virtual void LowerLayerDown(AsyncTransportLayer*); diff --git a/DNP3/TransportConstants.h b/DNP3/TransportConstants.h index 288c7026..141d335a 100644 --- a/DNP3/TransportConstants.h +++ b/DNP3/TransportConstants.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_CONSTANTS_H_ #define __TRANSPORT_CONSTANTS_H_ diff --git a/DNP3/TransportRx.h b/DNP3/TransportRx.h index 88629e65..86634bb5 100644 --- a/DNP3/TransportRx.h +++ b/DNP3/TransportRx.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_RX_H_ #define __TRANSPORT_RX_H_ @@ -52,7 +52,7 @@ class TransportRx : public Loggable size_t mNumBytesRead; int mSeq; - + size_t BufferRemaining() { return mBuffer.Size() - mNumBytesRead; } }; diff --git a/DNP3/TransportStates.h b/DNP3/TransportStates.h index 6d6da030..4c60082b 100644 --- a/DNP3/TransportStates.h +++ b/DNP3/TransportStates.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_STATES_H_ #define __TRANSPORT_STATES_H_ @@ -30,7 +30,7 @@ namespace apl { namespace dnp { class TLS_Closed : public TLS_Base { MACRO_STATE_SINGLETON_INSTANCE(TLS_Closed); - + void LowerLayerUp(AsyncTransportLayer*); }; @@ -39,7 +39,7 @@ namespace apl { namespace dnp { class TLS_Ready : public TLS_Base { MACRO_STATE_SINGLETON_INSTANCE(TLS_Ready); - + void Send(const byte_t*, size_t, AsyncTransportLayer*); void HandleReceive(const apl::byte_t*, size_t, AsyncTransportLayer*); void LowerLayerDown(AsyncTransportLayer*); diff --git a/DNP3/TransportTx.h b/DNP3/TransportTx.h index 626faa81..9f2d36c1 100644 --- a/DNP3/TransportTx.h +++ b/DNP3/TransportTx.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_TX_H_ #define __TRANSPORT_TX_H_ @@ -38,11 +38,11 @@ class TransportTx : public Loggable public: TransportTx(Logger*, AsyncTransportLayer*, size_t aFragSize); - + void Send(const apl::byte_t*, size_t); // A fresh call to Send() will reset the state bool SendSuccess(); - - + + static byte_t GetHeader(bool aFir, bool aFin, int aSeq); private: diff --git a/DNP3/UnsolicitedChannel.cpp b/DNP3/UnsolicitedChannel.cpp index 6b4bc12a..4d088a3f 100644 --- a/DNP3/UnsolicitedChannel.cpp +++ b/DNP3/UnsolicitedChannel.cpp @@ -16,43 +16,43 @@ // specific language governing permissions and limitations // under the License. // -#include "UnsolicitedChannel.h" - -#include -#include "AsyncAppLayer.h" - -namespace apl { namespace dnp { - - -UnsolicitedChannel::UnsolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout) : -AppLayerChannel("Unsolicited", apLogger, apApp, apTimerSrc, aTimeout) -{} - -void UnsolicitedChannel::OnUnsol(APDU& arAPDU) -{ - AppControlField acf = arAPDU.GetControl(); - - if(acf.SEQ == mSequence) - { - LOG_BLOCK(LEV_INFO, "Ignoring repeat unsol seq: " << acf.SEQ) - } - else // only process the data if the sequence number is new - { - mSequence = acf.SEQ; - mpAppLayer->mpUser->OnUnsolResponse(arAPDU); - } -} - -void UnsolicitedChannel::DoSendSuccess() -{ - mpAppLayer->mpUser->OnUnsolSendSuccess(); -} - -void UnsolicitedChannel::DoFailure() -{ - mpAppLayer->mpUser->OnUnsolFailure(); -} - -}} - - +#include "UnsolicitedChannel.h" + +#include +#include "AsyncAppLayer.h" + +namespace apl { namespace dnp { + + +UnsolicitedChannel::UnsolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout) : +AppLayerChannel("Unsolicited", apLogger, apApp, apTimerSrc, aTimeout) +{} + +void UnsolicitedChannel::OnUnsol(APDU& arAPDU) +{ + AppControlField acf = arAPDU.GetControl(); + + if(acf.SEQ == mSequence) + { + LOG_BLOCK(LEV_INFO, "Ignoring repeat unsol seq: " << acf.SEQ) + } + else // only process the data if the sequence number is new + { + mSequence = acf.SEQ; + mpAppLayer->mpUser->OnUnsolResponse(arAPDU); + } +} + +void UnsolicitedChannel::DoSendSuccess() +{ + mpAppLayer->mpUser->OnUnsolSendSuccess(); +} + +void UnsolicitedChannel::DoFailure() +{ + mpAppLayer->mpUser->OnUnsolFailure(); +} + +}} + + diff --git a/DNP3/UnsolicitedChannel.h b/DNP3/UnsolicitedChannel.h index ce582b19..50218773 100644 --- a/DNP3/UnsolicitedChannel.h +++ b/DNP3/UnsolicitedChannel.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,40 +6,40 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __UNSOLICITED_CHANNEL_H_ -#define __UNSOLICITED_CHANNEL_H_ - -#include "AppLayerChannel.h" - -namespace apl { namespace dnp { - -/** The application layer contains two virtual channels, one for - solicited and unsolicited communication. Each channel has a sequence - number and some state associated with wether it is sending, waiting - for a response, etc -*/ -class UnsolicitedChannel : public AppLayerChannel -{ - public: - UnsolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout); - virtual ~UnsolicitedChannel(){} - - void OnUnsol(APDU& arAPDU); - - void DoSendSuccess(); - void DoFailure(); -}; - -}} - -#endif +// +#ifndef __UNSOLICITED_CHANNEL_H_ +#define __UNSOLICITED_CHANNEL_H_ + +#include "AppLayerChannel.h" + +namespace apl { namespace dnp { + +/** The application layer contains two virtual channels, one for + solicited and unsolicited communication. Each channel has a sequence + number and some state associated with wether it is sending, waiting + for a response, etc +*/ +class UnsolicitedChannel : public AppLayerChannel +{ + public: + UnsolicitedChannel(Logger* apLogger, AsyncAppLayer* apApp, ITimerSource* apTimerSrc, millis_t aTimeout); + virtual ~UnsolicitedChannel(){} + + void OnUnsol(APDU& arAPDU); + + void DoSendSuccess(); + void DoFailure(); +}; + +}} + +#endif diff --git a/DNP3/rake.project.rb b/DNP3/rake.project.rb index 2560dc68..46d15676 100644 --- a/DNP3/rake.project.rb +++ b/DNP3/rake.project.rb @@ -16,8 +16,8 @@ # specific language governing permissions and limitations # under the License. # -#setup the psi project -$options = { -:target => 'libdnp3.a', -:includes => [Boost::get_includes_dir,DEFAULT_INCLUDES], -} +#setup the psi project +$options = { +:target => 'libdnp3.a', +:includes => [Boost::get_includes_dir,DEFAULT_INCLUDES], +} diff --git a/DNP3Java/DNP3Java.vcproj b/DNP3Java/DNP3Java.vcproj index 5711f4cc..cd3cf6da 100755 --- a/DNP3Java/DNP3Java.vcproj +++ b/DNP3Java/DNP3Java.vcproj @@ -1,197 +1,197 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DNP3Java/JNI_INCLUDES.vsprops b/DNP3Java/JNI_INCLUDES.vsprops index c7e4832a..73870148 100755 --- a/DNP3Java/JNI_INCLUDES.vsprops +++ b/DNP3Java/JNI_INCLUDES.vsprops @@ -1,11 +1,11 @@ - - - - + + + + diff --git a/DNP3Java/JavaDNP3.i b/DNP3Java/JavaDNP3.i index 9f549379..a5062804 100755 --- a/DNP3Java/JavaDNP3.i +++ b/DNP3Java/JavaDNP3.i @@ -1,82 +1,82 @@ -%module(directors="1") javadnp3 -%{ -/* Includes the header in the wrapper code */ - -#include - -using namespace apl; -using namespace apl::dnp; - -%} - -%pragma(java) jniclasscode=%{ - static { - - try{ - System.out.println("trying to load library"); - System.out.println("java.library.path="+System.getProperty("java.library.path")); - System.loadLibrary("dnp3java"); - System.out.println("Done loading library"); - }catch(UnsatisfiedLinkError e){ - System.out.println(e); - System.out.println("java.library.path="+System.getProperty("java.library.path")); - System.exit(-1); - } - } -%} - -%include -%include - -%template(VectorOfString) std::vector; - -%feature("director"); //generate directors for all classes that have virtual methods - -%include "APL/Types.h" -%include "APL/INotifier.h" -%include "APL/LogTypes.h" -%include "APL/LogBase.h" -%include "APL/PhysLayerSettings.h" -%include "APL/SerialTypes.h" -%include "APL/QualityMasks.h" -%include "APL/CommandTypes.h" -%include "APL/DataTypes.h" -%include "APL/DataInterfaces.h" -%include "APL/CommandInterfaces.h" - -%include "DNP3/PointClass.h" -%include "DNP3/LinkConfig.h" -%include "DNP3/AppConfig.h" -%include "DNP3/MasterConfigTypes.h" - -%template(VectorOfExceptionScan) std::vector; -%include "DNP3/MasterConfig.h" -%include "DNP3/SlaveConfig.h" - -%include "DNP3/DeviceTemplateTypes.h" -%template(VectorOfEventPointRecord) std::vector; -%template(VectorOfDeadbandPointRecord) std::vector; -%template(VectorOfControlRecord) std::vector; -%include "DNP3/DeviceTemplate.h" - -%include "DNP3/MasterStackConfig.h" -%include "DNP3/SlaveStackConfig.h" - - -%include -// provide an exception handler for the stack manager -%exception { - try { - $action - } - catch (apl::Exception ex) { - SWIG_exception(SWIG_ValueError, ex.what()); - } - catch (std::exception ex) { - SWIG_exception(SWIG_ValueError, ex.what()); - } -} - - -%include "DNP3/StackManager.h" - +%module(directors="1") javadnp3 +%{ +/* Includes the header in the wrapper code */ + +#include + +using namespace apl; +using namespace apl::dnp; + +%} + +%pragma(java) jniclasscode=%{ + static { + + try{ + System.out.println("trying to load library"); + System.out.println("java.library.path="+System.getProperty("java.library.path")); + System.loadLibrary("dnp3java"); + System.out.println("Done loading library"); + }catch(UnsatisfiedLinkError e){ + System.out.println(e); + System.out.println("java.library.path="+System.getProperty("java.library.path")); + System.exit(-1); + } + } +%} + +%include +%include + +%template(VectorOfString) std::vector; + +%feature("director"); //generate directors for all classes that have virtual methods + +%include "APL/Types.h" +%include "APL/INotifier.h" +%include "APL/LogTypes.h" +%include "APL/LogBase.h" +%include "APL/PhysLayerSettings.h" +%include "APL/SerialTypes.h" +%include "APL/QualityMasks.h" +%include "APL/CommandTypes.h" +%include "APL/DataTypes.h" +%include "APL/DataInterfaces.h" +%include "APL/CommandInterfaces.h" + +%include "DNP3/PointClass.h" +%include "DNP3/LinkConfig.h" +%include "DNP3/AppConfig.h" +%include "DNP3/MasterConfigTypes.h" + +%template(VectorOfExceptionScan) std::vector; +%include "DNP3/MasterConfig.h" +%include "DNP3/SlaveConfig.h" + +%include "DNP3/DeviceTemplateTypes.h" +%template(VectorOfEventPointRecord) std::vector; +%template(VectorOfDeadbandPointRecord) std::vector; +%template(VectorOfControlRecord) std::vector; +%include "DNP3/DeviceTemplate.h" + +%include "DNP3/MasterStackConfig.h" +%include "DNP3/SlaveStackConfig.h" + + +%include +// provide an exception handler for the stack manager +%exception { + try { + $action + } + catch (apl::Exception ex) { + SWIG_exception(SWIG_ValueError, ex.what()); + } + catch (std::exception ex) { + SWIG_exception(SWIG_ValueError, ex.what()); + } +} + + +%include "DNP3/StackManager.h" + diff --git a/DNP3Java/TestBinding.java b/DNP3Java/TestBinding.java index a165e976..803ebc4d 100755 --- a/DNP3Java/TestBinding.java +++ b/DNP3Java/TestBinding.java @@ -1,10 +1,10 @@ -import org.psi.dnp3.*; - -class TestBinding{ - - public static void main(String[] args){ - Setpoint s = new Setpoint(); - } - -} - +import org.psi.dnp3.*; + +class TestBinding{ + + public static void main(String[] args){ + Setpoint s = new Setpoint(); + } + +} + diff --git a/DNP3Java/rake.project.rb b/DNP3Java/rake.project.rb index fe5286c8..7013c751 100755 --- a/DNP3Java/rake.project.rb +++ b/DNP3Java/rake.project.rb @@ -1,13 +1,13 @@ - -$options = { -:allowed_platforms => ['pc_cygwin', 'Linux_i686'], -:target => 'libdnp3java.so', -:cc_release_flags => '-O1 -fPIC', #compiling the swig binding at O2 and above was causing programs to seg fault -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -:link_options => [], -:libs => $PLATFORM_LIBS + Boost::get_static_libs + $WINSOCK_LIBS, -:project_libs => [:dnp3, :apl], -:plugins => ['swigjava'], #swigjava specific options -:java_package => 'org.psi.dnp3', -:java_outdir => 'jar/org/psi/dnp3', -} + +$options = { +:allowed_platforms => ['pc_cygwin', 'Linux_i686'], +:target => 'libdnp3java.so', +:cc_release_flags => '-O1 -fPIC', #compiling the swig binding at O2 and above was causing programs to seg fault +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +:link_options => [], +:libs => $PLATFORM_LIBS + Boost::get_static_libs + $WINSOCK_LIBS, +:project_libs => [:dnp3, :apl], +:plugins => ['swigjava'], #swigjava specific options +:java_package => 'org.psi.dnp3', +:java_outdir => 'jar/org/psi/dnp3', +} diff --git a/DNP3Test/AppLayerTest.h b/DNP3Test/AppLayerTest.h index 5e7e88be..0e695dba 100644 --- a/DNP3Test/AppLayerTest.h +++ b/DNP3Test/AppLayerTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __APP_LAYER_TEST_H_ #define __APP_LAYER_TEST_H_ @@ -37,15 +37,15 @@ class AppLayerTest : public LogTester void SendUp(const std::string& aBytes); void SendUp(FunctionCodes aCode, bool aFIR, bool aFIN, bool aCON, bool aUNS, int aSEQ); - + void SendRequest(FunctionCodes aCode, bool aFIR, bool aFIN, bool aCON, bool aUNS); void SendResponse(FunctionCodes aCode, bool aFIR, bool aFIN, bool aCON, bool aUNS); void SendUnsolicited(FunctionCodes aCode, bool aFIR, bool aFIN, bool aCON, bool aUNS); - + bool CheckSentAPDU(FunctionCodes aCode, bool aFIR, bool aFIN, bool aCON, bool aUNS, int aSEQ); //bool CheckState() { return user.Equals(state); } - + MockAppUser user; MockLowerLayer lower; MockTimerSource mts; @@ -56,7 +56,7 @@ class AppLayerTest : public LogTester private: APDU mFragment; }; - + }} #endif diff --git a/DNP3Test/AsyncDatabaseTestObject.h b/DNP3Test/AsyncDatabaseTestObject.h index 4539e8be..b768160d 100644 --- a/DNP3Test/AsyncDatabaseTestObject.h +++ b/DNP3Test/AsyncDatabaseTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,69 +6,69 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_DATABASE_TEST_OBJECT_H_ -#define __ASYNC_DATABASE_TEST_OBJECT_H_ - -#include -#include -#include - -namespace apl { namespace dnp { - -class MockAsyncEventBuffer : public IAsyncEventBuffer -{ - public: - - virtual ~MockAsyncEventBuffer() {} - - void Update(const Binary& arEvent, PointClass aClass, size_t aIndex) - { - BinaryInfo v(arEvent, aClass, aIndex); - mBinaryEvents.push_back(v); - } - - void Update(const Analog& arEvent, PointClass aClass, size_t aIndex) - { - AnalogInfo v(arEvent, aClass, aIndex); - mAnalogEvents.push_back(v); - } - - void Update(const Counter& arEvent, PointClass aClass, size_t aIndex) - { - CounterInfo v(arEvent, aClass, aIndex); - mCounterEvents.push_back(v); - } - - std::deque mBinaryEvents; - std::deque mAnalogEvents; - std::deque mCounterEvents; -}; - -class AsyncDatabaseTestObject -{ - public: - AsyncDatabaseTestObject(FilterLevel aLevel = LEV_INFO) : - db(log.GetLogger(aLevel, "test")) - { - db.SetEventBuffer(&buffer); - } - - EventLog log; - MockAsyncEventBuffer buffer; - AsyncDatabase db; -}; - -}} - -#endif - +// +#ifndef __ASYNC_DATABASE_TEST_OBJECT_H_ +#define __ASYNC_DATABASE_TEST_OBJECT_H_ + +#include +#include +#include + +namespace apl { namespace dnp { + +class MockAsyncEventBuffer : public IAsyncEventBuffer +{ + public: + + virtual ~MockAsyncEventBuffer() {} + + void Update(const Binary& arEvent, PointClass aClass, size_t aIndex) + { + BinaryInfo v(arEvent, aClass, aIndex); + mBinaryEvents.push_back(v); + } + + void Update(const Analog& arEvent, PointClass aClass, size_t aIndex) + { + AnalogInfo v(arEvent, aClass, aIndex); + mAnalogEvents.push_back(v); + } + + void Update(const Counter& arEvent, PointClass aClass, size_t aIndex) + { + CounterInfo v(arEvent, aClass, aIndex); + mCounterEvents.push_back(v); + } + + std::deque mBinaryEvents; + std::deque mAnalogEvents; + std::deque mCounterEvents; +}; + +class AsyncDatabaseTestObject +{ + public: + AsyncDatabaseTestObject(FilterLevel aLevel = LEV_INFO) : + db(log.GetLogger(aLevel, "test")) + { + db.SetEventBuffer(&buffer); + } + + EventLog log; + MockAsyncEventBuffer buffer; + AsyncDatabase db; +}; + +}} + +#endif + diff --git a/DNP3Test/AsyncIntegrationTest.cpp b/DNP3Test/AsyncIntegrationTest.cpp index 87d6fa6a..b79cccaa 100644 --- a/DNP3Test/AsyncIntegrationTest.cpp +++ b/DNP3Test/AsyncIntegrationTest.cpp @@ -16,125 +16,125 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "AsyncIntegrationTest.h" - -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -using namespace std; - -namespace apl { namespace dnp { - -AsyncIntegrationTest::AsyncIntegrationTest(Logger* apLogger, FilterLevel aLevel, uint_16_t aStartPort, size_t aNumPairs, size_t aNumPoints) : -AsyncStackManager(apLogger), -M_START_PORT(aStartPort), -mChange(false), -mNotifier(boost::bind(&AsyncIntegrationTest::RegisterChange, this)) -{ - for(size_t i=0; imService.Get(), 10); } - -bool AsyncIntegrationTest::SameData() -{ - if(!mChange) return false; - - mChange = false; - - BOOST_FOREACH(FlexibleDataObserver* pObs, mMasterObservers) - { - if(!FlexibleDataObserver::StrictEquality(*pObs, mLocalFDO)) return false; - } - - return true; -} - -Binary AsyncIntegrationTest::RandomBinary() -{ - boost::uniform_int<> num(0,1); - boost::variate_generator > val(rng, num); - Binary v(val() ? true : false, BQ_ONLINE); - return v; -} - -Analog AsyncIntegrationTest::RandomAnalog() -{ - boost::uniform_int num; - boost::variate_generator > val(rng, num); - Analog v(val(), AQ_ONLINE); - return v; -} - -Counter AsyncIntegrationTest::RandomCounter() -{ - boost::uniform_int num; - boost::variate_generator > val(rng, num); - Counter v(val(), CQ_ONLINE); - return v; -} - -void AsyncIntegrationTest::AddStackPair(FilterLevel aLevel, size_t aNumPoints) -{ - uint_16_t port = M_START_PORT + this->mMasterObservers.size(); - - FlexibleDataObserver* pMasterFDO = new FlexibleDataObserver(); mMasterObservers.push_back(pMasterFDO); - pMasterFDO->AddObserver(&mNotifier); - - ostringstream oss; - oss << "Port: " << port; - std::string client = oss.str() + " Client "; - std::string server = oss.str() + " Server "; - - PhysLayerSettings s(aLevel, 1000); - this->AddTCPClient(client, s, "127.0.0.1", port); - this->AddTCPServer(server, s, port); - - { - MasterStackConfig cfg; - cfg.app.RspTimeout = 20000; - cfg.master.IntegrityRate = 60000; //set this to retry, if the task timer doesn't close properly this will seal the deal - cfg.master.EnableUnsol = true; - cfg.master.DoUnsolOnStartup = true; - cfg.master.UnsolClassMask = PC_ALL_EVENTS; - this->AddMaster(client, client, aLevel, pMasterFDO, cfg); - } - - { - SlaveStackConfig cfg; - cfg.app.RspTimeout = 20000; - cfg.slave.mDisableUnsol = false; - cfg.slave.mUnsolPackDelay = 0; - cfg.device = DeviceTemplate(aNumPoints, aNumPoints, aNumPoints); - IDataObserver* pObs = this->AddSlave(server, server, aLevel, &mCmdAcceptor, cfg); - this->mFanout.Add(pObs); - } - - -} - - -}} - - - +#include +#include "AsyncIntegrationTest.h" + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +using namespace std; + +namespace apl { namespace dnp { + +AsyncIntegrationTest::AsyncIntegrationTest(Logger* apLogger, FilterLevel aLevel, uint_16_t aStartPort, size_t aNumPairs, size_t aNumPoints) : +AsyncStackManager(apLogger), +M_START_PORT(aStartPort), +mChange(false), +mNotifier(boost::bind(&AsyncIntegrationTest::RegisterChange, this)) +{ + for(size_t i=0; imService.Get(), 10); } + +bool AsyncIntegrationTest::SameData() +{ + if(!mChange) return false; + + mChange = false; + + BOOST_FOREACH(FlexibleDataObserver* pObs, mMasterObservers) + { + if(!FlexibleDataObserver::StrictEquality(*pObs, mLocalFDO)) return false; + } + + return true; +} + +Binary AsyncIntegrationTest::RandomBinary() +{ + boost::uniform_int<> num(0,1); + boost::variate_generator > val(rng, num); + Binary v(val() ? true : false, BQ_ONLINE); + return v; +} + +Analog AsyncIntegrationTest::RandomAnalog() +{ + boost::uniform_int num; + boost::variate_generator > val(rng, num); + Analog v(val(), AQ_ONLINE); + return v; +} + +Counter AsyncIntegrationTest::RandomCounter() +{ + boost::uniform_int num; + boost::variate_generator > val(rng, num); + Counter v(val(), CQ_ONLINE); + return v; +} + +void AsyncIntegrationTest::AddStackPair(FilterLevel aLevel, size_t aNumPoints) +{ + uint_16_t port = M_START_PORT + this->mMasterObservers.size(); + + FlexibleDataObserver* pMasterFDO = new FlexibleDataObserver(); mMasterObservers.push_back(pMasterFDO); + pMasterFDO->AddObserver(&mNotifier); + + ostringstream oss; + oss << "Port: " << port; + std::string client = oss.str() + " Client "; + std::string server = oss.str() + " Server "; + + PhysLayerSettings s(aLevel, 1000); + this->AddTCPClient(client, s, "127.0.0.1", port); + this->AddTCPServer(server, s, port); + + { + MasterStackConfig cfg; + cfg.app.RspTimeout = 20000; + cfg.master.IntegrityRate = 60000; //set this to retry, if the task timer doesn't close properly this will seal the deal + cfg.master.EnableUnsol = true; + cfg.master.DoUnsolOnStartup = true; + cfg.master.UnsolClassMask = PC_ALL_EVENTS; + this->AddMaster(client, client, aLevel, pMasterFDO, cfg); + } + + { + SlaveStackConfig cfg; + cfg.app.RspTimeout = 20000; + cfg.slave.mDisableUnsol = false; + cfg.slave.mUnsolPackDelay = 0; + cfg.device = DeviceTemplate(aNumPoints, aNumPoints, aNumPoints); + IDataObserver* pObs = this->AddSlave(server, server, aLevel, &mCmdAcceptor, cfg); + this->mFanout.Add(pObs); + } + + +} + + +}} + + + diff --git a/DNP3Test/AsyncIntegrationTest.h b/DNP3Test/AsyncIntegrationTest.h index 98f69f88..d48bfd1e 100644 --- a/DNP3Test/AsyncIntegrationTest.h +++ b/DNP3Test/AsyncIntegrationTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,98 +6,98 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_INTEGRATION_TEST_H_ -#define __ASYNC_INTEGRATION_TEST_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace boost { namespace asio { class io_service; } } - -namespace apl { namespace dnp { - -class ObserverFanout : public IDataObserver -{ - public: - - void Add(IDataObserver* apObserver) { mObservers.push_back(apObserver); } - - void _Start() { mBuffer.Start(); } - void _End() - { - mBuffer.End(); - - BOOST_FOREACH(IDataObserver* p, mObservers) { mBuffer.FlushUpdates(p, false); } - - Transaction tr(&mBuffer); mBuffer.Clear(); - } - - void _Update(const Binary& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } - void _Update(const Analog& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } - void _Update(const Counter& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } - void _Update(const ControlStatus& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } - void _Update(const SetpointStatus& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } - - private: - ChangeBuffer mBuffer; - std::vector mObservers; - -}; - -class AsyncIntegrationTest : public AsyncTestObject, public AsyncStackManager -{ - public: - - AsyncIntegrationTest(Logger* apLogger, FilterLevel aLevel, uint_16_t aStartPort, size_t aNumPairs, size_t aNumPoints); - virtual ~AsyncIntegrationTest(); - - IDataObserver* GetFanout() { return &mFanout; } - - bool SameData(); - - Binary RandomBinary(); - Analog RandomAnalog(); - Counter RandomCounter(); - - private: - - void RegisterChange() { mChange = true; } - void AddStackPair(FilterLevel aLevel, size_t aNumPoints); - void Next(); - - ObserverFanout mFanout; - const uint_16_t M_START_PORT; - Logger* mpLogger; - - bool mChange; - BoundNotifier mNotifier; - std::vector mMasterObservers; - FlexibleDataObserver mLocalFDO; - MockCommandAcceptor mCmdAcceptor; - boost::mt19937 rng; //random number generator -}; - -}} - -#endif - +// +#ifndef __ASYNC_INTEGRATION_TEST_H_ +#define __ASYNC_INTEGRATION_TEST_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { namespace asio { class io_service; } } + +namespace apl { namespace dnp { + +class ObserverFanout : public IDataObserver +{ + public: + + void Add(IDataObserver* apObserver) { mObservers.push_back(apObserver); } + + void _Start() { mBuffer.Start(); } + void _End() + { + mBuffer.End(); + + BOOST_FOREACH(IDataObserver* p, mObservers) { mBuffer.FlushUpdates(p, false); } + + Transaction tr(&mBuffer); mBuffer.Clear(); + } + + void _Update(const Binary& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } + void _Update(const Analog& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } + void _Update(const Counter& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } + void _Update(const ControlStatus& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } + void _Update(const SetpointStatus& arPoint, size_t aIndex) { mBuffer.Update(arPoint, aIndex); } + + private: + ChangeBuffer mBuffer; + std::vector mObservers; + +}; + +class AsyncIntegrationTest : public AsyncTestObject, public AsyncStackManager +{ + public: + + AsyncIntegrationTest(Logger* apLogger, FilterLevel aLevel, uint_16_t aStartPort, size_t aNumPairs, size_t aNumPoints); + virtual ~AsyncIntegrationTest(); + + IDataObserver* GetFanout() { return &mFanout; } + + bool SameData(); + + Binary RandomBinary(); + Analog RandomAnalog(); + Counter RandomCounter(); + + private: + + void RegisterChange() { mChange = true; } + void AddStackPair(FilterLevel aLevel, size_t aNumPoints); + void Next(); + + ObserverFanout mFanout; + const uint_16_t M_START_PORT; + Logger* mpLogger; + + bool mChange; + BoundNotifier mNotifier; + std::vector mMasterObservers; + FlexibleDataObserver mLocalFDO; + MockCommandAcceptor mCmdAcceptor; + boost::mt19937 rng; //random number generator +}; + +}} + +#endif + diff --git a/DNP3Test/AsyncLinkLayerRouterTest.cpp b/DNP3Test/AsyncLinkLayerRouterTest.cpp index 708a6de3..11a72858 100644 --- a/DNP3Test/AsyncLinkLayerRouterTest.cpp +++ b/DNP3Test/AsyncLinkLayerRouterTest.cpp @@ -16,19 +16,19 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncLinkLayerRouterTest.h" - -namespace apl { namespace dnp { - -AsyncLinkLayerRouterTest::AsyncLinkLayerRouterTest(FilterLevel aLevel, bool aImmediate) : -LogTester(aImmediate), -mts(), -phys(mLog.GetLogger(aLevel, "Physical")), -router(mLog.GetLogger(aLevel, "Router"), &phys, &mts, 100) -{ - -} - - - -}} +#include "AsyncLinkLayerRouterTest.h" + +namespace apl { namespace dnp { + +AsyncLinkLayerRouterTest::AsyncLinkLayerRouterTest(FilterLevel aLevel, bool aImmediate) : +LogTester(aImmediate), +mts(), +phys(mLog.GetLogger(aLevel, "Physical")), +router(mLog.GetLogger(aLevel, "Router"), &phys, &mts, 100) +{ + +} + + + +}} diff --git a/DNP3Test/AsyncLinkLayerRouterTest.h b/DNP3Test/AsyncLinkLayerRouterTest.h index ad139fda..5916bff2 100644 --- a/DNP3Test/AsyncLinkLayerRouterTest.h +++ b/DNP3Test/AsyncLinkLayerRouterTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_LINK_LAYER_ROUTER_TEST_H_ #define __ASYNC_LINK_LAYER_ROUTER_TEST_H_ diff --git a/DNP3Test/AsyncLinkLayerTest.cpp b/DNP3Test/AsyncLinkLayerTest.cpp index 2317cda5..ddf848c9 100644 --- a/DNP3Test/AsyncLinkLayerTest.cpp +++ b/DNP3Test/AsyncLinkLayerTest.cpp @@ -16,32 +16,32 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncLinkLayerTest.h" - -namespace apl { namespace dnp { - - AsyncLinkLayerTest::AsyncLinkLayerTest(LinkConfig arCfg, FilterLevel aLevel, bool aImmediate) : - LogTester(aImmediate), - mts(), - upper(mLog.GetLogger(aLevel, "MockUpperLayer")), - link(mLog.GetLogger(aLevel, "LinkLayer"), &mts, arCfg), - mNumSend(0) - { - link.SetUpperLayer(&upper); - link.SetRouter(this); - } - - void AsyncLinkLayerTest::Transmit(const LinkFrame& arFrame) - { - mLastSend = arFrame; - ++mNumSend; - } - - LinkConfig AsyncLinkLayerTest::DefaultConfig() - { - LinkConfig cfg(true, false); - return cfg; - } - -}} - +#include "AsyncLinkLayerTest.h" + +namespace apl { namespace dnp { + + AsyncLinkLayerTest::AsyncLinkLayerTest(LinkConfig arCfg, FilterLevel aLevel, bool aImmediate) : + LogTester(aImmediate), + mts(), + upper(mLog.GetLogger(aLevel, "MockUpperLayer")), + link(mLog.GetLogger(aLevel, "LinkLayer"), &mts, arCfg), + mNumSend(0) + { + link.SetUpperLayer(&upper); + link.SetRouter(this); + } + + void AsyncLinkLayerTest::Transmit(const LinkFrame& arFrame) + { + mLastSend = arFrame; + ++mNumSend; + } + + LinkConfig AsyncLinkLayerTest::DefaultConfig() + { + LinkConfig cfg(true, false); + return cfg; + } + +}} + diff --git a/DNP3Test/AsyncLinkLayerTest.h b/DNP3Test/AsyncLinkLayerTest.h index d8a1e4be..8b8f2e00 100644 --- a/DNP3Test/AsyncLinkLayerTest.h +++ b/DNP3Test/AsyncLinkLayerTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_LINK_LAYER_TEST_H_ #define __ASYNC_LINK_LAYER_TEST_H_ diff --git a/DNP3Test/AsyncMasterTestObject.cpp b/DNP3Test/AsyncMasterTestObject.cpp index 38adf1f2..2cf44d5a 100644 --- a/DNP3Test/AsyncMasterTestObject.cpp +++ b/DNP3Test/AsyncMasterTestObject.cpp @@ -16,43 +16,43 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncMasterTestObject.h" - -#include -#include -#include - -using namespace std; - -namespace apl { namespace dnp { - -AsyncMasterTestObject::AsyncMasterTestObject(MasterConfig cfg, FilterLevel aLevel, bool aImmediate) : -LogTester(aImmediate), -fake_time(), -mts(), -ats(&mts, &fake_time), -fdo(), -app(mLog.GetLogger(aLevel, "MockAppLayer")), -master(mLog.GetLogger(aLevel,"master"), cfg, &app, &fdo, ats.NewGroup(), &mts, &fake_time) -{ - app.SetUser(&master); -} - -void AsyncMasterTestObject::RespondToMaster(const std::string& arData, bool aFinal) -{ - HexSequence hs(arData); - mAPDU.Reset(); - mAPDU.Write(hs, hs.Size()); - mAPDU.Interpret(); - if(aFinal) master.OnFinalResponse(mAPDU); - else master.OnPartialResponse(mAPDU); -} - -std::string AsyncMasterTestObject::Read() -{ - mAPDU = app.Read(); - std::string hex = toHex(mAPDU.GetBuffer(), mAPDU.Size(), true); - return hex; -} - -}} //end ns +#include "AsyncMasterTestObject.h" + +#include +#include +#include + +using namespace std; + +namespace apl { namespace dnp { + +AsyncMasterTestObject::AsyncMasterTestObject(MasterConfig cfg, FilterLevel aLevel, bool aImmediate) : +LogTester(aImmediate), +fake_time(), +mts(), +ats(&mts, &fake_time), +fdo(), +app(mLog.GetLogger(aLevel, "MockAppLayer")), +master(mLog.GetLogger(aLevel,"master"), cfg, &app, &fdo, ats.NewGroup(), &mts, &fake_time) +{ + app.SetUser(&master); +} + +void AsyncMasterTestObject::RespondToMaster(const std::string& arData, bool aFinal) +{ + HexSequence hs(arData); + mAPDU.Reset(); + mAPDU.Write(hs, hs.Size()); + mAPDU.Interpret(); + if(aFinal) master.OnFinalResponse(mAPDU); + else master.OnPartialResponse(mAPDU); +} + +std::string AsyncMasterTestObject::Read() +{ + mAPDU = app.Read(); + std::string hex = toHex(mAPDU.GetBuffer(), mAPDU.Size(), true); + return hex; +} + +}} //end ns diff --git a/DNP3Test/AsyncMasterTestObject.h b/DNP3Test/AsyncMasterTestObject.h index 9b435c36..6ee52c9d 100644 --- a/DNP3Test/AsyncMasterTestObject.h +++ b/DNP3Test/AsyncMasterTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_MASTER_TEST_OBJECT_H_ #define __ASYNC_MASTER_TEST_OBJECT_H_ @@ -37,7 +37,7 @@ class AsyncMasterTestObject : public LogTester AsyncMasterTestObject(MasterConfig, FilterLevel aLevel = LEV_INFO, bool aImmediate = false); void RespondToMaster(const std::string& arData, bool aFinal = true); - std::string Read(); + std::string Read(); MockTimeSource fake_time; MockTimerSource mts; diff --git a/DNP3Test/AsyncSlaveTestObject.h b/DNP3Test/AsyncSlaveTestObject.h index fec027ab..64be01f6 100644 --- a/DNP3Test/AsyncSlaveTestObject.h +++ b/DNP3Test/AsyncSlaveTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_SLAVE_TEST_OBJECT_H_ #define __ASYNC_SLAVE_TEST_OBJECT_H_ @@ -40,7 +40,7 @@ class AsyncSlaveTestObject : public LogTester void SendToSlave(const std::string& arData, SequenceInfo aSeq = SI_OTHER); std::string Read(); size_t Count() { return app.Count(); } - + //MockTimeSource fake_time; MockTimeManager fakeTime; diff --git a/DNP3Test/AsyncStartupTeardownTest.cpp b/DNP3Test/AsyncStartupTeardownTest.cpp index b2414340..d75003a9 100644 --- a/DNP3Test/AsyncStartupTeardownTest.cpp +++ b/DNP3Test/AsyncStartupTeardownTest.cpp @@ -16,40 +16,40 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "AsyncStartupTeardownTest.h" - -#include -#include - -#include - -namespace apl { namespace dnp { - -AsyncStartupTeardownTest::AsyncStartupTeardownTest(FilterLevel aLevel, bool aAutoStart) : -mLog(), -mMgr(mLog.GetLogger(aLevel, "mgr"), aAutoStart) -{ - -} - -void AsyncStartupTeardownTest::CreatePort(const std::string& arName, FilterLevel aLevel) -{ - std::string name = arName + " router"; - PhysLayerSettings s(aLevel, 1000); - mMgr.AddTCPClient(arName, s, "127.0.0.1", 30000); -} - -void AsyncStartupTeardownTest::AddMaster(const std::string& arStackName, const std::string& arPortName, uint_16_t aLocalAddress, FilterLevel aLevel) -{ - MasterStackConfig cfg; - cfg.link.LocalAddr = aLocalAddress; - mMgr.AddMaster(arPortName, arStackName, aLevel, &mFDO, cfg); -} - - - -}} - - - +#include +#include "AsyncStartupTeardownTest.h" + +#include +#include + +#include + +namespace apl { namespace dnp { + +AsyncStartupTeardownTest::AsyncStartupTeardownTest(FilterLevel aLevel, bool aAutoStart) : +mLog(), +mMgr(mLog.GetLogger(aLevel, "mgr"), aAutoStart) +{ + +} + +void AsyncStartupTeardownTest::CreatePort(const std::string& arName, FilterLevel aLevel) +{ + std::string name = arName + " router"; + PhysLayerSettings s(aLevel, 1000); + mMgr.AddTCPClient(arName, s, "127.0.0.1", 30000); +} + +void AsyncStartupTeardownTest::AddMaster(const std::string& arStackName, const std::string& arPortName, uint_16_t aLocalAddress, FilterLevel aLevel) +{ + MasterStackConfig cfg; + cfg.link.LocalAddr = aLocalAddress; + mMgr.AddMaster(arPortName, arStackName, aLevel, &mFDO, cfg); +} + + + +}} + + + diff --git a/DNP3Test/AsyncStartupTeardownTest.h b/DNP3Test/AsyncStartupTeardownTest.h index 2ad6eaca..ebcd7881 100644 --- a/DNP3Test/AsyncStartupTeardownTest.h +++ b/DNP3Test/AsyncStartupTeardownTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,52 +6,52 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_STARTUP_TEARDOWN_TEST_H_ -#define __ASYNC_STARTUP_TEARDOWN_TEST_H_ - -#include -#include -#include - - -namespace boost { namespace asio { class io_service; } } - -namespace apl { - class IPhysicalLayerAsync; -} - -namespace apl { namespace dnp { - -class AsyncStartupTeardownTest -{ - public: - - AsyncStartupTeardownTest(FilterLevel aLevel, bool aAutoStart); - - void CreatePort(const std::string& arName, FilterLevel aLevel); - void AddMaster(const std::string& arName, const std::string& arPortName, uint_16_t aLocalAddress, FilterLevel aLevel); - - void StartService() { mMgr.Start(); } - - private: - - EventLog mLog; - FilterLevel mLevel; - AsyncStackManager mMgr; - FlexibleDataObserver mFDO; -}; - -}} - -#endif - +// +#ifndef __ASYNC_STARTUP_TEARDOWN_TEST_H_ +#define __ASYNC_STARTUP_TEARDOWN_TEST_H_ + +#include +#include +#include + + +namespace boost { namespace asio { class io_service; } } + +namespace apl { + class IPhysicalLayerAsync; +} + +namespace apl { namespace dnp { + +class AsyncStartupTeardownTest +{ + public: + + AsyncStartupTeardownTest(FilterLevel aLevel, bool aAutoStart); + + void CreatePort(const std::string& arName, FilterLevel aLevel); + void AddMaster(const std::string& arName, const std::string& arPortName, uint_16_t aLocalAddress, FilterLevel aLevel); + + void StartService() { mMgr.Start(); } + + private: + + EventLog mLog; + FilterLevel mLevel; + AsyncStackManager mMgr; + FlexibleDataObserver mFDO; +}; + +}} + +#endif + diff --git a/DNP3Test/DNP3Test.vcproj b/DNP3Test/DNP3Test.vcproj index e9aca3ab..08475135 100755 --- a/DNP3Test/DNP3Test.vcproj +++ b/DNP3Test/DNP3Test.vcproj @@ -1,466 +1,466 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DNP3Test/DNPHelpers.h b/DNP3Test/DNPHelpers.h index 1ccb3b11..1df94a38 100644 --- a/DNP3Test/DNPHelpers.h +++ b/DNP3Test/DNPHelpers.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __DNP_HELPERS_H_ #define __DNP_HELPERS_H_ diff --git a/DNP3Test/LinkReceiverTest.h b/DNP3Test/LinkReceiverTest.h index 676701f2..8846dc8c 100644 --- a/DNP3Test/LinkReceiverTest.h +++ b/DNP3Test/LinkReceiverTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,55 +6,55 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __LINK_RECEIVER_TEST_H_ -#define __LINK_RECEIVER_TEST_H_ - -#include -#include -#include -#include "MockFrameSink.h" - -namespace apl { namespace dnp { - - class LinkReceiverTest : public LogTester - { - public: - LinkReceiverTest(FilterLevel aLevel = LEV_WARNING, bool aImmediate = false) : - LogTester(aImmediate), - mSink(), - mRx(mLog.GetLogger(aLevel, "ReceiverTest"), &mSink) - {} - - void WriteData(const LinkFrame& arFrame) - { - assert(arFrame.GetSize() <= mRx.NumWriteBytes()); - memcpy(mRx.WriteBuff(), arFrame.GetBuffer(), arFrame.GetSize()); - mRx.OnRead(arFrame.GetSize()); - } - - void WriteData(const std::string& arHex) - { - HexSequence hs(arHex); - assert(hs.Size() <= mRx.NumWriteBytes()); - memcpy(mRx.WriteBuff(), hs, hs.Size()); - mRx.OnRead(hs.Size()); - } - - MockFrameSink mSink; - LinkLayerReceiver mRx; - }; - -}} - -#endif - +// +#ifndef __LINK_RECEIVER_TEST_H_ +#define __LINK_RECEIVER_TEST_H_ + +#include +#include +#include +#include "MockFrameSink.h" + +namespace apl { namespace dnp { + + class LinkReceiverTest : public LogTester + { + public: + LinkReceiverTest(FilterLevel aLevel = LEV_WARNING, bool aImmediate = false) : + LogTester(aImmediate), + mSink(), + mRx(mLog.GetLogger(aLevel, "ReceiverTest"), &mSink) + {} + + void WriteData(const LinkFrame& arFrame) + { + assert(arFrame.GetSize() <= mRx.NumWriteBytes()); + memcpy(mRx.WriteBuff(), arFrame.GetBuffer(), arFrame.GetSize()); + mRx.OnRead(arFrame.GetSize()); + } + + void WriteData(const std::string& arHex) + { + HexSequence hs(arHex); + assert(hs.Size() <= mRx.NumWriteBytes()); + memcpy(mRx.WriteBuff(), hs, hs.Size()); + mRx.OnRead(hs.Size()); + } + + MockFrameSink mSink; + LinkLayerReceiver mRx; + }; + +}} + +#endif + diff --git a/DNP3Test/MockAppUser.cpp b/DNP3Test/MockAppUser.cpp index 4ff5e85b..7bdeea37 100644 --- a/DNP3Test/MockAppUser.cpp +++ b/DNP3Test/MockAppUser.cpp @@ -16,105 +16,105 @@ // specific language governing permissions and limitations // under the License. // -#include "MockAppUser.h" - -#include - -using namespace std; - -namespace apl { namespace dnp { - -ostream& operator<<(ostream& output, const MockAppUser::State& s) -{ - output << " LayerUp: " << s.NumLayerUp - << " LayerDown: " << s.NumLayerDown - << " Unsol: " << s.NumUnsol - << " SolSendSuccess: " << s.NumSolSendSuccess - << " SolFailure: " << s.NumSolFailure - << " UnsolSendSuccess: " << s.NumUnsolSendSuccess - << " UnsolFailure: " << s.NumUnsolFailure - << " PartialResponse: " << s.NumPartialRsp - << " FinalRsp: " << s.NumFinalRsp - << " Request: " << s.NumRequest - << " Unknown: " << s.NumUnknown; - - return output; -} - - -MockAppUser::State::State() : -NumLayerUp(0), -NumLayerDown(0), -NumUnsol(0), -NumSolSendSuccess(0), -NumSolFailure(0), -NumUnsolSendSuccess(0), -NumUnsolFailure(0), -NumPartialRsp(0), -NumFinalRsp(0), -NumRequest(0), -NumUnknown(0) -{} - -bool MockAppUser::State::operator==(const State& arState) const -{ - return this->NumLayerUp == arState.NumLayerUp && - this->NumLayerDown == arState.NumLayerDown && - this->NumUnsol == arState.NumUnsol && - this->NumSolSendSuccess == arState.NumSolSendSuccess && - this->NumSolFailure == arState.NumSolFailure && - this->NumUnsolSendSuccess == arState.NumUnsolSendSuccess && - this->NumUnsolFailure == arState.NumUnsolFailure && - this->NumPartialRsp == arState.NumPartialRsp && - this->NumFinalRsp == arState.NumFinalRsp && - this->NumRequest == arState.NumRequest && - this->NumUnknown == arState.NumUnknown; -} - -MockAppUser::MockAppUser(bool aIsMaster) : -mIsMaster(aIsMaster) -{} - -bool MockAppUser::IsMaster() -{ return mIsMaster; } - -// Implement IAsyncAppUser -void MockAppUser::OnLowerLayerUp() -{ ++mState.NumLayerUp; } - -void MockAppUser::OnLowerLayerDown() -{ ++mState.NumLayerDown; } - -void MockAppUser::OnSolSendSuccess() -{ ++mState.NumSolSendSuccess; } - -void MockAppUser::OnSolFailure() -{ ++mState.NumSolFailure; } - -void MockAppUser::OnUnsolSendSuccess() -{ ++mState.NumUnsolSendSuccess; } - -void MockAppUser::OnUnsolFailure() -{ ++mState.NumUnsolFailure; } - -void MockAppUser::OnPartialResponse(const APDU&) -{ ++mState.NumPartialRsp; } - -void MockAppUser::OnFinalResponse(const APDU&) -{ ++mState.NumFinalRsp; } - -void MockAppUser::OnUnsolResponse(const APDU&) -{ ++mState.NumUnsol; } - -void MockAppUser::OnRequest(const APDU&, SequenceInfo) -{ ++mState.NumRequest; } - -void MockAppUser::OnUnknownObject() -{ ++mState.NumUnknown; } - -bool MockAppUser::Equals(const MockAppUser::State& arState) const -{ - return mState == arState; -} - -}} //#end ns +#include "MockAppUser.h" + +#include + +using namespace std; + +namespace apl { namespace dnp { + +ostream& operator<<(ostream& output, const MockAppUser::State& s) +{ + output << " LayerUp: " << s.NumLayerUp + << " LayerDown: " << s.NumLayerDown + << " Unsol: " << s.NumUnsol + << " SolSendSuccess: " << s.NumSolSendSuccess + << " SolFailure: " << s.NumSolFailure + << " UnsolSendSuccess: " << s.NumUnsolSendSuccess + << " UnsolFailure: " << s.NumUnsolFailure + << " PartialResponse: " << s.NumPartialRsp + << " FinalRsp: " << s.NumFinalRsp + << " Request: " << s.NumRequest + << " Unknown: " << s.NumUnknown; + + return output; +} + + +MockAppUser::State::State() : +NumLayerUp(0), +NumLayerDown(0), +NumUnsol(0), +NumSolSendSuccess(0), +NumSolFailure(0), +NumUnsolSendSuccess(0), +NumUnsolFailure(0), +NumPartialRsp(0), +NumFinalRsp(0), +NumRequest(0), +NumUnknown(0) +{} + +bool MockAppUser::State::operator==(const State& arState) const +{ + return this->NumLayerUp == arState.NumLayerUp && + this->NumLayerDown == arState.NumLayerDown && + this->NumUnsol == arState.NumUnsol && + this->NumSolSendSuccess == arState.NumSolSendSuccess && + this->NumSolFailure == arState.NumSolFailure && + this->NumUnsolSendSuccess == arState.NumUnsolSendSuccess && + this->NumUnsolFailure == arState.NumUnsolFailure && + this->NumPartialRsp == arState.NumPartialRsp && + this->NumFinalRsp == arState.NumFinalRsp && + this->NumRequest == arState.NumRequest && + this->NumUnknown == arState.NumUnknown; +} + +MockAppUser::MockAppUser(bool aIsMaster) : +mIsMaster(aIsMaster) +{} + +bool MockAppUser::IsMaster() +{ return mIsMaster; } + +// Implement IAsyncAppUser +void MockAppUser::OnLowerLayerUp() +{ ++mState.NumLayerUp; } + +void MockAppUser::OnLowerLayerDown() +{ ++mState.NumLayerDown; } + +void MockAppUser::OnSolSendSuccess() +{ ++mState.NumSolSendSuccess; } + +void MockAppUser::OnSolFailure() +{ ++mState.NumSolFailure; } + +void MockAppUser::OnUnsolSendSuccess() +{ ++mState.NumUnsolSendSuccess; } + +void MockAppUser::OnUnsolFailure() +{ ++mState.NumUnsolFailure; } + +void MockAppUser::OnPartialResponse(const APDU&) +{ ++mState.NumPartialRsp; } + +void MockAppUser::OnFinalResponse(const APDU&) +{ ++mState.NumFinalRsp; } + +void MockAppUser::OnUnsolResponse(const APDU&) +{ ++mState.NumUnsol; } + +void MockAppUser::OnRequest(const APDU&, SequenceInfo) +{ ++mState.NumRequest; } + +void MockAppUser::OnUnknownObject() +{ ++mState.NumUnknown; } + +bool MockAppUser::Equals(const MockAppUser::State& arState) const +{ + return mState == arState; +} + +}} //#end ns diff --git a/DNP3Test/MockAppUser.h b/DNP3Test/MockAppUser.h index 9bf9366c..1d62c094 100644 --- a/DNP3Test/MockAppUser.h +++ b/DNP3Test/MockAppUser.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MOCK_APP_USER_H_ #define __MOCK_APP_USER_H_ @@ -52,11 +52,11 @@ class MockAppUser : public IAsyncAppUser }; MockAppUser(bool aIsMaster); - + // Implement IAsyncAppUser void OnLowerLayerUp(); void OnLowerLayerDown(); - + void OnSolSendSuccess(); void OnSolFailure(); @@ -65,8 +65,8 @@ class MockAppUser : public IAsyncAppUser bool IsMaster(); void OnPartialResponse(const APDU&); - void OnFinalResponse(const APDU&); - void OnUnsolResponse(const APDU&); + void OnFinalResponse(const APDU&); + void OnUnsolResponse(const APDU&); void OnRequest(const APDU&, SequenceInfo); void OnUnknownObject(); diff --git a/DNP3Test/MockAsyncAppLayer.cpp b/DNP3Test/MockAsyncAppLayer.cpp index c4f968f0..59e6c295 100644 --- a/DNP3Test/MockAsyncAppLayer.cpp +++ b/DNP3Test/MockAsyncAppLayer.cpp @@ -16,41 +16,41 @@ // specific language governing permissions and limitations // under the License. // -#include "MockAsyncAppLayer.h" - -#include -#include -#include - - -namespace apl { namespace dnp { - -MockAsyncAppLayer::MockAsyncAppLayer(Logger* apLogger) : -Loggable(apLogger), +#include "MockAsyncAppLayer.h" + +#include +#include +#include + + +namespace apl { namespace dnp { + +MockAsyncAppLayer::MockAsyncAppLayer(Logger* apLogger) : +Loggable(apLogger), mNumCancel(0), mpUser(NULL), mAutoSendCallback(true), -mIsSuccess(true) -{ - -} - -void MockAsyncAppLayer::SetUser(IAsyncAppUser* apUser) -{ - mpUser = apUser; -} - +mIsSuccess(true) +{ + +} + +void MockAsyncAppLayer::SetUser(IAsyncAppUser* apUser) +{ + mpUser = apUser; +} + void MockAsyncAppLayer::EnableAutoSendCallback(bool aIsSuccess) { mAutoSendCallback = true; mIsSuccess = aIsSuccess; } - -void MockAsyncAppLayer::DisableAutoSendCallback() -{ - mAutoSendCallback = false; -} - + +void MockAsyncAppLayer::DisableAutoSendCallback() +{ + mAutoSendCallback = false; +} + void MockAsyncAppLayer::DoSendUnsol() { if(mAutoSendCallback) { @@ -59,63 +59,63 @@ void MockAsyncAppLayer::DoSendUnsol() else mpUser->OnUnsolFailure(); } } - -void MockAsyncAppLayer::DoSendSol() -{ + +void MockAsyncAppLayer::DoSendSol() +{ if(mAutoSendCallback) { assert(mpUser != NULL); if(mIsSuccess) mpUser->OnSolSendSuccess(); else mpUser->OnSolFailure(); - } -} - -void MockAsyncAppLayer::SendResponse(APDU& arAPDU) -{ - LOG_BLOCK(LEV_COMM, "=> " << toHex(arAPDU.GetBuffer(), arAPDU.Size(), true)); - LOG_BLOCK(LEV_INTERPRET, "=> " << arAPDU.ToString()); - mFragments.push_back(arAPDU); - this->DoSendSol(); - -} - -void MockAsyncAppLayer::SendUnsolicited(APDU& arAPDU) -{ - LOG_BLOCK(LEV_COMM, "=> " << toHex(arAPDU.GetBuffer(), arAPDU.Size(), true)); - LOG_BLOCK(LEV_INTERPRET, "=> " << arAPDU.ToString()); - mFragments.push_back(arAPDU); - this->DoSendUnsol(); -} - -void MockAsyncAppLayer::SendRequest(APDU& arAPDU) -{ - LOG_BLOCK(LEV_COMM, "=> " << toHex(arAPDU.GetBuffer(), arAPDU.Size(), true)); - LOG_BLOCK(LEV_INTERPRET, "=> " << arAPDU.ToString()); - mFragments.push_back(arAPDU); -} - -APDU MockAsyncAppLayer::Read() -{ - if(mFragments.size() == 0) throw InvalidStateException(LOCATION, "no more fragments"); - APDU frag = mFragments.front(); - frag.Interpret(); - mFragments.pop_front(); - return frag; -} - -FunctionCodes MockAsyncAppLayer::ReadFunction() -{ - if(mFragments.size() == 0) throw InvalidStateException(LOCATION, "No more fragments"); - else - { - FunctionCodes func = mFragments.front().GetFunction(); - mFragments.pop_front(); - return func; - } -} - -void MockAsyncAppLayer::CancelResponse() -{ - ++mNumCancel; -} - -}} + } +} + +void MockAsyncAppLayer::SendResponse(APDU& arAPDU) +{ + LOG_BLOCK(LEV_COMM, "=> " << toHex(arAPDU.GetBuffer(), arAPDU.Size(), true)); + LOG_BLOCK(LEV_INTERPRET, "=> " << arAPDU.ToString()); + mFragments.push_back(arAPDU); + this->DoSendSol(); + +} + +void MockAsyncAppLayer::SendUnsolicited(APDU& arAPDU) +{ + LOG_BLOCK(LEV_COMM, "=> " << toHex(arAPDU.GetBuffer(), arAPDU.Size(), true)); + LOG_BLOCK(LEV_INTERPRET, "=> " << arAPDU.ToString()); + mFragments.push_back(arAPDU); + this->DoSendUnsol(); +} + +void MockAsyncAppLayer::SendRequest(APDU& arAPDU) +{ + LOG_BLOCK(LEV_COMM, "=> " << toHex(arAPDU.GetBuffer(), arAPDU.Size(), true)); + LOG_BLOCK(LEV_INTERPRET, "=> " << arAPDU.ToString()); + mFragments.push_back(arAPDU); +} + +APDU MockAsyncAppLayer::Read() +{ + if(mFragments.size() == 0) throw InvalidStateException(LOCATION, "no more fragments"); + APDU frag = mFragments.front(); + frag.Interpret(); + mFragments.pop_front(); + return frag; +} + +FunctionCodes MockAsyncAppLayer::ReadFunction() +{ + if(mFragments.size() == 0) throw InvalidStateException(LOCATION, "No more fragments"); + else + { + FunctionCodes func = mFragments.front().GetFunction(); + mFragments.pop_front(); + return func; + } +} + +void MockAsyncAppLayer::CancelResponse() +{ + ++mNumCancel; +} + +}} diff --git a/DNP3Test/MockAsyncAppLayer.h b/DNP3Test/MockAsyncAppLayer.h index 8969ddc7..af9333b2 100644 --- a/DNP3Test/MockAsyncAppLayer.h +++ b/DNP3Test/MockAsyncAppLayer.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __MOCK_ASYNC_APP_LAYER_H_ #define __MOCK_ASYNC_APP_LAYER_H_ @@ -52,7 +52,7 @@ class MockAsyncAppLayer : public IAsyncAppLayer, public Loggable void EnableAutoSendCallback(bool aIsSuccess); void DisableAutoSendCallback(); - APDU Read(); + APDU Read(); size_t Count() { return mFragments.size(); } FunctionCodes ReadFunction(); size_t NumAPDU() { return mFragments.size(); } @@ -64,8 +64,8 @@ class MockAsyncAppLayer : public IAsyncAppLayer, public Loggable IAsyncAppUser* mpUser; bool mAutoSendCallback; - bool mIsSuccess; - std::deque mFragments; + bool mIsSuccess; + std::deque mFragments; }; }} diff --git a/DNP3Test/MockFrameSink.cpp b/DNP3Test/MockFrameSink.cpp index 04432bf9..4263dc65 100644 --- a/DNP3Test/MockFrameSink.cpp +++ b/DNP3Test/MockFrameSink.cpp @@ -16,109 +16,109 @@ // specific language governing permissions and limitations // under the License. // -#include "MockFrameSink.h" - -namespace apl { namespace dnp { - -MockFrameSink::MockFrameSink() : mNumFrames(0), mLowerOnline(false) -{} - -void MockFrameSink::OnLowerLayerUp() -{ - mLowerOnline = true; -} - -void MockFrameSink::OnLowerLayerDown() -{ - mLowerOnline = false; -} - -void MockFrameSink::Reset() -{ - this->ClearBuffer(); - mNumFrames = 0; -} - -bool MockFrameSink::CheckLast(FuncCodes aCode, bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) -{ - return (mCode == aCode) && (aIsMaster == mIsMaster) && (mSrc == aSrc) && (mDest == aDest); -} - -bool MockFrameSink::CheckLastWithFCB(FuncCodes aCode, bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) -{ - return (mFcb == aFcb) && CheckLast(aCode, aIsMaster, aDest, aSrc); -} - -bool MockFrameSink::CheckLastWithDFC(FuncCodes aCode, bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - return (mIsRcvBuffFull == aIsRcvBuffFull) && CheckLast(aCode, aIsMaster, aDest, aSrc); -} - -// Sec to Pri - -void MockFrameSink::Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_SEC_ACK, aIsMaster, aDest, aSrc); - mIsRcvBuffFull = aIsRcvBuffFull; -} - -void MockFrameSink::Nack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_SEC_NACK, aIsMaster, aDest, aSrc); - mIsRcvBuffFull = aIsRcvBuffFull; -} - -void MockFrameSink::LinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_SEC_LINK_STATUS, aIsMaster, aDest, aSrc); - mIsRcvBuffFull = aIsRcvBuffFull; -} - -void MockFrameSink::NotSupported (bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_SEC_NOT_SUPPORTED, aIsMaster, aDest, aSrc); - mIsRcvBuffFull = aIsRcvBuffFull; -} - -// Pri to Sec - -void MockFrameSink::TestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_PRI_TEST_LINK_STATES, aIsMaster, aDest, aSrc); - mFcb = aFcb; -} - -void MockFrameSink::ResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_PRI_RESET_LINK_STATES, aIsMaster, aDest, aSrc); -} - -void MockFrameSink::RequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) -{ - this->Update(FC_PRI_REQUEST_LINK_STATUS, aIsMaster, aDest, aSrc); -} - -void MockFrameSink::ConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) -{ - this->Update(FC_PRI_CONFIRMED_USER_DATA, aIsMaster, aDest, aSrc); - this->WriteToBuffer(apData, aDataLength); - mFcb = aFcb; -} - -void MockFrameSink::UnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) -{ - this->Update(FC_PRI_UNCONFIRMED_USER_DATA, aIsMaster, aDest, aSrc); - this->WriteToBuffer(apData, aDataLength); -} - -void MockFrameSink::Update(FuncCodes aCode, bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) -{ - ++mNumFrames; - mCode = aCode; - mIsMaster = aIsMaster; - mDest = aDest; - mSrc = aSrc; -} - -}} - +#include "MockFrameSink.h" + +namespace apl { namespace dnp { + +MockFrameSink::MockFrameSink() : mNumFrames(0), mLowerOnline(false) +{} + +void MockFrameSink::OnLowerLayerUp() +{ + mLowerOnline = true; +} + +void MockFrameSink::OnLowerLayerDown() +{ + mLowerOnline = false; +} + +void MockFrameSink::Reset() +{ + this->ClearBuffer(); + mNumFrames = 0; +} + +bool MockFrameSink::CheckLast(FuncCodes aCode, bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) +{ + return (mCode == aCode) && (aIsMaster == mIsMaster) && (mSrc == aSrc) && (mDest == aDest); +} + +bool MockFrameSink::CheckLastWithFCB(FuncCodes aCode, bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) +{ + return (mFcb == aFcb) && CheckLast(aCode, aIsMaster, aDest, aSrc); +} + +bool MockFrameSink::CheckLastWithDFC(FuncCodes aCode, bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + return (mIsRcvBuffFull == aIsRcvBuffFull) && CheckLast(aCode, aIsMaster, aDest, aSrc); +} + +// Sec to Pri + +void MockFrameSink::Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_SEC_ACK, aIsMaster, aDest, aSrc); + mIsRcvBuffFull = aIsRcvBuffFull; +} + +void MockFrameSink::Nack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_SEC_NACK, aIsMaster, aDest, aSrc); + mIsRcvBuffFull = aIsRcvBuffFull; +} + +void MockFrameSink::LinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_SEC_LINK_STATUS, aIsMaster, aDest, aSrc); + mIsRcvBuffFull = aIsRcvBuffFull; +} + +void MockFrameSink::NotSupported (bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_SEC_NOT_SUPPORTED, aIsMaster, aDest, aSrc); + mIsRcvBuffFull = aIsRcvBuffFull; +} + +// Pri to Sec + +void MockFrameSink::TestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_PRI_TEST_LINK_STATES, aIsMaster, aDest, aSrc); + mFcb = aFcb; +} + +void MockFrameSink::ResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_PRI_RESET_LINK_STATES, aIsMaster, aDest, aSrc); +} + +void MockFrameSink::RequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) +{ + this->Update(FC_PRI_REQUEST_LINK_STATUS, aIsMaster, aDest, aSrc); +} + +void MockFrameSink::ConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) +{ + this->Update(FC_PRI_CONFIRMED_USER_DATA, aIsMaster, aDest, aSrc); + this->WriteToBuffer(apData, aDataLength); + mFcb = aFcb; +} + +void MockFrameSink::UnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength) +{ + this->Update(FC_PRI_UNCONFIRMED_USER_DATA, aIsMaster, aDest, aSrc); + this->WriteToBuffer(apData, aDataLength); +} + +void MockFrameSink::Update(FuncCodes aCode, bool aIsMaster, uint_16_t aDest, uint_16_t aSrc) +{ + ++mNumFrames; + mCode = aCode; + mIsMaster = aIsMaster; + mDest = aDest; + mSrc = aSrc; +} + +}} + diff --git a/DNP3Test/MockFrameSink.h b/DNP3Test/MockFrameSink.h index d75f228c..cb0a2225 100644 --- a/DNP3Test/MockFrameSink.h +++ b/DNP3Test/MockFrameSink.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,72 +6,72 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __MOCK_FRAME_SINK_H_ -#define __MOCK_FRAME_SINK_H_ - -#include -#include -#include - -namespace apl { namespace dnp { - -class MockFrameSink : public ILinkContext, public BufferTestObject -{ - public: - - MockFrameSink(); - - // ILinkContext members - void OnLowerLayerUp(); - void OnLowerLayerDown(); - - // Sec to Pri - void Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); - void Nack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); - void LinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); - void NotSupported (bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); - - // Pri to Sec - - void TestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc); - void ResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc); - void RequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc); - void ConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength); - void UnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength); - - void Reset(); - - size_t mNumFrames; - - bool CheckLast(FuncCodes aCode, bool aIsMaster, uint_16_t aDest, uint_16_t aSrc); - bool CheckLastWithFCB(FuncCodes aCode, bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc); - bool CheckLastWithDFC(FuncCodes aCode, bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); - - // Last frame information - FuncCodes mCode; - bool mIsMaster; - bool mIsRcvBuffFull; - uint_16_t mSrc; - uint_16_t mDest; - bool mFcb; - - bool mLowerOnline; - - private: - - void Update(FuncCodes aCode, bool aIsMaster, uint_16_t aSrc, uint_16_t aDest); -}; - -}} - -#endif +// +#ifndef __MOCK_FRAME_SINK_H_ +#define __MOCK_FRAME_SINK_H_ + +#include +#include +#include + +namespace apl { namespace dnp { + +class MockFrameSink : public ILinkContext, public BufferTestObject +{ + public: + + MockFrameSink(); + + // ILinkContext members + void OnLowerLayerUp(); + void OnLowerLayerDown(); + + // Sec to Pri + void Ack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); + void Nack(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); + void LinkStatus(bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); + void NotSupported (bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); + + // Pri to Sec + + void TestLinkStatus(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc); + void ResetLinkStates(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc); + void RequestLinkStatus(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc); + void ConfirmedUserData(bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength); + void UnconfirmedUserData(bool aIsMaster, uint_16_t aDest, uint_16_t aSrc, const apl::byte_t* apData, size_t aDataLength); + + void Reset(); + + size_t mNumFrames; + + bool CheckLast(FuncCodes aCode, bool aIsMaster, uint_16_t aDest, uint_16_t aSrc); + bool CheckLastWithFCB(FuncCodes aCode, bool aIsMaster, bool aFcb, uint_16_t aDest, uint_16_t aSrc); + bool CheckLastWithDFC(FuncCodes aCode, bool aIsMaster, bool aIsRcvBuffFull, uint_16_t aDest, uint_16_t aSrc); + + // Last frame information + FuncCodes mCode; + bool mIsMaster; + bool mIsRcvBuffFull; + uint_16_t mSrc; + uint_16_t mDest; + bool mFcb; + + bool mLowerOnline; + + private: + + void Update(FuncCodes aCode, bool aIsMaster, uint_16_t aSrc, uint_16_t aDest); +}; + +}} + +#endif diff --git a/DNP3Test/ResponseLoaderTestObject.cpp b/DNP3Test/ResponseLoaderTestObject.cpp index ceafe130..f7bb1c37 100644 --- a/DNP3Test/ResponseLoaderTestObject.cpp +++ b/DNP3Test/ResponseLoaderTestObject.cpp @@ -16,83 +16,83 @@ // specific language governing permissions and limitations // under the License. // -#include "ResponseLoaderTestObject.h" - -#include -#include -#include -#include - -#include - -namespace apl { namespace dnp { - -ResponseLoaderTestObject::ResponseLoaderTestObject() : -log(), -fdo(), -mpLogger(log.GetLogger(LEV_INFO, "rsp")) -{ - -} - -void ResponseLoaderTestObject::Load(const std::string& arAPDU, TimeStamp_t aTime) -{ - fdo.Clear(); - HexSequence hs(arAPDU); - APDU f; - f.Write(hs, hs.Size()); - f.Interpret(); - - ResponseLoader rl(mpLogger, aTime, &fdo); - for(HeaderReadIterator hdr = f.BeginRead(); !hdr.IsEnd(); ++hdr) - { - rl.Process(hdr); - } -} - -void ResponseLoaderTestObject::CheckBinaries(const std::string& arAPDU, TimeStamp_t aTime) -{ - this->Load(arAPDU, aTime); - - BOOST_REQUIRE_EQUAL(fdo.mBinaryMap.size(), 3); - BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 3); - - BOOST_REQUIRE(fdo.Check(false, BQ_ONLINE, 1, TimeStamp_t(20))); - BOOST_REQUIRE(fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(20))); - BOOST_REQUIRE(fdo.Check(false, BQ_ONLINE, 3, TimeStamp_t(20))); -} - -void ResponseLoaderTestObject::CheckCounters(const std::string& arAPDU, TimeStamp_t aTime) -{ - this->Load(arAPDU, aTime); - - BOOST_REQUIRE_EQUAL(fdo.mCounterMap.size(), 2); - BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 2); - - BOOST_REQUIRE(fdo.Check(4, CQ_ONLINE, 0, TimeStamp_t(20))); - BOOST_REQUIRE(fdo.Check(9, CQ_ONLINE, 1, TimeStamp_t(20))); -} - -void ResponseLoaderTestObject::CheckAnalogs(const std::string& arAPDU, TimeStamp_t aTime) -{ - this->Load(arAPDU, aTime); - - BOOST_REQUIRE_EQUAL(fdo.mAnalogMap.size(), 2); - BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 2); - - BOOST_REQUIRE(fdo.Check(4, AQ_ONLINE, 0, TimeStamp_t(20))); - BOOST_REQUIRE(fdo.Check(9, AQ_ONLINE, 1, TimeStamp_t(20))); -} - -void ResponseLoaderTestObject::CheckSetpointStatii(const std::string& arAPDU, TimeStamp_t aTime) -{ - this->Load(arAPDU, aTime); - - BOOST_REQUIRE_EQUAL(fdo.mSetpointStatusMap.size(), 2); - BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 2); - - BOOST_REQUIRE(fdo.Check(4, PQ_ONLINE, 0, TimeStamp_t(20))); - BOOST_REQUIRE(fdo.Check(9, PQ_ONLINE, 1, TimeStamp_t(20))); -} - -}} +#include "ResponseLoaderTestObject.h" + +#include +#include +#include +#include + +#include + +namespace apl { namespace dnp { + +ResponseLoaderTestObject::ResponseLoaderTestObject() : +log(), +fdo(), +mpLogger(log.GetLogger(LEV_INFO, "rsp")) +{ + +} + +void ResponseLoaderTestObject::Load(const std::string& arAPDU, TimeStamp_t aTime) +{ + fdo.Clear(); + HexSequence hs(arAPDU); + APDU f; + f.Write(hs, hs.Size()); + f.Interpret(); + + ResponseLoader rl(mpLogger, aTime, &fdo); + for(HeaderReadIterator hdr = f.BeginRead(); !hdr.IsEnd(); ++hdr) + { + rl.Process(hdr); + } +} + +void ResponseLoaderTestObject::CheckBinaries(const std::string& arAPDU, TimeStamp_t aTime) +{ + this->Load(arAPDU, aTime); + + BOOST_REQUIRE_EQUAL(fdo.mBinaryMap.size(), 3); + BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 3); + + BOOST_REQUIRE(fdo.Check(false, BQ_ONLINE, 1, TimeStamp_t(20))); + BOOST_REQUIRE(fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(20))); + BOOST_REQUIRE(fdo.Check(false, BQ_ONLINE, 3, TimeStamp_t(20))); +} + +void ResponseLoaderTestObject::CheckCounters(const std::string& arAPDU, TimeStamp_t aTime) +{ + this->Load(arAPDU, aTime); + + BOOST_REQUIRE_EQUAL(fdo.mCounterMap.size(), 2); + BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 2); + + BOOST_REQUIRE(fdo.Check(4, CQ_ONLINE, 0, TimeStamp_t(20))); + BOOST_REQUIRE(fdo.Check(9, CQ_ONLINE, 1, TimeStamp_t(20))); +} + +void ResponseLoaderTestObject::CheckAnalogs(const std::string& arAPDU, TimeStamp_t aTime) +{ + this->Load(arAPDU, aTime); + + BOOST_REQUIRE_EQUAL(fdo.mAnalogMap.size(), 2); + BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 2); + + BOOST_REQUIRE(fdo.Check(4, AQ_ONLINE, 0, TimeStamp_t(20))); + BOOST_REQUIRE(fdo.Check(9, AQ_ONLINE, 1, TimeStamp_t(20))); +} + +void ResponseLoaderTestObject::CheckSetpointStatii(const std::string& arAPDU, TimeStamp_t aTime) +{ + this->Load(arAPDU, aTime); + + BOOST_REQUIRE_EQUAL(fdo.mSetpointStatusMap.size(), 2); + BOOST_REQUIRE_EQUAL(fdo.GetTotalCount(), 2); + + BOOST_REQUIRE(fdo.Check(4, PQ_ONLINE, 0, TimeStamp_t(20))); + BOOST_REQUIRE(fdo.Check(9, PQ_ONLINE, 1, TimeStamp_t(20))); +} + +}} diff --git a/DNP3Test/ResponseLoaderTestObject.h b/DNP3Test/ResponseLoaderTestObject.h index 52afb377..a98b9d37 100644 --- a/DNP3Test/ResponseLoaderTestObject.h +++ b/DNP3Test/ResponseLoaderTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,47 +6,47 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __RESPONSE_LOADER_TEST_OBJECT_H_ -#define __RESPONSE_LOADER_TEST_OBJECT_H_ - -#include -#include - -namespace apl -{ - class Logger; -} - -namespace apl { namespace dnp { - -class ResponseLoaderTestObject -{ - public: - ResponseLoaderTestObject(); - - void CheckBinaries(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); - void CheckCounters(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); - void CheckAnalogs(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); - void CheckSetpointStatii(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); - - void Load(const std::string& arAPDU, TimeStamp_t aTime); - - private: EventLog log; - public: FlexibleDataObserver fdo; - private: Logger* mpLogger; -}; - -}} - -#endif - +// +#ifndef __RESPONSE_LOADER_TEST_OBJECT_H_ +#define __RESPONSE_LOADER_TEST_OBJECT_H_ + +#include +#include + +namespace apl +{ + class Logger; +} + +namespace apl { namespace dnp { + +class ResponseLoaderTestObject +{ + public: + ResponseLoaderTestObject(); + + void CheckBinaries(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); + void CheckCounters(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); + void CheckAnalogs(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); + void CheckSetpointStatii(const std::string& arAPDU, TimeStamp_t aTime = TimeStamp_t(0)); + + void Load(const std::string& arAPDU, TimeStamp_t aTime); + + private: EventLog log; + public: FlexibleDataObserver fdo; + private: Logger* mpLogger; +}; + +}} + +#endif + diff --git a/DNP3Test/TestAPDU.cpp b/DNP3Test/TestAPDU.cpp index eb4aeda7..e3d97cf6 100644 --- a/DNP3Test/TestAPDU.cpp +++ b/DNP3Test/TestAPDU.cpp @@ -16,411 +16,411 @@ // specific language governing permissions and limitations // under the License. // -#define BOOST_TEST_MODULE dnp3 -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; - - BOOST_AUTO_TEST_SUITE(APDUReading) - BOOST_AUTO_TEST_CASE(WriteTooMuch) - { - APDU frag(100); - byte_t buff[101]; - - BOOST_REQUIRE_THROW(frag.Write(buff, 101), ArgumentException); - } - - - BOOST_AUTO_TEST_CASE(ClassPollRequest) - { - APDU frag; - HexSequence hs("C3 01 3C 02 06 3C 03 06 3C 04 06 3C 01 06"); - frag.Write(hs, hs.Size()); - frag.Interpret(); - - //Test the Application header - AppControlField control = frag.GetControl(); - - BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_READ); - BOOST_REQUIRE(control.FIR); - BOOST_REQUIRE(control.FIN); - BOOST_REQUIRE(!control.CON); - BOOST_REQUIRE(!control.UNS); - BOOST_REQUIRE_EQUAL(control.SEQ, 3); - - bool except = false; - try{ IINField f = frag.GetIIN(); } - catch(Exception) { except = true; } - BOOST_REQUIRE(except); - - queue< pair > mObjVar; - mObjVar.push( pair(60,2) ); - mObjVar.push( pair(60,3) ); - mObjVar.push( pair(60,4) ); - mObjVar.push( pair(60,1) ); - - HeaderReadIterator hdrs = frag.BeginRead(); - - BOOST_REQUIRE_EQUAL(hdrs.Count(), 4); //assert that there are 4 headers - - for(; !hdrs.IsEnd(); ++hdrs) - { - ObjectReadIterator objs = hdrs.BeginRead(); - BOOST_REQUIRE_EQUAL(objs.Count(), 0); - - BOOST_REQUIRE(mObjVar.size() > 0); - BOOST_REQUIRE_EQUAL(hdrs->GetGroup(), mObjVar.front().first); - BOOST_REQUIRE_EQUAL(hdrs->GetVariation(), mObjVar.front().second); - mObjVar.pop(); - - //Check that the headers indicates it's at the end of iteration - BOOST_REQUIRE(objs.IsEnd()); - } - - BOOST_REQUIRE_EQUAL(mObjVar.size(),0); - } - - BOOST_AUTO_TEST_CASE(ResponseWithDataAndFlags) - { - APDU frag; - HexSequence hs("E3 81 96 00 02 01 28 01 00 00 00 01 02 01 28 01 00 01 00 01 02 01 28 01 00 02 00 01 02 01 28 01 00 03 00 01 20 02 28 01 00 00 00 01 00 00 20 02 28 01 00 01 00 01 00 00 01 01 01 00 00 03 00 00 1E 02 01 00 00 01 00 01 00 00 01 00 00"); - frag.Write(hs, hs.Size()); - frag.Interpret(); - - //Test the Application header - AppControlField control = frag.GetControl(); - BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_RESPONSE); - BOOST_REQUIRE(control.FIR); - BOOST_REQUIRE(control.FIN); - BOOST_REQUIRE(control.CON); - BOOST_REQUIRE(!control.UNS); - BOOST_REQUIRE_EQUAL(control.SEQ, 3); - - IINField iin = frag.GetIIN(); - - //device restart, need - //time, class 1 & 2 events should be set - BOOST_REQUIRE(iin.GetDeviceRestart()); - BOOST_REQUIRE(iin.GetNeedTime()); - BOOST_REQUIRE(iin.GetClass1Events()); - BOOST_REQUIRE(iin.GetClass2Events()); - - // the others should not - BOOST_REQUIRE(!iin.GetAllStations()); - BOOST_REQUIRE(!iin.GetAlreadyExecuting()); - BOOST_REQUIRE(!iin.GetClass3Events()); - BOOST_REQUIRE(!iin.GetConfigurationCorrupt()); - BOOST_REQUIRE(!iin.GetDeviceTrouble()); - BOOST_REQUIRE(!iin.GetEventBufferOverflow()); - BOOST_REQUIRE(!iin.GetFuncNotSupported()); - BOOST_REQUIRE(!iin.GetLocalControl()); - BOOST_REQUIRE(!iin.GetObjectUnknown()); - BOOST_REQUIRE(!iin.GetParameterError()); - BOOST_REQUIRE(!iin.GetReserved1()); - BOOST_REQUIRE(!iin.GetReserved2()); - - size_t hdr_count = 0; - - // 4 binary event headers (1 event), 2 analog event headers (1 event), 1 binary input header (1 Object,4 values), 1 analog input header (2) values = 8 headers - HeaderReadIterator i = frag.BeginRead(); - BOOST_REQUIRE_EQUAL(i.Count(), 8); - - for(; !i.IsEnd(); i++) - { - ObjectReadIterator j = i.BeginRead(); - - switch(hdr_count) - { - case(0): - case(1): - case(2): - case(3): - { - BOOST_REQUIRE_EQUAL(i->GetGroup(), 2); - BOOST_REQUIRE_EQUAL(i->GetVariation(), 1); - - BOOST_REQUIRE_EQUAL(j.Count(),1); - BOOST_REQUIRE_FALSE(j.IsEnd()); - BOOST_REQUIRE_EQUAL(j->Index(), hdr_count); - - const Group2Var1* pObj = static_cast(i->GetBaseObject()); - BOOST_REQUIRE_EQUAL(pObj->mFlag.Get(*j), 0x01); - - break; - } - case(4): // The analog events have indices 0 and 1 - { - BOOST_REQUIRE_EQUAL(j.Count(),1); - BOOST_REQUIRE_FALSE(j.IsEnd()); - BOOST_REQUIRE_EQUAL(j->Index(), 0); - - break; - } - case(5): - { - BOOST_REQUIRE_EQUAL(j.Count(),1); - BOOST_REQUIRE_FALSE(j.IsEnd()); - BOOST_REQUIRE_EQUAL(j->Index(), 1); - - break; - } - case(6): //The binary status is collective, so the index should be the starting index which is 0 - { - BOOST_REQUIRE_EQUAL(j.Count(),4); //four objects in bitfield obj - - BOOST_REQUIRE_EQUAL(i->GetObjectType(), OT_BITFIELD); - BOOST_REQUIRE_EQUAL(i->GetGroup(), 1); - BOOST_REQUIRE_EQUAL(i->GetVariation(), 1); - - const Group1Var1* pObj = static_cast(i->GetBaseObject()); - - for(size_t k=0; k<4; k++) - { - BOOST_REQUIRE_FALSE(j.IsEnd()); - BOOST_REQUIRE_EQUAL(j->Index(), k); - BOOST_REQUIRE_EQUAL(j->Start(), 0); - BOOST_REQUIRE_EQUAL( pObj->Read(*j, j->Start(), j->Index()), false); - j++; - } - - BOOST_REQUIRE(j.IsEnd());//no more values - - break; - } - case(7): - { - BOOST_REQUIRE_EQUAL(j.Count(),2); - BOOST_REQUIRE_FALSE(j.IsEnd()); - BOOST_REQUIRE_EQUAL(j->Index(), 0); - j++; - BOOST_REQUIRE_FALSE(j.IsEnd()); - BOOST_REQUIRE_EQUAL(j->Index(), 1); - j++; - BOOST_REQUIRE(j.IsEnd()); - } - } - - ++hdr_count; - - } - - BOOST_REQUIRE_EQUAL(hdr_count,8); - } - - BOOST_AUTO_TEST_CASE(Confirm) - { - APDU frag; - HexSequence hs("C3 00"); - frag.Write(hs, hs.Size()); - frag.Interpret(); - - AppControlField control = frag.GetControl(); - BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_CONFIRM); - BOOST_REQUIRE(control.FIR); - BOOST_REQUIRE(control.FIN); - BOOST_REQUIRE(!control.CON); - BOOST_REQUIRE(!control.UNS); - BOOST_REQUIRE_EQUAL(control.SEQ,3); - } - - BOOST_AUTO_TEST_CASE(ClearIIN) - { - APDU frag; - HexSequence hs("C4 02 50 01 00 07 07 00"); - frag.Write(hs, hs.Size()); - frag.Interpret(); - - AppControlField control = frag.GetControl(); - - - BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_WRITE); - - HeaderReadIterator hdrs = frag.BeginRead(); - BOOST_REQUIRE_EQUAL(hdrs.Count(),1); - - ObjectReadIterator objs = hdrs.BeginRead(); - BOOST_REQUIRE_EQUAL(objs.Count(),1); - BOOST_REQUIRE_EQUAL(hdrs->GetGroup(), 80); - BOOST_REQUIRE_EQUAL(hdrs->GetVariation(), 1); - - BOOST_REQUIRE_EQUAL(objs->Index(), 7); - BOOST_REQUIRE_EQUAL(objs->Start(), 7); - - const BitfieldObject* pObj = static_cast(hdrs->GetBaseObject()); - - BOOST_REQUIRE(pObj->Read(*objs, objs->Start(), objs->Index()) == false); - } - - BOOST_AUTO_TEST_CASE(ReadIndices) - { - APDU frag; - HexSequence hs("C0 01 01 02 17 03 01 03 05"); - frag.Write(hs, hs.Size()); - frag.Interpret(); - - HeaderReadIterator i = frag.BeginRead(); - BOOST_REQUIRE_EQUAL(i.Count(),1); - - ObjectReadIterator j = i.BeginRead(); - BOOST_REQUIRE_EQUAL(j.Count(),3); - BOOST_REQUIRE(!j.HasData()); - - BOOST_REQUIRE_EQUAL(j->Index(), 1); - ++j; - BOOST_REQUIRE_EQUAL(j->Index(), 3); - ++j; - BOOST_REQUIRE_EQUAL(j->Index(), 5); - ++j; - BOOST_REQUIRE( j.IsEnd() ); - } - - BOOST_AUTO_TEST_CASE(InsufficientDataForFragment) - { - APDU frag; - HexSequence hs("C4"); - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - BOOST_REQUIRE_EQUAL(code, ALERR_INSUFFICIENT_DATA_FOR_FRAG); - } - - BOOST_AUTO_TEST_CASE(InsufficientDataForResponse) - { - APDU frag; - HexSequence hs("C4 81 00"); - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - BOOST_REQUIRE_EQUAL(code, ALERR_INSUFFICIENT_DATA_FOR_RESPONSE); - } - - BOOST_AUTO_TEST_CASE(InsufficientDataForObjectHeader) - { - APDU frag; - HexSequence hs("C4 81 00 00 00"); - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - - BOOST_REQUIRE_EQUAL(code, ALERR_INSUFFICIENT_DATA_FOR_HEADER); - } - - BOOST_AUTO_TEST_CASE(UnknownGroupVar) - { - APDU frag; - HexSequence hs("C4 81 00 00 FF FF 06"); - frag.Write(hs, hs.Size()); - - bool gotIt = false; - try{ frag.Interpret(); } - catch(ObjectException ex) - { gotIt = true; } - - BOOST_REQUIRE(gotIt); - } - - BOOST_AUTO_TEST_CASE(StartStopMismach) - { - APDU frag; - HexSequence hs("C4 81 00 00 01 01 00 02 00 01 00"); //obj 1 var 1 with 1 octet start = 0x02, stop = 0x01 - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - - BOOST_REQUIRE_EQUAL(code, ALERR_START_STOP_MISMATCH); - } - - BOOST_AUTO_TEST_CASE(NonstaticObjectWithIndexPrefix) - { - APDU frag; - HexSequence hs("C4 81 00 00 01 01 17 00 00"); //obj 1 var 1 with 1 octet index prefix and 1 octet count - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - - BOOST_REQUIRE_EQUAL(code, ALERR_ILLEGAL_QUALIFIER_AND_OBJECT); - } - - BOOST_AUTO_TEST_CASE(NonvariableObjectWithSizePrefix) - { - APDU frag; - HexSequence hs("C4 81 00 00 01 01 4B 00 00"); //obj 1 var 1 with size prefix and variable array - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - - BOOST_REQUIRE_EQUAL(code, ALERR_ILLEGAL_QUALIFIER_AND_OBJECT); - } - - BOOST_AUTO_TEST_CASE(UnknownQualifer) - { - APDU frag; - HexSequence hs("C4 81 00 00 01 02 10 00 00"); //obj 1 var 2 with index 1octet prefix and 1octet start stop - frag.Write(hs, hs.Size()); - - int code = -1; - try{ frag.Interpret(); } - catch(Exception ex) - { code = ex.ErrorCode(); } - - BOOST_REQUIRE_EQUAL(code, ALERR_UNKNOWN_QUALIFIER); - } - - BOOST_AUTO_TEST_CASE(VirtualTerminalObjectWrite) - { - APDU frag; - HexSequence hs("C2 02 70 05 17 01 00 68 65 6C 6C 6F"); - frag.Write(hs, hs.Size()); - frag.Interpret(); - - HeaderReadIterator i = frag.BeginRead(); - BOOST_REQUIRE_EQUAL(i.Count(),1); - - BOOST_REQUIRE_EQUAL(i->GetGroup(), 112); - BOOST_REQUIRE_EQUAL(i->GetVariation(), 5); - - ObjectReadIterator j = i.BeginRead(); - BOOST_REQUIRE_EQUAL(j.Count(),1); - BOOST_REQUIRE(j.HasData()); - - const VariableByVariationObject* pObj = static_cast(i->GetBaseObject()); - - byte_t buff[100]; - pObj->Read(*j, i->GetVariation(), buff); - - BOOST_REQUIRE_EQUAL("hello", std::string(reinterpret_cast(buff), 5)); - - } - BOOST_AUTO_TEST_SUITE_END() - +#define BOOST_TEST_MODULE dnp3 +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; + + BOOST_AUTO_TEST_SUITE(APDUReading) + BOOST_AUTO_TEST_CASE(WriteTooMuch) + { + APDU frag(100); + byte_t buff[101]; + + BOOST_REQUIRE_THROW(frag.Write(buff, 101), ArgumentException); + } + + + BOOST_AUTO_TEST_CASE(ClassPollRequest) + { + APDU frag; + HexSequence hs("C3 01 3C 02 06 3C 03 06 3C 04 06 3C 01 06"); + frag.Write(hs, hs.Size()); + frag.Interpret(); + + //Test the Application header + AppControlField control = frag.GetControl(); + + BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_READ); + BOOST_REQUIRE(control.FIR); + BOOST_REQUIRE(control.FIN); + BOOST_REQUIRE(!control.CON); + BOOST_REQUIRE(!control.UNS); + BOOST_REQUIRE_EQUAL(control.SEQ, 3); + + bool except = false; + try{ IINField f = frag.GetIIN(); } + catch(Exception) { except = true; } + BOOST_REQUIRE(except); + + queue< pair > mObjVar; + mObjVar.push( pair(60,2) ); + mObjVar.push( pair(60,3) ); + mObjVar.push( pair(60,4) ); + mObjVar.push( pair(60,1) ); + + HeaderReadIterator hdrs = frag.BeginRead(); + + BOOST_REQUIRE_EQUAL(hdrs.Count(), 4); //assert that there are 4 headers + + for(; !hdrs.IsEnd(); ++hdrs) + { + ObjectReadIterator objs = hdrs.BeginRead(); + BOOST_REQUIRE_EQUAL(objs.Count(), 0); + + BOOST_REQUIRE(mObjVar.size() > 0); + BOOST_REQUIRE_EQUAL(hdrs->GetGroup(), mObjVar.front().first); + BOOST_REQUIRE_EQUAL(hdrs->GetVariation(), mObjVar.front().second); + mObjVar.pop(); + + //Check that the headers indicates it's at the end of iteration + BOOST_REQUIRE(objs.IsEnd()); + } + + BOOST_REQUIRE_EQUAL(mObjVar.size(),0); + } + + BOOST_AUTO_TEST_CASE(ResponseWithDataAndFlags) + { + APDU frag; + HexSequence hs("E3 81 96 00 02 01 28 01 00 00 00 01 02 01 28 01 00 01 00 01 02 01 28 01 00 02 00 01 02 01 28 01 00 03 00 01 20 02 28 01 00 00 00 01 00 00 20 02 28 01 00 01 00 01 00 00 01 01 01 00 00 03 00 00 1E 02 01 00 00 01 00 01 00 00 01 00 00"); + frag.Write(hs, hs.Size()); + frag.Interpret(); + + //Test the Application header + AppControlField control = frag.GetControl(); + BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_RESPONSE); + BOOST_REQUIRE(control.FIR); + BOOST_REQUIRE(control.FIN); + BOOST_REQUIRE(control.CON); + BOOST_REQUIRE(!control.UNS); + BOOST_REQUIRE_EQUAL(control.SEQ, 3); + + IINField iin = frag.GetIIN(); + + //device restart, need + //time, class 1 & 2 events should be set + BOOST_REQUIRE(iin.GetDeviceRestart()); + BOOST_REQUIRE(iin.GetNeedTime()); + BOOST_REQUIRE(iin.GetClass1Events()); + BOOST_REQUIRE(iin.GetClass2Events()); + + // the others should not + BOOST_REQUIRE(!iin.GetAllStations()); + BOOST_REQUIRE(!iin.GetAlreadyExecuting()); + BOOST_REQUIRE(!iin.GetClass3Events()); + BOOST_REQUIRE(!iin.GetConfigurationCorrupt()); + BOOST_REQUIRE(!iin.GetDeviceTrouble()); + BOOST_REQUIRE(!iin.GetEventBufferOverflow()); + BOOST_REQUIRE(!iin.GetFuncNotSupported()); + BOOST_REQUIRE(!iin.GetLocalControl()); + BOOST_REQUIRE(!iin.GetObjectUnknown()); + BOOST_REQUIRE(!iin.GetParameterError()); + BOOST_REQUIRE(!iin.GetReserved1()); + BOOST_REQUIRE(!iin.GetReserved2()); + + size_t hdr_count = 0; + + // 4 binary event headers (1 event), 2 analog event headers (1 event), 1 binary input header (1 Object,4 values), 1 analog input header (2) values = 8 headers + HeaderReadIterator i = frag.BeginRead(); + BOOST_REQUIRE_EQUAL(i.Count(), 8); + + for(; !i.IsEnd(); i++) + { + ObjectReadIterator j = i.BeginRead(); + + switch(hdr_count) + { + case(0): + case(1): + case(2): + case(3): + { + BOOST_REQUIRE_EQUAL(i->GetGroup(), 2); + BOOST_REQUIRE_EQUAL(i->GetVariation(), 1); + + BOOST_REQUIRE_EQUAL(j.Count(),1); + BOOST_REQUIRE_FALSE(j.IsEnd()); + BOOST_REQUIRE_EQUAL(j->Index(), hdr_count); + + const Group2Var1* pObj = static_cast(i->GetBaseObject()); + BOOST_REQUIRE_EQUAL(pObj->mFlag.Get(*j), 0x01); + + break; + } + case(4): // The analog events have indices 0 and 1 + { + BOOST_REQUIRE_EQUAL(j.Count(),1); + BOOST_REQUIRE_FALSE(j.IsEnd()); + BOOST_REQUIRE_EQUAL(j->Index(), 0); + + break; + } + case(5): + { + BOOST_REQUIRE_EQUAL(j.Count(),1); + BOOST_REQUIRE_FALSE(j.IsEnd()); + BOOST_REQUIRE_EQUAL(j->Index(), 1); + + break; + } + case(6): //The binary status is collective, so the index should be the starting index which is 0 + { + BOOST_REQUIRE_EQUAL(j.Count(),4); //four objects in bitfield obj + + BOOST_REQUIRE_EQUAL(i->GetObjectType(), OT_BITFIELD); + BOOST_REQUIRE_EQUAL(i->GetGroup(), 1); + BOOST_REQUIRE_EQUAL(i->GetVariation(), 1); + + const Group1Var1* pObj = static_cast(i->GetBaseObject()); + + for(size_t k=0; k<4; k++) + { + BOOST_REQUIRE_FALSE(j.IsEnd()); + BOOST_REQUIRE_EQUAL(j->Index(), k); + BOOST_REQUIRE_EQUAL(j->Start(), 0); + BOOST_REQUIRE_EQUAL( pObj->Read(*j, j->Start(), j->Index()), false); + j++; + } + + BOOST_REQUIRE(j.IsEnd());//no more values + + break; + } + case(7): + { + BOOST_REQUIRE_EQUAL(j.Count(),2); + BOOST_REQUIRE_FALSE(j.IsEnd()); + BOOST_REQUIRE_EQUAL(j->Index(), 0); + j++; + BOOST_REQUIRE_FALSE(j.IsEnd()); + BOOST_REQUIRE_EQUAL(j->Index(), 1); + j++; + BOOST_REQUIRE(j.IsEnd()); + } + } + + ++hdr_count; + + } + + BOOST_REQUIRE_EQUAL(hdr_count,8); + } + + BOOST_AUTO_TEST_CASE(Confirm) + { + APDU frag; + HexSequence hs("C3 00"); + frag.Write(hs, hs.Size()); + frag.Interpret(); + + AppControlField control = frag.GetControl(); + BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_CONFIRM); + BOOST_REQUIRE(control.FIR); + BOOST_REQUIRE(control.FIN); + BOOST_REQUIRE(!control.CON); + BOOST_REQUIRE(!control.UNS); + BOOST_REQUIRE_EQUAL(control.SEQ,3); + } + + BOOST_AUTO_TEST_CASE(ClearIIN) + { + APDU frag; + HexSequence hs("C4 02 50 01 00 07 07 00"); + frag.Write(hs, hs.Size()); + frag.Interpret(); + + AppControlField control = frag.GetControl(); + + + BOOST_REQUIRE_EQUAL(frag.GetFunction(), FC_WRITE); + + HeaderReadIterator hdrs = frag.BeginRead(); + BOOST_REQUIRE_EQUAL(hdrs.Count(),1); + + ObjectReadIterator objs = hdrs.BeginRead(); + BOOST_REQUIRE_EQUAL(objs.Count(),1); + BOOST_REQUIRE_EQUAL(hdrs->GetGroup(), 80); + BOOST_REQUIRE_EQUAL(hdrs->GetVariation(), 1); + + BOOST_REQUIRE_EQUAL(objs->Index(), 7); + BOOST_REQUIRE_EQUAL(objs->Start(), 7); + + const BitfieldObject* pObj = static_cast(hdrs->GetBaseObject()); + + BOOST_REQUIRE(pObj->Read(*objs, objs->Start(), objs->Index()) == false); + } + + BOOST_AUTO_TEST_CASE(ReadIndices) + { + APDU frag; + HexSequence hs("C0 01 01 02 17 03 01 03 05"); + frag.Write(hs, hs.Size()); + frag.Interpret(); + + HeaderReadIterator i = frag.BeginRead(); + BOOST_REQUIRE_EQUAL(i.Count(),1); + + ObjectReadIterator j = i.BeginRead(); + BOOST_REQUIRE_EQUAL(j.Count(),3); + BOOST_REQUIRE(!j.HasData()); + + BOOST_REQUIRE_EQUAL(j->Index(), 1); + ++j; + BOOST_REQUIRE_EQUAL(j->Index(), 3); + ++j; + BOOST_REQUIRE_EQUAL(j->Index(), 5); + ++j; + BOOST_REQUIRE( j.IsEnd() ); + } + + BOOST_AUTO_TEST_CASE(InsufficientDataForFragment) + { + APDU frag; + HexSequence hs("C4"); + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + BOOST_REQUIRE_EQUAL(code, ALERR_INSUFFICIENT_DATA_FOR_FRAG); + } + + BOOST_AUTO_TEST_CASE(InsufficientDataForResponse) + { + APDU frag; + HexSequence hs("C4 81 00"); + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + BOOST_REQUIRE_EQUAL(code, ALERR_INSUFFICIENT_DATA_FOR_RESPONSE); + } + + BOOST_AUTO_TEST_CASE(InsufficientDataForObjectHeader) + { + APDU frag; + HexSequence hs("C4 81 00 00 00"); + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + + BOOST_REQUIRE_EQUAL(code, ALERR_INSUFFICIENT_DATA_FOR_HEADER); + } + + BOOST_AUTO_TEST_CASE(UnknownGroupVar) + { + APDU frag; + HexSequence hs("C4 81 00 00 FF FF 06"); + frag.Write(hs, hs.Size()); + + bool gotIt = false; + try{ frag.Interpret(); } + catch(ObjectException ex) + { gotIt = true; } + + BOOST_REQUIRE(gotIt); + } + + BOOST_AUTO_TEST_CASE(StartStopMismach) + { + APDU frag; + HexSequence hs("C4 81 00 00 01 01 00 02 00 01 00"); //obj 1 var 1 with 1 octet start = 0x02, stop = 0x01 + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + + BOOST_REQUIRE_EQUAL(code, ALERR_START_STOP_MISMATCH); + } + + BOOST_AUTO_TEST_CASE(NonstaticObjectWithIndexPrefix) + { + APDU frag; + HexSequence hs("C4 81 00 00 01 01 17 00 00"); //obj 1 var 1 with 1 octet index prefix and 1 octet count + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + + BOOST_REQUIRE_EQUAL(code, ALERR_ILLEGAL_QUALIFIER_AND_OBJECT); + } + + BOOST_AUTO_TEST_CASE(NonvariableObjectWithSizePrefix) + { + APDU frag; + HexSequence hs("C4 81 00 00 01 01 4B 00 00"); //obj 1 var 1 with size prefix and variable array + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + + BOOST_REQUIRE_EQUAL(code, ALERR_ILLEGAL_QUALIFIER_AND_OBJECT); + } + + BOOST_AUTO_TEST_CASE(UnknownQualifer) + { + APDU frag; + HexSequence hs("C4 81 00 00 01 02 10 00 00"); //obj 1 var 2 with index 1octet prefix and 1octet start stop + frag.Write(hs, hs.Size()); + + int code = -1; + try{ frag.Interpret(); } + catch(Exception ex) + { code = ex.ErrorCode(); } + + BOOST_REQUIRE_EQUAL(code, ALERR_UNKNOWN_QUALIFIER); + } + + BOOST_AUTO_TEST_CASE(VirtualTerminalObjectWrite) + { + APDU frag; + HexSequence hs("C2 02 70 05 17 01 00 68 65 6C 6C 6F"); + frag.Write(hs, hs.Size()); + frag.Interpret(); + + HeaderReadIterator i = frag.BeginRead(); + BOOST_REQUIRE_EQUAL(i.Count(),1); + + BOOST_REQUIRE_EQUAL(i->GetGroup(), 112); + BOOST_REQUIRE_EQUAL(i->GetVariation(), 5); + + ObjectReadIterator j = i.BeginRead(); + BOOST_REQUIRE_EQUAL(j.Count(),1); + BOOST_REQUIRE(j.HasData()); + + const VariableByVariationObject* pObj = static_cast(i->GetBaseObject()); + + byte_t buff[100]; + pObj->Read(*j, i->GetVariation(), buff); + + BOOST_REQUIRE_EQUAL("hello", std::string(reinterpret_cast(buff), 5)); + + } + BOOST_AUTO_TEST_SUITE_END() + diff --git a/DNP3Test/TestAPDUWriting.cpp b/DNP3Test/TestAPDUWriting.cpp index 643c4af6..7a22339b 100644 --- a/DNP3Test/TestAPDUWriting.cpp +++ b/DNP3Test/TestAPDUWriting.cpp @@ -16,330 +16,330 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace apl; -using namespace apl::dnp; -using namespace std; - - - bool AreBuffersEqual(const byte_t* ap1, const byte_t* ap2, size_t aNumBytes) - { - for(size_t i=0; iWrite(*i, 7, 7, false); - ++i; - - BOOST_REQUIRE(i.IsEnd()); - - BOOST_REQUIRE_EQUAL(hs.Size(), frag.Size()); - BOOST_REQUIRE( AreBuffersEqual(hs, frag.GetBuffer(), hs.Size()) ); - } - - BOOST_AUTO_TEST_CASE(ResponseWithDataAndFlags) - { - HexSequence hs("E3 81 96 00 02 01 28 01 00 00 00 01 02 01 28 01 00 01 00 01 02 01 28 01 00 02 00 01 02 01 28 01 00 03 00 01 20 02 28 01 00 00 00 01 00 00 20 02 28 01 00 01 00 01 00 00 01 01 01 00 00 03 00 00 1E 02 01 00 00 01 00 01 00 00 01 00 00"); - - APDU frag; - frag.SetFunction(FC_RESPONSE); - frag.SetControl(true, true, true, false, 3); - IINField iin; - iin.SetDeviceRestart(true); - iin.SetNeedTime(true); - iin.SetClass1Events(true); - iin.SetClass2Events(true); - frag.SetIIN(iin); - - BOOST_REQUIRE_EQUAL(frag.Size(), 4); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); - - - - { - Group2Var1* pObj = Group2Var1::Inst(); - IndexedWriteIterator i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); //300 max index forces the index bit with to 2 octet - i.SetIndex(0); - pObj->mFlag.Set(*i, BQ_ONLINE); - ++i; - BOOST_REQUIRE(i.IsEnd()); - - BOOST_REQUIRE_EQUAL(frag.Size(), 12); - i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); - i.SetIndex(1); - pObj->mFlag.Set(*i, BQ_ONLINE); - ++i; - BOOST_REQUIRE(i.IsEnd()); - - BOOST_REQUIRE_EQUAL(frag.Size(), 20); - - i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); - i.SetIndex(2); - pObj->mFlag.Set(*i, BQ_ONLINE); - ++i; - BOOST_REQUIRE(i.IsEnd()); - - BOOST_REQUIRE_EQUAL(frag.Size(), 28); - - i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); - i.SetIndex(3); - pObj->mFlag.Set(*i, BQ_ONLINE); - - ++i; - BOOST_REQUIRE(i.IsEnd()); - - } - - BOOST_REQUIRE_EQUAL(frag.Size(), 36); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); - - - { - // 20 02 28 01 00 00 00 01 00 00 - Group32Var2 , 2 octet count w/ 2 octet index - Group32Var2* pObj = Group32Var2::Inst(); - IndexedWriteIterator i = frag.WriteIndexed(pObj, 1, 300); - i.SetIndex(0); - pObj->mFlag.Set(*i, AQ_ONLINE); - pObj->mValue.Set(*i, 0); - ++i; - BOOST_REQUIRE(i.IsEnd()); - BOOST_REQUIRE_EQUAL(frag.Size(), 46); - - // same again with index of 1 - i = frag.WriteIndexed(pObj, 1, 300); - i.SetIndex(1); - pObj->mFlag.Set(*i, AQ_ONLINE); - pObj->mValue.Set(*i, 0); - ++i; - BOOST_REQUIRE(i.IsEnd()); - } - - BOOST_REQUIRE_EQUAL(frag.Size(), 56); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); - - { - // 01 01 01 00 00 03 00 00 - Obj1Var1 with 2octet start/stop indices - Group1Var1* pObj = Group1Var1::Inst(); - ObjectWriteIterator i = frag.WriteContiguous(pObj, 0, 3, QC_2B_START_STOP); - - pObj->Write(*i, 0, 0, false); - ++i; - BOOST_REQUIRE_FALSE(i.IsEnd()); - - pObj->Write(*i, 0, 1, false); - ++i; - BOOST_REQUIRE_FALSE(i.IsEnd()); - - pObj->Write(*i, 0, 2, false); - ++i; - BOOST_REQUIRE_FALSE(i.IsEnd()); - - pObj->Write(*i, 0, 3, false); - ++i; - BOOST_REQUIRE(i.IsEnd()); - } - - BOOST_REQUIRE_EQUAL(frag.Size(), 64); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); - - // 1E 02 01 00 00 01 00 01 00 00 01 00 00 - Obj30Var2 with 2octet start/stop indices 00->01 - - { - Group30Var2* pObj = Group30Var2::Inst(); - ObjectWriteIterator i = frag.WriteContiguous(pObj, 0, 1, QC_2B_START_STOP); - - pObj->mFlag.Set(*i, AQ_ONLINE); - pObj->mValue.Set(*i, 0); - ++i; - BOOST_REQUIRE_FALSE(i.IsEnd()); - - pObj->mFlag.Set(*i, AQ_ONLINE); - pObj->mValue.Set(*i, 0); - ++i; - BOOST_REQUIRE(i.IsEnd()); - } - - BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); - } - - BOOST_AUTO_TEST_CASE(Obj1Var1Write) - { - HexSequence hs("C0 81 00 00 01 01 00 00 05 2A"); - - APDU frag; - frag.SetFunction(FC_RESPONSE); - IINField iin; - frag.SetIIN(iin); - frag.SetControl(true, true); - - BitfieldObject* pObj = Group1Var1::Inst(); - ObjectWriteIterator owi = frag.WriteContiguous(Group1Var1::Inst(), 0, 5);//, BWM_AUTO, true); - - for(int i=0; i<6; ++i) { - pObj->Write(*owi, 0, i, (i%2)==1); - ++owi; - } - - - BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); - - } - - - - BOOST_AUTO_TEST_CASE(SingleSetpoint) - { - APDU frag; - frag.SetFunction(FC_RESPONSE); - IINField f; - frag.SetIIN(f); - frag.SetControl(true, true, false, false, 0); - - IndexedWriteIterator itr = frag.WriteIndexed(Group41Var3::Inst(), 1, QC_1B_CNT_1B_INDEX); - Setpoint s(100.0); - - itr.SetIndex(1); - Group41Var3::Inst()->Write(*itr, s); - string rsp = toHex(frag.GetBuffer(), frag.Size(), true); - - // group 41 var 4, count = 1, index = 0, value = 100.0, status = CS_SUCCESS - BOOST_REQUIRE_EQUAL("C0 81 00 00 29 03 17 01 01 00 00 C8 42 00", rsp); - } - - BOOST_AUTO_TEST_CASE(DoubleSetpoint) - { - APDU frag; - frag.SetFunction(FC_RESPONSE); - IINField f; - frag.SetIIN(f); - frag.SetControl(true, true, false, false, 0); - - IndexedWriteIterator itr = frag.WriteIndexed(Group41Var4::Inst(), 1, QC_1B_CNT_1B_INDEX); - Setpoint s(100.0); - - itr.SetIndex(1); - - Group41Var4::Inst()->Write(*itr, s); - string rsp = toHex(frag.GetBuffer(), frag.Size(), true); - - // group 41 var 4, count = 1, index = 0, value = 100.0, status = CS_SUCCESS - BOOST_REQUIRE_EQUAL("C0 81 00 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00", rsp); - } - - BOOST_AUTO_TEST_CASE(ClassPollRequest) - { - HexSequence hs("C3 01 3C 02 06 3C 03 06 3C 04 06 3C 01 06"); - - APDU frag; - frag.SetFunction(FC_READ); - frag.SetControl(true, true, false, false, 3); - - BOOST_REQUIRE_EQUAL(frag.Size(), 2); - - frag.DoPlaceholderWrite(Group60Var2::Inst()); - BOOST_REQUIRE_EQUAL(frag.Size(), 5); - frag.DoPlaceholderWrite(Group60Var3::Inst()); - BOOST_REQUIRE_EQUAL(frag.Size(), 8); - frag.DoPlaceholderWrite(Group60Var4::Inst()); - BOOST_REQUIRE_EQUAL(frag.Size(), 11); - frag.DoPlaceholderWrite(Group60Var1::Inst()); - BOOST_REQUIRE_EQUAL(frag.Size(), 14); - - BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); - } - - BOOST_AUTO_TEST_CASE(Confirm) - { - HexSequence hs("C3 00"); - - APDU frag; - frag.SetFunction(FC_CONFIRM); - frag.SetControl(true, true, false, false, 3); - - BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); - } - - BOOST_AUTO_TEST_CASE(IndexRead) - { - HexSequence hs("C0 01 01 02 17 03 01 03 05"); - - APDU frag; - frag.SetFunction(FC_READ); - frag.SetControl(true, true); - IndexedWriteIterator i = frag.WriteIndexed(Group1Var2::Inst(), 3, 255); - - i.SetIndex(1); ++i; - i.SetIndex(3); ++i; - i.SetIndex(5); ++i; - - BOOST_REQUIRE(i.IsEnd()); - - BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); - } - - BOOST_AUTO_TEST_CASE(Sequence15Correct) - { - HexSequence hs("CF 00"); - - APDU frag; - frag.SetFunction(FC_CONFIRM); - frag.SetControl(true, true, false, false, 15); - - BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); - BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); - - } - - BOOST_AUTO_TEST_CASE(VirtualTerminalWrite) - { - APDU frag; - frag.SetFunction(FC_WRITE); - frag.SetControl(true, true, false, false, 2); - - std::string str("hello"); - size_t outSize = str.size(); - int index = 0; - - IndexedWriteIterator i = frag.WriteIndexed(Group112Var0::Inst(), outSize, index); - i.SetIndex(index); - const byte_t* ptr = reinterpret_cast(str.c_str()); - Group112Var0::Inst()->Write(*i, outSize, ptr); - - std::string output = toHex(frag.GetBuffer(), frag.Size(), true); - BOOST_REQUIRE_EQUAL(output, "C2 02 70 05 17 01 00 68 65 6C 6C 6F"); - } - BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace apl; +using namespace apl::dnp; +using namespace std; + + + bool AreBuffersEqual(const byte_t* ap1, const byte_t* ap2, size_t aNumBytes) + { + for(size_t i=0; iWrite(*i, 7, 7, false); + ++i; + + BOOST_REQUIRE(i.IsEnd()); + + BOOST_REQUIRE_EQUAL(hs.Size(), frag.Size()); + BOOST_REQUIRE( AreBuffersEqual(hs, frag.GetBuffer(), hs.Size()) ); + } + + BOOST_AUTO_TEST_CASE(ResponseWithDataAndFlags) + { + HexSequence hs("E3 81 96 00 02 01 28 01 00 00 00 01 02 01 28 01 00 01 00 01 02 01 28 01 00 02 00 01 02 01 28 01 00 03 00 01 20 02 28 01 00 00 00 01 00 00 20 02 28 01 00 01 00 01 00 00 01 01 01 00 00 03 00 00 1E 02 01 00 00 01 00 01 00 00 01 00 00"); + + APDU frag; + frag.SetFunction(FC_RESPONSE); + frag.SetControl(true, true, true, false, 3); + IINField iin; + iin.SetDeviceRestart(true); + iin.SetNeedTime(true); + iin.SetClass1Events(true); + iin.SetClass2Events(true); + frag.SetIIN(iin); + + BOOST_REQUIRE_EQUAL(frag.Size(), 4); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); + + + + { + Group2Var1* pObj = Group2Var1::Inst(); + IndexedWriteIterator i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); //300 max index forces the index bit with to 2 octet + i.SetIndex(0); + pObj->mFlag.Set(*i, BQ_ONLINE); + ++i; + BOOST_REQUIRE(i.IsEnd()); + + BOOST_REQUIRE_EQUAL(frag.Size(), 12); + i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); + i.SetIndex(1); + pObj->mFlag.Set(*i, BQ_ONLINE); + ++i; + BOOST_REQUIRE(i.IsEnd()); + + BOOST_REQUIRE_EQUAL(frag.Size(), 20); + + i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); + i.SetIndex(2); + pObj->mFlag.Set(*i, BQ_ONLINE); + ++i; + BOOST_REQUIRE(i.IsEnd()); + + BOOST_REQUIRE_EQUAL(frag.Size(), 28); + + i = frag.WriteIndexed(pObj, 1, QC_2B_CNT_2B_INDEX); + i.SetIndex(3); + pObj->mFlag.Set(*i, BQ_ONLINE); + + ++i; + BOOST_REQUIRE(i.IsEnd()); + + } + + BOOST_REQUIRE_EQUAL(frag.Size(), 36); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); + + + { + // 20 02 28 01 00 00 00 01 00 00 - Group32Var2 , 2 octet count w/ 2 octet index + Group32Var2* pObj = Group32Var2::Inst(); + IndexedWriteIterator i = frag.WriteIndexed(pObj, 1, 300); + i.SetIndex(0); + pObj->mFlag.Set(*i, AQ_ONLINE); + pObj->mValue.Set(*i, 0); + ++i; + BOOST_REQUIRE(i.IsEnd()); + BOOST_REQUIRE_EQUAL(frag.Size(), 46); + + // same again with index of 1 + i = frag.WriteIndexed(pObj, 1, 300); + i.SetIndex(1); + pObj->mFlag.Set(*i, AQ_ONLINE); + pObj->mValue.Set(*i, 0); + ++i; + BOOST_REQUIRE(i.IsEnd()); + } + + BOOST_REQUIRE_EQUAL(frag.Size(), 56); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); + + { + // 01 01 01 00 00 03 00 00 - Obj1Var1 with 2octet start/stop indices + Group1Var1* pObj = Group1Var1::Inst(); + ObjectWriteIterator i = frag.WriteContiguous(pObj, 0, 3, QC_2B_START_STOP); + + pObj->Write(*i, 0, 0, false); + ++i; + BOOST_REQUIRE_FALSE(i.IsEnd()); + + pObj->Write(*i, 0, 1, false); + ++i; + BOOST_REQUIRE_FALSE(i.IsEnd()); + + pObj->Write(*i, 0, 2, false); + ++i; + BOOST_REQUIRE_FALSE(i.IsEnd()); + + pObj->Write(*i, 0, 3, false); + ++i; + BOOST_REQUIRE(i.IsEnd()); + } + + BOOST_REQUIRE_EQUAL(frag.Size(), 64); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, frag.Size())); + + // 1E 02 01 00 00 01 00 01 00 00 01 00 00 - Obj30Var2 with 2octet start/stop indices 00->01 + + { + Group30Var2* pObj = Group30Var2::Inst(); + ObjectWriteIterator i = frag.WriteContiguous(pObj, 0, 1, QC_2B_START_STOP); + + pObj->mFlag.Set(*i, AQ_ONLINE); + pObj->mValue.Set(*i, 0); + ++i; + BOOST_REQUIRE_FALSE(i.IsEnd()); + + pObj->mFlag.Set(*i, AQ_ONLINE); + pObj->mValue.Set(*i, 0); + ++i; + BOOST_REQUIRE(i.IsEnd()); + } + + BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); + } + + BOOST_AUTO_TEST_CASE(Obj1Var1Write) + { + HexSequence hs("C0 81 00 00 01 01 00 00 05 2A"); + + APDU frag; + frag.SetFunction(FC_RESPONSE); + IINField iin; + frag.SetIIN(iin); + frag.SetControl(true, true); + + BitfieldObject* pObj = Group1Var1::Inst(); + ObjectWriteIterator owi = frag.WriteContiguous(Group1Var1::Inst(), 0, 5);//, BWM_AUTO, true); + + for(int i=0; i<6; ++i) { + pObj->Write(*owi, 0, i, (i%2)==1); + ++owi; + } + + + BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); + + } + + + + BOOST_AUTO_TEST_CASE(SingleSetpoint) + { + APDU frag; + frag.SetFunction(FC_RESPONSE); + IINField f; + frag.SetIIN(f); + frag.SetControl(true, true, false, false, 0); + + IndexedWriteIterator itr = frag.WriteIndexed(Group41Var3::Inst(), 1, QC_1B_CNT_1B_INDEX); + Setpoint s(100.0); + + itr.SetIndex(1); + Group41Var3::Inst()->Write(*itr, s); + string rsp = toHex(frag.GetBuffer(), frag.Size(), true); + + // group 41 var 4, count = 1, index = 0, value = 100.0, status = CS_SUCCESS + BOOST_REQUIRE_EQUAL("C0 81 00 00 29 03 17 01 01 00 00 C8 42 00", rsp); + } + + BOOST_AUTO_TEST_CASE(DoubleSetpoint) + { + APDU frag; + frag.SetFunction(FC_RESPONSE); + IINField f; + frag.SetIIN(f); + frag.SetControl(true, true, false, false, 0); + + IndexedWriteIterator itr = frag.WriteIndexed(Group41Var4::Inst(), 1, QC_1B_CNT_1B_INDEX); + Setpoint s(100.0); + + itr.SetIndex(1); + + Group41Var4::Inst()->Write(*itr, s); + string rsp = toHex(frag.GetBuffer(), frag.Size(), true); + + // group 41 var 4, count = 1, index = 0, value = 100.0, status = CS_SUCCESS + BOOST_REQUIRE_EQUAL("C0 81 00 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00", rsp); + } + + BOOST_AUTO_TEST_CASE(ClassPollRequest) + { + HexSequence hs("C3 01 3C 02 06 3C 03 06 3C 04 06 3C 01 06"); + + APDU frag; + frag.SetFunction(FC_READ); + frag.SetControl(true, true, false, false, 3); + + BOOST_REQUIRE_EQUAL(frag.Size(), 2); + + frag.DoPlaceholderWrite(Group60Var2::Inst()); + BOOST_REQUIRE_EQUAL(frag.Size(), 5); + frag.DoPlaceholderWrite(Group60Var3::Inst()); + BOOST_REQUIRE_EQUAL(frag.Size(), 8); + frag.DoPlaceholderWrite(Group60Var4::Inst()); + BOOST_REQUIRE_EQUAL(frag.Size(), 11); + frag.DoPlaceholderWrite(Group60Var1::Inst()); + BOOST_REQUIRE_EQUAL(frag.Size(), 14); + + BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); + } + + BOOST_AUTO_TEST_CASE(Confirm) + { + HexSequence hs("C3 00"); + + APDU frag; + frag.SetFunction(FC_CONFIRM); + frag.SetControl(true, true, false, false, 3); + + BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); + } + + BOOST_AUTO_TEST_CASE(IndexRead) + { + HexSequence hs("C0 01 01 02 17 03 01 03 05"); + + APDU frag; + frag.SetFunction(FC_READ); + frag.SetControl(true, true); + IndexedWriteIterator i = frag.WriteIndexed(Group1Var2::Inst(), 3, 255); + + i.SetIndex(1); ++i; + i.SetIndex(3); ++i; + i.SetIndex(5); ++i; + + BOOST_REQUIRE(i.IsEnd()); + + BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); + } + + BOOST_AUTO_TEST_CASE(Sequence15Correct) + { + HexSequence hs("CF 00"); + + APDU frag; + frag.SetFunction(FC_CONFIRM); + frag.SetControl(true, true, false, false, 15); + + BOOST_REQUIRE_EQUAL(frag.Size(), hs.Size()); + BOOST_REQUIRE(AreBuffersEqual(frag.GetBuffer(), hs, hs.Size())); + + } + + BOOST_AUTO_TEST_CASE(VirtualTerminalWrite) + { + APDU frag; + frag.SetFunction(FC_WRITE); + frag.SetControl(true, true, false, false, 2); + + std::string str("hello"); + size_t outSize = str.size(); + int index = 0; + + IndexedWriteIterator i = frag.WriteIndexed(Group112Var0::Inst(), outSize, index); + i.SetIndex(index); + const byte_t* ptr = reinterpret_cast(str.c_str()); + Group112Var0::Inst()->Write(*i, outSize, ptr); + + std::string output = toHex(frag.GetBuffer(), frag.Size(), true); + BOOST_REQUIRE_EQUAL(output, "C2 02 70 05 17 01 00 68 65 6C 6C 6F"); + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncAppLayer.cpp b/DNP3Test/TestAsyncAppLayer.cpp index b8bb3945..b411b6b4 100644 --- a/DNP3Test/TestAsyncAppLayer.cpp +++ b/DNP3Test/TestAsyncAppLayer.cpp @@ -16,480 +16,480 @@ // specific language governing permissions and limitations // under the License. // -#include - -#include -#include -#include "AppLayerTest.h" - - -using namespace apl; -using namespace apl::dnp; - -using namespace boost; - -BOOST_AUTO_TEST_SUITE(AsyncAppLayerSuite) - - /// Test the accessible events to demonstrate do not work if the layer is offline - BOOST_AUTO_TEST_CASE(InitialState) - { - AppLayerTest t; - BOOST_REQUIRE_THROW(t.app.OnLowerLayerDown(), InvalidStateException); - BOOST_REQUIRE_THROW(t.app.OnSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.app.OnSendFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.lower.SendUp(""), InvalidStateException); - } - - /// Check that Up/Down are forwarded correctly - /// and that the state gets reset correctly - BOOST_AUTO_TEST_CASE(LayerUpDown) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.SendRequest(FC_READ, true, true, false, false); - t.lower.ThisLayerDown(); ++t.state.NumLayerDown; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.SendRequest(FC_READ, true, true, false, false); - } - - - /// Malformed data should be getting logged - BOOST_AUTO_TEST_CASE(ParsingErrorsCaptured) - { - AppLayerTest t; t.lower.ThisLayerUp(); - t.lower.SendUp(""); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_INSUFFICIENT_DATA_FOR_FRAG); - } - - /// Test that the correct header validation occurs before passing up Unsol datas - BOOST_AUTO_TEST_CASE(UnsolErrors) - { - AppLayerTest t(false); // slaves can't accept unsol responsess - t.lower.ThisLayerUp(); - t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, false, 0); // UNS = false - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_UNSOL_BIT); - t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 0); // UNS = true - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), SERR_FUNC_NOT_SUPPORTED); - } - - /// Test that unsol data is correctly confirmed, passed up, - /// and that flooding is logged+ignored - BOOST_AUTO_TEST_CASE(UnsolSuccess) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.lower.DisableAutoSendCallback(); - t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 0); ++t.state.NumUnsol; - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE(t.CheckSentAPDU(FC_CONFIRM, true, true, false, true, 0)); - - // if frame requiring confirmation is sent before confirm send success - // it gets ignored and logged - t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 0); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_UNSOL_FLOOD); - - t.app.OnSendSuccess(); //doesn't throw exception - } - - /// Test that the various send methods reject - /// illegal function codes. Also check that the app layer - /// is slave/master aware with respect to send - BOOST_AUTO_TEST_CASE(SendBadFuncCodeSlave) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); - - // can't send a response until at least 1 request has been received - // to set the sequence number - BOOST_REQUIRE_THROW( - t.SendResponse(FC_RESPONSE, true, true, false, false), - apl::InvalidStateException); - - BOOST_REQUIRE_THROW( - t.SendUnsolicited(FC_RESPONSE, true, true, false, false), - apl::ArgumentException); - - BOOST_REQUIRE_THROW( - t.SendRequest(FC_WRITE, true, true, false, false), // master only - apl::Exception); - } - - /// Same test for the master - BOOST_AUTO_TEST_CASE(SendBadFuncCodeMaster) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); - - BOOST_REQUIRE_THROW( - t.SendResponse(FC_RESPONSE, true, true, false, false), // slave only - apl::Exception); - - BOOST_REQUIRE_THROW( - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, false, false), // slave only - apl::Exception); - - BOOST_REQUIRE_THROW( - t.SendRequest(FC_RESPONSE, true, true, false, false), //bad code - apl::ArgumentException); - - BOOST_REQUIRE_THROW( - t.SendRequest(FC_WRITE, true, true, true, false), // bad CON bit - apl::ArgumentException); - - BOOST_REQUIRE_THROW( - t.SendRequest(FC_WRITE, true, true, false, true), // bad UNS bit - apl::ArgumentException); - - BOOST_REQUIRE_THROW( - t.SendRequest(FC_WRITE, false, true, false, false), // bad FIR - apl::ArgumentException); - } - - BOOST_AUTO_TEST_CASE(SendObjectUnknownResponse) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - // doesn't matter what the sequence number is - t.SendUp("C4 01 00 00 06"); ++t.state.NumUnknown; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.SendResponse(FC_RESPONSE, true, true, false, false); // no confirmation - BOOST_REQUIRE(t.CheckSentAPDU(FC_RESPONSE, true, true, false, false, 4)); //check correct seq - } - - /// Test a simple send without confirm transaction - BOOST_AUTO_TEST_CASE(SendResponseWithoutConfirm) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - // doesn't matter what the sequence number is - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.SendResponse(FC_RESPONSE, true, true, false, false); // no confirmation - BOOST_REQUIRE(t.CheckSentAPDU(FC_RESPONSE, true, true, false, false, 4)); //check correct seq - ++t.state.NumSolSendSuccess; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - - } - - /// Test a simple send without confirm transaction - BOOST_AUTO_TEST_CASE(SendResponseFailure) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.lower.EnableAutoSendCallback(false); - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.SendResponse(FC_RESPONSE, true, true, false, false); // no confirmation - ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a send with confirm - BOOST_AUTO_TEST_CASE(SendResponseWithConfirm) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation, should start on timer - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - t.SendUp(FC_CONFIRM, true, true, false, false, 4); ++t.state.NumSolSendSuccess; - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a send with confirm - BOOST_AUTO_TEST_CASE(CancelResponseWhileSending) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.lower.DisableAutoSendCallback(); - t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - - // before any send success or failure comes back, cancel the operation - t.app.CancelResponse(); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - - // now report that that the send has completed successfully, but this should cause the - // the app layer to inform the user that the send has failed - - t.app.OnSendSuccess(); ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a send with confirm - BOOST_AUTO_TEST_CASE(CancelResponseWhileAwaitingConfirm) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - - t.app.CancelResponse(); ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); //the timer should get canceled - } - - - BOOST_AUTO_TEST_CASE(NewRequestWhileAwaitingConfirm) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.app.CancelResponse(); ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); //the timer should get canceled - t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - } - - /// Test a send with confirm timeout - BOOST_AUTO_TEST_CASE(SendResponseWithConfirmTimeout) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a non-fir send, this should - /// increment the sequence number - BOOST_AUTO_TEST_CASE(SendResponseNonFIR) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; - t.SendResponse(FC_RESPONSE, false, false, true, false); //non-FIR, will increment seq number - - t.SendUp(FC_CONFIRM, true, true, false, false, 2); //wrong seq number - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_UNEXPECTED_CONFIRM); - t.SendUp(FC_CONFIRM, true, true, false, false, 5); ++t.state.NumSolSendSuccess; // correct seq - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test the formatting exceptions for unsol send - BOOST_AUTO_TEST_CASE(SendUnsolBadFormatting) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); - - BOOST_REQUIRE_THROW( - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, false, true, true), //bad FIN - apl::ArgumentException - ); - - BOOST_REQUIRE_THROW( - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, false), //bad UNS - apl::ArgumentException - ); - } - - /// Test an unsol send with confirm transaction - BOOST_AUTO_TEST_CASE(SendUnsolicitedWithConfirm) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - t.SendUp(FC_CONFIRM, true, true, false, false, 0); // solicited confirm, should do nothing - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_UNEXPECTED_CONFIRM); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.SendUp(FC_CONFIRM, true, true, false, true, 0); ++t.state.NumUnsolSendSuccess; // unsol confirm - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test an unsol send with confirm timeout - BOOST_AUTO_TEST_CASE(SendUnsolicitedWithConfirmTimeout) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); - BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumUnsolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a single response transaction - BOOST_AUTO_TEST_CASE(SendRequestSingleResponse) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendRequest(FC_READ, true, true, false, false); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); //check that we're waiting for a response - t.SendUp(FC_RESPONSE, true, true, false, false, 0); ++t.state.NumFinalRsp; // final response - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a response timeout - BOOST_AUTO_TEST_CASE(SendRequestResponseTimeout) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - t.SendRequest(FC_READ, true, true, false, false); - BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// Test a multi-fragmented response transaction - BOOST_AUTO_TEST_CASE(SendRequestMultiResponse) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendRequest(FC_READ, true, true, false, false); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); //check that we're waiting for a response - - t.SendUp(FC_RESPONSE, false, true, false, false, 0); // check that bad FIR is rejected - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_FIR_FIN); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - - t.SendUp(FC_RESPONSE, true, false, false, false, 0); ++t.state.NumPartialRsp; // partial response - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - - t.SendUp(FC_RESPONSE, false, false, false, false, 0); // check that a bad sequence number is rejected - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_SEQUENCE); - - t.SendUp(FC_RESPONSE, false, false, false, false, 1); ++t.state.NumPartialRsp; - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - - t.SendUp(FC_RESPONSE, true, true, false, false, 2); // check that a bad FIR bit is rejected - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_FIR_FIN); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - - t.SendUp(FC_RESPONSE, false, true, false, false, 2); ++t.state.NumFinalRsp; - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /// The SendRequest transaction needs to gracefully confirm and handle - /// incoming unsolicited data before receiving it's response - BOOST_AUTO_TEST_CASE(MasterUnsolictedDuringRequest) - { - AppLayerTest t(true); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendRequest(FC_READ, true, true, false, false); // write a request - BOOST_REQUIRE(t.CheckSentAPDU(FC_READ, true, true, false, false, 0)); //verify and clear the buffer - - // this should queue a confirm and pass the data up immediately - t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 5); ++t.state.NumUnsol; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE(t.CheckSentAPDU(FC_CONFIRM, true, true, false, true, 5)); //verify and clear the buffer - - t.SendUp(FC_RESPONSE, true, true, true, false, 0); ++t.state.NumFinalRsp; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - BOOST_REQUIRE(t.CheckSentAPDU(FC_CONFIRM, true, true, false, false, 0)); // check that the response gets confirmed - } - - /** The SendUnsolicited transaction needs to gracefully pass up - requests while doing an unsolicited transaction. It's up to the - slave itself to buffer the last such request and process it - after the unsol transaction is complete. */ - BOOST_AUTO_TEST_CASE(SlaveRequestDuringUnsolicited) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); - - // this should queue a confirm and pass the data up immediately - t.SendUp(FC_READ, true, true, false, false, 0); ++t.state.NumRequest; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - t.SendUp(FC_CONFIRM, true, true, false, true, 0); ++t.state.NumUnsolSendSuccess; //confirm the unsolicited - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /** Test that no retries are performed by default */ - BOOST_AUTO_TEST_CASE(TestNoRetries) - { - AppLayerTest t(false); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); - BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 1); - BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumUnsolFailure;// timeout the unsol confirm - BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 1); - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /** Test that retries are performed for unsol */ - BOOST_AUTO_TEST_CASE(TestUnsolRetries) - { - const size_t RETRIES = 3; - - AppLayerTest t(false, RETRIES); // slave - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); - - for(size_t i=0; i<(RETRIES+1); ++i) { - BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), i+1); - BOOST_REQUIRE(t.mts.DispatchOne()); // timeout the confirm - } - - ++t.state.NumUnsolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /** Test that retries are performed for a solicited request */ - BOOST_AUTO_TEST_CASE(TestOperateRetries) - { - const size_t RETRIES = 3; - - AppLayerTest t(true, RETRIES); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendRequest(FC_OPERATE, true, true, false, false); - - for(size_t i=0; i<(RETRIES+1); ++i) { - BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), i+1); - BOOST_REQUIRE(t.mts.DispatchOne()); // timeout the response - } - - ++t.state.NumSolFailure; - BOOST_REQUIRE_EQUAL(t.state, t.user.mState); - } - - /** Test that retries are performed for a solicited request */ - BOOST_AUTO_TEST_CASE(TestRetrieReentrancy) - { - const size_t RETRIES = 1; - - AppLayerTest t(true, RETRIES); // master - t.lower.ThisLayerUp(); ++t.state.NumLayerUp; - - t.SendRequest(FC_OPERATE, true, true, false, false); - BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 1); - BOOST_REQUIRE(t.mts.DispatchOne()); // timeout the response - BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 2); - } - -BOOST_AUTO_TEST_SUITE_END() //end suite - +#include + +#include +#include +#include "AppLayerTest.h" + + +using namespace apl; +using namespace apl::dnp; + +using namespace boost; + +BOOST_AUTO_TEST_SUITE(AsyncAppLayerSuite) + + /// Test the accessible events to demonstrate do not work if the layer is offline + BOOST_AUTO_TEST_CASE(InitialState) + { + AppLayerTest t; + BOOST_REQUIRE_THROW(t.app.OnLowerLayerDown(), InvalidStateException); + BOOST_REQUIRE_THROW(t.app.OnSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.app.OnSendFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.lower.SendUp(""), InvalidStateException); + } + + /// Check that Up/Down are forwarded correctly + /// and that the state gets reset correctly + BOOST_AUTO_TEST_CASE(LayerUpDown) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.SendRequest(FC_READ, true, true, false, false); + t.lower.ThisLayerDown(); ++t.state.NumLayerDown; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.SendRequest(FC_READ, true, true, false, false); + } + + + /// Malformed data should be getting logged + BOOST_AUTO_TEST_CASE(ParsingErrorsCaptured) + { + AppLayerTest t; t.lower.ThisLayerUp(); + t.lower.SendUp(""); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_INSUFFICIENT_DATA_FOR_FRAG); + } + + /// Test that the correct header validation occurs before passing up Unsol datas + BOOST_AUTO_TEST_CASE(UnsolErrors) + { + AppLayerTest t(false); // slaves can't accept unsol responsess + t.lower.ThisLayerUp(); + t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, false, 0); // UNS = false + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_UNSOL_BIT); + t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 0); // UNS = true + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), SERR_FUNC_NOT_SUPPORTED); + } + + /// Test that unsol data is correctly confirmed, passed up, + /// and that flooding is logged+ignored + BOOST_AUTO_TEST_CASE(UnsolSuccess) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.lower.DisableAutoSendCallback(); + t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 0); ++t.state.NumUnsol; + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE(t.CheckSentAPDU(FC_CONFIRM, true, true, false, true, 0)); + + // if frame requiring confirmation is sent before confirm send success + // it gets ignored and logged + t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 0); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_UNSOL_FLOOD); + + t.app.OnSendSuccess(); //doesn't throw exception + } + + /// Test that the various send methods reject + /// illegal function codes. Also check that the app layer + /// is slave/master aware with respect to send + BOOST_AUTO_TEST_CASE(SendBadFuncCodeSlave) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); + + // can't send a response until at least 1 request has been received + // to set the sequence number + BOOST_REQUIRE_THROW( + t.SendResponse(FC_RESPONSE, true, true, false, false), + apl::InvalidStateException); + + BOOST_REQUIRE_THROW( + t.SendUnsolicited(FC_RESPONSE, true, true, false, false), + apl::ArgumentException); + + BOOST_REQUIRE_THROW( + t.SendRequest(FC_WRITE, true, true, false, false), // master only + apl::Exception); + } + + /// Same test for the master + BOOST_AUTO_TEST_CASE(SendBadFuncCodeMaster) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); + + BOOST_REQUIRE_THROW( + t.SendResponse(FC_RESPONSE, true, true, false, false), // slave only + apl::Exception); + + BOOST_REQUIRE_THROW( + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, false, false), // slave only + apl::Exception); + + BOOST_REQUIRE_THROW( + t.SendRequest(FC_RESPONSE, true, true, false, false), //bad code + apl::ArgumentException); + + BOOST_REQUIRE_THROW( + t.SendRequest(FC_WRITE, true, true, true, false), // bad CON bit + apl::ArgumentException); + + BOOST_REQUIRE_THROW( + t.SendRequest(FC_WRITE, true, true, false, true), // bad UNS bit + apl::ArgumentException); + + BOOST_REQUIRE_THROW( + t.SendRequest(FC_WRITE, false, true, false, false), // bad FIR + apl::ArgumentException); + } + + BOOST_AUTO_TEST_CASE(SendObjectUnknownResponse) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + // doesn't matter what the sequence number is + t.SendUp("C4 01 00 00 06"); ++t.state.NumUnknown; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.SendResponse(FC_RESPONSE, true, true, false, false); // no confirmation + BOOST_REQUIRE(t.CheckSentAPDU(FC_RESPONSE, true, true, false, false, 4)); //check correct seq + } + + /// Test a simple send without confirm transaction + BOOST_AUTO_TEST_CASE(SendResponseWithoutConfirm) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + // doesn't matter what the sequence number is + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.SendResponse(FC_RESPONSE, true, true, false, false); // no confirmation + BOOST_REQUIRE(t.CheckSentAPDU(FC_RESPONSE, true, true, false, false, 4)); //check correct seq + ++t.state.NumSolSendSuccess; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + + } + + /// Test a simple send without confirm transaction + BOOST_AUTO_TEST_CASE(SendResponseFailure) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.lower.EnableAutoSendCallback(false); + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.SendResponse(FC_RESPONSE, true, true, false, false); // no confirmation + ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a send with confirm + BOOST_AUTO_TEST_CASE(SendResponseWithConfirm) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation, should start on timer + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + t.SendUp(FC_CONFIRM, true, true, false, false, 4); ++t.state.NumSolSendSuccess; + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a send with confirm + BOOST_AUTO_TEST_CASE(CancelResponseWhileSending) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.lower.DisableAutoSendCallback(); + t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + + // before any send success or failure comes back, cancel the operation + t.app.CancelResponse(); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + + // now report that that the send has completed successfully, but this should cause the + // the app layer to inform the user that the send has failed + + t.app.OnSendSuccess(); ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a send with confirm + BOOST_AUTO_TEST_CASE(CancelResponseWhileAwaitingConfirm) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + + t.app.CancelResponse(); ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); //the timer should get canceled + } + + + BOOST_AUTO_TEST_CASE(NewRequestWhileAwaitingConfirm) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.app.CancelResponse(); ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); //the timer should get canceled + t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + } + + /// Test a send with confirm timeout + BOOST_AUTO_TEST_CASE(SendResponseWithConfirmTimeout) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.SendResponse(FC_RESPONSE, true, false, true, false); // with confirmation + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a non-fir send, this should + /// increment the sequence number + BOOST_AUTO_TEST_CASE(SendResponseNonFIR) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUp(FC_READ, true, true, false, false, 4); ++t.state.NumRequest; + t.SendResponse(FC_RESPONSE, false, false, true, false); //non-FIR, will increment seq number + + t.SendUp(FC_CONFIRM, true, true, false, false, 2); //wrong seq number + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_UNEXPECTED_CONFIRM); + t.SendUp(FC_CONFIRM, true, true, false, false, 5); ++t.state.NumSolSendSuccess; // correct seq + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test the formatting exceptions for unsol send + BOOST_AUTO_TEST_CASE(SendUnsolBadFormatting) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); + + BOOST_REQUIRE_THROW( + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, false, true, true), //bad FIN + apl::ArgumentException + ); + + BOOST_REQUIRE_THROW( + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, false), //bad UNS + apl::ArgumentException + ); + } + + /// Test an unsol send with confirm transaction + BOOST_AUTO_TEST_CASE(SendUnsolicitedWithConfirm) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + t.SendUp(FC_CONFIRM, true, true, false, false, 0); // solicited confirm, should do nothing + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_UNEXPECTED_CONFIRM); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.SendUp(FC_CONFIRM, true, true, false, true, 0); ++t.state.NumUnsolSendSuccess; // unsol confirm + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test an unsol send with confirm timeout + BOOST_AUTO_TEST_CASE(SendUnsolicitedWithConfirmTimeout) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); + BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumUnsolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a single response transaction + BOOST_AUTO_TEST_CASE(SendRequestSingleResponse) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendRequest(FC_READ, true, true, false, false); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); //check that we're waiting for a response + t.SendUp(FC_RESPONSE, true, true, false, false, 0); ++t.state.NumFinalRsp; // final response + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a response timeout + BOOST_AUTO_TEST_CASE(SendRequestResponseTimeout) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + t.SendRequest(FC_READ, true, true, false, false); + BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// Test a multi-fragmented response transaction + BOOST_AUTO_TEST_CASE(SendRequestMultiResponse) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendRequest(FC_READ, true, true, false, false); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); //check that we're waiting for a response + + t.SendUp(FC_RESPONSE, false, true, false, false, 0); // check that bad FIR is rejected + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_FIR_FIN); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + + t.SendUp(FC_RESPONSE, true, false, false, false, 0); ++t.state.NumPartialRsp; // partial response + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + + t.SendUp(FC_RESPONSE, false, false, false, false, 0); // check that a bad sequence number is rejected + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_SEQUENCE); + + t.SendUp(FC_RESPONSE, false, false, false, false, 1); ++t.state.NumPartialRsp; + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + + t.SendUp(FC_RESPONSE, true, true, false, false, 2); // check that a bad FIR bit is rejected + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), ALERR_BAD_FIR_FIN); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + + t.SendUp(FC_RESPONSE, false, true, false, false, 2); ++t.state.NumFinalRsp; + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /// The SendRequest transaction needs to gracefully confirm and handle + /// incoming unsolicited data before receiving it's response + BOOST_AUTO_TEST_CASE(MasterUnsolictedDuringRequest) + { + AppLayerTest t(true); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendRequest(FC_READ, true, true, false, false); // write a request + BOOST_REQUIRE(t.CheckSentAPDU(FC_READ, true, true, false, false, 0)); //verify and clear the buffer + + // this should queue a confirm and pass the data up immediately + t.SendUp(FC_UNSOLICITED_RESPONSE, true, true, true, true, 5); ++t.state.NumUnsol; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE(t.CheckSentAPDU(FC_CONFIRM, true, true, false, true, 5)); //verify and clear the buffer + + t.SendUp(FC_RESPONSE, true, true, true, false, 0); ++t.state.NumFinalRsp; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + BOOST_REQUIRE(t.CheckSentAPDU(FC_CONFIRM, true, true, false, false, 0)); // check that the response gets confirmed + } + + /** The SendUnsolicited transaction needs to gracefully pass up + requests while doing an unsolicited transaction. It's up to the + slave itself to buffer the last such request and process it + after the unsol transaction is complete. */ + BOOST_AUTO_TEST_CASE(SlaveRequestDuringUnsolicited) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); + + // this should queue a confirm and pass the data up immediately + t.SendUp(FC_READ, true, true, false, false, 0); ++t.state.NumRequest; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + t.SendUp(FC_CONFIRM, true, true, false, true, 0); ++t.state.NumUnsolSendSuccess; //confirm the unsolicited + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /** Test that no retries are performed by default */ + BOOST_AUTO_TEST_CASE(TestNoRetries) + { + AppLayerTest t(false); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); + BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 1); + BOOST_REQUIRE(t.mts.DispatchOne()); ++t.state.NumUnsolFailure;// timeout the unsol confirm + BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 1); + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /** Test that retries are performed for unsol */ + BOOST_AUTO_TEST_CASE(TestUnsolRetries) + { + const size_t RETRIES = 3; + + AppLayerTest t(false, RETRIES); // slave + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendUnsolicited(FC_UNSOLICITED_RESPONSE, true, true, true, true); + + for(size_t i=0; i<(RETRIES+1); ++i) { + BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), i+1); + BOOST_REQUIRE(t.mts.DispatchOne()); // timeout the confirm + } + + ++t.state.NumUnsolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /** Test that retries are performed for a solicited request */ + BOOST_AUTO_TEST_CASE(TestOperateRetries) + { + const size_t RETRIES = 3; + + AppLayerTest t(true, RETRIES); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendRequest(FC_OPERATE, true, true, false, false); + + for(size_t i=0; i<(RETRIES+1); ++i) { + BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), i+1); + BOOST_REQUIRE(t.mts.DispatchOne()); // timeout the response + } + + ++t.state.NumSolFailure; + BOOST_REQUIRE_EQUAL(t.state, t.user.mState); + } + + /** Test that retries are performed for a solicited request */ + BOOST_AUTO_TEST_CASE(TestRetrieReentrancy) + { + const size_t RETRIES = 1; + + AppLayerTest t(true, RETRIES); // master + t.lower.ThisLayerUp(); ++t.state.NumLayerUp; + + t.SendRequest(FC_OPERATE, true, true, false, false); + BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 1); + BOOST_REQUIRE(t.mts.DispatchOne()); // timeout the response + BOOST_REQUIRE_EQUAL(t.lower.NumWrites(), 2); + } + +BOOST_AUTO_TEST_SUITE_END() //end suite + diff --git a/DNP3Test/TestAsyncDatabase.cpp b/DNP3Test/TestAsyncDatabase.cpp index 19cc0270..f468f0c0 100644 --- a/DNP3Test/TestAsyncDatabase.cpp +++ b/DNP3Test/TestAsyncDatabase.cpp @@ -16,181 +16,181 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include "AsyncDatabaseTestObject.h" - -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; - - - template - void TestDataEvent(bool aIsEvent, const T& val1, const T& val2, double aDeadband) - { - if(aIsEvent) { - BOOST_REQUIRE(val1.ShouldGenerateEvent(val2, aDeadband, val1.GetValue())); - } - else { - BOOST_REQUIRE_FALSE(val1.ShouldGenerateEvent(val2, aDeadband, val1.GetValue())); - } - } - - template - void TestBufferForEvent(bool aIsEvent, const T& arNewVal, AsyncDatabaseTestObject& test, std::deque< PointInfo >& arQueue) - { - Transaction tr(&test.db); - test.db.Update(arNewVal, 0); - - if(aIsEvent) { - BOOST_REQUIRE_EQUAL(arQueue.size(), 1); - BOOST_REQUIRE_EQUAL(arNewVal, arQueue.front().mValue); - BOOST_REQUIRE_EQUAL(0, arQueue.front().mIndex); - arQueue.pop_front(); - } - else { - BOOST_REQUIRE_EQUAL(arQueue.size(), 0); - } - } - - BOOST_AUTO_TEST_SUITE(TestAsyncDatabase) - // Show that updating a value with an invalid index throws an exception - BOOST_AUTO_TEST_CASE(IndexOutOfBounds) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_BINARY, 1); - - Transaction tr(&t.db); - Binary b; - BOOST_REQUIRE_THROW(t.db.Update(b, 1), IndexOutOfBoundsException); - } - - // tests for the various analog event conditions - - BOOST_AUTO_TEST_CASE(AnalogEventZeroDeadband) - { - TestDataEvent(true, Analog(0), Analog(1), 0); - } - - BOOST_AUTO_TEST_CASE(AnalogEventOnDeadband) - { - TestDataEvent(false, Analog(0), Analog(1), 1); - } - - BOOST_AUTO_TEST_CASE(AnalogEventNegative) - { - TestDataEvent(true, Analog(-34), Analog(-36), 1); - } - - BOOST_AUTO_TEST_CASE(AnalogNoEventNegative) - { - TestDataEvent(false, Analog(-34), Analog(-36), 2); - } - - BOOST_AUTO_TEST_CASE(AnalogMaxRangeNoEvent) - { - TestDataEvent(false, Analog(Analog::MAX_VALUE), Analog(0), std::numeric_limits::max()); - TestDataEvent(false, Analog(0), Analog(Analog::MAX_VALUE), std::numeric_limits::max()); - } - - BOOST_AUTO_TEST_CASE(AnalogMaxRangeEvent) - { - TestDataEvent(true, Analog(Analog::MAX_VALUE), Analog(Analog::MIN_VALUE), std::numeric_limits::max()); - TestDataEvent(true, Analog(Analog::MIN_VALUE), Analog(Analog::MAX_VALUE), std::numeric_limits::max()); - } - - BOOST_AUTO_TEST_CASE(CounterMaxRangeNoEvent) - { - TestDataEvent(false, Counter(Counter::MAX_VALUE), Counter(Counter::MIN_VALUE), std::numeric_limits::max()); - TestDataEvent(false, Counter(Counter::MIN_VALUE), Counter(Counter::MAX_VALUE), std::numeric_limits::max()); - } - - BOOST_AUTO_TEST_CASE(CounterMaxRangeEvent) - { - TestDataEvent(true, Counter(Counter::MAX_VALUE), Counter(Counter::MIN_VALUE), std::numeric_limits::max()-1); - TestDataEvent(true, Counter(Counter::MIN_VALUE), Counter(Counter::MAX_VALUE), std::numeric_limits::max()-1); - } - - // Next 3 tests prove that "no change" doesn't get forwared to IAsyncEventBuffer - BOOST_AUTO_TEST_CASE(BinaryNoChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, 0, PC_CLASS_1); - TestBufferForEvent(false, Binary(false), t, t.buffer.mBinaryEvents); - } - - BOOST_AUTO_TEST_CASE(AnalogNoChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_ANALOG, 1); - t.db.SetClass(DT_ANALOG, 0, PC_CLASS_1); - TestBufferForEvent(false, Analog(0), t, t.buffer.mAnalogEvents); - } - - BOOST_AUTO_TEST_CASE(CounterNoChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_COUNTER, 1); - t.db.SetClass(DT_COUNTER, 0, PC_CLASS_1); - TestBufferForEvent(false, Counter(0), t, t.buffer.mCounterEvents); - } - - // Next 3 tests prove that a change detection will forward to the buffer - BOOST_AUTO_TEST_CASE(BinaryChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, 0, PC_CLASS_1); - TestBufferForEvent(true, Binary(false, BQ_ONLINE), t, t.buffer.mBinaryEvents); - } - - BOOST_AUTO_TEST_CASE(AnalogChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_ANALOG, 1); - t.db.SetClass(DT_ANALOG, 0, PC_CLASS_1); - TestBufferForEvent(true, Analog(0, AQ_ONLINE), t, t.buffer.mAnalogEvents); - } - - BOOST_AUTO_TEST_CASE(CounterChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_COUNTER, 1); - t.db.SetClass(DT_COUNTER, 0, PC_CLASS_1); - TestBufferForEvent(true, Counter(0, CQ_ONLINE), t, t.buffer.mCounterEvents); - } - - //show that the last reported change gets recorded correctly and applied correctly for each type - BOOST_AUTO_TEST_CASE(AnalogLastReportedChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_ANALOG, 1); - t.db.SetClass(DT_ANALOG, 0, PC_CLASS_1); - t.db.SetDeadband(DT_ANALOG, 0, 5); //value must change by more than 5 before being reported - - TestBufferForEvent(false, Analog(-2), t, t.buffer.mAnalogEvents); - TestBufferForEvent(false, Analog(5), t, t.buffer.mAnalogEvents); - TestBufferForEvent(true, Analog(6), t, t.buffer.mAnalogEvents); //change by 6, so 6 should get recorded - TestBufferForEvent(false, Analog(1), t, t.buffer.mAnalogEvents); - TestBufferForEvent(true, Analog(-1), t, t.buffer.mAnalogEvents); - } - - BOOST_AUTO_TEST_CASE(CounterLastReportedChange) - { - AsyncDatabaseTestObject t; - t.db.Configure(DT_COUNTER, 1); - t.db.SetClass(DT_COUNTER, 0, PC_CLASS_1); - t.db.SetDeadband(DT_COUNTER, 0, 5); //value must change by more than 5 before being reported - - TestBufferForEvent(false, Counter(1), t, t.buffer.mCounterEvents); - TestBufferForEvent(false, Counter(5), t, t.buffer.mCounterEvents); - TestBufferForEvent(true, Counter(6), t, t.buffer.mCounterEvents); //change by 6, so 6 should get recorded - TestBufferForEvent(false, Counter(1), t, t.buffer.mCounterEvents); - TestBufferForEvent(true, Counter(0), t, t.buffer.mCounterEvents); - } - - BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include "AsyncDatabaseTestObject.h" + +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; + + + template + void TestDataEvent(bool aIsEvent, const T& val1, const T& val2, double aDeadband) + { + if(aIsEvent) { + BOOST_REQUIRE(val1.ShouldGenerateEvent(val2, aDeadband, val1.GetValue())); + } + else { + BOOST_REQUIRE_FALSE(val1.ShouldGenerateEvent(val2, aDeadband, val1.GetValue())); + } + } + + template + void TestBufferForEvent(bool aIsEvent, const T& arNewVal, AsyncDatabaseTestObject& test, std::deque< PointInfo >& arQueue) + { + Transaction tr(&test.db); + test.db.Update(arNewVal, 0); + + if(aIsEvent) { + BOOST_REQUIRE_EQUAL(arQueue.size(), 1); + BOOST_REQUIRE_EQUAL(arNewVal, arQueue.front().mValue); + BOOST_REQUIRE_EQUAL(0, arQueue.front().mIndex); + arQueue.pop_front(); + } + else { + BOOST_REQUIRE_EQUAL(arQueue.size(), 0); + } + } + + BOOST_AUTO_TEST_SUITE(TestAsyncDatabase) + // Show that updating a value with an invalid index throws an exception + BOOST_AUTO_TEST_CASE(IndexOutOfBounds) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_BINARY, 1); + + Transaction tr(&t.db); + Binary b; + BOOST_REQUIRE_THROW(t.db.Update(b, 1), IndexOutOfBoundsException); + } + + // tests for the various analog event conditions + + BOOST_AUTO_TEST_CASE(AnalogEventZeroDeadband) + { + TestDataEvent(true, Analog(0), Analog(1), 0); + } + + BOOST_AUTO_TEST_CASE(AnalogEventOnDeadband) + { + TestDataEvent(false, Analog(0), Analog(1), 1); + } + + BOOST_AUTO_TEST_CASE(AnalogEventNegative) + { + TestDataEvent(true, Analog(-34), Analog(-36), 1); + } + + BOOST_AUTO_TEST_CASE(AnalogNoEventNegative) + { + TestDataEvent(false, Analog(-34), Analog(-36), 2); + } + + BOOST_AUTO_TEST_CASE(AnalogMaxRangeNoEvent) + { + TestDataEvent(false, Analog(Analog::MAX_VALUE), Analog(0), std::numeric_limits::max()); + TestDataEvent(false, Analog(0), Analog(Analog::MAX_VALUE), std::numeric_limits::max()); + } + + BOOST_AUTO_TEST_CASE(AnalogMaxRangeEvent) + { + TestDataEvent(true, Analog(Analog::MAX_VALUE), Analog(Analog::MIN_VALUE), std::numeric_limits::max()); + TestDataEvent(true, Analog(Analog::MIN_VALUE), Analog(Analog::MAX_VALUE), std::numeric_limits::max()); + } + + BOOST_AUTO_TEST_CASE(CounterMaxRangeNoEvent) + { + TestDataEvent(false, Counter(Counter::MAX_VALUE), Counter(Counter::MIN_VALUE), std::numeric_limits::max()); + TestDataEvent(false, Counter(Counter::MIN_VALUE), Counter(Counter::MAX_VALUE), std::numeric_limits::max()); + } + + BOOST_AUTO_TEST_CASE(CounterMaxRangeEvent) + { + TestDataEvent(true, Counter(Counter::MAX_VALUE), Counter(Counter::MIN_VALUE), std::numeric_limits::max()-1); + TestDataEvent(true, Counter(Counter::MIN_VALUE), Counter(Counter::MAX_VALUE), std::numeric_limits::max()-1); + } + + // Next 3 tests prove that "no change" doesn't get forwared to IAsyncEventBuffer + BOOST_AUTO_TEST_CASE(BinaryNoChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, 0, PC_CLASS_1); + TestBufferForEvent(false, Binary(false), t, t.buffer.mBinaryEvents); + } + + BOOST_AUTO_TEST_CASE(AnalogNoChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_ANALOG, 1); + t.db.SetClass(DT_ANALOG, 0, PC_CLASS_1); + TestBufferForEvent(false, Analog(0), t, t.buffer.mAnalogEvents); + } + + BOOST_AUTO_TEST_CASE(CounterNoChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_COUNTER, 1); + t.db.SetClass(DT_COUNTER, 0, PC_CLASS_1); + TestBufferForEvent(false, Counter(0), t, t.buffer.mCounterEvents); + } + + // Next 3 tests prove that a change detection will forward to the buffer + BOOST_AUTO_TEST_CASE(BinaryChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, 0, PC_CLASS_1); + TestBufferForEvent(true, Binary(false, BQ_ONLINE), t, t.buffer.mBinaryEvents); + } + + BOOST_AUTO_TEST_CASE(AnalogChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_ANALOG, 1); + t.db.SetClass(DT_ANALOG, 0, PC_CLASS_1); + TestBufferForEvent(true, Analog(0, AQ_ONLINE), t, t.buffer.mAnalogEvents); + } + + BOOST_AUTO_TEST_CASE(CounterChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_COUNTER, 1); + t.db.SetClass(DT_COUNTER, 0, PC_CLASS_1); + TestBufferForEvent(true, Counter(0, CQ_ONLINE), t, t.buffer.mCounterEvents); + } + + //show that the last reported change gets recorded correctly and applied correctly for each type + BOOST_AUTO_TEST_CASE(AnalogLastReportedChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_ANALOG, 1); + t.db.SetClass(DT_ANALOG, 0, PC_CLASS_1); + t.db.SetDeadband(DT_ANALOG, 0, 5); //value must change by more than 5 before being reported + + TestBufferForEvent(false, Analog(-2), t, t.buffer.mAnalogEvents); + TestBufferForEvent(false, Analog(5), t, t.buffer.mAnalogEvents); + TestBufferForEvent(true, Analog(6), t, t.buffer.mAnalogEvents); //change by 6, so 6 should get recorded + TestBufferForEvent(false, Analog(1), t, t.buffer.mAnalogEvents); + TestBufferForEvent(true, Analog(-1), t, t.buffer.mAnalogEvents); + } + + BOOST_AUTO_TEST_CASE(CounterLastReportedChange) + { + AsyncDatabaseTestObject t; + t.db.Configure(DT_COUNTER, 1); + t.db.SetClass(DT_COUNTER, 0, PC_CLASS_1); + t.db.SetDeadband(DT_COUNTER, 0, 5); //value must change by more than 5 before being reported + + TestBufferForEvent(false, Counter(1), t, t.buffer.mCounterEvents); + TestBufferForEvent(false, Counter(5), t, t.buffer.mCounterEvents); + TestBufferForEvent(true, Counter(6), t, t.buffer.mCounterEvents); //change by 6, so 6 should get recorded + TestBufferForEvent(false, Counter(1), t, t.buffer.mCounterEvents); + TestBufferForEvent(true, Counter(0), t, t.buffer.mCounterEvents); + } + + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncEventBufferBase.cpp b/DNP3Test/TestAsyncEventBufferBase.cpp index a5c5b061..91a0c2af 100644 --- a/DNP3Test/TestAsyncEventBufferBase.cpp +++ b/DNP3Test/TestAsyncEventBufferBase.cpp @@ -16,132 +16,132 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include - -#include -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; - -template -struct SetWrapper -{ - struct ValueOrder - { - bool operator()(const T& a, const T& b) - { return a.mValue < b.mValue; } - }; - - typedef std::set Type; -}; - -template -class SimpleBuffer : public AsyncEventBufferBase > -{ -public: - - SimpleBuffer(size_t aMaxEvents) : AsyncEventBufferBase >(aMaxEvents) - {} -}; - -BOOST_AUTO_TEST_SUITE(TestAsyncEventBufferBase) - typedef EventInfo intevt; - - BOOST_AUTO_TEST_CASE(SetInitState) - { - SimpleBuffer< intevt > b(2); - - BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 0); - BOOST_REQUIRE_EQUAL(b.Deselect(), 0); - } - - BOOST_AUTO_TEST_CASE(SetUpdate) - { - SimpleBuffer< intevt > b(2); - - b.Update(1, PC_CLASS_1, 0); - BOOST_REQUIRE_EQUAL(b.Size(), 1); - b.Update(1, PC_CLASS_1, 0); - BOOST_REQUIRE_EQUAL(b.Size(), 1); - } - - BOOST_AUTO_TEST_CASE(SimpleOverflow) - { - SimpleBuffer< intevt > b(1); - - b.Update(1, PC_CLASS_1, 0); - BOOST_REQUIRE_EQUAL(b.Size(), 1); - b.Update(2, PC_CLASS_1, 0); - BOOST_REQUIRE_EQUAL(b.Size(), 1); - BOOST_REQUIRE(b.IsOverflown()); - } - - BOOST_AUTO_TEST_CASE(OverflowDuringSelection) - { - SimpleBuffer< intevt > b(2); - - b.Update(1, PC_CLASS_1, 0); - b.Update(2, PC_CLASS_1, 1); - - BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1, 1), 1); - - b.Update(3, PC_CLASS_1, 0); - - // b/c the selected events don't count towards overflow, this should still be false - BOOST_REQUIRE_FALSE(b.IsOverflown()); - - b.Update(4, PC_CLASS_1, 2); - BOOST_REQUIRE(b.IsOverflown()); //now we lose an event - - //clear the buffer and make sure the overflown flag gets cleared - - b.Begin()->mWritten = true; - BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 1); - BOOST_REQUIRE_EQUAL(b.Size(), 2); - BOOST_REQUIRE(b.IsOverflown()); // still overflow until we remove an event - - b.Select(PC_CLASS_1, 1); - b.Begin()->mWritten = true; - BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 1); - BOOST_REQUIRE_FALSE(b.IsOverflown()); - } - - BOOST_AUTO_TEST_CASE(SelectDeselect) - { - SimpleBuffer< intevt > b(5); - - b.Update(1, PC_CLASS_1, 0); - b.Update(2, PC_CLASS_1, 0); - - BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_2), 0); - BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 2); - BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 0); //performing an additional select should add no more values - - BOOST_REQUIRE_EQUAL(b.Deselect(),2); // all events should go back into the buffer - BOOST_REQUIRE_EQUAL(b.Deselect(),0); // all events should go back into the buffer - } - - BOOST_AUTO_TEST_CASE(SelectAndClear) - { - SimpleBuffer< intevt > b(5); - - b.Update(1, PC_CLASS_1, 0); - b.Update(2, PC_CLASS_1, 0); - - BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 2); - BOOST_REQUIRE_EQUAL(b.NumSelected(), 2); - BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 0); //performing an additional select should add no more values - BOOST_REQUIRE_EQUAL(b.NumSelected(), 2); - EvtItr::Type itr = b.Begin(); - - itr->mWritten = true; - - BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 1); - BOOST_REQUIRE_EQUAL(b.NumSelected(), 1); - } -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include + +#include +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; + +template +struct SetWrapper +{ + struct ValueOrder + { + bool operator()(const T& a, const T& b) + { return a.mValue < b.mValue; } + }; + + typedef std::set Type; +}; + +template +class SimpleBuffer : public AsyncEventBufferBase > +{ +public: + + SimpleBuffer(size_t aMaxEvents) : AsyncEventBufferBase >(aMaxEvents) + {} +}; + +BOOST_AUTO_TEST_SUITE(TestAsyncEventBufferBase) + typedef EventInfo intevt; + + BOOST_AUTO_TEST_CASE(SetInitState) + { + SimpleBuffer< intevt > b(2); + + BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 0); + BOOST_REQUIRE_EQUAL(b.Deselect(), 0); + } + + BOOST_AUTO_TEST_CASE(SetUpdate) + { + SimpleBuffer< intevt > b(2); + + b.Update(1, PC_CLASS_1, 0); + BOOST_REQUIRE_EQUAL(b.Size(), 1); + b.Update(1, PC_CLASS_1, 0); + BOOST_REQUIRE_EQUAL(b.Size(), 1); + } + + BOOST_AUTO_TEST_CASE(SimpleOverflow) + { + SimpleBuffer< intevt > b(1); + + b.Update(1, PC_CLASS_1, 0); + BOOST_REQUIRE_EQUAL(b.Size(), 1); + b.Update(2, PC_CLASS_1, 0); + BOOST_REQUIRE_EQUAL(b.Size(), 1); + BOOST_REQUIRE(b.IsOverflown()); + } + + BOOST_AUTO_TEST_CASE(OverflowDuringSelection) + { + SimpleBuffer< intevt > b(2); + + b.Update(1, PC_CLASS_1, 0); + b.Update(2, PC_CLASS_1, 1); + + BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1, 1), 1); + + b.Update(3, PC_CLASS_1, 0); + + // b/c the selected events don't count towards overflow, this should still be false + BOOST_REQUIRE_FALSE(b.IsOverflown()); + + b.Update(4, PC_CLASS_1, 2); + BOOST_REQUIRE(b.IsOverflown()); //now we lose an event + + //clear the buffer and make sure the overflown flag gets cleared + + b.Begin()->mWritten = true; + BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 1); + BOOST_REQUIRE_EQUAL(b.Size(), 2); + BOOST_REQUIRE(b.IsOverflown()); // still overflow until we remove an event + + b.Select(PC_CLASS_1, 1); + b.Begin()->mWritten = true; + BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 1); + BOOST_REQUIRE_FALSE(b.IsOverflown()); + } + + BOOST_AUTO_TEST_CASE(SelectDeselect) + { + SimpleBuffer< intevt > b(5); + + b.Update(1, PC_CLASS_1, 0); + b.Update(2, PC_CLASS_1, 0); + + BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_2), 0); + BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 2); + BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 0); //performing an additional select should add no more values + + BOOST_REQUIRE_EQUAL(b.Deselect(),2); // all events should go back into the buffer + BOOST_REQUIRE_EQUAL(b.Deselect(),0); // all events should go back into the buffer + } + + BOOST_AUTO_TEST_CASE(SelectAndClear) + { + SimpleBuffer< intevt > b(5); + + b.Update(1, PC_CLASS_1, 0); + b.Update(2, PC_CLASS_1, 0); + + BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 2); + BOOST_REQUIRE_EQUAL(b.NumSelected(), 2); + BOOST_REQUIRE_EQUAL(b.Select(PC_CLASS_1), 0); //performing an additional select should add no more values + BOOST_REQUIRE_EQUAL(b.NumSelected(), 2); + EvtItr::Type itr = b.Begin(); + + itr->mWritten = true; + + BOOST_REQUIRE_EQUAL(b.ClearWrittenEvents(), 1); + BOOST_REQUIRE_EQUAL(b.NumSelected(), 1); + } +BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncEventBuffers.cpp b/DNP3Test/TestAsyncEventBuffers.cpp index 95810f87..d40a3f26 100644 --- a/DNP3Test/TestAsyncEventBuffers.cpp +++ b/DNP3Test/TestAsyncEventBuffers.cpp @@ -16,106 +16,106 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include - -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; - - - BOOST_AUTO_TEST_SUITE(AsyncSingleEventBufferSuite) - BOOST_AUTO_TEST_CASE(SingleIndexSorting) - { - AsyncSingleEventBuffer b(3); - - b.Update(Analog(0), PC_CLASS_1, 0); - b.Update(Analog(0), PC_CLASS_1, 1); - - BOOST_REQUIRE_EQUAL(b.Size(), 2); - - Analog a(0); a.SetTime(TimeStamp_t(2)); //newer timestamp - b.Update(a, PC_CLASS_1, 0); //repeat index 0 - - BOOST_REQUIRE_EQUAL(b.Size(), 2); - b.Select(PC_CLASS_1); - BOOST_REQUIRE_EQUAL(b.Begin()->mValue.GetTime(), TimeStamp_t(2)); //prove the newest value was kept - } - BOOST_AUTO_TEST_SUITE_END() - - // index is irrelevant in these tests, only insertion order matters - BOOST_AUTO_TEST_SUITE(AsyncInsertionOrderedEventBufferSuite) - typedef EventInfo intevt; - - BOOST_AUTO_TEST_CASE(InsertionOrderSorting) - { - const size_t NUM = 3; - - AsyncInsertionOrderedEventBuffer b(NUM); - - int vals[NUM] = {2, 1, 0}; - - for(size_t i=0; i::Type itr = b.Begin(); - - for(size_t i=0; imValue, vals[i]); - ++itr; - } - } - - b.Deselect(); - - { - //now verify the order - b.Select(PC_CLASS_1); - EvtItr::Type itr = b.Begin(); - - for(size_t i=0; imValue, vals[i]); - ++itr; - } - } - - } - BOOST_AUTO_TEST_SUITE_END() - - BOOST_AUTO_TEST_SUITE(AsyncTimeOrderedEventBufferSuite) - BOOST_AUTO_TEST_CASE(TimeBasedSorting) - { - const size_t NUM = 3; - AsyncTimeOrderedEventBuffer b(NUM); - - TimeStamp_t times[NUM] = {TimeStamp_t(3), TimeStamp_t(2), TimeStamp_t(1)}; - - Binary v; // false, restart, t = 0 - - for(size_t i=0; i::Type itr = b.Begin(); - - for(size_t i=0; imValue.GetTime(), times[NUM-i-1]); //reverse order of array above - ++itr; - } - - - } - BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include + +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; + + + BOOST_AUTO_TEST_SUITE(AsyncSingleEventBufferSuite) + BOOST_AUTO_TEST_CASE(SingleIndexSorting) + { + AsyncSingleEventBuffer b(3); + + b.Update(Analog(0), PC_CLASS_1, 0); + b.Update(Analog(0), PC_CLASS_1, 1); + + BOOST_REQUIRE_EQUAL(b.Size(), 2); + + Analog a(0); a.SetTime(TimeStamp_t(2)); //newer timestamp + b.Update(a, PC_CLASS_1, 0); //repeat index 0 + + BOOST_REQUIRE_EQUAL(b.Size(), 2); + b.Select(PC_CLASS_1); + BOOST_REQUIRE_EQUAL(b.Begin()->mValue.GetTime(), TimeStamp_t(2)); //prove the newest value was kept + } + BOOST_AUTO_TEST_SUITE_END() + + // index is irrelevant in these tests, only insertion order matters + BOOST_AUTO_TEST_SUITE(AsyncInsertionOrderedEventBufferSuite) + typedef EventInfo intevt; + + BOOST_AUTO_TEST_CASE(InsertionOrderSorting) + { + const size_t NUM = 3; + + AsyncInsertionOrderedEventBuffer b(NUM); + + int vals[NUM] = {2, 1, 0}; + + for(size_t i=0; i::Type itr = b.Begin(); + + for(size_t i=0; imValue, vals[i]); + ++itr; + } + } + + b.Deselect(); + + { + //now verify the order + b.Select(PC_CLASS_1); + EvtItr::Type itr = b.Begin(); + + for(size_t i=0; imValue, vals[i]); + ++itr; + } + } + + } + BOOST_AUTO_TEST_SUITE_END() + + BOOST_AUTO_TEST_SUITE(AsyncTimeOrderedEventBufferSuite) + BOOST_AUTO_TEST_CASE(TimeBasedSorting) + { + const size_t NUM = 3; + AsyncTimeOrderedEventBuffer b(NUM); + + TimeStamp_t times[NUM] = {TimeStamp_t(3), TimeStamp_t(2), TimeStamp_t(1)}; + + Binary v; // false, restart, t = 0 + + for(size_t i=0; i::Type itr = b.Begin(); + + for(size_t i=0; imValue.GetTime(), times[NUM-i-1]); //reverse order of array above + ++itr; + } + + + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncIntegration.cpp b/DNP3Test/TestAsyncIntegration.cpp index cf859434..120b2bb1 100644 --- a/DNP3Test/TestAsyncIntegration.cpp +++ b/DNP3Test/TestAsyncIntegration.cpp @@ -16,67 +16,67 @@ // specific language governing permissions and limitations // under the License. // -#include -#include -#include - -#include -#include -#include "AsyncIntegrationTest.h" - -using namespace apl; -using namespace apl::dnp; - -BOOST_AUTO_TEST_SUITE(AsyncIntegrationSuite) - - BOOST_AUTO_TEST_CASE(MasterToSlave) - { - #ifdef WIN32 - uint_16_t port = 50000; - size_t NUM_PAIRS = 10; - #else - uint_16_t port = 30000; - #ifdef ARM - size_t NUM_PAIRS = 10; - #else - size_t NUM_PAIRS = 100; - #endif - #endif - - - StopWatch sw; - - size_t NUM_POINTS = 500; - size_t NUM_CHANGES = 10; - - EventLog log; - //log.AddLogSubscriber(LogToStdio::Inst()); - AsyncIntegrationTest t(log.GetLogger(LEV_WARNING, "test"), LEV_WARNING - , port, NUM_PAIRS, NUM_POINTS); - - IDataObserver* pObs = t.GetFanout(); - - for(size_t j=0; j < NUM_CHANGES; ++j) { - - { - Transaction tr(pObs); - for(size_t i = 0; iUpdate(t.RandomBinary(), i); - for(size_t i = 0; iUpdate(t.RandomAnalog(), i); - for(size_t i = 0; iUpdate(t.RandomCounter(), i); - } - - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&AsyncIntegrationTest::SameData, &t))); - //std::cout << "*** Finished change set " << j << " ***" << std::endl; - } - - /* - double elapsed_sec = sw.Elapsed()/1000.0; - size_t points = 3*NUM_POINTS*NUM_CHANGES*NUM_PAIRS*2; - std::cout << "num points: " << points << std::endl; - std::cout << "elapsed seconds: " << elapsed_sec << std::endl; - std::cout << "points/sec: " << points/elapsed_sec << std::endl; - */ - } - -BOOST_AUTO_TEST_SUITE_END() - +#include +#include +#include + +#include +#include +#include "AsyncIntegrationTest.h" + +using namespace apl; +using namespace apl::dnp; + +BOOST_AUTO_TEST_SUITE(AsyncIntegrationSuite) + + BOOST_AUTO_TEST_CASE(MasterToSlave) + { + #ifdef WIN32 + uint_16_t port = 50000; + size_t NUM_PAIRS = 10; + #else + uint_16_t port = 30000; + #ifdef ARM + size_t NUM_PAIRS = 10; + #else + size_t NUM_PAIRS = 100; + #endif + #endif + + + StopWatch sw; + + size_t NUM_POINTS = 500; + size_t NUM_CHANGES = 10; + + EventLog log; + //log.AddLogSubscriber(LogToStdio::Inst()); + AsyncIntegrationTest t(log.GetLogger(LEV_WARNING, "test"), LEV_WARNING + , port, NUM_PAIRS, NUM_POINTS); + + IDataObserver* pObs = t.GetFanout(); + + for(size_t j=0; j < NUM_CHANGES; ++j) { + + { + Transaction tr(pObs); + for(size_t i = 0; iUpdate(t.RandomBinary(), i); + for(size_t i = 0; iUpdate(t.RandomAnalog(), i); + for(size_t i = 0; iUpdate(t.RandomCounter(), i); + } + + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&AsyncIntegrationTest::SameData, &t))); + //std::cout << "*** Finished change set " << j << " ***" << std::endl; + } + + /* + double elapsed_sec = sw.Elapsed()/1000.0; + size_t points = 3*NUM_POINTS*NUM_CHANGES*NUM_PAIRS*2; + std::cout << "num points: " << points << std::endl; + std::cout << "elapsed seconds: " << elapsed_sec << std::endl; + std::cout << "points/sec: " << points/elapsed_sec << std::endl; + */ + } + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/DNP3Test/TestAsyncLinkLayer.cpp b/DNP3Test/TestAsyncLinkLayer.cpp index c26f0e12..1a99106f 100644 --- a/DNP3Test/TestAsyncLinkLayer.cpp +++ b/DNP3Test/TestAsyncLinkLayer.cpp @@ -16,401 +16,401 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include -#include - -#include "AsyncLinkLayerTest.h" - -using namespace apl; -using namespace apl::dnp; - -BOOST_AUTO_TEST_SUITE(AsyncLinkLayerSuite) - - /// All operations should fail except for OnLowerLayerUp, just a representative - /// number of them - BOOST_AUTO_TEST_CASE(ClosedState) - { - AsyncLinkLayerTest t; - BOOST_REQUIRE_THROW(t.upper.SendDown("00"), InvalidStateException); - BOOST_REQUIRE_THROW(t.link.OnLowerLayerDown(), InvalidStateException); - BOOST_REQUIRE_THROW(t.link.Ack(false, false, 1, 2), InvalidStateException); - } - - /// Prove that the upper layer is notified when the lower layer comes online - BOOST_AUTO_TEST_CASE(ForwardsOnLowerLayerUp) - { - AsyncLinkLayerTest t; - BOOST_REQUIRE_FALSE(t.upper.IsLowerLayerUp()); - t.link.OnLowerLayerUp(); - BOOST_REQUIRE(t.upper.IsLowerLayerUp()); - } - - /// Check that once the layer comes up, validation errors can occur - BOOST_AUTO_TEST_CASE(ValidatesMasterSlaveBit) - { - AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); - t.link.Ack(true, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_MASTER_BIT_MATCH); - } - - /// Only process frames from your designated remote address - BOOST_AUTO_TEST_CASE(ValidatesSourceAddress) - { - AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); - t.link.Ack(false, false, 1, 1023); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_SOURCE); - } - - /// This should actually never happen when using the AsyncLinkLayerRouter - /// Only process frame addressed to you - BOOST_AUTO_TEST_CASE(ValidatesDestinationAddress) - { - AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); - t.link.Ack(false, false, 2, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_DESTINATION); - } - - /// Show that the base state of idle logs SecToPri frames as errors - BOOST_AUTO_TEST_CASE(SecToPriNoContext) - { - AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); - - BOOST_REQUIRE(t.IsLogErrorFree()); - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); - - - BOOST_REQUIRE(t.IsLogErrorFree()); - t.link.Nack(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); - - - BOOST_REQUIRE(t.IsLogErrorFree()); - t.link.LinkStatus(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); - - - BOOST_REQUIRE(t.IsLogErrorFree()); - t.link.NotSupported(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); - } - - /// Show that the base state of idle forwards unconfirmed user data - BOOST_AUTO_TEST_CASE(UnconfirmedDataPassedUpFromIdleUnreset) - { - AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); - ByteStr bs(250, 0); - t.link.UnconfirmedUserData(false, 1, 1024, bs, bs.Size()); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE(t.upper.BufferEquals(bs, bs.Size())); - } - - /// Show that the base state of idle forwards unconfirmed user data - BOOST_AUTO_TEST_CASE(ConfirmedDataIgnoredFromIdleUnreset) - { - AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); - ByteStr bs(250, 0); - t.link.ConfirmedUserData(false, false, 1, 1024, bs, bs.Size()); - BOOST_REQUIRE(t.upper.IsBufferEmpty()); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); - } - - /// Secondary Reset Links - BOOST_AUTO_TEST_CASE(SecondaryResetLink) - { - AsyncLinkLayerTest t(AsyncLinkLayerTest::DefaultConfig(), LEV_INTERPRET, true); - t.link.OnLowerLayerUp(); - t.link.ResetLinkStates(false, 1, 1024); - LinkFrame f; f.FormatAck(true, false, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - } - - BOOST_AUTO_TEST_CASE(SecAckWrongFCB) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); - t.link.OnLowerLayerUp(); - t.link.ResetLinkStates(false, 1, 1024); - - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - - ByteStr b(250, 0); - t.link.ConfirmedUserData(false, false, 1, 1024, b, b.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - LinkFrame f; f.FormatAck(true, false, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - BOOST_REQUIRE(t.upper.IsBufferEmpty()); //data should not be passed up! - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_WRONG_FCB_ON_RECEIVE_DATA); - } - - /// When we get another reset links when we're already reset, - /// ACK it and reset the link state - BOOST_AUTO_TEST_CASE(SecondaryResetResetLinkStates) - { - AsyncLinkLayerTest t; - t.link.OnLowerLayerUp(); - t.link.ResetLinkStates(false, 1, 1024); - - t.link.ResetLinkStates(false, 1, 1024); - LinkFrame f; f.FormatAck(true, false, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - } - - BOOST_AUTO_TEST_CASE(SecondaryResetConfirmedUserData) - { - AsyncLinkLayerTest t; - t.link.OnLowerLayerUp(); - t.link.ResetLinkStates(false, 1, 1024); - - ByteStr bytes(250, 0); - t.link.ConfirmedUserData(false, true, 1, 1024, bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - BOOST_REQUIRE(t.upper.BufferEquals(bytes, bytes.Size())); - BOOST_REQUIRE(t.IsLogErrorFree()); - t.upper.ClearBuffer(); - - t.link.ConfirmedUserData(false, true, 1, 1024, bytes, bytes.Size()); //send with wrong FCB - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); //should still get an ACK - BOOST_REQUIRE(t.upper.IsBufferEmpty()); //but no data - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_WRONG_FCB_ON_RECEIVE_DATA); - } - - BOOST_AUTO_TEST_CASE(RequestStatusOfLink) - { - AsyncLinkLayerTest t; - t.link.OnLowerLayerUp(); - t.link.RequestLinkStatus(false, 1, 1024); //should be able to request this before the link is reset - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - LinkFrame f; f.FormatLinkStatus(true, false, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - t.link.ResetLinkStates(false, 1, 1024); - - - t.link.RequestLinkStatus(false, 1, 1024); //should be able to request this before the link is reset - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - } - - BOOST_AUTO_TEST_CASE(TestLinkStates) - { - AsyncLinkLayerTest t; - t.link.OnLowerLayerUp(); - t.link.TestLinkStatus(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); - - t.link.ResetLinkStates(false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - - t.link.TestLinkStatus(false, true, 1, 1024); - LinkFrame f; f.FormatAck(true, false, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - } - - BOOST_AUTO_TEST_CASE(SendUnconfirmed) - { - AsyncLinkLayerTest t; - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - LinkFrame f; f.FormatUnconfirmedUserData(true, 1024, 1, bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mSuccessCnt, 1); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - } - - BOOST_AUTO_TEST_CASE(CloseBehavior) - { - AsyncLinkLayerTest t; - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE(t.upper.CountersEqual(1,0)); - t.link.OnLowerLayerDown(); //take it down during the middle of a send - BOOST_REQUIRE_FALSE(t.upper.IsLowerLayerUp()); - - - t.link.OnLowerLayerUp(); - BOOST_REQUIRE(t.upper.IsLowerLayerUp()); - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - - } - - BOOST_AUTO_TEST_CASE(ResetLinkTimerExpiration) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - LinkFrame f; f.FormatResetLinkStates(true, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - BOOST_REQUIRE(t.upper.CountersEqual(0,0)); - - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE(t.mts.DispatchOne()); //trigger the timeout callback - BOOST_REQUIRE(t.upper.CountersEqual(0,1)); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_NO_RETRY); - } - - BOOST_AUTO_TEST_CASE(ResetLinkTimerExpirationWithRetry) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.NumRetry = 1; - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); - BOOST_REQUIRE(t.upper.CountersEqual(0,0));//check that the send is still occuring - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - LinkFrame f; f.FormatResetLinkStates(true, 1024, 1); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); // check that reset links got sent again - - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); - f.FormatConfirmedUserData(true, true, 1024, 1, bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); // check that reset links got sent again - - BOOST_REQUIRE(t.mts.DispatchOne()); //timeout the ACK - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_NO_RETRY); - BOOST_REQUIRE(t.upper.CountersEqual(0,1)); - - // Test retry reset - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 4); - - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); - BOOST_REQUIRE(t.upper.CountersEqual(0,1));//check that the send is still occuring - } - BOOST_AUTO_TEST_CASE(ResetLinkTimerExpirationWithRetryResetState) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.NumRetry = 1; - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); - t.link.Ack(false, false, 1, 1024); - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE(t.upper.CountersEqual(1,0)); - - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); - - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); - BOOST_REQUIRE(t.upper.CountersEqual(1,0));//check that the send is still occuring - BOOST_REQUIRE_EQUAL(t.mNumSend, 4); - - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE(t.upper.CountersEqual(2,0)); - - // Test retry reset - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 5); // Should now be waiting for an ACK with active timer - - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); - BOOST_REQUIRE(t.upper.CountersEqual(2,0)); //check that the send is still occuring - } - - BOOST_AUTO_TEST_CASE(ConfirmedDataRetry) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.NumRetry = 1; - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); // Should now be waiting for an ACK with active timer - - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - - BOOST_REQUIRE(t.mts.DispatchOne()); //timeout the ConfData, check that it retransmits - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); - LinkFrame f; f.FormatConfirmedUserData(true, true, 1024, 1, bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); - BOOST_REQUIRE(t.upper.CountersEqual(1,0)); - } - - BOOST_AUTO_TEST_CASE(SendDataTimerExpiration) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 1); - t.link.Ack(false, false, 1, 1024); // ACK the reset links - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - LinkFrame f; f.FormatConfirmedUserData(true, true, 1024, 1, bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 2); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); // check that data was sent - BOOST_REQUIRE(t.mts.DispatchOne()); //trigger the timeout callback - BOOST_REQUIRE(t.upper.CountersEqual(0,1)); - } - - BOOST_AUTO_TEST_CASE(SendDataSuccess) - { - LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); - cfg.UseConfirms = true; - - AsyncLinkLayerTest t(cfg); - t.link.OnLowerLayerUp(); - - ByteStr bytes(250, 0); - t.link.Send(bytes, bytes.Size()); // Should now be waiting for an ACK - t.link.Ack(false, false, 1, 1024); //this - - t.link.Ack(false, false, 1, 1024); - BOOST_REQUIRE(t.upper.CountersEqual(1,0)); - - t.link.Send(bytes, bytes.Size()); // now we should be directly sending w/o having to reset, and the FCB should flip - LinkFrame f; f.FormatConfirmedUserData(true, false, 1024, 1, bytes, bytes.Size()); - BOOST_REQUIRE_EQUAL(t.mNumSend, 3); - BOOST_REQUIRE_EQUAL(t.mLastSend, f); - } - -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include +#include +#include + +#include "AsyncLinkLayerTest.h" + +using namespace apl; +using namespace apl::dnp; + +BOOST_AUTO_TEST_SUITE(AsyncLinkLayerSuite) + + /// All operations should fail except for OnLowerLayerUp, just a representative + /// number of them + BOOST_AUTO_TEST_CASE(ClosedState) + { + AsyncLinkLayerTest t; + BOOST_REQUIRE_THROW(t.upper.SendDown("00"), InvalidStateException); + BOOST_REQUIRE_THROW(t.link.OnLowerLayerDown(), InvalidStateException); + BOOST_REQUIRE_THROW(t.link.Ack(false, false, 1, 2), InvalidStateException); + } + + /// Prove that the upper layer is notified when the lower layer comes online + BOOST_AUTO_TEST_CASE(ForwardsOnLowerLayerUp) + { + AsyncLinkLayerTest t; + BOOST_REQUIRE_FALSE(t.upper.IsLowerLayerUp()); + t.link.OnLowerLayerUp(); + BOOST_REQUIRE(t.upper.IsLowerLayerUp()); + } + + /// Check that once the layer comes up, validation errors can occur + BOOST_AUTO_TEST_CASE(ValidatesMasterSlaveBit) + { + AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); + t.link.Ack(true, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_MASTER_BIT_MATCH); + } + + /// Only process frames from your designated remote address + BOOST_AUTO_TEST_CASE(ValidatesSourceAddress) + { + AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); + t.link.Ack(false, false, 1, 1023); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_SOURCE); + } + + /// This should actually never happen when using the AsyncLinkLayerRouter + /// Only process frame addressed to you + BOOST_AUTO_TEST_CASE(ValidatesDestinationAddress) + { + AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); + t.link.Ack(false, false, 2, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_DESTINATION); + } + + /// Show that the base state of idle logs SecToPri frames as errors + BOOST_AUTO_TEST_CASE(SecToPriNoContext) + { + AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); + + BOOST_REQUIRE(t.IsLogErrorFree()); + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); + + + BOOST_REQUIRE(t.IsLogErrorFree()); + t.link.Nack(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); + + + BOOST_REQUIRE(t.IsLogErrorFree()); + t.link.LinkStatus(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); + + + BOOST_REQUIRE(t.IsLogErrorFree()); + t.link.NotSupported(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); + } + + /// Show that the base state of idle forwards unconfirmed user data + BOOST_AUTO_TEST_CASE(UnconfirmedDataPassedUpFromIdleUnreset) + { + AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); + ByteStr bs(250, 0); + t.link.UnconfirmedUserData(false, 1, 1024, bs, bs.Size()); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE(t.upper.BufferEquals(bs, bs.Size())); + } + + /// Show that the base state of idle forwards unconfirmed user data + BOOST_AUTO_TEST_CASE(ConfirmedDataIgnoredFromIdleUnreset) + { + AsyncLinkLayerTest t; t.link.OnLowerLayerUp(); + ByteStr bs(250, 0); + t.link.ConfirmedUserData(false, false, 1, 1024, bs, bs.Size()); + BOOST_REQUIRE(t.upper.IsBufferEmpty()); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); + } + + /// Secondary Reset Links + BOOST_AUTO_TEST_CASE(SecondaryResetLink) + { + AsyncLinkLayerTest t(AsyncLinkLayerTest::DefaultConfig(), LEV_INTERPRET, true); + t.link.OnLowerLayerUp(); + t.link.ResetLinkStates(false, 1, 1024); + LinkFrame f; f.FormatAck(true, false, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + } + + BOOST_AUTO_TEST_CASE(SecAckWrongFCB) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); + t.link.OnLowerLayerUp(); + t.link.ResetLinkStates(false, 1, 1024); + + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + + ByteStr b(250, 0); + t.link.ConfirmedUserData(false, false, 1, 1024, b, b.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + LinkFrame f; f.FormatAck(true, false, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + BOOST_REQUIRE(t.upper.IsBufferEmpty()); //data should not be passed up! + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_WRONG_FCB_ON_RECEIVE_DATA); + } + + /// When we get another reset links when we're already reset, + /// ACK it and reset the link state + BOOST_AUTO_TEST_CASE(SecondaryResetResetLinkStates) + { + AsyncLinkLayerTest t; + t.link.OnLowerLayerUp(); + t.link.ResetLinkStates(false, 1, 1024); + + t.link.ResetLinkStates(false, 1, 1024); + LinkFrame f; f.FormatAck(true, false, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + } + + BOOST_AUTO_TEST_CASE(SecondaryResetConfirmedUserData) + { + AsyncLinkLayerTest t; + t.link.OnLowerLayerUp(); + t.link.ResetLinkStates(false, 1, 1024); + + ByteStr bytes(250, 0); + t.link.ConfirmedUserData(false, true, 1, 1024, bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + BOOST_REQUIRE(t.upper.BufferEquals(bytes, bytes.Size())); + BOOST_REQUIRE(t.IsLogErrorFree()); + t.upper.ClearBuffer(); + + t.link.ConfirmedUserData(false, true, 1, 1024, bytes, bytes.Size()); //send with wrong FCB + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); //should still get an ACK + BOOST_REQUIRE(t.upper.IsBufferEmpty()); //but no data + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_WRONG_FCB_ON_RECEIVE_DATA); + } + + BOOST_AUTO_TEST_CASE(RequestStatusOfLink) + { + AsyncLinkLayerTest t; + t.link.OnLowerLayerUp(); + t.link.RequestLinkStatus(false, 1, 1024); //should be able to request this before the link is reset + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + LinkFrame f; f.FormatLinkStatus(true, false, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + t.link.ResetLinkStates(false, 1, 1024); + + + t.link.RequestLinkStatus(false, 1, 1024); //should be able to request this before the link is reset + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + } + + BOOST_AUTO_TEST_CASE(TestLinkStates) + { + AsyncLinkLayerTest t; + t.link.OnLowerLayerUp(); + t.link.TestLinkStatus(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FRAME); + + t.link.ResetLinkStates(false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + + t.link.TestLinkStatus(false, true, 1, 1024); + LinkFrame f; f.FormatAck(true, false, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + } + + BOOST_AUTO_TEST_CASE(SendUnconfirmed) + { + AsyncLinkLayerTest t; + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + LinkFrame f; f.FormatUnconfirmedUserData(true, 1024, 1, bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mSuccessCnt, 1); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + } + + BOOST_AUTO_TEST_CASE(CloseBehavior) + { + AsyncLinkLayerTest t; + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE(t.upper.CountersEqual(1,0)); + t.link.OnLowerLayerDown(); //take it down during the middle of a send + BOOST_REQUIRE_FALSE(t.upper.IsLowerLayerUp()); + + + t.link.OnLowerLayerUp(); + BOOST_REQUIRE(t.upper.IsLowerLayerUp()); + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + + } + + BOOST_AUTO_TEST_CASE(ResetLinkTimerExpiration) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + LinkFrame f; f.FormatResetLinkStates(true, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + BOOST_REQUIRE(t.upper.CountersEqual(0,0)); + + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE(t.mts.DispatchOne()); //trigger the timeout callback + BOOST_REQUIRE(t.upper.CountersEqual(0,1)); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_NO_RETRY); + } + + BOOST_AUTO_TEST_CASE(ResetLinkTimerExpirationWithRetry) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.NumRetry = 1; + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); + BOOST_REQUIRE(t.upper.CountersEqual(0,0));//check that the send is still occuring + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + LinkFrame f; f.FormatResetLinkStates(true, 1024, 1); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); // check that reset links got sent again + + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); + f.FormatConfirmedUserData(true, true, 1024, 1, bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); // check that reset links got sent again + + BOOST_REQUIRE(t.mts.DispatchOne()); //timeout the ACK + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_NO_RETRY); + BOOST_REQUIRE(t.upper.CountersEqual(0,1)); + + // Test retry reset + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 4); + + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); + BOOST_REQUIRE(t.upper.CountersEqual(0,1));//check that the send is still occuring + } + BOOST_AUTO_TEST_CASE(ResetLinkTimerExpirationWithRetryResetState) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.NumRetry = 1; + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); + t.link.Ack(false, false, 1, 1024); + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE(t.upper.CountersEqual(1,0)); + + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); + + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); + BOOST_REQUIRE(t.upper.CountersEqual(1,0));//check that the send is still occuring + BOOST_REQUIRE_EQUAL(t.mNumSend, 4); + + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE(t.upper.CountersEqual(2,0)); + + // Test retry reset + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 5); // Should now be waiting for an ACK with active timer + + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); + BOOST_REQUIRE(t.upper.CountersEqual(2,0)); //check that the send is still occuring + } + + BOOST_AUTO_TEST_CASE(ConfirmedDataRetry) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.NumRetry = 1; + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); // Should now be waiting for an ACK with active timer + + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + + BOOST_REQUIRE(t.mts.DispatchOne()); //timeout the ConfData, check that it retransmits + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_TIMEOUT_RETRY); + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); + LinkFrame f; f.FormatConfirmedUserData(true, true, 1024, 1, bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); + BOOST_REQUIRE(t.upper.CountersEqual(1,0)); + } + + BOOST_AUTO_TEST_CASE(SendDataTimerExpiration) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 1); + t.link.Ack(false, false, 1, 1024); // ACK the reset links + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + LinkFrame f; f.FormatConfirmedUserData(true, true, 1024, 1, bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 2); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); // check that data was sent + BOOST_REQUIRE(t.mts.DispatchOne()); //trigger the timeout callback + BOOST_REQUIRE(t.upper.CountersEqual(0,1)); + } + + BOOST_AUTO_TEST_CASE(SendDataSuccess) + { + LinkConfig cfg = AsyncLinkLayerTest::DefaultConfig(); + cfg.UseConfirms = true; + + AsyncLinkLayerTest t(cfg); + t.link.OnLowerLayerUp(); + + ByteStr bytes(250, 0); + t.link.Send(bytes, bytes.Size()); // Should now be waiting for an ACK + t.link.Ack(false, false, 1, 1024); //this + + t.link.Ack(false, false, 1, 1024); + BOOST_REQUIRE(t.upper.CountersEqual(1,0)); + + t.link.Send(bytes, bytes.Size()); // now we should be directly sending w/o having to reset, and the FCB should flip + LinkFrame f; f.FormatConfirmedUserData(true, false, 1024, 1, bytes, bytes.Size()); + BOOST_REQUIRE_EQUAL(t.mNumSend, 3); + BOOST_REQUIRE_EQUAL(t.mLastSend, f); + } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncLinkLayerRouter.cpp b/DNP3Test/TestAsyncLinkLayerRouter.cpp index d0e090b2..779500c8 100644 --- a/DNP3Test/TestAsyncLinkLayerRouter.cpp +++ b/DNP3Test/TestAsyncLinkLayerRouter.cpp @@ -16,133 +16,133 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include - -#include "AsyncLinkLayerRouterTest.h" -#include "MockFrameSink.h" - -using namespace apl; -using namespace apl::dnp; - -BOOST_AUTO_TEST_SUITE(AsyncLinkLayerRouterSuite) - - /// Test the open retry behavior - BOOST_AUTO_TEST_CASE(OpenRetryBehavior) { - AsyncLinkLayerRouterTest t; - t.router.Start(); - BOOST_REQUIRE_EQUAL(t.phys.NumOpen(), 1); - BOOST_REQUIRE_EQUAL(t.phys.NumOpenSuccess(), 0); - BOOST_REQUIRE_EQUAL(t.phys.NumOpenFailure(), 0); - t.phys.SignalOpenFailure(); - BOOST_REQUIRE_EQUAL(t.phys.NumOpen(), 1); - BOOST_REQUIRE_EQUAL(t.phys.NumOpenSuccess(), 0); - BOOST_REQUIRE_EQUAL(t.phys.NumOpenFailure(), 1); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.phys.NumOpen(), 2); - BOOST_REQUIRE_EQUAL(t.phys.NumOpenSuccess(), 0); - BOOST_REQUIRE_EQUAL(t.phys.NumOpenFailure(), 1); - } - - /// Test that send frames from unknown sources are rejected - BOOST_AUTO_TEST_CASE(UnknownSourceException) { - AsyncLinkLayerRouterTest t; - LinkFrame f; - f.FormatAck(true, false, 1, 2); - BOOST_REQUIRE_THROW(t.router.Transmit(f), ArgumentException); - } - - /// Test that frames with unknown destinations are correctly logged - BOOST_AUTO_TEST_CASE(UnknownDestination){ - AsyncLinkLayerRouterTest t; - t.router.Start(); - t.phys.SignalOpenSuccess(); - t.phys.TriggerRead("05 64 05 C0 01 00 00 04 E9 21"); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_DESTINATION); - } - - /// Test that the router rejects sends until it is online - BOOST_AUTO_TEST_CASE(LayerNotOnline){ - AsyncLinkLayerRouterTest t; - MockFrameSink mfs; - t.router.AddContext(&mfs, 1024); - LinkFrame f; - f.FormatAck(true, false, 1, 1024); - BOOST_REQUIRE_THROW(t.router.Transmit(f), InvalidStateException); - } - - /// Test that router is correctly clears the send buffer on close - BOOST_AUTO_TEST_CASE(CloseBehavior){ - AsyncLinkLayerRouterTest t; - MockFrameSink mfs; - t.router.AddContext(&mfs, 1024); - t.router.Start(); t.phys.SignalOpenSuccess(); - LinkFrame f; - f.FormatAck(true, false, 1, 1024); - t.router.Transmit(f); // puts the router in the send state - BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 1); - t.phys.AsyncClose(); //we're both reading and writing so this doesn't trigger a callback yet - BOOST_REQUIRE(mfs.mLowerOnline); - t.phys.SignalSendFailure(); - BOOST_REQUIRE(mfs.mLowerOnline); - t.phys.SignalReadFailure(); - - // now the layer should go offline, this should clear the transmitt queue, - // the router should also try to restart - BOOST_REQUIRE_FALSE(mfs.mLowerOnline); - - t.phys.ClearBuffer(); - - t.phys.SignalOpenSuccess(); - - //format another request, but change the to address - LinkFrame f2; f2.FormatAck(true, false, 2, 1024); - t.router.Transmit(f2); - BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); - BOOST_REQUIRE(t.phys.BufferEquals(f2.GetBuffer(), f2.GetSize())); - t.phys.SignalSendSuccess(); - BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); - - - } - - /// Test that the second bind fails when a non-unique address is added - BOOST_AUTO_TEST_CASE(MultiAddressBindError){ - AsyncLinkLayerRouterTest t; - MockFrameSink mfs; - t.router.AddContext(&mfs, 1024); - BOOST_REQUIRE_THROW(t.router.AddContext(&mfs, 1024), ArgumentException); - } - - /// Test that the second bind fails when a non-unique context is added - BOOST_AUTO_TEST_CASE(MultiContextBindError){ - AsyncLinkLayerRouterTest t; - MockFrameSink mfs; - t.router.AddContext(&mfs, 1024); - BOOST_REQUIRE_THROW(t.router.AddContext(&mfs, 2048), ArgumentException); - } - - /// Test that router correctly buffers and sends frames from multiple contexts - BOOST_AUTO_TEST_CASE(MultiContextSend){ - AsyncLinkLayerRouterTest t; - MockFrameSink mfs1; - MockFrameSink mfs2; - t.router.AddContext(&mfs1, 1024); - t.router.AddContext(&mfs2, 2048); - LinkFrame f1; f1.FormatAck(true, false, 1, 1024); - LinkFrame f2; f2.FormatAck(true, false, 1, 2048); - t.router.Start(); t.phys.SignalOpenSuccess(); - t.router.Transmit(f1); - t.router.Transmit(f2); - BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 1); - t.phys.SignalSendSuccess(); - BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); - t.phys.SignalSendSuccess(); - BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); - } - - - -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include + +#include "AsyncLinkLayerRouterTest.h" +#include "MockFrameSink.h" + +using namespace apl; +using namespace apl::dnp; + +BOOST_AUTO_TEST_SUITE(AsyncLinkLayerRouterSuite) + + /// Test the open retry behavior + BOOST_AUTO_TEST_CASE(OpenRetryBehavior) { + AsyncLinkLayerRouterTest t; + t.router.Start(); + BOOST_REQUIRE_EQUAL(t.phys.NumOpen(), 1); + BOOST_REQUIRE_EQUAL(t.phys.NumOpenSuccess(), 0); + BOOST_REQUIRE_EQUAL(t.phys.NumOpenFailure(), 0); + t.phys.SignalOpenFailure(); + BOOST_REQUIRE_EQUAL(t.phys.NumOpen(), 1); + BOOST_REQUIRE_EQUAL(t.phys.NumOpenSuccess(), 0); + BOOST_REQUIRE_EQUAL(t.phys.NumOpenFailure(), 1); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.phys.NumOpen(), 2); + BOOST_REQUIRE_EQUAL(t.phys.NumOpenSuccess(), 0); + BOOST_REQUIRE_EQUAL(t.phys.NumOpenFailure(), 1); + } + + /// Test that send frames from unknown sources are rejected + BOOST_AUTO_TEST_CASE(UnknownSourceException) { + AsyncLinkLayerRouterTest t; + LinkFrame f; + f.FormatAck(true, false, 1, 2); + BOOST_REQUIRE_THROW(t.router.Transmit(f), ArgumentException); + } + + /// Test that frames with unknown destinations are correctly logged + BOOST_AUTO_TEST_CASE(UnknownDestination){ + AsyncLinkLayerRouterTest t; + t.router.Start(); + t.phys.SignalOpenSuccess(); + t.phys.TriggerRead("05 64 05 C0 01 00 00 04 E9 21"); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_DESTINATION); + } + + /// Test that the router rejects sends until it is online + BOOST_AUTO_TEST_CASE(LayerNotOnline){ + AsyncLinkLayerRouterTest t; + MockFrameSink mfs; + t.router.AddContext(&mfs, 1024); + LinkFrame f; + f.FormatAck(true, false, 1, 1024); + BOOST_REQUIRE_THROW(t.router.Transmit(f), InvalidStateException); + } + + /// Test that router is correctly clears the send buffer on close + BOOST_AUTO_TEST_CASE(CloseBehavior){ + AsyncLinkLayerRouterTest t; + MockFrameSink mfs; + t.router.AddContext(&mfs, 1024); + t.router.Start(); t.phys.SignalOpenSuccess(); + LinkFrame f; + f.FormatAck(true, false, 1, 1024); + t.router.Transmit(f); // puts the router in the send state + BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 1); + t.phys.AsyncClose(); //we're both reading and writing so this doesn't trigger a callback yet + BOOST_REQUIRE(mfs.mLowerOnline); + t.phys.SignalSendFailure(); + BOOST_REQUIRE(mfs.mLowerOnline); + t.phys.SignalReadFailure(); + + // now the layer should go offline, this should clear the transmitt queue, + // the router should also try to restart + BOOST_REQUIRE_FALSE(mfs.mLowerOnline); + + t.phys.ClearBuffer(); + + t.phys.SignalOpenSuccess(); + + //format another request, but change the to address + LinkFrame f2; f2.FormatAck(true, false, 2, 1024); + t.router.Transmit(f2); + BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); + BOOST_REQUIRE(t.phys.BufferEquals(f2.GetBuffer(), f2.GetSize())); + t.phys.SignalSendSuccess(); + BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); + + + } + + /// Test that the second bind fails when a non-unique address is added + BOOST_AUTO_TEST_CASE(MultiAddressBindError){ + AsyncLinkLayerRouterTest t; + MockFrameSink mfs; + t.router.AddContext(&mfs, 1024); + BOOST_REQUIRE_THROW(t.router.AddContext(&mfs, 1024), ArgumentException); + } + + /// Test that the second bind fails when a non-unique context is added + BOOST_AUTO_TEST_CASE(MultiContextBindError){ + AsyncLinkLayerRouterTest t; + MockFrameSink mfs; + t.router.AddContext(&mfs, 1024); + BOOST_REQUIRE_THROW(t.router.AddContext(&mfs, 2048), ArgumentException); + } + + /// Test that router correctly buffers and sends frames from multiple contexts + BOOST_AUTO_TEST_CASE(MultiContextSend){ + AsyncLinkLayerRouterTest t; + MockFrameSink mfs1; + MockFrameSink mfs2; + t.router.AddContext(&mfs1, 1024); + t.router.AddContext(&mfs2, 2048); + LinkFrame f1; f1.FormatAck(true, false, 1, 1024); + LinkFrame f2; f2.FormatAck(true, false, 1, 2048); + t.router.Start(); t.phys.SignalOpenSuccess(); + t.router.Transmit(f1); + t.router.Transmit(f2); + BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 1); + t.phys.SignalSendSuccess(); + BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); + t.phys.SignalSendSuccess(); + BOOST_REQUIRE_EQUAL(t.phys.NumWrites(), 2); + } + + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncMaster.cpp b/DNP3Test/TestAsyncMaster.cpp index 4c36ea9a..81d2330c 100644 --- a/DNP3Test/TestAsyncMaster.cpp +++ b/DNP3Test/TestAsyncMaster.cpp @@ -16,549 +16,549 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - - -#include -#include - -#include "AsyncMasterTestObject.h" - -using namespace apl; -using namespace apl::dnp; -using namespace boost; - - - void TestForIntegrityPoll(AsyncMasterTestObject& t) - { - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); - t.RespondToMaster("C0 81 00 00"); - } - - void DoControlSelect(AsyncMasterTestObject& t, CommandResponseQueue& q) - { - TestForIntegrityPoll(t); - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets - - BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; - t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &q); - BOOST_REQUIRE(t.mts.DispatchOne()); - - // Group 12 Var1, 1 byte count/index, index = 1, time on/off = 1000, CS_SUCCESS - std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); - } - - void DoControlSelectOperate(AsyncMasterTestObject& t, CommandResponseQueue& q) - { - TestForIntegrityPoll(t); - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets - - BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; - t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &q); - BOOST_REQUIRE(t.mts.DispatchOne()); - - // Group 12 Var1, 1 byte count/index, index = 1, time on/off = 1000, CS_SUCCESS - std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); // SELECT - t.RespondToMaster("C0 81 00 00 " + crob); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 04 " + crob); // OPERATE - } - - template - void TestSetpointExecution(const std::string& setpointhex, T aValue) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - TestForIntegrityPoll(t); - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets - - Setpoint st(aValue); st.mStatus = CS_SUCCESS; - CommandResponseQueue mRspQueue; - t.master.GetCmdAcceptor()->AcceptCommand(st, 1, 7, &mRspQueue); - BOOST_REQUIRE(t.mts.DispatchOne()); - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + setpointhex); // SELECT - t.RespondToMaster("C0 81 00 00 " + setpointhex); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 04 " + setpointhex); // OPERATE - t.RespondToMaster("C0 81 00 00 " + setpointhex); - - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //nore more packets - - CommandResponse cr; - BOOST_REQUIRE(mRspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_SUCCESS); - } - - BOOST_AUTO_TEST_SUITE(AsyncMasterSuite) - - BOOST_AUTO_TEST_CASE(InitialState) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - - APDU f; - f.Set(FC_RESPONSE); - IINField iin; - f.SetIIN(iin); - - BOOST_REQUIRE_THROW(t.master.OnLowerLayerDown(), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnSolSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnUnsolSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnSolFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnUnsolFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnPartialResponse(f), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnFinalResponse(f), InvalidStateException); - BOOST_REQUIRE_THROW(t.master.OnUnsolResponse(f), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(IntegrityOnStartup) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - TestForIntegrityPoll(t); - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); - } - - BOOST_AUTO_TEST_CASE(UnsolDisableEnableOnStartup) - { - MasterConfig master_cfg; - master_cfg.DoUnsolOnStartup = true; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - // create a generic response packet with no IIN bits set - std::string rsp = "C0 81 00 00"; - - // disable unsol on grp 60 var2, var3, var4 - BOOST_REQUIRE_EQUAL("C0 15 3C 02 06 3C 03 06 3C 04 06", t.Read()); - t.RespondToMaster(rsp); - - TestForIntegrityPoll(t); - - // enable unsol - BOOST_REQUIRE_EQUAL("C0 14 3C 02 06 3C 03 06 3C 04 06", t.Read()); - t.RespondToMaster(rsp); - - // check that the master sends no more packets - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); - } - - BOOST_AUTO_TEST_CASE(RestartAndTimeBits) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch - - BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); ; //integrity - t.RespondToMaster("C0 81 90 00"); // need time and device restart - - // Device restart should happen before time task - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - t.RespondToMaster("C0 81 10 00"); // need time - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); ; //Delay measure - t.fake_time.Advance(100); //advance time by 100ms so that the master sees 100ms for a response - t.RespondToMaster("C0 81 10 00 34 02 07 01 0A 00"); // still need time, 52 Var 2, delay == 10ms - - // Write group 50 var 1 - // 200-100-10/2 = 45 => 45 + 200 - 0xF5 - BOOST_REQUIRE_EQUAL("C0 02 32 01 07 01 F5 00 00 00 00 00", t.Read()); - t.RespondToMaster("C0 81 00 00"); // time bit is now clear - - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // no more packets - } - - BOOST_AUTO_TEST_CASE(RestartFailure) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch - - BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity - t.RespondToMaster("C0 81 90 00"); // need time and device restart - - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - - t.master.OnSolFailure(); - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - } - - BOOST_AUTO_TEST_CASE(RestartLayerDown) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch - - BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity - t.RespondToMaster("C0 81 90 00"); // need time and device restart - - // Device restart should happen before time task - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - - t.master.OnLowerLayerDown(); - t.master.OnLowerLayerUp(); - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - } - - BOOST_AUTO_TEST_CASE(DelayMeasLayerDown) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch - - BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity - t.RespondToMaster("C0 81 90 00"); // need time and device restart - - // Device restart should happen before time task - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - t.RespondToMaster("C0 81 10 00"); // need time - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure - t.master.OnLowerLayerDown(); - t.master.OnLowerLayerUp(); - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure - } - - BOOST_AUTO_TEST_CASE(DelayMeasFailure) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch - - BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity - t.RespondToMaster("C0 81 90 00"); // need time and device restart - - // Device restart should happen before time task - BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN - t.RespondToMaster("C0 81 10 00"); // need time - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure - t.master.OnSolFailure(); - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure - } - - BOOST_AUTO_TEST_CASE(RestartBadResponses) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch - - BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity - t.RespondToMaster("C0 81 10 00"); // need time - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); // Delay measure - t.RespondToMaster("C0 81 10 00"); // no header - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); // retry - t.RespondToMaster("C0 81 10 00 3C 01 06"); // wrong header - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); // retry - t.RespondToMaster("C0 81 10 00 34 02 07 02 0A 00 03 00"); // too many objects - - BOOST_REQUIRE_EQUAL("C0 17", t.Read()); ; //Delay measure - t.fake_time.Advance(100); //advance time by 100ms so that the master sees 100ms for a response - t.RespondToMaster("C0 81 10 00 34 02 07 01 90 01"); // still need time, 52 Var 2, delay == 400ms - - // Write group 50 var 1 - // 400 > 200, so delay is 0 + 200 - BOOST_REQUIRE_EQUAL("C0 02 32 01 07 01 C8 00 00 00 00 00", t.Read()); - t.RespondToMaster("C0 81 00 00"); // time bit is now clear - - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // no more packets - } - - BOOST_AUTO_TEST_CASE(ControlExecutionClosedState) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - - ICommandAcceptor* pAcceptor = t.master.GetCmdAcceptor(); - - BinaryOutput bo(CC_PULSE); - CommandResponseQueue mRspQueue; - pAcceptor->AcceptCommand(bo, 1, 7, &mRspQueue); - BOOST_REQUIRE(t.mts.DispatchOne()); - CommandResponse cr; - BOOST_REQUIRE(mRspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); - } - - BOOST_AUTO_TEST_CASE(ControlExecution) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - TestForIntegrityPoll(t); - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets - - BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; - CommandResponseQueue mRspQueue; - t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &mRspQueue); - BOOST_REQUIRE(t.mts.DispatchOne()); - - // Group 12 Var1, 1 byte count/index, index = 1, time on/off = 1000, CS_SUCCESS - std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); // SELECT - t.RespondToMaster("C0 81 00 00 " + crob); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 04 " + crob); // OPERATE - t.RespondToMaster("C0 81 00 00 " + crob); - - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //nore more packets - - CommandResponse cr; - BOOST_REQUIRE(mRspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_SUCCESS); - } - - BOOST_AUTO_TEST_CASE(ControlExecutionSelectFailure) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - CommandResponseQueue rspQueue; - - DoControlSelect(t, rspQueue); - t.master.OnSolFailure(); - - CommandResponse cr; - BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); - } - - BOOST_AUTO_TEST_CASE(ControlExecutionSelectLayerDown) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - CommandResponseQueue rspQueue; - - DoControlSelect(t, rspQueue); - t.master.OnLowerLayerDown(); - t.master.OnLowerLayerUp(); - - CommandResponse cr; - BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); - } - - BOOST_AUTO_TEST_CASE(ControlExecutionSelectErrorResponse) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - CommandResponseQueue rspQueue; - - DoControlSelect(t, rspQueue); - t.RespondToMaster("C0 81 00 00 0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 04"); // not supported - - CommandResponse cr; - BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_NOT_SUPPORTED); - } - - BOOST_AUTO_TEST_CASE(ControlExecutionSelectPartialResponse) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - CommandResponseQueue rspQueue; - - DoControlSelect(t, rspQueue); - t.RespondToMaster("80 81 00 00 0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00", false); - - CommandResponse cr; - BOOST_REQUIRE_FALSE(rspQueue.WaitForResponse(cr, 7, 0)); - //BOOST_REQUIRE_EQUAL(cr.mResult, CS_NOT_SUPPORTED); - - t.RespondToMaster("C0 81 00 00 0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 04"); // not supported - - BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_NOT_SUPPORTED); - } - - BOOST_AUTO_TEST_CASE(ControlExecutionOperateFailure) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - CommandResponseQueue rspQueue; - - DoControlSelectOperate(t, rspQueue); - t.master.OnSolFailure(); - - CommandResponse cr; - BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); - } - - BOOST_AUTO_TEST_CASE(ControlExecutionOperateLayerDown) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - CommandResponseQueue rspQueue; - - DoControlSelectOperate(t, rspQueue); - t.master.OnLowerLayerDown(); - t.master.OnLowerLayerUp(); - - CommandResponse cr; - BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); - BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); - } - - BOOST_AUTO_TEST_CASE(DeferredControlExecution) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.master.OnLowerLayerUp(); - - // check that a read request was made on startup - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; - - //issue a command while the master is waiting for a response from the slave - BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; - CommandResponseQueue mRspQueue; - t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &mRspQueue); - BOOST_REQUIRE(t.mts.DispatchOne()); - CommandResponse cr; - BOOST_REQUIRE_FALSE(mRspQueue.WaitForResponse(cr, 7, 0)); - - t.RespondToMaster("C0 81 00 00"); //now master gets response to integrity - - - std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; - BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); //select - } - - BOOST_AUTO_TEST_CASE(SingleSetpointExecution)// Group 41 Var4 - { - // 100.0 - TestSetpointExecution("29 03 17 01 01 00 00 C8 42 00", 100.0); - - // 95.6 - TestSetpointExecution("29 03 17 01 01 33 33 BF 42 00", 95.6); - } - - BOOST_AUTO_TEST_CASE(DoubleSetpointExecution) - { - TestSetpointExecution("29 04 17 01 01 00 00 00 E7 FF FF 58 48 00", SingleFloat::Max*100.0); - } - - BOOST_AUTO_TEST_CASE(Int32SetpointExecution) - { - // Group 41 Var1, Int32, 65536 - TestSetpointExecution("29 01 17 01 01 00 00 01 00 00", 65536); - } - - BOOST_AUTO_TEST_CASE(Int16SetpointExecution) - { - // Group 41 Var2, Int16, 100 - TestSetpointExecution("29 02 17 01 01 64 00 00", 100); - } - - BOOST_AUTO_TEST_CASE(SolicitedResponseWithData) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.fake_time.SetTime(TimeStamp_t(0)); - t.master.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; - t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true - - BOOST_REQUIRE(t.fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(0))); - } - - BOOST_AUTO_TEST_CASE(SolicitedResponseFailure) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.fake_time.SetTime(TimeStamp_t(0)); - t.master.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; - t.master.OnSolFailure(); - t.fake_time.Advance(master_cfg.TaskRetryRate); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; - } - - BOOST_AUTO_TEST_CASE(SolicitedResponseLayerDown) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.fake_time.SetTime(TimeStamp_t(0)); - t.master.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; - t.master.OnLowerLayerDown(); - t.master.OnLowerLayerUp(); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; - } - - BOOST_AUTO_TEST_CASE(SolicitedMultiFragResponse) - { - MasterConfig master_cfg; - AsyncMasterTestObject t(master_cfg); - t.fake_time.SetTime(TimeStamp_t(0)); - t.master.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); - - t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81", false); //trigger partial response - BOOST_REQUIRE(t.fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(0))); - - t.RespondToMaster("C0 81 00 00 01 02 00 03 03 02"); - BOOST_REQUIRE(t.fdo.Check(false, BQ_RESTART, 3, TimeStamp_t(0))); - } - - BOOST_AUTO_TEST_CASE(EventPoll) - { - MasterConfig master_cfg; - ExceptionScan scan; - scan.ClassMask = PC_CLASS_1 | PC_CLASS_2; - scan.ScanRate = 10; - master_cfg.mScans.push_back(scan); - scan.ClassMask = PC_CLASS_3; - master_cfg.mScans.push_back(scan); - AsyncMasterTestObject t(master_cfg); - t.fake_time.SetTime(TimeStamp_t(0)); - t.master.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); - t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 02 06 3C 03 06"); - t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true - - BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 04 06"); - t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true - - BOOST_REQUIRE(t.fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(0))); - } - - BOOST_AUTO_TEST_SUITE_END() //end suite - +#include +#include + + +#include +#include + +#include "AsyncMasterTestObject.h" + +using namespace apl; +using namespace apl::dnp; +using namespace boost; + + + void TestForIntegrityPoll(AsyncMasterTestObject& t) + { + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); + t.RespondToMaster("C0 81 00 00"); + } + + void DoControlSelect(AsyncMasterTestObject& t, CommandResponseQueue& q) + { + TestForIntegrityPoll(t); + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets + + BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; + t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &q); + BOOST_REQUIRE(t.mts.DispatchOne()); + + // Group 12 Var1, 1 byte count/index, index = 1, time on/off = 1000, CS_SUCCESS + std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); + } + + void DoControlSelectOperate(AsyncMasterTestObject& t, CommandResponseQueue& q) + { + TestForIntegrityPoll(t); + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets + + BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; + t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &q); + BOOST_REQUIRE(t.mts.DispatchOne()); + + // Group 12 Var1, 1 byte count/index, index = 1, time on/off = 1000, CS_SUCCESS + std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); // SELECT + t.RespondToMaster("C0 81 00 00 " + crob); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 04 " + crob); // OPERATE + } + + template + void TestSetpointExecution(const std::string& setpointhex, T aValue) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + TestForIntegrityPoll(t); + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets + + Setpoint st(aValue); st.mStatus = CS_SUCCESS; + CommandResponseQueue mRspQueue; + t.master.GetCmdAcceptor()->AcceptCommand(st, 1, 7, &mRspQueue); + BOOST_REQUIRE(t.mts.DispatchOne()); + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + setpointhex); // SELECT + t.RespondToMaster("C0 81 00 00 " + setpointhex); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 04 " + setpointhex); // OPERATE + t.RespondToMaster("C0 81 00 00 " + setpointhex); + + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //nore more packets + + CommandResponse cr; + BOOST_REQUIRE(mRspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_SUCCESS); + } + + BOOST_AUTO_TEST_SUITE(AsyncMasterSuite) + + BOOST_AUTO_TEST_CASE(InitialState) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + + APDU f; + f.Set(FC_RESPONSE); + IINField iin; + f.SetIIN(iin); + + BOOST_REQUIRE_THROW(t.master.OnLowerLayerDown(), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnSolSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnUnsolSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnSolFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnUnsolFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnPartialResponse(f), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnFinalResponse(f), InvalidStateException); + BOOST_REQUIRE_THROW(t.master.OnUnsolResponse(f), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(IntegrityOnStartup) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + TestForIntegrityPoll(t); + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); + } + + BOOST_AUTO_TEST_CASE(UnsolDisableEnableOnStartup) + { + MasterConfig master_cfg; + master_cfg.DoUnsolOnStartup = true; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + // create a generic response packet with no IIN bits set + std::string rsp = "C0 81 00 00"; + + // disable unsol on grp 60 var2, var3, var4 + BOOST_REQUIRE_EQUAL("C0 15 3C 02 06 3C 03 06 3C 04 06", t.Read()); + t.RespondToMaster(rsp); + + TestForIntegrityPoll(t); + + // enable unsol + BOOST_REQUIRE_EQUAL("C0 14 3C 02 06 3C 03 06 3C 04 06", t.Read()); + t.RespondToMaster(rsp); + + // check that the master sends no more packets + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); + } + + BOOST_AUTO_TEST_CASE(RestartAndTimeBits) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch + + BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); ; //integrity + t.RespondToMaster("C0 81 90 00"); // need time and device restart + + // Device restart should happen before time task + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + t.RespondToMaster("C0 81 10 00"); // need time + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); ; //Delay measure + t.fake_time.Advance(100); //advance time by 100ms so that the master sees 100ms for a response + t.RespondToMaster("C0 81 10 00 34 02 07 01 0A 00"); // still need time, 52 Var 2, delay == 10ms + + // Write group 50 var 1 + // 200-100-10/2 = 45 => 45 + 200 - 0xF5 + BOOST_REQUIRE_EQUAL("C0 02 32 01 07 01 F5 00 00 00 00 00", t.Read()); + t.RespondToMaster("C0 81 00 00"); // time bit is now clear + + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // no more packets + } + + BOOST_AUTO_TEST_CASE(RestartFailure) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch + + BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity + t.RespondToMaster("C0 81 90 00"); // need time and device restart + + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + + t.master.OnSolFailure(); + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + } + + BOOST_AUTO_TEST_CASE(RestartLayerDown) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch + + BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity + t.RespondToMaster("C0 81 90 00"); // need time and device restart + + // Device restart should happen before time task + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + + t.master.OnLowerLayerDown(); + t.master.OnLowerLayerUp(); + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + } + + BOOST_AUTO_TEST_CASE(DelayMeasLayerDown) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch + + BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity + t.RespondToMaster("C0 81 90 00"); // need time and device restart + + // Device restart should happen before time task + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + t.RespondToMaster("C0 81 10 00"); // need time + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure + t.master.OnLowerLayerDown(); + t.master.OnLowerLayerUp(); + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure + } + + BOOST_AUTO_TEST_CASE(DelayMeasFailure) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch + + BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity + t.RespondToMaster("C0 81 90 00"); // need time and device restart + + // Device restart should happen before time task + BOOST_REQUIRE_EQUAL("C0 02 50 01 00 07 07 00", t.Read()); //write IIN + t.RespondToMaster("C0 81 10 00"); // need time + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure + t.master.OnSolFailure(); + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); //Delay measure + } + + BOOST_AUTO_TEST_CASE(RestartBadResponses) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + t.fake_time.SetTime(TimeStamp_t(100)); //100 ms since epoch + + BOOST_REQUIRE_EQUAL("C0 01 3C 01 06", t.Read()); //integrity + t.RespondToMaster("C0 81 10 00"); // need time + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); // Delay measure + t.RespondToMaster("C0 81 10 00"); // no header + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); // retry + t.RespondToMaster("C0 81 10 00 3C 01 06"); // wrong header + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); // retry + t.RespondToMaster("C0 81 10 00 34 02 07 02 0A 00 03 00"); // too many objects + + BOOST_REQUIRE_EQUAL("C0 17", t.Read()); ; //Delay measure + t.fake_time.Advance(100); //advance time by 100ms so that the master sees 100ms for a response + t.RespondToMaster("C0 81 10 00 34 02 07 01 90 01"); // still need time, 52 Var 2, delay == 400ms + + // Write group 50 var 1 + // 400 > 200, so delay is 0 + 200 + BOOST_REQUIRE_EQUAL("C0 02 32 01 07 01 C8 00 00 00 00 00", t.Read()); + t.RespondToMaster("C0 81 00 00"); // time bit is now clear + + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // no more packets + } + + BOOST_AUTO_TEST_CASE(ControlExecutionClosedState) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + + ICommandAcceptor* pAcceptor = t.master.GetCmdAcceptor(); + + BinaryOutput bo(CC_PULSE); + CommandResponseQueue mRspQueue; + pAcceptor->AcceptCommand(bo, 1, 7, &mRspQueue); + BOOST_REQUIRE(t.mts.DispatchOne()); + CommandResponse cr; + BOOST_REQUIRE(mRspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); + } + + BOOST_AUTO_TEST_CASE(ControlExecution) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + TestForIntegrityPoll(t); + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); // check that the master sends no more packets + + BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; + CommandResponseQueue mRspQueue; + t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &mRspQueue); + BOOST_REQUIRE(t.mts.DispatchOne()); + + // Group 12 Var1, 1 byte count/index, index = 1, time on/off = 1000, CS_SUCCESS + std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); // SELECT + t.RespondToMaster("C0 81 00 00 " + crob); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 04 " + crob); // OPERATE + t.RespondToMaster("C0 81 00 00 " + crob); + + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //nore more packets + + CommandResponse cr; + BOOST_REQUIRE(mRspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_SUCCESS); + } + + BOOST_AUTO_TEST_CASE(ControlExecutionSelectFailure) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + CommandResponseQueue rspQueue; + + DoControlSelect(t, rspQueue); + t.master.OnSolFailure(); + + CommandResponse cr; + BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); + } + + BOOST_AUTO_TEST_CASE(ControlExecutionSelectLayerDown) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + CommandResponseQueue rspQueue; + + DoControlSelect(t, rspQueue); + t.master.OnLowerLayerDown(); + t.master.OnLowerLayerUp(); + + CommandResponse cr; + BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); + } + + BOOST_AUTO_TEST_CASE(ControlExecutionSelectErrorResponse) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + CommandResponseQueue rspQueue; + + DoControlSelect(t, rspQueue); + t.RespondToMaster("C0 81 00 00 0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 04"); // not supported + + CommandResponse cr; + BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_NOT_SUPPORTED); + } + + BOOST_AUTO_TEST_CASE(ControlExecutionSelectPartialResponse) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + CommandResponseQueue rspQueue; + + DoControlSelect(t, rspQueue); + t.RespondToMaster("80 81 00 00 0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00", false); + + CommandResponse cr; + BOOST_REQUIRE_FALSE(rspQueue.WaitForResponse(cr, 7, 0)); + //BOOST_REQUIRE_EQUAL(cr.mResult, CS_NOT_SUPPORTED); + + t.RespondToMaster("C0 81 00 00 0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 04"); // not supported + + BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_NOT_SUPPORTED); + } + + BOOST_AUTO_TEST_CASE(ControlExecutionOperateFailure) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + CommandResponseQueue rspQueue; + + DoControlSelectOperate(t, rspQueue); + t.master.OnSolFailure(); + + CommandResponse cr; + BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); + } + + BOOST_AUTO_TEST_CASE(ControlExecutionOperateLayerDown) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + CommandResponseQueue rspQueue; + + DoControlSelectOperate(t, rspQueue); + t.master.OnLowerLayerDown(); + t.master.OnLowerLayerUp(); + + CommandResponse cr; + BOOST_REQUIRE(rspQueue.WaitForResponse(cr, 7, 0)); + BOOST_REQUIRE_EQUAL(cr.mResult, CS_HARDWARE_ERROR); + } + + BOOST_AUTO_TEST_CASE(DeferredControlExecution) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.master.OnLowerLayerUp(); + + // check that a read request was made on startup + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; + + //issue a command while the master is waiting for a response from the slave + BinaryOutput bo(CC_PULSE); bo.mStatus = CS_SUCCESS; + CommandResponseQueue mRspQueue; + t.master.GetCmdAcceptor()->AcceptCommand(bo, 1, 7, &mRspQueue); + BOOST_REQUIRE(t.mts.DispatchOne()); + CommandResponse cr; + BOOST_REQUIRE_FALSE(mRspQueue.WaitForResponse(cr, 7, 0)); + + t.RespondToMaster("C0 81 00 00"); //now master gets response to integrity + + + std::string crob = "0C 01 17 01 01 01 01 64 00 00 00 64 00 00 00 00"; + BOOST_REQUIRE_EQUAL(t.Read(), "C0 03 " + crob); //select + } + + BOOST_AUTO_TEST_CASE(SingleSetpointExecution)// Group 41 Var4 + { + // 100.0 + TestSetpointExecution("29 03 17 01 01 00 00 C8 42 00", 100.0); + + // 95.6 + TestSetpointExecution("29 03 17 01 01 33 33 BF 42 00", 95.6); + } + + BOOST_AUTO_TEST_CASE(DoubleSetpointExecution) + { + TestSetpointExecution("29 04 17 01 01 00 00 00 E7 FF FF 58 48 00", SingleFloat::Max*100.0); + } + + BOOST_AUTO_TEST_CASE(Int32SetpointExecution) + { + // Group 41 Var1, Int32, 65536 + TestSetpointExecution("29 01 17 01 01 00 00 01 00 00", 65536); + } + + BOOST_AUTO_TEST_CASE(Int16SetpointExecution) + { + // Group 41 Var2, Int16, 100 + TestSetpointExecution("29 02 17 01 01 64 00 00", 100); + } + + BOOST_AUTO_TEST_CASE(SolicitedResponseWithData) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.fake_time.SetTime(TimeStamp_t(0)); + t.master.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; + t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true + + BOOST_REQUIRE(t.fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(0))); + } + + BOOST_AUTO_TEST_CASE(SolicitedResponseFailure) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.fake_time.SetTime(TimeStamp_t(0)); + t.master.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; + t.master.OnSolFailure(); + t.fake_time.Advance(master_cfg.TaskRetryRate); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; + } + + BOOST_AUTO_TEST_CASE(SolicitedResponseLayerDown) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.fake_time.SetTime(TimeStamp_t(0)); + t.master.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; + t.master.OnLowerLayerDown(); + t.master.OnLowerLayerUp(); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); ; + } + + BOOST_AUTO_TEST_CASE(SolicitedMultiFragResponse) + { + MasterConfig master_cfg; + AsyncMasterTestObject t(master_cfg); + t.fake_time.SetTime(TimeStamp_t(0)); + t.master.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); + + t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81", false); //trigger partial response + BOOST_REQUIRE(t.fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(0))); + + t.RespondToMaster("C0 81 00 00 01 02 00 03 03 02"); + BOOST_REQUIRE(t.fdo.Check(false, BQ_RESTART, 3, TimeStamp_t(0))); + } + + BOOST_AUTO_TEST_CASE(EventPoll) + { + MasterConfig master_cfg; + ExceptionScan scan; + scan.ClassMask = PC_CLASS_1 | PC_CLASS_2; + scan.ScanRate = 10; + master_cfg.mScans.push_back(scan); + scan.ClassMask = PC_CLASS_3; + master_cfg.mScans.push_back(scan); + AsyncMasterTestObject t(master_cfg); + t.fake_time.SetTime(TimeStamp_t(0)); + t.master.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 01 06"); + t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 02 06 3C 03 06"); + t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true + + BOOST_REQUIRE_EQUAL(t.Read(), "C0 01 3C 04 06"); + t.RespondToMaster("C0 81 00 00 01 02 00 02 02 81"); //group 2 var 1, index = 2, 0x81 = Online, true + + BOOST_REQUIRE(t.fdo.Check(true, BQ_ONLINE, 2, TimeStamp_t(0))); + } + + BOOST_AUTO_TEST_SUITE_END() //end suite + diff --git a/DNP3Test/TestAsyncSlave.cpp b/DNP3Test/TestAsyncSlave.cpp index 47f1ea91..39f92091 100644 --- a/DNP3Test/TestAsyncSlave.cpp +++ b/DNP3Test/TestAsyncSlave.cpp @@ -16,1282 +16,1282 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include "AsyncSlaveTestObject.h" - -#include -#include -#include -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; -using namespace boost; - - -BOOST_AUTO_TEST_SUITE(AsyncSlaveSuite) - - BOOST_AUTO_TEST_CASE(InitialState) - { - SlaveConfig cfg; - AsyncSlaveTestObject t(cfg); - - APDU f; - - BOOST_REQUIRE_THROW(t.slave.OnLowerLayerDown(), InvalidStateException); - BOOST_REQUIRE_THROW(t.slave.OnSolSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.slave.OnUnsolSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.slave.OnSolFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.slave.OnUnsolFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.slave.OnRequest(f, SequenceInfo()), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(TimersCancledOnClose) - { - SlaveConfig cfg; cfg.mAllowTimeSync = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - t.slave.OnLowerLayerDown(); - - //timer for time - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - } - - BOOST_AUTO_TEST_CASE(DataPost) - { - SlaveConfig cfg; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - - t.db.SetClass(DT_BINARY, PC_CLASS_1); - - IDataObserver* pObs = t.slave.GetDataObserver(); - { - Transaction t(pObs); - Binary b(true, BQ_ONLINE); - pObs->Update(b, 0); - } - - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - } - - BOOST_AUTO_TEST_CASE(DataPostToNonExistent) - { - SlaveConfig cfg; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - - t.db.SetClass(DT_BINARY, PC_CLASS_1); - - IDataObserver* pObs = t.slave.GetDataObserver(); - { - Transaction t(pObs); - Binary b(true, BQ_ONLINE); - pObs->Update(b, 5); - } - - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - - { - Transaction t(pObs); - Binary b(true, BQ_ONLINE); - pObs->Update(b, 0); - } - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); - } - - BOOST_AUTO_TEST_CASE(UnsupportedFunction) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 10"); // func = initialize application (16) - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // IIN = device restart + func not supported - } - - BOOST_AUTO_TEST_CASE(WriteIIN) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 50 01 00 07 07 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 00 00"); - } - - BOOST_AUTO_TEST_CASE(WriteIINEnabled) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 50 01 00 07 07 01"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04"); - } - - BOOST_AUTO_TEST_CASE(WriteIINWrongBit) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 50 01 00 04 04 01"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04"); - } - - BOOST_AUTO_TEST_CASE(WriteNonWriteObject) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 02 01 00 07 07 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); - } - - BOOST_AUTO_TEST_CASE(DelayMeasure) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 17"); //delay measure - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 34 02 07 01 00 00"); // response, Grp51Var2, count 1, value == 00 00 - } - - BOOST_AUTO_TEST_CASE(WriteTimeDate) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - cfg.mAllowTimeSync = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 32 01 07 01 D2 04 00 00 00 00"); //write Grp50Var1, value = 1234 ms after epoch - BOOST_REQUIRE_EQUAL(t.fakeTime.GetTime(), 1234); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); - } - BOOST_AUTO_TEST_CASE(WriteTimeDateNotAsking) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - cfg.mAllowTimeSync = false; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 32 01 07 01 D2 04 00 00 00 00"); //write Grp50Var1, value = 1234 ms after epoch - BOOST_REQUIRE_EQUAL(t.fakeTime.GetTime(), 0); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); - } - BOOST_AUTO_TEST_CASE(WriteTimeDateMultipleObjects) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - cfg.mAllowTimeSync = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 02 32 01 07 02 D2 04 00 00 00 00 D2 04 00 00 00 00"); //write Grp50Var1, value = 1234 ms after epoch - BOOST_REQUIRE_EQUAL(t.fakeTime.GetTime(), 0); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 90 04"); - } - - BOOST_AUTO_TEST_CASE(BlankIntegrityPoll) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 01 3C 01 06"); // Read class 0 - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); - } - - BOOST_AUTO_TEST_CASE(BlankExceptionScan) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 01 3C 02 06"); // Read class 1 - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); - } - - BOOST_AUTO_TEST_CASE(ReadClass0MultiFrag) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - cfg.mMaxFragSize = 20; // override to use a fragment length of 20 - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_ANALOG, 8); - t.slave.OnLowerLayerUp(); - - { - Transaction tr(&t.db); - for(size_t i=0; i<8; i++) t.db.Update(Analog(0,AQ_ONLINE), i); - } - - t.SendToSlave("C0 01 3C 01 06"); // Read class 0 - - // Response should be (30,1)x2 per fragment, quality ONLINE, value 0 - // 4 fragment response, first 3 fragments should be confirmed, last one shouldn't be - BOOST_REQUIRE_EQUAL(t.Read(), "A0 81 80 00 1E 01 00 00 01 01 00 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "20 81 80 00 1E 01 00 02 03 01 00 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "20 81 80 00 1E 01 00 04 05 01 00 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "40 81 80 00 1E 01 00 06 07 01 00 00 00 00 01 00 00 00 00"); - } - - BOOST_AUTO_TEST_CASE(ReadClass1) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - - t.db.Configure(DT_ANALOG, 100); - t.db.SetClass(DT_ANALOG, 23, PC_CLASS_1); - t.db.SetClass(DT_ANALOG, 05, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - { - Transaction tr(&t.db); - t.db.Update(Analog(12345, AQ_ONLINE), 23); - t.db.Update(Analog(2, AQ_ONLINE), 5); - } - - t.SendToSlave("C0 01 3C 02 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "E0 81 80 00 20 01 17 02 05 01 02 00 00 00 17 01 39 30 00 00"); // 12345 in Little endian hex is 39 30 00 00 - - - t.SendToSlave("C0 01 3C 02 06"); // Repeat read class 1 - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); // Buffer should have been cleared - - } - - BOOST_AUTO_TEST_CASE(NullUnsolOnStartup) - { - SlaveConfig cfg; cfg.mAllowTimeSync = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Null UNSOL, FIR, FIN, CON, UNS, w/ restart and need-time IIN - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 90 00"); - } - - BOOST_AUTO_TEST_CASE(UnsolRetryDelay) - { - SlaveConfig cfg; - AsyncSlaveTestObject t(cfg); - t.app.EnableAutoSendCallback(false); //will respond with failure - t.slave.OnLowerLayerUp(); - - // check for the startup null unsol packet, but fail the transaction - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); // this should cause a timer to become active - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - } - - BOOST_AUTO_TEST_CASE(UnsolData) - { - SlaveConfig cfg; - cfg.mUnsolMask.class1 = true; // this allows the EnableUnsol sequence to be skipped - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - - // do a transaction before the layer comes online to prove that the null transaction - // is occuring before unsol data is sent - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); - } - - BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event - - t.slave.OnLowerLayerUp(); - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - - // should immediately try to send another unsol packet, - // Grp2Var1, qual 0x17, count 1, index 0, quality+val == 0x01 - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 01"); - - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no more frags are sent - } - - BOOST_AUTO_TEST_CASE(UnsolMultiFragments) - { - SlaveConfig cfg; - cfg.mMaxFragSize = 10; //this will cause the unsol response to get fragmented - cfg.mUnsolMask.class1 = true; // this allows the EnableUnsol sequence to be skipped - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 2); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - - t.slave.OnLowerLayerUp(); - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no more frags are sent - - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 1); - t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); - } - - BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event - - BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); // unsol pack timer should be active - - BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the unsol pack timer - - // Only enough room to in the APDU to carry a single value - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 01 01"); - // should immediately try to send another unsol packet - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 01"); - } - - // Test that non-read fragments are immediately responded to while waiting for a - // response to unsolicited data - BOOST_AUTO_TEST_CASE(WriteDuringUnsol) - { - SlaveConfig cfg; cfg.mUnsolPackDelay = 0; - cfg.mUnsolMask.class1 = true; //allows us to skip this step - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(true, BQ_ONLINE), 0); - } - - t.app.DisableAutoSendCallback(); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 81"); - - //now send a write IIN request, and test that the slave answers immediately - t.SendToSlave("C0 02 50 01 00 07 07 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 00 00"); - - t.slave.OnUnsolSendSuccess(); - BOOST_REQUIRE_EQUAL(t.Count(), 0); - } - - BOOST_AUTO_TEST_CASE(ReadDuringUnsol) - { - SlaveConfig cfg; cfg.mUnsolPackDelay = 0; - cfg.mUnsolMask.class1 = true; //allows us to skip this step - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(true, BQ_ONLINE), 0); - } - - t.app.DisableAutoSendCallback(); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 81"); - - t.SendToSlave("C0 01 3C 02 06"); - - t.slave.OnUnsolSendSuccess(); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); - } - - BOOST_AUTO_TEST_CASE(ReadWriteDuringUnsol) - { - SlaveConfig cfg; cfg.mUnsolPackDelay = 0; - cfg.mUnsolMask.class1 = true; //allows us to skip this step - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); - - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(true, BQ_ONLINE), 0); - } - - t.app.DisableAutoSendCallback(); - BOOST_REQUIRE(t.mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 81"); - - t.SendToSlave("C0 01 3C 01 06"); - - //now send a write IIN request, and test that the slave answers immediately - t.SendToSlave("C0 02 50 01 00 07 07 00"); - t.slave.OnUnsolSendSuccess(); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 00 00"); - } - - BOOST_AUTO_TEST_CASE(SelectCROB) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED - } - BOOST_AUTO_TEST_CASE(SelectCROBTooMany) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - cfg.mMaxControls = 1; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 4, 4, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 02 03 01 01 01 00 00 00 01 00 00 00 00 04 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 02 03 01 01 01 00 00 00 01 00 00 00 00 04 01 01 01 00 00 00 01 00 00 00 08"); // 0x08 status == CS_TOO_MANY_OPS - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROB) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate - t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBWrongSequence) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate - t.SendToSlave("C2 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffQual) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate (with 0x23 as qual) - t.SendToSlave("C1 04 0C 01 28 01 00 03 00 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 28 01 00 03 00 01 01 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffCode) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate (with control code 02) - t.SendToSlave("C1 04 0C 01 17 01 03 02 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 02 01 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffCount) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate (with control code 02) - t.SendToSlave("C1 04 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffOnTime) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate (with on time as 2 instead of 1) - t.SendToSlave("C1 04 0C 01 17 01 03 01 01 02 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 02 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffOffTime) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate (with off time as 2 instead of 1) - t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 02 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 02 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBRetry) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate - t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - - - // operate - t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_PREV); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - - } - - BOOST_AUTO_TEST_CASE(SelectOperateCROBRetryDifferent) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate - t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); - - - // operate - t.SendToSlave("C1 04 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 00", SI_PREV); // byte changed (count) - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectDirectOperateFails) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, CM_SBO_ONLY, 5000, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 12 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate - t.SendToSlave("C1 05 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED - - } - - BOOST_AUTO_TEST_CASE(SelectGroup41Var1) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 29 01 17 01 03 00 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 01 17 01 03 00 00 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED - } - - BOOST_AUTO_TEST_CASE(SelectGroup41Var1TooMany) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - cfg.mMaxControls = 1; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); - t.cmd_master.BindCommand(CT_SETPOINT, 4, 4, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 29 01 17 02 03 00 00 00 00 00 04 00 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 02 03 00 00 00 00 00 04 00 00 00 00 08"); // 0x08 status == CS_TOO_MANY_OPS - } - - BOOST_AUTO_TEST_CASE(SelectGroup41Var2) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 2, count = 1, index = 3 - t.SendToSlave("C0 03 29 02 17 01 03 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 02 17 01 03 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED - } - - BOOST_AUTO_TEST_CASE(SelectGroup41Var3) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 3, count = 1, index = 1, value = 100.0 - t.SendToSlave("C0 03 29 03 17 01 01 00 00 C8 42 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 03 17 01 01 00 00 C8 42 04"); // 0x04 status == CS_NOT_SUPPORTED - } - - BOOST_AUTO_TEST_CASE(SelectGroup41Var4) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 4, count = 1, index = 1, value = 100.0 - t.SendToSlave("C0 03 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 04 17 01 01 00 00 00 00 00 00 59 40 04"); // 0x04 status == CS_NOT_SUPPORTED - } - - - - BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var1) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 29 01 17 01 03 00 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C1 04 29 01 17 01 03 00 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS - - } - - BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var1DiffVal) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C0 03 29 01 17 01 03 00 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C1 04 29 01 17 01 03 01 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT - - } - - BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var2) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 2, count = 1, index = 3 - t.SendToSlave("C0 03 29 02 17 01 03 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 02 17 01 03 00 00 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C1 04 29 02 17 01 03 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 02 17 01 03 00 00 00"); // 0x00 status == CS_SUCCESS - - } - - BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var3) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 3, count = 1, index = 1 - t.SendToSlave("C0 03 29 03 17 01 01 00 00 C8 42 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 03 17 01 01 00 00 C8 42 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate group 41 Var 3, count = 1, index = 1 - t.SendToSlave("C1 04 29 03 17 01 01 00 00 C8 42 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 03 17 01 01 00 00 C8 42 00"); // 0x00 status == CS_SUCCESS - - - Setpoint s = t.cmd_acceptor.NextSetpoint(); - - BOOST_REQUIRE_FLOAT_EQUAL(100.0, s.GetValue()); - BOOST_REQUIRE_EQUAL(CS_SUCCESS, s.mStatus); - BOOST_REQUIRE_EQUAL(SPET_FLOAT, s.GetEncodingType()); - } - - BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var4) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - // Select group 41 Var 4, count = 1, index = 1 - t.SendToSlave("C0 03 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); // 0x00 status == CS_SUCCESS - - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate group 41 Var 4, count = 1, index = 1 - t.SendToSlave("C1 04 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); // 0x00 status == CS_SUCCESS - - - Setpoint s = t.cmd_acceptor.NextSetpoint(); - - BOOST_REQUIRE_FLOAT_EQUAL(100.0, s.GetValue()); - BOOST_REQUIRE_EQUAL(CS_SUCCESS, s.mStatus); - BOOST_REQUIRE_EQUAL(SPET_DOUBLE, s.GetEncodingType()); - } - - BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var1) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, CM_DO_ONLY, 5000, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C1 05 29 01 17 01 03 00 00 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS - - } - BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var2) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, CM_DO_ONLY, 5000, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // Select group 41 Var 1, count = 1, index = 3 - t.SendToSlave("C1 05 29 02 17 01 03 00 00 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 02 17 01 03 00 00 00"); // 0x00 status == CS_SUCCESS - - } - BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var3) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, CM_DO_ONLY, 5000, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate group 41 Var 3, count = 1, index = 1 - t.SendToSlave("C1 05 29 03 17 01 01 00 00 C8 42 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 03 17 01 01 00 00 C8 42 00"); // 0x00 status == CS_SUCCESS - - } - BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var4) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, CM_DO_ONLY, 5000, &t.cmd_acceptor); - t.slave.OnLowerLayerUp(); - - t.cmd_acceptor.Queue(CS_SUCCESS); - - // operate group 41 Var 4, count = 1, index = 1 - t.SendToSlave("C1 05 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); // 0x00 status == CS_SUCCESS - - } - - BOOST_AUTO_TEST_CASE(SelectBadObject) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Select a binary input - t.SendToSlave("C0 03 02 01 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // 0x04 status == CS_NOT_SUPPORTED - } - - BOOST_AUTO_TEST_CASE(OperateBadObject) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Operate a binary input - t.SendToSlave("C0 04 02 01 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // 0x04 status == CS_NOT_SUPPORTED - } - BOOST_AUTO_TEST_CASE(DirectOperateBadObject) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - // Operate a binary input - t.SendToSlave("C0 05 02 01 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // 0x04 status == CS_NOT_SUPPORTED - } - - BOOST_AUTO_TEST_CASE(UnsolEnable) - { - SlaveConfig cfg; cfg.mUnsolPackDelay = 0; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); //Null UNSOL - - // do a transaction to show that unsol data is not being reported yet - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); - } - - BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no unsol packets are generated - - t.SendToSlave("C0 14 3C 02 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); - - // should automatically send the previous data as unsol - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 01"); - } - - BOOST_AUTO_TEST_CASE(UnsolEnableBadObject) - { - SlaveConfig cfg; cfg.mUnsolPackDelay = 0; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); //Null UNSOL - - // do a transaction to show that unsol data is not being reported yet - { - Transaction tr(t.slave.GetDataObserver()); - t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); - } - - BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event - BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no unsol packets are generated - - t.SendToSlave("C0 14 01 02 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); - } - - BOOST_AUTO_TEST_CASE(UnsolEnableDisableFailure) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 14 3C 02 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); //FUNC_NOT_SUPPORTED - } - - BOOST_AUTO_TEST_CASE(ReadFuncNotSupported) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 01 0C 01 06"); //try to read 12/1 (control block) - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); //restart/func not supported - } - - void TestStaticRead(const std::string& arRequest, const std::string& arResponse) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.Configure(DT_ANALOG, 1); - t.db.Configure(DT_COUNTER, 1); - t.db.Configure(DT_CONTROL_STATUS, 1); - t.db.Configure(DT_SETPOINT_STATUS, 1); - t.slave.OnLowerLayerUp(); - - t.SendToSlave(arRequest); - BOOST_REQUIRE_EQUAL(t.Read(), arResponse); - } - - /* ---- Static data reads ----- */ - - - /*BOOST_AUTO_TEST_CASE(ReadGrp1Var1) - { - SlaveConfig cfg; cfg.mStaticBinary = GrpVar(1,1); - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 9); - t.slave.OnLowerLayerUp(); - - t.SendToSlave("C0 01 01 01 06"); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 01 01 00 00 00 00 00"); // 1 byte start/stop, 2 bytes for bitfield with 9 members - }*/ - - BOOST_AUTO_TEST_CASE(ReadGrp1Var0) - { - TestStaticRead("C0 01 01 00 06", "C0 81 80 00 01 02 00 00 00 02"); // 1 byte start/stop, RESTART quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp10Var0) - { - TestStaticRead("C0 01 0A 00 06", "C0 81 80 00 0A 02 00 00 00 02"); // 1 byte start/stop, RESTART quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp20Var0) - { - TestStaticRead("C0 01 14 00 06", "C0 81 80 00 14 01 00 00 00 02 00 00 00 00"); // 1 byte start/stop, RESTART quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp30Var0) - { - TestStaticRead("C0 01 1E 00 06", "C0 81 80 00 1E 01 00 00 00 02 00 00 00 00"); // 1 byte start/stop, RESTART quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp40Var0) - { - TestStaticRead("C0 01 28 00 06", "C0 81 80 00 28 01 00 00 00 02 00 00 00 00"); // 1 byte start/stop, RESTART quality - } - - // test that asking for a specific data type returns the requested type - void TestEventRead(const std::string& arRequest, const std::string& arResponse) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, 1); - t.db.Configure(DT_ANALOG, 1); - t.db.Configure(DT_COUNTER, 1); - t.db.Configure(DT_CONTROL_STATUS, 1); - t.db.Configure(DT_SETPOINT_STATUS, 1); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.db.SetClass(DT_ANALOG, PC_CLASS_1); - t.db.SetClass(DT_COUNTER, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - - { - Transaction tr(&t.db); - t.db.Update(Binary(false, BQ_ONLINE), 0); - t.db.Update(Counter(0, CQ_ONLINE), 0); - t.db.Update(Analog(0.0, AQ_ONLINE), 0); - t.db.Update(ControlStatus(false, TQ_ONLINE), 0); - t.db.Update(SetpointStatus(0.0, PQ_ONLINE), 0); - } - - t.SendToSlave(arRequest); - BOOST_REQUIRE_EQUAL(t.Read(), arResponse); - } - - BOOST_AUTO_TEST_CASE(ReadGrp2Var0) - { - TestEventRead("C0 01 02 00 06", "E0 81 80 00 02 01 17 01 00 01"); // 1 byte count == 1, ONLINE quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp22Var0) - { - TestEventRead("C0 01 16 00 06", "E0 81 80 00 16 01 17 01 00 01 00 00 00 00"); // 1 byte count == 1, ONLINE quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp32Var0) - { - TestEventRead("C0 01 20 00 06", "E0 81 80 00 20 01 17 01 00 01 00 00 00 00"); // 1 byte count == 1, ONLINE quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp2Var1) - { - TestEventRead("C0 01 02 01 06", "E0 81 80 00 02 01 17 01 00 01"); // 1 byte count == 1, ONLINE quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp2Var2) - { - TestEventRead("C0 01 02 02 06", "E0 81 80 00 02 02 17 01 00 01 00 00 00 00 00 00"); // 1 byte count == 1, ONLINE quality - } - - BOOST_AUTO_TEST_CASE(ReadGrp2Var3) - { - TestEventRead("C0 01 02 03 06", "E0 81 80 00 33 01 07 01 00 00 00 00 00 00 02 03 17 01 00 01 00 00"); // 1 byte count == 1, ONLINE quality - } - - BOOST_AUTO_TEST_CASE(InvalidObject) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.slave.OnLowerLayerUp(); - - t.slave.OnUnknownObject(); - BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 02"); - } - - - BOOST_AUTO_TEST_CASE(ComplexReadSequence) - { - const size_t NUM = 4; - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_BINARY, NUM); - t.db.SetClass(DT_BINARY, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - { - Transaction tr(&t.db); - for(size_t i=0; i - void TestStaticType(apl::dnp::SlaveConfig& aCfg, apl::dnp::GrpVar& aGrpVar, int aGroup, int aVar, T aVal, const std::string& aRsp) - { - aGrpVar = GrpVar(aGroup,aVar); - AsyncSlaveTestObject t(aCfg); - t.db.Configure(PointType::MeasEnum, 1); - t.db.SetClass(PointType::MeasEnum, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - { - Transaction tr(&t.db); - t.db.Update(PointType(aVal, PointType::ONLINE), 0); - } - - t.SendToSlave("C0 01 3C 01 06"); // Read class 0 - BOOST_REQUIRE_EQUAL(t.Read(), aRsp); - } - - template - void TestStaticCounter(int aVar, T aVal, const std::string& aRsp) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - TestStaticType(cfg, cfg.mStaticCounter, 20, aVar, aVal, aRsp); - } - - BOOST_AUTO_TEST_CASE(ReadGrp20Var1) - { - TestStaticCounter(1, 5, "C0 81 80 00 14 01 00 00 00 01 05 00 00 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp20Var2) - { - TestStaticCounter(2, 5, "C0 81 80 00 14 02 00 00 00 01 05 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp20Var5) - { - TestStaticCounter(5, 5, "C0 81 80 00 14 05 00 00 00 05 00 00 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp20Var6) - { - TestStaticCounter(6, 5, "C0 81 80 00 14 06 00 00 00 05 00"); - } - - template - void TestStaticAnalog(int aVar, T aVal, const std::string& aRsp) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - TestStaticType(cfg, cfg.mStaticAnalog, 30, aVar, aVal, aRsp); - } - - BOOST_AUTO_TEST_CASE(ReadGrp30Var2) - { - TestStaticAnalog(2, 100, "C0 81 80 00 1E 02 00 00 00 01 64 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp30Var3) - { - TestStaticAnalog(3, 65536, "C0 81 80 00 1E 03 00 00 00 00 00 01 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp30Var4) - { - TestStaticAnalog(4, 100, "C0 81 80 00 1E 04 00 00 00 64 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp30Var5) - { - TestStaticAnalog(5, 95.6, "C0 81 80 00 1E 05 00 00 00 01 33 33 BF 42"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp30Var6) - { - TestStaticAnalog(6, -20, "C0 81 80 00 1E 06 00 00 00 01 00 00 00 00 00 00 34 C0"); - } - - template - void TestStaticControlStatus(int aVar, T aVal, const std::string& aRsp) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - AsyncSlaveTestObject t(cfg); - t.db.Configure(DT_CONTROL_STATUS, 1); - t.db.SetClass(DT_CONTROL_STATUS, PC_CLASS_1); - t.slave.OnLowerLayerUp(); - - { - Transaction tr(&t.db); - t.db.Update(ControlStatus(aVal, TQ_ONLINE), 0); - } - - t.SendToSlave("C0 01 3C 01 06"); // Read class 0 - BOOST_REQUIRE_EQUAL(t.Read(), aRsp); - } - - BOOST_AUTO_TEST_CASE(ReadGrp10Var2) - { - TestStaticControlStatus(2, true, "C0 81 80 00 0A 02 00 00 00 81"); - } - - - template - void TestStaticSetpointStatus(int aVar, T aVal, const string& aRsp) - { - SlaveConfig cfg; cfg.mDisableUnsol = true; - TestStaticType(cfg, cfg.mStaticSetpointStatus, 40, aVar, aVal, aRsp); - } - - BOOST_AUTO_TEST_CASE(ReadGrp40Var1) - { - TestStaticSetpointStatus(1, 100, "C0 81 80 00 28 01 00 00 00 01 64 00 00 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp40Var2) - { - TestStaticSetpointStatus(2, 100, "C0 81 80 00 28 02 00 00 00 01 64 00"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp40Var3) - { - TestStaticSetpointStatus(3, 95.6, "C0 81 80 00 28 03 00 00 00 01 33 33 BF 42"); - } - - BOOST_AUTO_TEST_CASE(ReadGrp40Var4) - { - TestStaticSetpointStatus(4, -20.0, "C0 81 80 00 28 04 00 00 00 01 00 00 00 00 00 00 34 C0"); - } - - -BOOST_AUTO_TEST_SUITE_END() - +#include +#include + +#include "AsyncSlaveTestObject.h" + +#include +#include +#include +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; +using namespace boost; + + +BOOST_AUTO_TEST_SUITE(AsyncSlaveSuite) + + BOOST_AUTO_TEST_CASE(InitialState) + { + SlaveConfig cfg; + AsyncSlaveTestObject t(cfg); + + APDU f; + + BOOST_REQUIRE_THROW(t.slave.OnLowerLayerDown(), InvalidStateException); + BOOST_REQUIRE_THROW(t.slave.OnSolSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.slave.OnUnsolSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.slave.OnSolFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.slave.OnUnsolFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.slave.OnRequest(f, SequenceInfo()), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(TimersCancledOnClose) + { + SlaveConfig cfg; cfg.mAllowTimeSync = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + t.slave.OnLowerLayerDown(); + + //timer for time + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + } + + BOOST_AUTO_TEST_CASE(DataPost) + { + SlaveConfig cfg; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + + t.db.SetClass(DT_BINARY, PC_CLASS_1); + + IDataObserver* pObs = t.slave.GetDataObserver(); + { + Transaction t(pObs); + Binary b(true, BQ_ONLINE); + pObs->Update(b, 0); + } + + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + } + + BOOST_AUTO_TEST_CASE(DataPostToNonExistent) + { + SlaveConfig cfg; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + + t.db.SetClass(DT_BINARY, PC_CLASS_1); + + IDataObserver* pObs = t.slave.GetDataObserver(); + { + Transaction t(pObs); + Binary b(true, BQ_ONLINE); + pObs->Update(b, 5); + } + + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + + { + Transaction t(pObs); + Binary b(true, BQ_ONLINE); + pObs->Update(b, 0); + } + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 0); + } + + BOOST_AUTO_TEST_CASE(UnsupportedFunction) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 10"); // func = initialize application (16) + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // IIN = device restart + func not supported + } + + BOOST_AUTO_TEST_CASE(WriteIIN) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 50 01 00 07 07 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 00 00"); + } + + BOOST_AUTO_TEST_CASE(WriteIINEnabled) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 50 01 00 07 07 01"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04"); + } + + BOOST_AUTO_TEST_CASE(WriteIINWrongBit) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 50 01 00 04 04 01"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04"); + } + + BOOST_AUTO_TEST_CASE(WriteNonWriteObject) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 02 01 00 07 07 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); + } + + BOOST_AUTO_TEST_CASE(DelayMeasure) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 17"); //delay measure + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 34 02 07 01 00 00"); // response, Grp51Var2, count 1, value == 00 00 + } + + BOOST_AUTO_TEST_CASE(WriteTimeDate) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + cfg.mAllowTimeSync = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 32 01 07 01 D2 04 00 00 00 00"); //write Grp50Var1, value = 1234 ms after epoch + BOOST_REQUIRE_EQUAL(t.fakeTime.GetTime(), 1234); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); + } + BOOST_AUTO_TEST_CASE(WriteTimeDateNotAsking) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + cfg.mAllowTimeSync = false; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 32 01 07 01 D2 04 00 00 00 00"); //write Grp50Var1, value = 1234 ms after epoch + BOOST_REQUIRE_EQUAL(t.fakeTime.GetTime(), 0); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); + } + BOOST_AUTO_TEST_CASE(WriteTimeDateMultipleObjects) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + cfg.mAllowTimeSync = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 02 32 01 07 02 D2 04 00 00 00 00 D2 04 00 00 00 00"); //write Grp50Var1, value = 1234 ms after epoch + BOOST_REQUIRE_EQUAL(t.fakeTime.GetTime(), 0); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 90 04"); + } + + BOOST_AUTO_TEST_CASE(BlankIntegrityPoll) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 01 3C 01 06"); // Read class 0 + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); + } + + BOOST_AUTO_TEST_CASE(BlankExceptionScan) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 01 3C 02 06"); // Read class 1 + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); + } + + BOOST_AUTO_TEST_CASE(ReadClass0MultiFrag) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + cfg.mMaxFragSize = 20; // override to use a fragment length of 20 + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_ANALOG, 8); + t.slave.OnLowerLayerUp(); + + { + Transaction tr(&t.db); + for(size_t i=0; i<8; i++) t.db.Update(Analog(0,AQ_ONLINE), i); + } + + t.SendToSlave("C0 01 3C 01 06"); // Read class 0 + + // Response should be (30,1)x2 per fragment, quality ONLINE, value 0 + // 4 fragment response, first 3 fragments should be confirmed, last one shouldn't be + BOOST_REQUIRE_EQUAL(t.Read(), "A0 81 80 00 1E 01 00 00 01 01 00 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "20 81 80 00 1E 01 00 02 03 01 00 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "20 81 80 00 1E 01 00 04 05 01 00 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "40 81 80 00 1E 01 00 06 07 01 00 00 00 00 01 00 00 00 00"); + } + + BOOST_AUTO_TEST_CASE(ReadClass1) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + + t.db.Configure(DT_ANALOG, 100); + t.db.SetClass(DT_ANALOG, 23, PC_CLASS_1); + t.db.SetClass(DT_ANALOG, 05, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + { + Transaction tr(&t.db); + t.db.Update(Analog(12345, AQ_ONLINE), 23); + t.db.Update(Analog(2, AQ_ONLINE), 5); + } + + t.SendToSlave("C0 01 3C 02 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "E0 81 80 00 20 01 17 02 05 01 02 00 00 00 17 01 39 30 00 00"); // 12345 in Little endian hex is 39 30 00 00 + + + t.SendToSlave("C0 01 3C 02 06"); // Repeat read class 1 + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); // Buffer should have been cleared + + } + + BOOST_AUTO_TEST_CASE(NullUnsolOnStartup) + { + SlaveConfig cfg; cfg.mAllowTimeSync = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Null UNSOL, FIR, FIN, CON, UNS, w/ restart and need-time IIN + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 90 00"); + } + + BOOST_AUTO_TEST_CASE(UnsolRetryDelay) + { + SlaveConfig cfg; + AsyncSlaveTestObject t(cfg); + t.app.EnableAutoSendCallback(false); //will respond with failure + t.slave.OnLowerLayerUp(); + + // check for the startup null unsol packet, but fail the transaction + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); // this should cause a timer to become active + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + } + + BOOST_AUTO_TEST_CASE(UnsolData) + { + SlaveConfig cfg; + cfg.mUnsolMask.class1 = true; // this allows the EnableUnsol sequence to be skipped + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + + // do a transaction before the layer comes online to prove that the null transaction + // is occuring before unsol data is sent + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); + } + + BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event + + t.slave.OnLowerLayerUp(); + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + + // should immediately try to send another unsol packet, + // Grp2Var1, qual 0x17, count 1, index 0, quality+val == 0x01 + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 01"); + + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no more frags are sent + } + + BOOST_AUTO_TEST_CASE(UnsolMultiFragments) + { + SlaveConfig cfg; + cfg.mMaxFragSize = 10; //this will cause the unsol response to get fragmented + cfg.mUnsolMask.class1 = true; // this allows the EnableUnsol sequence to be skipped + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 2); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + + t.slave.OnLowerLayerUp(); + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no more frags are sent + + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 1); + t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); + } + + BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event + + BOOST_REQUIRE_EQUAL(t.mts.NumActive(), 1); // unsol pack timer should be active + + BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the unsol pack timer + + // Only enough room to in the APDU to carry a single value + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 01 01"); + // should immediately try to send another unsol packet + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 01"); + } + + // Test that non-read fragments are immediately responded to while waiting for a + // response to unsolicited data + BOOST_AUTO_TEST_CASE(WriteDuringUnsol) + { + SlaveConfig cfg; cfg.mUnsolPackDelay = 0; + cfg.mUnsolMask.class1 = true; //allows us to skip this step + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(true, BQ_ONLINE), 0); + } + + t.app.DisableAutoSendCallback(); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 81"); + + //now send a write IIN request, and test that the slave answers immediately + t.SendToSlave("C0 02 50 01 00 07 07 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 00 00"); + + t.slave.OnUnsolSendSuccess(); + BOOST_REQUIRE_EQUAL(t.Count(), 0); + } + + BOOST_AUTO_TEST_CASE(ReadDuringUnsol) + { + SlaveConfig cfg; cfg.mUnsolPackDelay = 0; + cfg.mUnsolMask.class1 = true; //allows us to skip this step + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(true, BQ_ONLINE), 0); + } + + t.app.DisableAutoSendCallback(); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 81"); + + t.SendToSlave("C0 01 3C 02 06"); + + t.slave.OnUnsolSendSuccess(); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); + } + + BOOST_AUTO_TEST_CASE(ReadWriteDuringUnsol) + { + SlaveConfig cfg; cfg.mUnsolPackDelay = 0; + cfg.mUnsolMask.class1 = true; //allows us to skip this step + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); + + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(true, BQ_ONLINE), 0); + } + + t.app.DisableAutoSendCallback(); + BOOST_REQUIRE(t.mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 81"); + + t.SendToSlave("C0 01 3C 01 06"); + + //now send a write IIN request, and test that the slave answers immediately + t.SendToSlave("C0 02 50 01 00 07 07 00"); + t.slave.OnUnsolSendSuccess(); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 00 00"); + } + + BOOST_AUTO_TEST_CASE(SelectCROB) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED + } + BOOST_AUTO_TEST_CASE(SelectCROBTooMany) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + cfg.mMaxControls = 1; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 4, 4, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 02 03 01 01 01 00 00 00 01 00 00 00 00 04 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 02 03 01 01 01 00 00 00 01 00 00 00 00 04 01 01 01 00 00 00 01 00 00 00 08"); // 0x08 status == CS_TOO_MANY_OPS + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROB) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate + t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBWrongSequence) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate + t.SendToSlave("C2 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffQual) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate (with 0x23 as qual) + t.SendToSlave("C1 04 0C 01 28 01 00 03 00 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 28 01 00 03 00 01 01 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffCode) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate (with control code 02) + t.SendToSlave("C1 04 0C 01 17 01 03 02 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 02 01 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffCount) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate (with control code 02) + t.SendToSlave("C1 04 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffOnTime) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate (with on time as 2 instead of 1) + t.SendToSlave("C1 04 0C 01 17 01 03 01 01 02 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 02 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBDiffOffTime) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate (with off time as 2 instead of 1) + t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 02 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 02 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBRetry) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate + t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + + + // operate + t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_PREV); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + + } + + BOOST_AUTO_TEST_CASE(SelectOperateCROBRetryDifferent) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate + t.SendToSlave("C1 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); + + + // operate + t.SendToSlave("C1 04 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 00", SI_PREV); // byte changed (count) + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 02 01 00 00 00 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectDirectOperateFails) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_BINARY_OUTPUT, 3, 3, CM_SBO_ONLY, 5000, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 12 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_OTHER); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate + t.SendToSlave("C1 05 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 00", SI_CORRECT); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 0C 01 17 01 03 01 01 01 00 00 00 01 00 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED + + } + + BOOST_AUTO_TEST_CASE(SelectGroup41Var1) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 29 01 17 01 03 00 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 01 17 01 03 00 00 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED + } + + BOOST_AUTO_TEST_CASE(SelectGroup41Var1TooMany) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + cfg.mMaxControls = 1; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); + t.cmd_master.BindCommand(CT_SETPOINT, 4, 4, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 29 01 17 02 03 00 00 00 00 00 04 00 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 02 03 00 00 00 00 00 04 00 00 00 00 08"); // 0x08 status == CS_TOO_MANY_OPS + } + + BOOST_AUTO_TEST_CASE(SelectGroup41Var2) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 2, count = 1, index = 3 + t.SendToSlave("C0 03 29 02 17 01 03 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 02 17 01 03 00 00 04"); // 0x04 status == CS_NOT_SUPPORTED + } + + BOOST_AUTO_TEST_CASE(SelectGroup41Var3) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 3, count = 1, index = 1, value = 100.0 + t.SendToSlave("C0 03 29 03 17 01 01 00 00 C8 42 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 03 17 01 01 00 00 C8 42 04"); // 0x04 status == CS_NOT_SUPPORTED + } + + BOOST_AUTO_TEST_CASE(SelectGroup41Var4) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 4, count = 1, index = 1, value = 100.0 + t.SendToSlave("C0 03 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 04 29 04 17 01 01 00 00 00 00 00 00 59 40 04"); // 0x04 status == CS_NOT_SUPPORTED + } + + + + BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var1) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 29 01 17 01 03 00 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C1 04 29 01 17 01 03 00 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS + + } + + BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var1DiffVal) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C0 03 29 01 17 01 03 00 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C1 04 29 01 17 01 03 01 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 01 00 00 00 02"); // 0x02 status == CS_NO_SELECT + + } + + BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var2) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 2, count = 1, index = 3 + t.SendToSlave("C0 03 29 02 17 01 03 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 02 17 01 03 00 00 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C1 04 29 02 17 01 03 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 02 17 01 03 00 00 00"); // 0x00 status == CS_SUCCESS + + } + + BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var3) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 3, count = 1, index = 1 + t.SendToSlave("C0 03 29 03 17 01 01 00 00 C8 42 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 03 17 01 01 00 00 C8 42 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate group 41 Var 3, count = 1, index = 1 + t.SendToSlave("C1 04 29 03 17 01 01 00 00 C8 42 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 03 17 01 01 00 00 C8 42 00"); // 0x00 status == CS_SUCCESS + + + Setpoint s = t.cmd_acceptor.NextSetpoint(); + + BOOST_REQUIRE_FLOAT_EQUAL(100.0, s.GetValue()); + BOOST_REQUIRE_EQUAL(CS_SUCCESS, s.mStatus); + BOOST_REQUIRE_EQUAL(SPET_FLOAT, s.GetEncodingType()); + } + + BOOST_AUTO_TEST_CASE(SelectOperateGroup41Var4) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + // Select group 41 Var 4, count = 1, index = 1 + t.SendToSlave("C0 03 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); // 0x00 status == CS_SUCCESS + + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate group 41 Var 4, count = 1, index = 1 + t.SendToSlave("C1 04 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); // 0x00 status == CS_SUCCESS + + + Setpoint s = t.cmd_acceptor.NextSetpoint(); + + BOOST_REQUIRE_FLOAT_EQUAL(100.0, s.GetValue()); + BOOST_REQUIRE_EQUAL(CS_SUCCESS, s.mStatus); + BOOST_REQUIRE_EQUAL(SPET_DOUBLE, s.GetEncodingType()); + } + + BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var1) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, CM_DO_ONLY, 5000, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C1 05 29 01 17 01 03 00 00 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 01 17 01 03 00 00 00 00 00"); // 0x00 status == CS_SUCCESS + + } + BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var2) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 3, 3, CM_DO_ONLY, 5000, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // Select group 41 Var 1, count = 1, index = 3 + t.SendToSlave("C1 05 29 02 17 01 03 00 00 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 02 17 01 03 00 00 00"); // 0x00 status == CS_SUCCESS + + } + BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var3) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, CM_DO_ONLY, 5000, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate group 41 Var 3, count = 1, index = 1 + t.SendToSlave("C1 05 29 03 17 01 01 00 00 C8 42 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 03 17 01 01 00 00 C8 42 00"); // 0x00 status == CS_SUCCESS + + } + BOOST_AUTO_TEST_CASE(DirectOperateGroup41Var4) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.cmd_master.BindCommand(CT_SETPOINT, 1, 1, CM_DO_ONLY, 5000, &t.cmd_acceptor); + t.slave.OnLowerLayerUp(); + + t.cmd_acceptor.Queue(CS_SUCCESS); + + // operate group 41 Var 4, count = 1, index = 1 + t.SendToSlave("C1 05 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 29 04 17 01 01 00 00 00 00 00 00 59 40 00"); // 0x00 status == CS_SUCCESS + + } + + BOOST_AUTO_TEST_CASE(SelectBadObject) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Select a binary input + t.SendToSlave("C0 03 02 01 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // 0x04 status == CS_NOT_SUPPORTED + } + + BOOST_AUTO_TEST_CASE(OperateBadObject) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Operate a binary input + t.SendToSlave("C0 04 02 01 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // 0x04 status == CS_NOT_SUPPORTED + } + BOOST_AUTO_TEST_CASE(DirectOperateBadObject) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + // Operate a binary input + t.SendToSlave("C0 05 02 01 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); // 0x04 status == CS_NOT_SUPPORTED + } + + BOOST_AUTO_TEST_CASE(UnsolEnable) + { + SlaveConfig cfg; cfg.mUnsolPackDelay = 0; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); //Null UNSOL + + // do a transaction to show that unsol data is not being reported yet + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); + } + + BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no unsol packets are generated + + t.SendToSlave("C0 14 3C 02 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00"); + + // should automatically send the previous data as unsol + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00 02 01 17 01 00 01"); + } + + BOOST_AUTO_TEST_CASE(UnsolEnableBadObject) + { + SlaveConfig cfg; cfg.mUnsolPackDelay = 0; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + BOOST_REQUIRE_EQUAL(t.Read(), "F0 82 80 00"); //Null UNSOL + + // do a transaction to show that unsol data is not being reported yet + { + Transaction tr(t.slave.GetDataObserver()); + t.slave.GetDataObserver()->Update(Binary(false, BQ_ONLINE), 0); + } + + BOOST_REQUIRE(t.mts.DispatchOne()); //dispatch the data update event + BOOST_REQUIRE_EQUAL(t.app.NumAPDU(), 0); //check that no unsol packets are generated + + t.SendToSlave("C0 14 01 02 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); + } + + BOOST_AUTO_TEST_CASE(UnsolEnableDisableFailure) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 14 3C 02 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); //FUNC_NOT_SUPPORTED + } + + BOOST_AUTO_TEST_CASE(ReadFuncNotSupported) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 01 0C 01 06"); //try to read 12/1 (control block) + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 01"); //restart/func not supported + } + + void TestStaticRead(const std::string& arRequest, const std::string& arResponse) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.Configure(DT_ANALOG, 1); + t.db.Configure(DT_COUNTER, 1); + t.db.Configure(DT_CONTROL_STATUS, 1); + t.db.Configure(DT_SETPOINT_STATUS, 1); + t.slave.OnLowerLayerUp(); + + t.SendToSlave(arRequest); + BOOST_REQUIRE_EQUAL(t.Read(), arResponse); + } + + /* ---- Static data reads ----- */ + + + /*BOOST_AUTO_TEST_CASE(ReadGrp1Var1) + { + SlaveConfig cfg; cfg.mStaticBinary = GrpVar(1,1); + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 9); + t.slave.OnLowerLayerUp(); + + t.SendToSlave("C0 01 01 01 06"); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 00 01 01 00 00 00 00 00"); // 1 byte start/stop, 2 bytes for bitfield with 9 members + }*/ + + BOOST_AUTO_TEST_CASE(ReadGrp1Var0) + { + TestStaticRead("C0 01 01 00 06", "C0 81 80 00 01 02 00 00 00 02"); // 1 byte start/stop, RESTART quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp10Var0) + { + TestStaticRead("C0 01 0A 00 06", "C0 81 80 00 0A 02 00 00 00 02"); // 1 byte start/stop, RESTART quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp20Var0) + { + TestStaticRead("C0 01 14 00 06", "C0 81 80 00 14 01 00 00 00 02 00 00 00 00"); // 1 byte start/stop, RESTART quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp30Var0) + { + TestStaticRead("C0 01 1E 00 06", "C0 81 80 00 1E 01 00 00 00 02 00 00 00 00"); // 1 byte start/stop, RESTART quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp40Var0) + { + TestStaticRead("C0 01 28 00 06", "C0 81 80 00 28 01 00 00 00 02 00 00 00 00"); // 1 byte start/stop, RESTART quality + } + + // test that asking for a specific data type returns the requested type + void TestEventRead(const std::string& arRequest, const std::string& arResponse) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, 1); + t.db.Configure(DT_ANALOG, 1); + t.db.Configure(DT_COUNTER, 1); + t.db.Configure(DT_CONTROL_STATUS, 1); + t.db.Configure(DT_SETPOINT_STATUS, 1); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.db.SetClass(DT_ANALOG, PC_CLASS_1); + t.db.SetClass(DT_COUNTER, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + + { + Transaction tr(&t.db); + t.db.Update(Binary(false, BQ_ONLINE), 0); + t.db.Update(Counter(0, CQ_ONLINE), 0); + t.db.Update(Analog(0.0, AQ_ONLINE), 0); + t.db.Update(ControlStatus(false, TQ_ONLINE), 0); + t.db.Update(SetpointStatus(0.0, PQ_ONLINE), 0); + } + + t.SendToSlave(arRequest); + BOOST_REQUIRE_EQUAL(t.Read(), arResponse); + } + + BOOST_AUTO_TEST_CASE(ReadGrp2Var0) + { + TestEventRead("C0 01 02 00 06", "E0 81 80 00 02 01 17 01 00 01"); // 1 byte count == 1, ONLINE quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp22Var0) + { + TestEventRead("C0 01 16 00 06", "E0 81 80 00 16 01 17 01 00 01 00 00 00 00"); // 1 byte count == 1, ONLINE quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp32Var0) + { + TestEventRead("C0 01 20 00 06", "E0 81 80 00 20 01 17 01 00 01 00 00 00 00"); // 1 byte count == 1, ONLINE quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp2Var1) + { + TestEventRead("C0 01 02 01 06", "E0 81 80 00 02 01 17 01 00 01"); // 1 byte count == 1, ONLINE quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp2Var2) + { + TestEventRead("C0 01 02 02 06", "E0 81 80 00 02 02 17 01 00 01 00 00 00 00 00 00"); // 1 byte count == 1, ONLINE quality + } + + BOOST_AUTO_TEST_CASE(ReadGrp2Var3) + { + TestEventRead("C0 01 02 03 06", "E0 81 80 00 33 01 07 01 00 00 00 00 00 00 02 03 17 01 00 01 00 00"); // 1 byte count == 1, ONLINE quality + } + + BOOST_AUTO_TEST_CASE(InvalidObject) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.slave.OnLowerLayerUp(); + + t.slave.OnUnknownObject(); + BOOST_REQUIRE_EQUAL(t.Read(), "C0 81 80 02"); + } + + + BOOST_AUTO_TEST_CASE(ComplexReadSequence) + { + const size_t NUM = 4; + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_BINARY, NUM); + t.db.SetClass(DT_BINARY, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + { + Transaction tr(&t.db); + for(size_t i=0; i + void TestStaticType(apl::dnp::SlaveConfig& aCfg, apl::dnp::GrpVar& aGrpVar, int aGroup, int aVar, T aVal, const std::string& aRsp) + { + aGrpVar = GrpVar(aGroup,aVar); + AsyncSlaveTestObject t(aCfg); + t.db.Configure(PointType::MeasEnum, 1); + t.db.SetClass(PointType::MeasEnum, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + { + Transaction tr(&t.db); + t.db.Update(PointType(aVal, PointType::ONLINE), 0); + } + + t.SendToSlave("C0 01 3C 01 06"); // Read class 0 + BOOST_REQUIRE_EQUAL(t.Read(), aRsp); + } + + template + void TestStaticCounter(int aVar, T aVal, const std::string& aRsp) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + TestStaticType(cfg, cfg.mStaticCounter, 20, aVar, aVal, aRsp); + } + + BOOST_AUTO_TEST_CASE(ReadGrp20Var1) + { + TestStaticCounter(1, 5, "C0 81 80 00 14 01 00 00 00 01 05 00 00 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp20Var2) + { + TestStaticCounter(2, 5, "C0 81 80 00 14 02 00 00 00 01 05 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp20Var5) + { + TestStaticCounter(5, 5, "C0 81 80 00 14 05 00 00 00 05 00 00 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp20Var6) + { + TestStaticCounter(6, 5, "C0 81 80 00 14 06 00 00 00 05 00"); + } + + template + void TestStaticAnalog(int aVar, T aVal, const std::string& aRsp) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + TestStaticType(cfg, cfg.mStaticAnalog, 30, aVar, aVal, aRsp); + } + + BOOST_AUTO_TEST_CASE(ReadGrp30Var2) + { + TestStaticAnalog(2, 100, "C0 81 80 00 1E 02 00 00 00 01 64 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp30Var3) + { + TestStaticAnalog(3, 65536, "C0 81 80 00 1E 03 00 00 00 00 00 01 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp30Var4) + { + TestStaticAnalog(4, 100, "C0 81 80 00 1E 04 00 00 00 64 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp30Var5) + { + TestStaticAnalog(5, 95.6, "C0 81 80 00 1E 05 00 00 00 01 33 33 BF 42"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp30Var6) + { + TestStaticAnalog(6, -20, "C0 81 80 00 1E 06 00 00 00 01 00 00 00 00 00 00 34 C0"); + } + + template + void TestStaticControlStatus(int aVar, T aVal, const std::string& aRsp) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + AsyncSlaveTestObject t(cfg); + t.db.Configure(DT_CONTROL_STATUS, 1); + t.db.SetClass(DT_CONTROL_STATUS, PC_CLASS_1); + t.slave.OnLowerLayerUp(); + + { + Transaction tr(&t.db); + t.db.Update(ControlStatus(aVal, TQ_ONLINE), 0); + } + + t.SendToSlave("C0 01 3C 01 06"); // Read class 0 + BOOST_REQUIRE_EQUAL(t.Read(), aRsp); + } + + BOOST_AUTO_TEST_CASE(ReadGrp10Var2) + { + TestStaticControlStatus(2, true, "C0 81 80 00 0A 02 00 00 00 81"); + } + + + template + void TestStaticSetpointStatus(int aVar, T aVal, const string& aRsp) + { + SlaveConfig cfg; cfg.mDisableUnsol = true; + TestStaticType(cfg, cfg.mStaticSetpointStatus, 40, aVar, aVal, aRsp); + } + + BOOST_AUTO_TEST_CASE(ReadGrp40Var1) + { + TestStaticSetpointStatus(1, 100, "C0 81 80 00 28 01 00 00 00 01 64 00 00 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp40Var2) + { + TestStaticSetpointStatus(2, 100, "C0 81 80 00 28 02 00 00 00 01 64 00"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp40Var3) + { + TestStaticSetpointStatus(3, 95.6, "C0 81 80 00 28 03 00 00 00 01 33 33 BF 42"); + } + + BOOST_AUTO_TEST_CASE(ReadGrp40Var4) + { + TestStaticSetpointStatus(4, -20.0, "C0 81 80 00 28 04 00 00 00 01 00 00 00 00 00 00 34 C0"); + } + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/DNP3Test/TestAsyncSlaveEventBuffer.cpp b/DNP3Test/TestAsyncSlaveEventBuffer.cpp index 808f65f2..db1de63b 100644 --- a/DNP3Test/TestAsyncSlaveEventBuffer.cpp +++ b/DNP3Test/TestAsyncSlaveEventBuffer.cpp @@ -16,110 +16,110 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; - - - BOOST_AUTO_TEST_SUITE(AsyncSlaveEventBufferSuite) - void PushEvents(AsyncSlaveEventBuffer& b, size_t aNumEvent, size_t aNumIndices) - { - for(size_t i=0; i - void OverflowTest(const T& first, const T& second) - { - AsyncSlaveEventBuffer b(1, 1, 1); - b.Update(first, PC_CLASS_1, 0); - BOOST_REQUIRE_FALSE(b.IsOverflow()); - BOOST_REQUIRE(b.HasEventData()); - BOOST_REQUIRE_EQUAL(b.NumType(T::MeasEnum), 1); - b.Update(second, PC_CLASS_1, 1); - BOOST_REQUIRE(b.IsOverflow()); - } - - BOOST_AUTO_TEST_CASE(AnalogInsertion) - { - const size_t NUM_EVENT = 100; - const size_t NUM_INDICES = 10; - - AsyncSlaveEventBuffer b(0, NUM_INDICES, 0); - - PushEvents(b, NUM_EVENT, NUM_INDICES); //push lots of events but only - BOOST_REQUIRE_FALSE(b.IsOverflow()); - BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), NUM_INDICES); - - b.Select(DT_ANALOG, PC_CLASS_1); //select all the events - BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), NUM_INDICES); - PushEvents(b, NUM_EVENT, NUM_INDICES); - BOOST_REQUIRE_FALSE(b.IsOverflow()); - BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), 2*NUM_INDICES); - - //now deselect - b.Deselect(); - BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), NUM_INDICES); - BOOST_REQUIRE_FALSE(b.IsOverflow()); //still shouldn't be - - } - - BOOST_AUTO_TEST_CASE(OverflowAnalog) - { - OverflowTest(Analog(5), Analog(6)); - } - BOOST_AUTO_TEST_CASE(OverflowBinary) - { - OverflowTest(Binary(true), Binary(false)); - } - BOOST_AUTO_TEST_CASE(OverflowCounter) - { - OverflowTest(Counter(1), Counter(6)); - } - - BOOST_AUTO_TEST_CASE(ClassSelect) - { - AsyncSlaveEventBuffer b(10, 10, 10); - b.Update(Binary(true), PC_CLASS_1, 0); - b.Update(Binary(false), PC_CLASS_1, 0); - b.Update(Analog(5), PC_CLASS_1, 0); - b.Update(Analog(6), PC_CLASS_1, 1); - b.Update(Counter(1), PC_CLASS_1, 0); - b.Update(Counter(3), PC_CLASS_1, 1); - - b.Select(PC_CLASS_1, 1); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 1); - b.Deselect(); - - b.Select(PC_CLASS_1, 3); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 2); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_ANALOG), 1); - b.Deselect(); - - b.Select(PC_CLASS_1, 5); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 2); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_ANALOG), 2); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_COUNTER), 1); - b.Deselect(); - - b.Select(PC_CLASS_1, 6); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 2); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_ANALOG), 2); - BOOST_REQUIRE_EQUAL(b.NumSelected(DT_COUNTER), 2); - } - - BOOST_AUTO_TEST_CASE(TypeExceptions) - { - AsyncSlaveEventBuffer b(10, 10, 10); - BOOST_REQUIRE_THROW(b.NumType(DT_CONTROL_STATUS), ArgumentException); - BOOST_REQUIRE_THROW(b.NumSelected(DT_CONTROL_STATUS), ArgumentException); - } - BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include +#include +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; + + + BOOST_AUTO_TEST_SUITE(AsyncSlaveEventBufferSuite) + void PushEvents(AsyncSlaveEventBuffer& b, size_t aNumEvent, size_t aNumIndices) + { + for(size_t i=0; i + void OverflowTest(const T& first, const T& second) + { + AsyncSlaveEventBuffer b(1, 1, 1); + b.Update(first, PC_CLASS_1, 0); + BOOST_REQUIRE_FALSE(b.IsOverflow()); + BOOST_REQUIRE(b.HasEventData()); + BOOST_REQUIRE_EQUAL(b.NumType(T::MeasEnum), 1); + b.Update(second, PC_CLASS_1, 1); + BOOST_REQUIRE(b.IsOverflow()); + } + + BOOST_AUTO_TEST_CASE(AnalogInsertion) + { + const size_t NUM_EVENT = 100; + const size_t NUM_INDICES = 10; + + AsyncSlaveEventBuffer b(0, NUM_INDICES, 0); + + PushEvents(b, NUM_EVENT, NUM_INDICES); //push lots of events but only + BOOST_REQUIRE_FALSE(b.IsOverflow()); + BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), NUM_INDICES); + + b.Select(DT_ANALOG, PC_CLASS_1); //select all the events + BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), NUM_INDICES); + PushEvents(b, NUM_EVENT, NUM_INDICES); + BOOST_REQUIRE_FALSE(b.IsOverflow()); + BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), 2*NUM_INDICES); + + //now deselect + b.Deselect(); + BOOST_REQUIRE_EQUAL(b.NumType(DT_ANALOG), NUM_INDICES); + BOOST_REQUIRE_FALSE(b.IsOverflow()); //still shouldn't be + + } + + BOOST_AUTO_TEST_CASE(OverflowAnalog) + { + OverflowTest(Analog(5), Analog(6)); + } + BOOST_AUTO_TEST_CASE(OverflowBinary) + { + OverflowTest(Binary(true), Binary(false)); + } + BOOST_AUTO_TEST_CASE(OverflowCounter) + { + OverflowTest(Counter(1), Counter(6)); + } + + BOOST_AUTO_TEST_CASE(ClassSelect) + { + AsyncSlaveEventBuffer b(10, 10, 10); + b.Update(Binary(true), PC_CLASS_1, 0); + b.Update(Binary(false), PC_CLASS_1, 0); + b.Update(Analog(5), PC_CLASS_1, 0); + b.Update(Analog(6), PC_CLASS_1, 1); + b.Update(Counter(1), PC_CLASS_1, 0); + b.Update(Counter(3), PC_CLASS_1, 1); + + b.Select(PC_CLASS_1, 1); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 1); + b.Deselect(); + + b.Select(PC_CLASS_1, 3); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 2); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_ANALOG), 1); + b.Deselect(); + + b.Select(PC_CLASS_1, 5); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 2); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_ANALOG), 2); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_COUNTER), 1); + b.Deselect(); + + b.Select(PC_CLASS_1, 6); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_BINARY), 2); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_ANALOG), 2); + BOOST_REQUIRE_EQUAL(b.NumSelected(DT_COUNTER), 2); + } + + BOOST_AUTO_TEST_CASE(TypeExceptions) + { + AsyncSlaveEventBuffer b(10, 10, 10); + BOOST_REQUIRE_THROW(b.NumType(DT_CONTROL_STATUS), ArgumentException); + BOOST_REQUIRE_THROW(b.NumSelected(DT_CONTROL_STATUS), ArgumentException); + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncTransportLayer.cpp b/DNP3Test/TestAsyncTransportLayer.cpp index cce423f1..ab46d684 100644 --- a/DNP3Test/TestAsyncTransportLayer.cpp +++ b/DNP3Test/TestAsyncTransportLayer.cpp @@ -1,253 +1,253 @@ -// -// Licensed to Green Energy Corp (www.greenenergycorp.com) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. Green Enery Corp licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// -#include -#include - -#include "TransportTestObject.h" -#include - -#include -#include -#include - -#include - -using namespace std; -using namespace apl; -using namespace apl::dnp; - - - -BOOST_AUTO_TEST_SUITE(AsyncTransportSuite) - - // make sure an invalid state exception gets thrown - // for every event other than LowerLayerUp() since - // the layer starts in the online state - BOOST_AUTO_TEST_CASE(TestStateOffline) - { - TransportTestObject test; - - BOOST_REQUIRE_THROW(test.upper.SendDown("00"), InvalidStateException); - BOOST_REQUIRE_THROW(test.lower.SendUp(""), InvalidStateException); - BOOST_REQUIRE_THROW(test.lower.SendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(test.lower.ThisLayerDown(), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(TestStateReady) - { - TransportTestObject test(true); //makes an implicit call to 'test.lower.ThisLayerUp()' - - //check that that the transport layer is correctly forwarding up/down - BOOST_REQUIRE(test.upper.IsLowerLayerUp()); - test.lower.ThisLayerDown(); - BOOST_REQUIRE_FALSE(test.upper.IsLowerLayerUp()); - test.lower.ThisLayerUp(); - BOOST_REQUIRE(test.upper.IsLowerLayerUp()); - - //check that these actions all throw InvalidStateException - BOOST_REQUIRE_THROW(test.lower.ThisLayerUp(), InvalidStateException); - BOOST_REQUIRE_THROW(test.lower.SendSuccess(), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(TestReceiveBadArguments) - { - TransportTestObject test(true); - //check that the wrong aruments throw argument exceptions, and it's doesn't go to the sending state - BOOST_REQUIRE_THROW(test.lower.SendUp(""), ArgumentException); // length 0 - BOOST_REQUIRE_THROW(test.lower.SendUp(test.GetData("C0", 0, 250)), ArgumentException); // length 251 - } - - BOOST_AUTO_TEST_CASE(TestReceiveNoPayload) - { - TransportTestObject test(true); - //try sending a FIR/FIN packet with no payload (1 byte) - test.lower.SendUp("C0"); // FIR/FIN - BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_NO_PAYLOAD); - } - - BOOST_AUTO_TEST_CASE(TestReceiveNoFIR) - { - TransportTestObject test(true); - //try sending a non-FIR w/ no prior packet - test.lower.SendUp("80 77"); // _/FIN - BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_MESSAGE_WITHOUT_FIR); - } - - BOOST_AUTO_TEST_CASE(TestReceiveWrongSequence) - { - TransportTestObject test(true); - //send a FIR, followed by a FIN w/ the wrong sequence - test.lower.SendUp(test.GetData("40")); // FIR/_/0 - test.lower.SendUp(test.GetData("82")); // _/FIN/2 - BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_BAD_SEQUENCE); - } - - BOOST_AUTO_TEST_CASE(TestReceiveSinglePacket) - { - TransportTestObject test(true); - //now try receiving 1 a single FIR/FIN with a magic value - test.lower.SendUp("C0 77"); - test.upper.BufferEquals("77"); - } - - BOOST_AUTO_TEST_CASE(TestReceiveLargestPossibleAPDU) - { - TransportTestObject test(true); - - size_t num_packets = CalcMaxPackets(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); - size_t last_packet_length = CalcLastPacketSize(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); - - vector packets; - string apdu = test.GeneratePacketSequence(packets, num_packets, last_packet_length); - BOOST_FOREACH(string s, packets) { test.lower.SendUp(s); } - - BOOST_REQUIRE(test.IsLogErrorFree()); - BOOST_REQUIRE(test.upper.BufferEquals(apdu)); //check that the correct data was written - } - - BOOST_AUTO_TEST_CASE(TestReceiveBufferOverflow) - { - TransportTestObject test(true); - - size_t num_packets = CalcMaxPackets(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); - size_t last_packet_length = CalcLastPacketSize(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); - - //send 1 more packet than possible - vector packets; - string apdu = test.GeneratePacketSequence(packets, num_packets+1, last_packet_length); - BOOST_FOREACH(string s, packets) { test.lower.SendUp(s); } - - BOOST_REQUIRE(test.upper.IsBufferEmpty()); - BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_BUFFER_FULL); - } - - BOOST_AUTO_TEST_CASE(TestReceiveNewFir) - { - TransportTestObject test(true); - - test.lower.SendUp(test.GetData("40")); // FIR/_/0 - BOOST_REQUIRE(test.upper.IsBufferEmpty()); - - test.lower.SendUp(test.GetData("C0")); // FIR/FIN/0 - test.upper.BufferEquals(test.GetData("")); - BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_NEW_FIR); - } - - BOOST_AUTO_TEST_CASE(TestSendArguments) - { - TransportTestObject test(true); - BOOST_REQUIRE_THROW(test.upper.SendDown(""), ArgumentException); // 0 Length - BOOST_REQUIRE_THROW(test.upper.SendDown(test.GetData("", 0, DEFAULT_FRAG_SIZE+1)), ArgumentException); // Max Size + 1 - } - - BOOST_AUTO_TEST_CASE(TestStateSending) - { - TransportTestObject test(true); - - test.lower.DisableAutoSendCallback(); - - // this puts the layer into the Sending state - test.upper.SendDown("11"); - BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); //FIR/FIN SEQ=0 - - // Check that while we're sending, all other send requests are rejected - BOOST_REQUIRE_THROW(test.upper.SendDown("00"), InvalidStateException); - BOOST_REQUIRE_THROW(test.lower.ThisLayerUp(), InvalidStateException); - - //while we are sending, we should still be able to receive data as normal - test.lower.SendUp("C0 77"); - test.upper.BufferEquals("77"); - - //this should put us back in the Ready state since it was a single tpdu send - test.lower.SendSuccess(); - BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 1); - - BOOST_REQUIRE_THROW(test.lower.SendSuccess(), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(TestSendFailure) - { - TransportTestObject test(true); - - test.lower.DisableAutoSendCallback(); - - // this puts the layer into the Sending state - test.upper.SendDown("11"); - BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); //FIR/FIN SEQ=0 - - //this should put us back in the Ready state - test.lower.SendFailure(); - BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 0); - BOOST_REQUIRE_EQUAL(test.upper.GetState().mFailureCnt, 1); - - test.lower.ClearBuffer(); - test.upper.SendDown("11"); - BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); // should resend with the same sequence number FIR/FIN SEQ=0 - test.lower.SendSuccess(); - BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 1); - BOOST_REQUIRE_EQUAL(test.upper.GetState().mFailureCnt, 1); - } - - BOOST_AUTO_TEST_CASE(TestSendSuccess) - { - TransportTestObject test(true); - - // this puts the layer into the Sending state - test.upper.SendDown("11"); - BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); //FIR/FIN SEQ=0 - test.lower.ClearBuffer(); - - // this puts the layer into the Sending state - test.upper.SendDown("11"); - BOOST_REQUIRE(test.lower.BufferEquals("C1 11")); //FIR/FIN SEQ=1 - BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 2); - } - - //if we're in the middle of a send and the layer goes down - BOOST_AUTO_TEST_CASE(TestClosedWhileSending) - { - TransportTestObject test(true); - test.upper.SendDown("11"); //get the layer into the sending state - - test.lower.ThisLayerDown(); // go to the TS_ClosedAfterSend state - BOOST_REQUIRE_FALSE(test.upper.IsLowerLayerUp()); - } - - BOOST_AUTO_TEST_CASE(TestSendFullAPDU) - { - TransportTestObject test(true); - - size_t num_packets = CalcMaxPackets(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); - size_t last_packet_length = CalcLastPacketSize(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); - - vector packets; - std::string apdu = test.GeneratePacketSequence(packets, num_packets, last_packet_length); - test.lower.DisableAutoSendCallback(); - test.upper.SendDown(apdu); - - BOOST_FOREACH(string tpdu, packets) //verify that each packet is received correctly - { - BOOST_REQUIRE(test.lower.BufferEquals(tpdu)); - test.lower.ClearBuffer(); //clear the buffer, otherwise the packets accumulate - test.lower.SendSuccess(); - } - } - - -BOOST_AUTO_TEST_SUITE_END() +// +// Licensed to Green Energy Corp (www.greenenergycorp.com) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. Green Enery Corp licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +#include +#include + +#include "TransportTestObject.h" +#include + +#include +#include +#include + +#include + +using namespace std; +using namespace apl; +using namespace apl::dnp; + + + +BOOST_AUTO_TEST_SUITE(AsyncTransportSuite) + + // make sure an invalid state exception gets thrown + // for every event other than LowerLayerUp() since + // the layer starts in the online state + BOOST_AUTO_TEST_CASE(TestStateOffline) + { + TransportTestObject test; + + BOOST_REQUIRE_THROW(test.upper.SendDown("00"), InvalidStateException); + BOOST_REQUIRE_THROW(test.lower.SendUp(""), InvalidStateException); + BOOST_REQUIRE_THROW(test.lower.SendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(test.lower.ThisLayerDown(), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(TestStateReady) + { + TransportTestObject test(true); //makes an implicit call to 'test.lower.ThisLayerUp()' + + //check that that the transport layer is correctly forwarding up/down + BOOST_REQUIRE(test.upper.IsLowerLayerUp()); + test.lower.ThisLayerDown(); + BOOST_REQUIRE_FALSE(test.upper.IsLowerLayerUp()); + test.lower.ThisLayerUp(); + BOOST_REQUIRE(test.upper.IsLowerLayerUp()); + + //check that these actions all throw InvalidStateException + BOOST_REQUIRE_THROW(test.lower.ThisLayerUp(), InvalidStateException); + BOOST_REQUIRE_THROW(test.lower.SendSuccess(), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(TestReceiveBadArguments) + { + TransportTestObject test(true); + //check that the wrong aruments throw argument exceptions, and it's doesn't go to the sending state + BOOST_REQUIRE_THROW(test.lower.SendUp(""), ArgumentException); // length 0 + BOOST_REQUIRE_THROW(test.lower.SendUp(test.GetData("C0", 0, 250)), ArgumentException); // length 251 + } + + BOOST_AUTO_TEST_CASE(TestReceiveNoPayload) + { + TransportTestObject test(true); + //try sending a FIR/FIN packet with no payload (1 byte) + test.lower.SendUp("C0"); // FIR/FIN + BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_NO_PAYLOAD); + } + + BOOST_AUTO_TEST_CASE(TestReceiveNoFIR) + { + TransportTestObject test(true); + //try sending a non-FIR w/ no prior packet + test.lower.SendUp("80 77"); // _/FIN + BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_MESSAGE_WITHOUT_FIR); + } + + BOOST_AUTO_TEST_CASE(TestReceiveWrongSequence) + { + TransportTestObject test(true); + //send a FIR, followed by a FIN w/ the wrong sequence + test.lower.SendUp(test.GetData("40")); // FIR/_/0 + test.lower.SendUp(test.GetData("82")); // _/FIN/2 + BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_BAD_SEQUENCE); + } + + BOOST_AUTO_TEST_CASE(TestReceiveSinglePacket) + { + TransportTestObject test(true); + //now try receiving 1 a single FIR/FIN with a magic value + test.lower.SendUp("C0 77"); + test.upper.BufferEquals("77"); + } + + BOOST_AUTO_TEST_CASE(TestReceiveLargestPossibleAPDU) + { + TransportTestObject test(true); + + size_t num_packets = CalcMaxPackets(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); + size_t last_packet_length = CalcLastPacketSize(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); + + vector packets; + string apdu = test.GeneratePacketSequence(packets, num_packets, last_packet_length); + BOOST_FOREACH(string s, packets) { test.lower.SendUp(s); } + + BOOST_REQUIRE(test.IsLogErrorFree()); + BOOST_REQUIRE(test.upper.BufferEquals(apdu)); //check that the correct data was written + } + + BOOST_AUTO_TEST_CASE(TestReceiveBufferOverflow) + { + TransportTestObject test(true); + + size_t num_packets = CalcMaxPackets(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); + size_t last_packet_length = CalcLastPacketSize(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); + + //send 1 more packet than possible + vector packets; + string apdu = test.GeneratePacketSequence(packets, num_packets+1, last_packet_length); + BOOST_FOREACH(string s, packets) { test.lower.SendUp(s); } + + BOOST_REQUIRE(test.upper.IsBufferEmpty()); + BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_BUFFER_FULL); + } + + BOOST_AUTO_TEST_CASE(TestReceiveNewFir) + { + TransportTestObject test(true); + + test.lower.SendUp(test.GetData("40")); // FIR/_/0 + BOOST_REQUIRE(test.upper.IsBufferEmpty()); + + test.lower.SendUp(test.GetData("C0")); // FIR/FIN/0 + test.upper.BufferEquals(test.GetData("")); + BOOST_REQUIRE_EQUAL(test.NextErrorCode(), TLERR_NEW_FIR); + } + + BOOST_AUTO_TEST_CASE(TestSendArguments) + { + TransportTestObject test(true); + BOOST_REQUIRE_THROW(test.upper.SendDown(""), ArgumentException); // 0 Length + BOOST_REQUIRE_THROW(test.upper.SendDown(test.GetData("", 0, DEFAULT_FRAG_SIZE+1)), ArgumentException); // Max Size + 1 + } + + BOOST_AUTO_TEST_CASE(TestStateSending) + { + TransportTestObject test(true); + + test.lower.DisableAutoSendCallback(); + + // this puts the layer into the Sending state + test.upper.SendDown("11"); + BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); //FIR/FIN SEQ=0 + + // Check that while we're sending, all other send requests are rejected + BOOST_REQUIRE_THROW(test.upper.SendDown("00"), InvalidStateException); + BOOST_REQUIRE_THROW(test.lower.ThisLayerUp(), InvalidStateException); + + //while we are sending, we should still be able to receive data as normal + test.lower.SendUp("C0 77"); + test.upper.BufferEquals("77"); + + //this should put us back in the Ready state since it was a single tpdu send + test.lower.SendSuccess(); + BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 1); + + BOOST_REQUIRE_THROW(test.lower.SendSuccess(), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(TestSendFailure) + { + TransportTestObject test(true); + + test.lower.DisableAutoSendCallback(); + + // this puts the layer into the Sending state + test.upper.SendDown("11"); + BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); //FIR/FIN SEQ=0 + + //this should put us back in the Ready state + test.lower.SendFailure(); + BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 0); + BOOST_REQUIRE_EQUAL(test.upper.GetState().mFailureCnt, 1); + + test.lower.ClearBuffer(); + test.upper.SendDown("11"); + BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); // should resend with the same sequence number FIR/FIN SEQ=0 + test.lower.SendSuccess(); + BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 1); + BOOST_REQUIRE_EQUAL(test.upper.GetState().mFailureCnt, 1); + } + + BOOST_AUTO_TEST_CASE(TestSendSuccess) + { + TransportTestObject test(true); + + // this puts the layer into the Sending state + test.upper.SendDown("11"); + BOOST_REQUIRE(test.lower.BufferEquals("C0 11")); //FIR/FIN SEQ=0 + test.lower.ClearBuffer(); + + // this puts the layer into the Sending state + test.upper.SendDown("11"); + BOOST_REQUIRE(test.lower.BufferEquals("C1 11")); //FIR/FIN SEQ=1 + BOOST_REQUIRE_EQUAL(test.upper.GetState().mSuccessCnt, 2); + } + + //if we're in the middle of a send and the layer goes down + BOOST_AUTO_TEST_CASE(TestClosedWhileSending) + { + TransportTestObject test(true); + test.upper.SendDown("11"); //get the layer into the sending state + + test.lower.ThisLayerDown(); // go to the TS_ClosedAfterSend state + BOOST_REQUIRE_FALSE(test.upper.IsLowerLayerUp()); + } + + BOOST_AUTO_TEST_CASE(TestSendFullAPDU) + { + TransportTestObject test(true); + + size_t num_packets = CalcMaxPackets(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); + size_t last_packet_length = CalcLastPacketSize(DEFAULT_FRAG_SIZE, TL_MAX_TPDU_PAYLOAD); + + vector packets; + std::string apdu = test.GeneratePacketSequence(packets, num_packets, last_packet_length); + test.lower.DisableAutoSendCallback(); + test.upper.SendDown(apdu); + + BOOST_FOREACH(string tpdu, packets) //verify that each packet is received correctly + { + BOOST_REQUIRE(test.lower.BufferEquals(tpdu)); + test.lower.ClearBuffer(); //clear the buffer, otherwise the packets accumulate + test.lower.SendSuccess(); + } + } + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncTransportLoopback.cpp b/DNP3Test/TestAsyncTransportLoopback.cpp index 30d9e83d..3004cf4a 100644 --- a/DNP3Test/TestAsyncTransportLoopback.cpp +++ b/DNP3Test/TestAsyncTransportLoopback.cpp @@ -16,84 +16,84 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "TransportLoopbackTestObject.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -using namespace std; -using namespace apl; -using namespace boost; -using namespace apl::dnp; - -BOOST_AUTO_TEST_SUITE(AsyncTransportLoopback) - - /// Do a bidirectional send operation and proceed until both sides have correctly - /// received all the data - void TestLoopback(TransportLoopbackTestObject* apTest, size_t aNumBytes) - { - apTest->Start(); - - BOOST_REQUIRE(apTest->ProceedUntil(bind(&TransportLoopbackTestObject::LayersUp, apTest))); - - ByteStr b(aNumBytes, 0); - - apTest->mUpperA.SendDown(b, b.Size()); - apTest->mUpperB.SendDown(b, b.Size()); - - BOOST_REQUIRE(apTest->ProceedUntil(bind(&MockUpperLayer::SizeEquals, &(apTest->mUpperA), b.Size()))); - BOOST_REQUIRE(apTest->ProceedUntil(bind(&MockUpperLayer::SizeEquals, &(apTest->mUpperB), b.Size()))); - BOOST_REQUIRE(apTest->mUpperA.BufferEquals(b, b.Size())); - BOOST_REQUIRE(apTest->mUpperB.BufferEquals(b, b.Size())); - } - - BOOST_AUTO_TEST_CASE(TestTransportWithMockLoopback) - { - LinkConfig cfgA(true, true); - LinkConfig cfgB(false, true); - - EventLog log; - boost::asio::io_service service; - LoopbackPhysicalLayerAsync phys(log.GetLogger(LEV_WARNING, "loopback"), &service); - TransportLoopbackTestObject t(&service, &phys, cfgA, cfgB); - - TestLoopback(&t, DEFAULT_FRAG_SIZE); - } - -// Run this test on ARM to give us some regression protection for serial -#ifdef SERIAL_PORT - BOOST_AUTO_TEST_CASE(TestTransportWithSerialLoopback) - { - LinkConfig cfgA(true, true); - LinkConfig cfgB(false, true); - - cfgA.NumRetry = cfgB.NumRetry = 3; - - SerialSettings s; - s.mDevice = TOSTRING(SERIAL_PORT); - s.mBaud = 57600; - s.mDataBits = 8; - s.mStopBits = 1; - s.mParity = PAR_NONE; - s.mFlowType = FLOW_NONE; - - EventLog log; - boost::asio::io_service service; - PhysicalLayerAsyncSerial phys(log.GetLogger(LEV_WARNING, "serial"), &service, s); - TransportLoopbackTestObject t(&service, &phys, cfgA, cfgB); - - TestLoopback(&t, DEFAULT_FRAG_SIZE); - } -#endif - -BOOST_AUTO_TEST_SUITE_END() +#include +#include "TransportLoopbackTestObject.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace apl; +using namespace boost; +using namespace apl::dnp; + +BOOST_AUTO_TEST_SUITE(AsyncTransportLoopback) + + /// Do a bidirectional send operation and proceed until both sides have correctly + /// received all the data + void TestLoopback(TransportLoopbackTestObject* apTest, size_t aNumBytes) + { + apTest->Start(); + + BOOST_REQUIRE(apTest->ProceedUntil(bind(&TransportLoopbackTestObject::LayersUp, apTest))); + + ByteStr b(aNumBytes, 0); + + apTest->mUpperA.SendDown(b, b.Size()); + apTest->mUpperB.SendDown(b, b.Size()); + + BOOST_REQUIRE(apTest->ProceedUntil(bind(&MockUpperLayer::SizeEquals, &(apTest->mUpperA), b.Size()))); + BOOST_REQUIRE(apTest->ProceedUntil(bind(&MockUpperLayer::SizeEquals, &(apTest->mUpperB), b.Size()))); + BOOST_REQUIRE(apTest->mUpperA.BufferEquals(b, b.Size())); + BOOST_REQUIRE(apTest->mUpperB.BufferEquals(b, b.Size())); + } + + BOOST_AUTO_TEST_CASE(TestTransportWithMockLoopback) + { + LinkConfig cfgA(true, true); + LinkConfig cfgB(false, true); + + EventLog log; + boost::asio::io_service service; + LoopbackPhysicalLayerAsync phys(log.GetLogger(LEV_WARNING, "loopback"), &service); + TransportLoopbackTestObject t(&service, &phys, cfgA, cfgB); + + TestLoopback(&t, DEFAULT_FRAG_SIZE); + } + +// Run this test on ARM to give us some regression protection for serial +#ifdef SERIAL_PORT + BOOST_AUTO_TEST_CASE(TestTransportWithSerialLoopback) + { + LinkConfig cfgA(true, true); + LinkConfig cfgB(false, true); + + cfgA.NumRetry = cfgB.NumRetry = 3; + + SerialSettings s; + s.mDevice = TOSTRING(SERIAL_PORT); + s.mBaud = 57600; + s.mDataBits = 8; + s.mStopBits = 1; + s.mParity = PAR_NONE; + s.mFlowType = FLOW_NONE; + + EventLog log; + boost::asio::io_service service; + PhysicalLayerAsyncSerial phys(log.GetLogger(LEV_WARNING, "serial"), &service, s); + TransportLoopbackTestObject t(&service, &phys, cfgA, cfgB); + + TestLoopback(&t, DEFAULT_FRAG_SIZE); + } +#endif + +BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestAsyncTransportScalability.cpp b/DNP3Test/TestAsyncTransportScalability.cpp index 4fb86224..8f8af626 100644 --- a/DNP3Test/TestAsyncTransportScalability.cpp +++ b/DNP3Test/TestAsyncTransportScalability.cpp @@ -16,65 +16,65 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "TransportScalabilityTestObject.h" - -#include -#include - -#include -#include -#include - - -#include -#include - -using namespace std; -using namespace apl; -using namespace boost; -using namespace apl::dnp; - - - - BOOST_AUTO_TEST_SUITE(AsyncTransportScalability) - - - BOOST_AUTO_TEST_CASE(TestSimpleSend) - { - LinkConfig client(true, true); - LinkConfig server(false, true); - - // Ubuntu and windows use different ephemeral port ranges... - - #ifdef WIN32 - uint_32_t port = 50000; - #else - uint_32_t port = 30000; - #endif - - // turned down the number of pairs for arm b/c of how long it takes to run. - #ifdef ARM - size_t NUM_PAIRS = 50; - #else - size_t NUM_PAIRS = 100; - #endif - - TransportScalabilityTestObject t(client, server, port, NUM_PAIRS); - - t.Start(); - - BOOST_REQUIRE(t.ProceedUntil(bind(&TransportScalabilityTestObject::AllLayersUp, &t))); - - ByteStr b(2048, 0); - - t.SendToAll(b, b.Size()); - - BOOST_REQUIRE(t.ProceedUntil(bind(&TransportScalabilityTestObject::AllLayerReceived, &t, b.Size()), 120000)); - BOOST_REQUIRE(t.AllLayerEqual(b, b.Size())); - } - - - - - BOOST_AUTO_TEST_SUITE_END() +#include +#include "TransportScalabilityTestObject.h" + +#include +#include + +#include +#include +#include + + +#include +#include + +using namespace std; +using namespace apl; +using namespace boost; +using namespace apl::dnp; + + + + BOOST_AUTO_TEST_SUITE(AsyncTransportScalability) + + + BOOST_AUTO_TEST_CASE(TestSimpleSend) + { + LinkConfig client(true, true); + LinkConfig server(false, true); + + // Ubuntu and windows use different ephemeral port ranges... + + #ifdef WIN32 + uint_32_t port = 50000; + #else + uint_32_t port = 30000; + #endif + + // turned down the number of pairs for arm b/c of how long it takes to run. + #ifdef ARM + size_t NUM_PAIRS = 50; + #else + size_t NUM_PAIRS = 100; + #endif + + TransportScalabilityTestObject t(client, server, port, NUM_PAIRS); + + t.Start(); + + BOOST_REQUIRE(t.ProceedUntil(bind(&TransportScalabilityTestObject::AllLayersUp, &t))); + + ByteStr b(2048, 0); + + t.SendToAll(b, b.Size()); + + BOOST_REQUIRE(t.ProceedUntil(bind(&TransportScalabilityTestObject::AllLayerReceived, &t, b.Size()), 120000)); + BOOST_REQUIRE(t.AllLayerEqual(b, b.Size())); + } + + + + + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestCRC.cpp b/DNP3Test/TestCRC.cpp index 3d743baa..9776a08e 100644 --- a/DNP3Test/TestCRC.cpp +++ b/DNP3Test/TestCRC.cpp @@ -16,30 +16,30 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include - -#include -#include -#include -#include - - -using namespace std; -using namespace apl; -using namespace apl::dnp; - - -BOOST_AUTO_TEST_SUITE(CRC) - - BOOST_AUTO_TEST_CASE(CrcTest) - { - HexSequence hs("05 64 05 C0 01 00 00 04 E9 21"); - BOOST_REQUIRE_EQUAL(hs.Size(), 10); - BOOST_REQUIRE_EQUAL(DNPCrc::CalcCrc(hs, 8), 0x21E9); - } - -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include +#include + +#include +#include +#include +#include + + +using namespace std; +using namespace apl; +using namespace apl::dnp; + + +BOOST_AUTO_TEST_SUITE(CRC) + + BOOST_AUTO_TEST_CASE(CrcTest) + { + HexSequence hs("05 64 05 C0 01 00 00 04 E9 21"); + BOOST_REQUIRE_EQUAL(hs.Size(), 10); + BOOST_REQUIRE_EQUAL(DNPCrc::CalcCrc(hs, 8), 0x21E9); + } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestLinkFrameDNP.cpp b/DNP3Test/TestLinkFrameDNP.cpp index 82ad012f..e636a6eb 100644 --- a/DNP3Test/TestLinkFrameDNP.cpp +++ b/DNP3Test/TestLinkFrameDNP.cpp @@ -16,134 +16,134 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include -#include - -#include "DNPHelpers.h" - -using namespace apl; -using namespace apl::dnp; - -void FormatUserData(apl::dnp::LinkFrame& f, bool aIsMaster, bool aIsConfirmed, int aDest, int aSrc, const std::string& arData, bool aFcb = false) -{ - HexSequence hs(arData); - BOOST_REQUIRE(hs.Size() < 250); - - if(aIsConfirmed) { - f.FormatConfirmedUserData(aIsMaster, aFcb, aDest, aSrc, hs, hs.Size()); - } - else { - f.FormatUnconfirmedUserData(aIsMaster, aDest, aSrc, hs, hs.Size()); - } -} - -BOOST_AUTO_TEST_SUITE(DNPLinkFrame) - - BOOST_AUTO_TEST_CASE(CopyConstructor) //make sure the default copies the buffer properly - { - LinkFrame a; - for(size_t i=0; i(i); - - LinkFrame b(a); - - //verify that the buffers are equal - for(size_t i=0; i +#include + +#include +#include +#include + +#include "DNPHelpers.h" + +using namespace apl; +using namespace apl::dnp; + +void FormatUserData(apl::dnp::LinkFrame& f, bool aIsMaster, bool aIsConfirmed, int aDest, int aSrc, const std::string& arData, bool aFcb = false) +{ + HexSequence hs(arData); + BOOST_REQUIRE(hs.Size() < 250); + + if(aIsConfirmed) { + f.FormatConfirmedUserData(aIsMaster, aFcb, aDest, aSrc, hs, hs.Size()); + } + else { + f.FormatUnconfirmedUserData(aIsMaster, aDest, aSrc, hs, hs.Size()); + } +} + +BOOST_AUTO_TEST_SUITE(DNPLinkFrame) + + BOOST_AUTO_TEST_CASE(CopyConstructor) //make sure the default copies the buffer properly + { + LinkFrame a; + for(size_t i=0; i(i); + + LinkFrame b(a); + + //verify that the buffers are equal + for(size_t i=0; i -#include - - -#include "LinkReceiverTest.h" -#include "DNPHelpers.h" - -using namespace apl; -using namespace apl::dnp; - - - - BOOST_AUTO_TEST_SUITE(AsyncLinkReceiver) - - BOOST_AUTO_TEST_CASE(InitializationState){ - LinkReceiverTest t; - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - } - - ////////////////////////////////////////////////////////////// - // CRC Failures - ////////////////////////////////////////////////////////////// - - BOOST_AUTO_TEST_CASE(HeaderCRCError) { - LinkReceiverTest t; - t.WriteData("05 64 05 C0 01 00 00 04 E9 20"); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_CRC); - } - - BOOST_AUTO_TEST_CASE(BodyCRCError) { - LinkReceiverTest t; - t.WriteData("05 64 14 F3 01 00 00 04 0A 3B C0 C3 01 3C 02 06 3C 03 06 3C 04 06 3C 01 06 9A 11"); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_CRC); - } - - ////////////////////////////////////////////////////////////// - // Illegal packets of one form or another - ////////////////////////////////////////////////////////////// - - // Change the length to something from 5 to something in [0,4] and recalc the crc - // A valid reset link states packet would be: 05 64 05 C0 01 00 00 04 E9 21 - BOOST_AUTO_TEST_CASE(BadLengthError) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 01 C0 01 00 00 04 E9 21")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_INVALID_LENGTH); - } - - //Test that the presence of user data disagrees with the function code - BOOST_AUTO_TEST_CASE(UnexpectedData) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 08 C0 01 00 00 04 E9 21")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_DATA); - } - - // Test that the absence of user data disagrees with the function code - // This is the first 10 bytes of an unconfirmed user data packet w/ the length set to 5 - BOOST_AUTO_TEST_CASE(AbsenceOfData) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 05 73 00 04 01 00 03 FC")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_NO_DATA); - } - - // Test that the parser can handle an unknown PriToSec function code - // Reset Links w/ function code changed from 0 to 6 - BOOST_AUTO_TEST_CASE(UnknownFunction) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 05 C6 01 00 00 04 E9 21")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_FUNC); - } - - // Test that the parser can handle an unexpected FCV bit - // Reset Links w/ FCV toggled on - BOOST_AUTO_TEST_CASE(UnexpectedFCV) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 05 D0 01 00 00 04 E9 21")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCV); - } - - // Test that the parser can handle an unexpected FCB bit for SecToPri - // ACK w/ FCB toggled on - BOOST_AUTO_TEST_CASE(UnexpectedFCB) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 05 20 00 04 01 00 19 A6")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCB); - } - - // Write two bad packets back-to-back tests that this produces - // back to back errors with a single write call - BOOST_AUTO_TEST_CASE(CombinedFailures) { - LinkReceiverTest t; - t.WriteData(RepairCRC("05 64 05 20 00 04 01 00 19 A6") - + " " + RepairCRC("05 64 05 D0 01 00 00 04 E9 21")); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCB); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCV); - } - - ////////////////////////////////////////////////////////////// - // Successful packets - Sec to Pri - ////////////////////////////////////////////////////////////// - - BOOST_AUTO_TEST_CASE(ReadACK) { - LinkReceiverTest t; - LinkFrame f; - f.FormatAck(true, false, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_ACK, true, false, 1, 2)); - } - - BOOST_AUTO_TEST_CASE(ReadNACK) { - LinkReceiverTest t; - LinkFrame f; - f.FormatNack(false, true, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_NACK, false, true, 1, 2)); - } - - BOOST_AUTO_TEST_CASE(LinkStatus) { - LinkReceiverTest t; - LinkFrame f; - f.FormatLinkStatus(true, true, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_LINK_STATUS, true, true, 1, 2)); - } - - BOOST_AUTO_TEST_CASE(NotSupported) { - LinkReceiverTest t; - LinkFrame f; - f.FormatNotSupported(true, false, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_NOT_SUPPORTED, true, false, 1, 2)); - } - - ////////////////////////////////////////////////////////////// - // Successful packets - Pri To Sec - ////////////////////////////////////////////////////////////// - - BOOST_AUTO_TEST_CASE(TestLinkStates) { - LinkReceiverTest t; - LinkFrame f; - f.FormatTestLinkStatus(false, true, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLastWithFCB(FC_PRI_TEST_LINK_STATES, false, true, 1, 2)); - } - - BOOST_AUTO_TEST_CASE(ResetLinkStates) { - LinkReceiverTest t; - LinkFrame f; - f.FormatResetLinkStates(false, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_RESET_LINK_STATES, false, 1, 2)); - } - - BOOST_AUTO_TEST_CASE(RequestLinkStatus) { - LinkReceiverTest t; - LinkFrame f; - f.FormatRequestLinkStatus(true, 1, 2); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_REQUEST_LINK_STATUS, true, 1, 2)); - } - - BOOST_AUTO_TEST_CASE(UnconfirmedUserData) { - LinkReceiverTest t; - LinkFrame f; - ByteStr data(250, 0); //initializes a buffer with increasing value - f.FormatUnconfirmedUserData(true, 1, 2, data, data.Size()); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_UNCONFIRMED_USER_DATA, true, 1, 2)); - BOOST_REQUIRE(t.mSink.BufferEquals(data, data.Size())); - } - - BOOST_AUTO_TEST_CASE(ConfirmedUserData) { - LinkReceiverTest t; - LinkFrame f; - ByteStr data(250, 0); //initializes a buffer with increasing value - f.FormatConfirmedUserData(true, true, 1, 2, data, data.Size()); - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLastWithFCB(FC_PRI_CONFIRMED_USER_DATA, true, true, 1, 2)); - BOOST_REQUIRE(t.mSink.BufferEquals(data, data.Size())); - } - - ////////////////////////////////////////////////////////////// - // multi packets - ////////////////////////////////////////////////////////////// - - BOOST_AUTO_TEST_CASE(TestTwoPackets) { - LinkReceiverTest t; - // back to back reset link - t.WriteData("05 64 05 C0 01 00 00 04 E9 21 05 64 05 C0 01 00 00 04 E9 21"); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 2); - BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_RESET_LINK_STATES, true, 1, 1024)); - } - - ////////////////////////////////////////////////////////////// - // framing errors - ////////////////////////////////////////////////////////////// - - // Test that the parser is able to resync without discarding - BOOST_AUTO_TEST_CASE(Resync0564) { - LinkReceiverTest t; - t.WriteData("05 64 05 64 05 C0 01 00 00 04 E9 21"); - BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_CRC); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); - BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_RESET_LINK_STATES, true, 1, 1024)); - } - - ////////////////////////////////////////////////////////////// - // many packets - ////////////////////////////////////////////////////////////// - - // Test that the parser is able to handle many packets successively without - // doing something stupid like overflowing it's buffer - BOOST_AUTO_TEST_CASE(ManyReceives) { - LinkReceiverTest t; - LinkFrame f; - f.FormatAck(true, false, 1, 2); - - for(size_t i=1; i<100; ++i) { - t.WriteData(f); - BOOST_REQUIRE(t.IsLogErrorFree()); - BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, i); - BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_ACK, true, false, 1, 2)); - } - } - BOOST_AUTO_TEST_SUITE_END() +#include +#include + + +#include "LinkReceiverTest.h" +#include "DNPHelpers.h" + +using namespace apl; +using namespace apl::dnp; + + + + BOOST_AUTO_TEST_SUITE(AsyncLinkReceiver) + + BOOST_AUTO_TEST_CASE(InitializationState){ + LinkReceiverTest t; + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + } + + ////////////////////////////////////////////////////////////// + // CRC Failures + ////////////////////////////////////////////////////////////// + + BOOST_AUTO_TEST_CASE(HeaderCRCError) { + LinkReceiverTest t; + t.WriteData("05 64 05 C0 01 00 00 04 E9 20"); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_CRC); + } + + BOOST_AUTO_TEST_CASE(BodyCRCError) { + LinkReceiverTest t; + t.WriteData("05 64 14 F3 01 00 00 04 0A 3B C0 C3 01 3C 02 06 3C 03 06 3C 04 06 3C 01 06 9A 11"); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_CRC); + } + + ////////////////////////////////////////////////////////////// + // Illegal packets of one form or another + ////////////////////////////////////////////////////////////// + + // Change the length to something from 5 to something in [0,4] and recalc the crc + // A valid reset link states packet would be: 05 64 05 C0 01 00 00 04 E9 21 + BOOST_AUTO_TEST_CASE(BadLengthError) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 01 C0 01 00 00 04 E9 21")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_INVALID_LENGTH); + } + + //Test that the presence of user data disagrees with the function code + BOOST_AUTO_TEST_CASE(UnexpectedData) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 08 C0 01 00 00 04 E9 21")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_DATA); + } + + // Test that the absence of user data disagrees with the function code + // This is the first 10 bytes of an unconfirmed user data packet w/ the length set to 5 + BOOST_AUTO_TEST_CASE(AbsenceOfData) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 05 73 00 04 01 00 03 FC")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_NO_DATA); + } + + // Test that the parser can handle an unknown PriToSec function code + // Reset Links w/ function code changed from 0 to 6 + BOOST_AUTO_TEST_CASE(UnknownFunction) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 05 C6 01 00 00 04 E9 21")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNKNOWN_FUNC); + } + + // Test that the parser can handle an unexpected FCV bit + // Reset Links w/ FCV toggled on + BOOST_AUTO_TEST_CASE(UnexpectedFCV) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 05 D0 01 00 00 04 E9 21")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCV); + } + + // Test that the parser can handle an unexpected FCB bit for SecToPri + // ACK w/ FCB toggled on + BOOST_AUTO_TEST_CASE(UnexpectedFCB) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 05 20 00 04 01 00 19 A6")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCB); + } + + // Write two bad packets back-to-back tests that this produces + // back to back errors with a single write call + BOOST_AUTO_TEST_CASE(CombinedFailures) { + LinkReceiverTest t; + t.WriteData(RepairCRC("05 64 05 20 00 04 01 00 19 A6") + + " " + RepairCRC("05 64 05 D0 01 00 00 04 E9 21")); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 0); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCB); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_UNEXPECTED_FCV); + } + + ////////////////////////////////////////////////////////////// + // Successful packets - Sec to Pri + ////////////////////////////////////////////////////////////// + + BOOST_AUTO_TEST_CASE(ReadACK) { + LinkReceiverTest t; + LinkFrame f; + f.FormatAck(true, false, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_ACK, true, false, 1, 2)); + } + + BOOST_AUTO_TEST_CASE(ReadNACK) { + LinkReceiverTest t; + LinkFrame f; + f.FormatNack(false, true, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_NACK, false, true, 1, 2)); + } + + BOOST_AUTO_TEST_CASE(LinkStatus) { + LinkReceiverTest t; + LinkFrame f; + f.FormatLinkStatus(true, true, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_LINK_STATUS, true, true, 1, 2)); + } + + BOOST_AUTO_TEST_CASE(NotSupported) { + LinkReceiverTest t; + LinkFrame f; + f.FormatNotSupported(true, false, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_NOT_SUPPORTED, true, false, 1, 2)); + } + + ////////////////////////////////////////////////////////////// + // Successful packets - Pri To Sec + ////////////////////////////////////////////////////////////// + + BOOST_AUTO_TEST_CASE(TestLinkStates) { + LinkReceiverTest t; + LinkFrame f; + f.FormatTestLinkStatus(false, true, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLastWithFCB(FC_PRI_TEST_LINK_STATES, false, true, 1, 2)); + } + + BOOST_AUTO_TEST_CASE(ResetLinkStates) { + LinkReceiverTest t; + LinkFrame f; + f.FormatResetLinkStates(false, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_RESET_LINK_STATES, false, 1, 2)); + } + + BOOST_AUTO_TEST_CASE(RequestLinkStatus) { + LinkReceiverTest t; + LinkFrame f; + f.FormatRequestLinkStatus(true, 1, 2); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_REQUEST_LINK_STATUS, true, 1, 2)); + } + + BOOST_AUTO_TEST_CASE(UnconfirmedUserData) { + LinkReceiverTest t; + LinkFrame f; + ByteStr data(250, 0); //initializes a buffer with increasing value + f.FormatUnconfirmedUserData(true, 1, 2, data, data.Size()); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_UNCONFIRMED_USER_DATA, true, 1, 2)); + BOOST_REQUIRE(t.mSink.BufferEquals(data, data.Size())); + } + + BOOST_AUTO_TEST_CASE(ConfirmedUserData) { + LinkReceiverTest t; + LinkFrame f; + ByteStr data(250, 0); //initializes a buffer with increasing value + f.FormatConfirmedUserData(true, true, 1, 2, data, data.Size()); + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLastWithFCB(FC_PRI_CONFIRMED_USER_DATA, true, true, 1, 2)); + BOOST_REQUIRE(t.mSink.BufferEquals(data, data.Size())); + } + + ////////////////////////////////////////////////////////////// + // multi packets + ////////////////////////////////////////////////////////////// + + BOOST_AUTO_TEST_CASE(TestTwoPackets) { + LinkReceiverTest t; + // back to back reset link + t.WriteData("05 64 05 C0 01 00 00 04 E9 21 05 64 05 C0 01 00 00 04 E9 21"); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 2); + BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_RESET_LINK_STATES, true, 1, 1024)); + } + + ////////////////////////////////////////////////////////////// + // framing errors + ////////////////////////////////////////////////////////////// + + // Test that the parser is able to resync without discarding + BOOST_AUTO_TEST_CASE(Resync0564) { + LinkReceiverTest t; + t.WriteData("05 64 05 64 05 C0 01 00 00 04 E9 21"); + BOOST_REQUIRE_EQUAL(t.NextErrorCode(), DLERR_CRC); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, 1); + BOOST_REQUIRE(t.mSink.CheckLast(FC_PRI_RESET_LINK_STATES, true, 1, 1024)); + } + + ////////////////////////////////////////////////////////////// + // many packets + ////////////////////////////////////////////////////////////// + + // Test that the parser is able to handle many packets successively without + // doing something stupid like overflowing it's buffer + BOOST_AUTO_TEST_CASE(ManyReceives) { + LinkReceiverTest t; + LinkFrame f; + f.FormatAck(true, false, 1, 2); + + for(size_t i=1; i<100; ++i) { + t.WriteData(f); + BOOST_REQUIRE(t.IsLogErrorFree()); + BOOST_REQUIRE_EQUAL(t.mSink.mNumFrames, i); + BOOST_REQUIRE(t.mSink.CheckLastWithDFC(FC_SEC_ACK, true, false, 1, 2)); + } + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestObjects.cpp b/DNP3Test/TestObjects.cpp index 16d91179..ed189a6b 100644 --- a/DNP3Test/TestObjects.cpp +++ b/DNP3Test/TestObjects.cpp @@ -16,63 +16,63 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include - -using namespace apl; -using namespace std; -using namespace apl::dnp; - - - - BOOST_AUTO_TEST_SUITE(ObjectTests) - template - bool TestRange(size_t start) - { - size_t stop = start + T*8 - 1; - - Group1Var1* pObj = Group1Var1::Inst(); - - assert( stop >= start ); - assert( (stop - start + 1) <= (T*8) ); - - byte_t data[T]; - for(size_t i=0; iWrite(data, start, i, true); } - for(size_t i=0; iWrite(data, start, i, false); } - for(size_t i=0; iWrite(data, start, i, true); - BOOST_REQUIRE_EQUAL(*pPos, 1 << bit); - pObj->Write(data, start, i, false); - BOOST_REQUIRE_EQUAL(*pPos, 0); - - } - - return true; - } - - BOOST_AUTO_TEST_CASE(BitfieldObjects) - { - TestRange<1>(0); - TestRange<1>(1); - TestRange<2>(0); - TestRange<2>(3); - TestRange<4>(1234); - } - BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include + +using namespace apl; +using namespace std; +using namespace apl::dnp; + + + + BOOST_AUTO_TEST_SUITE(ObjectTests) + template + bool TestRange(size_t start) + { + size_t stop = start + T*8 - 1; + + Group1Var1* pObj = Group1Var1::Inst(); + + assert( stop >= start ); + assert( (stop - start + 1) <= (T*8) ); + + byte_t data[T]; + for(size_t i=0; iWrite(data, start, i, true); } + for(size_t i=0; iWrite(data, start, i, false); } + for(size_t i=0; iWrite(data, start, i, true); + BOOST_REQUIRE_EQUAL(*pPos, 1 << bit); + pObj->Write(data, start, i, false); + BOOST_REQUIRE_EQUAL(*pPos, 0); + + } + + return true; + } + + BOOST_AUTO_TEST_CASE(BitfieldObjects) + { + TestRange<1>(0); + TestRange<1>(1); + TestRange<2>(0); + TestRange<2>(3); + TestRange<4>(1234); + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/DNP3Test/TestResponseLoader.cpp b/DNP3Test/TestResponseLoader.cpp index 2ab15bbe..721a2459 100644 --- a/DNP3Test/TestResponseLoader.cpp +++ b/DNP3Test/TestResponseLoader.cpp @@ -16,122 +16,122 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include "ResponseLoaderTestObject.h" - - -using namespace apl; -using namespace apl::dnp; -using namespace boost; - - - BOOST_AUTO_TEST_SUITE(ResponseLoaderSuite) - BOOST_AUTO_TEST_CASE(Group1Var1) - { - ResponseLoaderTestObject t; - t.CheckBinaries("C0 81 00 00 01 01 00 01 03 02", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group1Var2) - { - ResponseLoaderTestObject t; - t.CheckBinaries("C0 81 00 00 01 02 00 01 03 01 81 01", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var1) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 01 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var2) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 02 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var3) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 03 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var4) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 04 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var5) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 05 00 00 01 04 00 00 00 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var6) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 06 00 00 01 04 00 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var7) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 07 00 00 01 04 00 00 00 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group20Var8) - { - ResponseLoaderTestObject t; - t.CheckCounters("C0 81 00 00 14 08 00 00 01 04 00 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group30Var1) - { - ResponseLoaderTestObject t; - t.CheckAnalogs("C0 81 00 00 1E 01 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group30Var2) - { - ResponseLoaderTestObject t; - t.CheckAnalogs("C0 81 00 00 1E 02 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group30Var3) - { - ResponseLoaderTestObject t; - t.CheckAnalogs("C0 81 00 00 1E 03 00 00 01 04 00 00 00 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group30Var4) - { - ResponseLoaderTestObject t; - t.CheckAnalogs("C0 81 00 00 1E 04 00 00 01 04 00 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group30Var6) - { - ResponseLoaderTestObject t; - t.Load("C0 81 00 00 1E 06 00 00 00 01 20 74 85 2F C7 2B A2 C0", TimeStamp_t(20)); - - BOOST_REQUIRE_EQUAL(t.fdo.mAnalogMap.size(), 1); - BOOST_REQUIRE_EQUAL(t.fdo.GetTotalCount(), 1); - } - - BOOST_AUTO_TEST_CASE(Group40Var1) - { - ResponseLoaderTestObject t; - t.CheckSetpointStatii("C0 81 00 00 28 01 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_CASE(Group40Var2) - { - ResponseLoaderTestObject t; - t.CheckSetpointStatii("C0 81 00 00 28 02 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); - } - - BOOST_AUTO_TEST_SUITE_END() //end suite - +#include +#include + +#include "ResponseLoaderTestObject.h" + + +using namespace apl; +using namespace apl::dnp; +using namespace boost; + + + BOOST_AUTO_TEST_SUITE(ResponseLoaderSuite) + BOOST_AUTO_TEST_CASE(Group1Var1) + { + ResponseLoaderTestObject t; + t.CheckBinaries("C0 81 00 00 01 01 00 01 03 02", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group1Var2) + { + ResponseLoaderTestObject t; + t.CheckBinaries("C0 81 00 00 01 02 00 01 03 01 81 01", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var1) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 01 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var2) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 02 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var3) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 03 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var4) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 04 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var5) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 05 00 00 01 04 00 00 00 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var6) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 06 00 00 01 04 00 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var7) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 07 00 00 01 04 00 00 00 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group20Var8) + { + ResponseLoaderTestObject t; + t.CheckCounters("C0 81 00 00 14 08 00 00 01 04 00 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group30Var1) + { + ResponseLoaderTestObject t; + t.CheckAnalogs("C0 81 00 00 1E 01 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group30Var2) + { + ResponseLoaderTestObject t; + t.CheckAnalogs("C0 81 00 00 1E 02 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group30Var3) + { + ResponseLoaderTestObject t; + t.CheckAnalogs("C0 81 00 00 1E 03 00 00 01 04 00 00 00 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group30Var4) + { + ResponseLoaderTestObject t; + t.CheckAnalogs("C0 81 00 00 1E 04 00 00 01 04 00 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group30Var6) + { + ResponseLoaderTestObject t; + t.Load("C0 81 00 00 1E 06 00 00 00 01 20 74 85 2F C7 2B A2 C0", TimeStamp_t(20)); + + BOOST_REQUIRE_EQUAL(t.fdo.mAnalogMap.size(), 1); + BOOST_REQUIRE_EQUAL(t.fdo.GetTotalCount(), 1); + } + + BOOST_AUTO_TEST_CASE(Group40Var1) + { + ResponseLoaderTestObject t; + t.CheckSetpointStatii("C0 81 00 00 28 01 00 00 01 01 04 00 00 00 01 09 00 00 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_CASE(Group40Var2) + { + ResponseLoaderTestObject t; + t.CheckSetpointStatii("C0 81 00 00 28 02 00 00 01 01 04 00 01 09 00", TimeStamp_t(20)); + } + + BOOST_AUTO_TEST_SUITE_END() //end suite + diff --git a/DNP3Test/TestStartupTeardown.cpp b/DNP3Test/TestStartupTeardown.cpp index e7f2700e..812036f7 100644 --- a/DNP3Test/TestStartupTeardown.cpp +++ b/DNP3Test/TestStartupTeardown.cpp @@ -16,46 +16,46 @@ // specific language governing permissions and limitations // under the License. // -#include -#include -#include - -#include "AsyncStartupTeardownTest.h" - -using namespace std; -using namespace apl; -using namespace apl::dnp; - -BOOST_AUTO_TEST_SUITE(AsyncIntegrationSuite) - - /// This test aggressively starts and stops stacks - /// while the io_service is running - BOOST_AUTO_TEST_CASE(StackTearDown) - { - const size_t NUM_STACKS = 10; - const size_t NUM_PORTS = 10; - - FilterLevel lev = LEV_WARNING; - - AsyncStartupTeardownTest t(lev, true); //autostart = true - - for(size_t i=0; i(i), LEV_WARNING); - } - } - - // shutdown starts when the destructor is called. - } - -BOOST_AUTO_TEST_SUITE_END() - +#include +#include +#include + +#include "AsyncStartupTeardownTest.h" + +using namespace std; +using namespace apl; +using namespace apl::dnp; + +BOOST_AUTO_TEST_SUITE(AsyncIntegrationSuite) + + /// This test aggressively starts and stops stacks + /// while the io_service is running + BOOST_AUTO_TEST_CASE(StackTearDown) + { + const size_t NUM_STACKS = 10; + const size_t NUM_PORTS = 10; + + FilterLevel lev = LEV_WARNING; + + AsyncStartupTeardownTest t(lev, true); //autostart = true + + for(size_t i=0; i(i), LEV_WARNING); + } + } + + // shutdown starts when the destructor is called. + } + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/DNP3Test/TransportIntegrationStack.h b/DNP3Test/TransportIntegrationStack.h index d375ce6e..6fab5ae3 100644 --- a/DNP3Test/TransportIntegrationStack.h +++ b/DNP3Test/TransportIntegrationStack.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_INTEGRATION_STACK_H_ #define __TRANSPORT_INTEGRATION_STACK_H_ diff --git a/DNP3Test/TransportLoopbackTestObject.cpp b/DNP3Test/TransportLoopbackTestObject.cpp index 5a07f3a9..06d6e2b2 100644 --- a/DNP3Test/TransportLoopbackTestObject.cpp +++ b/DNP3Test/TransportLoopbackTestObject.cpp @@ -16,65 +16,65 @@ // specific language governing permissions and limitations // under the License. // -#include "TransportLoopbackTestObject.h" - -#include -#include - -using namespace std; - -namespace apl { namespace dnp { - -TransportLoopbackTestObject::TransportLoopbackTestObject( - boost::asio::io_service* apService, - IPhysicalLayerAsync* apPhys, - LinkConfig aCfgA, - LinkConfig aCfgB, - FilterLevel aLevel, - bool aImmediate) : - -LogTester(aImmediate), -AsyncTestObjectASIO(apService), -mpLogger(mLog.GetLogger(aLevel, "test")), -mTimerSource(this->GetService()), -mCfgA(aCfgA), -mCfgB(aCfgB), -mLinkA(mpLogger, &mTimerSource, aCfgA), -mLinkB(mpLogger, &mTimerSource, aCfgB), -mTransA(mpLogger), -mTransB(mpLogger), -mRouter(mpLogger, apPhys, &mTimerSource, 1000), -mUpperA(mpLogger), -mUpperB(mpLogger) -{ - mRouter.AddContext(&mLinkA, mCfgA.LocalAddr); - mRouter.AddContext(&mLinkB, mCfgB.LocalAddr); - - mLinkA.SetUpperLayer(&mTransA); - mLinkB.SetUpperLayer(&mTransB); - - mLinkA.SetRouter(&mRouter); - mLinkB.SetRouter(&mRouter); - - mTransA.SetUpperLayer(&mUpperA); - mTransB.SetUpperLayer(&mUpperB); -} - -TransportLoopbackTestObject::~TransportLoopbackTestObject() -{ - mRouter.Stop(); -} - -bool TransportLoopbackTestObject::LayersUp() -{ - return mUpperA.IsLowerLayerUp() && mUpperB.IsLowerLayerUp(); -} - -void TransportLoopbackTestObject::Start() -{ - mRouter.Start(); -} - -}} - - +#include "TransportLoopbackTestObject.h" + +#include +#include + +using namespace std; + +namespace apl { namespace dnp { + +TransportLoopbackTestObject::TransportLoopbackTestObject( + boost::asio::io_service* apService, + IPhysicalLayerAsync* apPhys, + LinkConfig aCfgA, + LinkConfig aCfgB, + FilterLevel aLevel, + bool aImmediate) : + +LogTester(aImmediate), +AsyncTestObjectASIO(apService), +mpLogger(mLog.GetLogger(aLevel, "test")), +mTimerSource(this->GetService()), +mCfgA(aCfgA), +mCfgB(aCfgB), +mLinkA(mpLogger, &mTimerSource, aCfgA), +mLinkB(mpLogger, &mTimerSource, aCfgB), +mTransA(mpLogger), +mTransB(mpLogger), +mRouter(mpLogger, apPhys, &mTimerSource, 1000), +mUpperA(mpLogger), +mUpperB(mpLogger) +{ + mRouter.AddContext(&mLinkA, mCfgA.LocalAddr); + mRouter.AddContext(&mLinkB, mCfgB.LocalAddr); + + mLinkA.SetUpperLayer(&mTransA); + mLinkB.SetUpperLayer(&mTransB); + + mLinkA.SetRouter(&mRouter); + mLinkB.SetRouter(&mRouter); + + mTransA.SetUpperLayer(&mUpperA); + mTransB.SetUpperLayer(&mUpperB); +} + +TransportLoopbackTestObject::~TransportLoopbackTestObject() +{ + mRouter.Stop(); +} + +bool TransportLoopbackTestObject::LayersUp() +{ + return mUpperA.IsLowerLayerUp() && mUpperB.IsLowerLayerUp(); +} + +void TransportLoopbackTestObject::Start() +{ + mRouter.Start(); +} + +}} + + diff --git a/DNP3Test/TransportLoopbackTestObject.h b/DNP3Test/TransportLoopbackTestObject.h index 1f1bab6a..73b7313a 100644 --- a/DNP3Test/TransportLoopbackTestObject.h +++ b/DNP3Test/TransportLoopbackTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_LOOPBACK_TEST_OBJECT_H_ #define __TRANSPORT_LOOPBACK_TEST_OBJECT_H_ @@ -49,12 +49,12 @@ class TransportLoopbackTestObject : public LogTester, public AsyncTestObjectASIO bool LayersUp(); void Start(); - + private: Logger* mpLogger; TimerSourceASIO mTimerSource; - + LinkConfig mCfgA; LinkConfig mCfgB; diff --git a/DNP3Test/TransportScalabilityTestObject.cpp b/DNP3Test/TransportScalabilityTestObject.cpp index df1749b6..ff238ba6 100644 --- a/DNP3Test/TransportScalabilityTestObject.cpp +++ b/DNP3Test/TransportScalabilityTestObject.cpp @@ -16,88 +16,88 @@ // specific language governing permissions and limitations // under the License. // -#include - -#include "TransportScalabilityTestObject.h" -#include -#include - -using namespace std; - -namespace apl { namespace dnp { - -TransportScalabilityTestObject::TransportScalabilityTestObject( - LinkConfig aClientCfg, - LinkConfig aServerCfg, - uint_16_t aPortStart, - uint_16_t aNumPair, - FilterLevel aLevel, - bool aImmediate) : - -LogTester(aImmediate), -AsyncTestObjectASIO(), -mpLogger(mLog.GetLogger(aLevel, "test")), -mTimerSource(this->GetService()) -{ - const uint_16_t START = aPortStart; - const uint_16_t STOP = START + aNumPair; - - for(uint_16_t port = START; port < STOP; ++port) { - ostringstream oss; - oss << "pair" << port; - Logger* pLogger = mpLogger->GetSubLogger(oss.str()); - TransportStackPair* pPair = new TransportStackPair(aClientCfg, aServerCfg, pLogger, this->GetService(), &mTimerSource, port); - mPairs.push_back(pPair); - } -} - -TransportScalabilityTestObject::~TransportScalabilityTestObject() -{ - BOOST_FOREACH(TransportStackPair* pPair, mPairs) delete pPair; -} - -bool TransportScalabilityTestObject::AllLayersUp() -{ - BOOST_FOREACH(TransportStackPair* pPair, mPairs) { - if(!pPair->BothLayersUp()) return false; - } - - return true; -} - -bool TransportScalabilityTestObject::AllLayerEqual(const byte_t* apData, size_t aNumBytes) -{ - BOOST_FOREACH(TransportStackPair* pPair, mPairs) { - if(! pPair->mServerStack.mUpper.BufferEquals(apData, aNumBytes)) return false; - if(! pPair->mClientStack.mUpper.BufferEquals(apData, aNumBytes)) return false; - } - - return true; -} - -bool TransportScalabilityTestObject::AllLayerReceived(size_t aNumBytes) -{ - BOOST_FOREACH(TransportStackPair* pPair, mPairs) { - if(pPair->mServerStack.mUpper.Size() != aNumBytes) return false; - if(pPair->mClientStack.mUpper.Size() != aNumBytes) return false; - } - - return true; -} - -void TransportScalabilityTestObject::SendToAll(const byte_t* apData, size_t aNumBytes) -{ - BOOST_FOREACH(TransportStackPair* pPair, mPairs) { - pPair->mClientStack.mUpper.SendDown(apData, aNumBytes); - pPair->mServerStack.mUpper.SendDown(apData, aNumBytes); - } -} - -void TransportScalabilityTestObject::Start() -{ - BOOST_FOREACH(TransportStackPair* pPair, mPairs) { pPair->Start(); } -} - -}} - - +#include + +#include "TransportScalabilityTestObject.h" +#include +#include + +using namespace std; + +namespace apl { namespace dnp { + +TransportScalabilityTestObject::TransportScalabilityTestObject( + LinkConfig aClientCfg, + LinkConfig aServerCfg, + uint_16_t aPortStart, + uint_16_t aNumPair, + FilterLevel aLevel, + bool aImmediate) : + +LogTester(aImmediate), +AsyncTestObjectASIO(), +mpLogger(mLog.GetLogger(aLevel, "test")), +mTimerSource(this->GetService()) +{ + const uint_16_t START = aPortStart; + const uint_16_t STOP = START + aNumPair; + + for(uint_16_t port = START; port < STOP; ++port) { + ostringstream oss; + oss << "pair" << port; + Logger* pLogger = mpLogger->GetSubLogger(oss.str()); + TransportStackPair* pPair = new TransportStackPair(aClientCfg, aServerCfg, pLogger, this->GetService(), &mTimerSource, port); + mPairs.push_back(pPair); + } +} + +TransportScalabilityTestObject::~TransportScalabilityTestObject() +{ + BOOST_FOREACH(TransportStackPair* pPair, mPairs) delete pPair; +} + +bool TransportScalabilityTestObject::AllLayersUp() +{ + BOOST_FOREACH(TransportStackPair* pPair, mPairs) { + if(!pPair->BothLayersUp()) return false; + } + + return true; +} + +bool TransportScalabilityTestObject::AllLayerEqual(const byte_t* apData, size_t aNumBytes) +{ + BOOST_FOREACH(TransportStackPair* pPair, mPairs) { + if(! pPair->mServerStack.mUpper.BufferEquals(apData, aNumBytes)) return false; + if(! pPair->mClientStack.mUpper.BufferEquals(apData, aNumBytes)) return false; + } + + return true; +} + +bool TransportScalabilityTestObject::AllLayerReceived(size_t aNumBytes) +{ + BOOST_FOREACH(TransportStackPair* pPair, mPairs) { + if(pPair->mServerStack.mUpper.Size() != aNumBytes) return false; + if(pPair->mClientStack.mUpper.Size() != aNumBytes) return false; + } + + return true; +} + +void TransportScalabilityTestObject::SendToAll(const byte_t* apData, size_t aNumBytes) +{ + BOOST_FOREACH(TransportStackPair* pPair, mPairs) { + pPair->mClientStack.mUpper.SendDown(apData, aNumBytes); + pPair->mServerStack.mUpper.SendDown(apData, aNumBytes); + } +} + +void TransportScalabilityTestObject::Start() +{ + BOOST_FOREACH(TransportStackPair* pPair, mPairs) { pPair->Start(); } +} + +}} + + diff --git a/DNP3Test/TransportScalabilityTestObject.h b/DNP3Test/TransportScalabilityTestObject.h index fb046957..480fd108 100644 --- a/DNP3Test/TransportScalabilityTestObject.h +++ b/DNP3Test/TransportScalabilityTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_SCALABILITY_TEST_OBJECT_H_ #define __TRANSPORT_SCALABILITY_TEST_OBJECT_H_ @@ -42,7 +42,7 @@ class TransportScalabilityTestObject : public LogTester, public AsyncTestObjectA void Start(); - + // Test helpers bool AllLayersUp(); bool AllLayerReceived(size_t aNumBytes); @@ -53,7 +53,7 @@ class TransportScalabilityTestObject : public LogTester, public AsyncTestObjectA public: Logger* mpLogger; TimerSourceASIO mTimerSource; - std::vector mPairs; + std::vector mPairs; }; }} diff --git a/DNP3Test/TransportStackPair.cpp b/DNP3Test/TransportStackPair.cpp index 1b591252..93e03509 100644 --- a/DNP3Test/TransportStackPair.cpp +++ b/DNP3Test/TransportStackPair.cpp @@ -16,41 +16,41 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "TransportStackPair.h" - -#include - -namespace apl { namespace dnp { - -TransportStackPair::TransportStackPair( - LinkConfig aClientCfg, - LinkConfig aServerCfg, - Logger* apLogger, - boost::asio::io_service* apService, - ITimerSource* apTimerSrc, - uint_16_t aPort) : - -mClient(apLogger->GetSubLogger("TCPClient"), apService, "127.0.0.1", aPort), -mServer(apLogger->GetSubLogger("TCPServer"), apService, aPort), -mClientStack(apLogger->GetSubLogger("ClientStack"), apTimerSrc, &mClient, aClientCfg), -mServerStack(apLogger->GetSubLogger("ServerStack"), apTimerSrc, &mServer, aServerCfg) -{ - -} - -bool TransportStackPair::BothLayersUp() -{ - return mServerStack.mUpper.IsLowerLayerUp() - && mClientStack.mUpper.IsLowerLayerUp(); -} - -void TransportStackPair::Start() -{ - mServerStack.mRouter.Start(); - mClientStack.mRouter.Start(); -} - - -}} - +#include +#include "TransportStackPair.h" + +#include + +namespace apl { namespace dnp { + +TransportStackPair::TransportStackPair( + LinkConfig aClientCfg, + LinkConfig aServerCfg, + Logger* apLogger, + boost::asio::io_service* apService, + ITimerSource* apTimerSrc, + uint_16_t aPort) : + +mClient(apLogger->GetSubLogger("TCPClient"), apService, "127.0.0.1", aPort), +mServer(apLogger->GetSubLogger("TCPServer"), apService, aPort), +mClientStack(apLogger->GetSubLogger("ClientStack"), apTimerSrc, &mClient, aClientCfg), +mServerStack(apLogger->GetSubLogger("ServerStack"), apTimerSrc, &mServer, aServerCfg) +{ + +} + +bool TransportStackPair::BothLayersUp() +{ + return mServerStack.mUpper.IsLowerLayerUp() + && mClientStack.mUpper.IsLowerLayerUp(); +} + +void TransportStackPair::Start() +{ + mServerStack.mRouter.Start(); + mClientStack.mRouter.Start(); +} + + +}} + diff --git a/DNP3Test/TransportStackPair.h b/DNP3Test/TransportStackPair.h index dedeb84e..6ac59c2f 100644 --- a/DNP3Test/TransportStackPair.h +++ b/DNP3Test/TransportStackPair.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_STACK_PAIR_H_ #define __TRANSPORT_STACK_PAIR_H_ @@ -54,7 +54,7 @@ class TransportStackPair TransportIntegrationStack mClientStack; TransportIntegrationStack mServerStack; - + }; }} diff --git a/DNP3Test/TransportTestObject.cpp b/DNP3Test/TransportTestObject.cpp index 54ea6f81..57a303e1 100644 --- a/DNP3Test/TransportTestObject.cpp +++ b/DNP3Test/TransportTestObject.cpp @@ -16,59 +16,59 @@ // specific language governing permissions and limitations // under the License. // -#include "TransportTestObject.h" - -#include -#include -#include -#include - - -using namespace std; - -namespace apl { namespace dnp { - -TransportTestObject::TransportTestObject(bool aOpenOnStart, FilterLevel aLevel, bool aImmediate) : -LogTester(aImmediate), -mpLogger(mLog.GetLogger(aLevel, "TransportTestObject")), -transport(mpLogger), -lower(mpLogger), -upper(mpLogger) -{ - lower.SetUpperLayer(&transport); - transport.SetUpperLayer(&upper); - - if(aOpenOnStart) lower.ThisLayerUp(); -} - -std::string TransportTestObject::GetData(const std::string& arHdr, byte_t aSeed, size_t aLength) -{ - ByteStr buff(aLength); - byte_t val = aSeed; - for(size_t i=0; i 0) oss << arHdr << " "; - oss << toHex(buff, buff.Size(), true); - return oss.str(); -} - -std::string TransportTestObject::GeneratePacketSequence(vector< std::string >& arVec, size_t aNumPackets, size_t aLastPacketLength) -{ - ostringstream oss; - for(size_t i=0; i(i%64); - size_t len = fin ? aLastPacketLength : TL_MAX_TPDU_PAYLOAD; - byte_t hdr = TransportTx::GetHeader(fir, fin, seq); - std::string data = this->GetData("", 0, len); //raw data with no header - oss << ((i==0) ? "" : " ") << data; //cache the data in the string stream - arVec.push_back(toHex(&hdr, 1, true) + " " + data); - } - - return oss.str(); -} - -}} +#include "TransportTestObject.h" + +#include +#include +#include +#include + + +using namespace std; + +namespace apl { namespace dnp { + +TransportTestObject::TransportTestObject(bool aOpenOnStart, FilterLevel aLevel, bool aImmediate) : +LogTester(aImmediate), +mpLogger(mLog.GetLogger(aLevel, "TransportTestObject")), +transport(mpLogger), +lower(mpLogger), +upper(mpLogger) +{ + lower.SetUpperLayer(&transport); + transport.SetUpperLayer(&upper); + + if(aOpenOnStart) lower.ThisLayerUp(); +} + +std::string TransportTestObject::GetData(const std::string& arHdr, byte_t aSeed, size_t aLength) +{ + ByteStr buff(aLength); + byte_t val = aSeed; + for(size_t i=0; i 0) oss << arHdr << " "; + oss << toHex(buff, buff.Size(), true); + return oss.str(); +} + +std::string TransportTestObject::GeneratePacketSequence(vector< std::string >& arVec, size_t aNumPackets, size_t aLastPacketLength) +{ + ostringstream oss; + for(size_t i=0; i(i%64); + size_t len = fin ? aLastPacketLength : TL_MAX_TPDU_PAYLOAD; + byte_t hdr = TransportTx::GetHeader(fir, fin, seq); + std::string data = this->GetData("", 0, len); //raw data with no header + oss << ((i==0) ? "" : " ") << data; //cache the data in the string stream + arVec.push_back(toHex(&hdr, 1, true) + " " + data); + } + + return oss.str(); +} + +}} diff --git a/DNP3Test/TransportTestObject.h b/DNP3Test/TransportTestObject.h index bd77cee3..6ab6b943 100644 --- a/DNP3Test/TransportTestObject.h +++ b/DNP3Test/TransportTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __TRANSPORT_TEST_OBJECT_H_ #define __TRANSPORT_TEST_OBJECT_H_ @@ -39,7 +39,7 @@ class TransportTestObject : public LogTester /// Generate a complete packet sequence inside the vector and /// return the corresponding reassembled APDU std::string GeneratePacketSequence(std::vector&, size_t aNumPackets, size_t aLastPacketLength); - + /// Get a Sequence of data w/ optional header std::string GetData(const std::string& arHdr, byte_t aSeed = 0, size_t aLength = TL_MAX_TPDU_PAYLOAD); @@ -48,10 +48,10 @@ class TransportTestObject : public LogTester AsyncTransportLayer transport; public: - + MockLowerLayer lower; MockUpperLayer upper; - + }; diff --git a/DNP3Test/rake.project.rb b/DNP3Test/rake.project.rb index 220d8ea3..ee4f5894 100644 --- a/DNP3Test/rake.project.rb +++ b/DNP3Test/rake.project.rb @@ -16,10 +16,10 @@ # specific language governing permissions and limitations # under the License. # -#setup the dnp3test project -$options = { -:target => 'dnp3test.exe', -:project_libs => [:dnp3, :apltesttools, :apl], -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -:libs => $PLATFORM_LIBS + Boost::get_static_libs -} +#setup the dnp3test project +$options = { +:target => 'dnp3test.exe', +:project_libs => [:dnp3, :apltesttools, :apl], +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +:libs => $PLATFORM_LIBS + Boost::get_static_libs +} diff --git a/DNP3XML/DNP3XML.vcproj b/DNP3XML/DNP3XML.vcproj index 479e28e9..9b03b66c 100755 --- a/DNP3XML/DNP3XML.vcproj +++ b/DNP3XML/DNP3XML.vcproj @@ -1,175 +1,175 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DNP3XML/XML_DNP3.cpp b/DNP3XML/XML_DNP3.cpp index aaa5e1f1..cb93ee16 100644 --- a/DNP3XML/XML_DNP3.cpp +++ b/DNP3XML/XML_DNP3.cpp @@ -16,184 +16,184 @@ // specific language governing permissions and limitations // under the License. // -#include "XML_DNP3.h" - -#include -#include - -#include - -#include -#include -#include -#include - -namespace apl{ namespace dnp{ - - void XML_DNP3::Configure(APLXML_DNP::Master_t& arMaster, bool aUnsol) - { - arMaster.MasterSettings.TaskRetryMS = 5000; - - arMaster.Unsol.DoTask = aUnsol; - arMaster.Unsol.Enable = aUnsol; - arMaster.Unsol.Class1 = true; - arMaster.Unsol.Class2 = true; - arMaster.Unsol.Class3 = true; - - arMaster.MasterSettings.IntegrityPeriodMS = 60000; - - if(!aUnsol) - { - APLXML_DNP::ExceptionScan_t* pScan = new APLXML_DNP::ExceptionScan_t(); - pScan->Class1 = pScan->Class2 = pScan->Class3 = true; - pScan->PeriodMS = 2000; - arMaster.ScanList.ExceptionScanVector.push_back(pScan); - } - - // Configure the LinkLayer - Configure(arMaster.Stack, false); - } - - void XML_DNP3::Configure(APLXML_DNP::Slave_t& arSlave) - { - //arSlave.SlaveConfig.SlaveConfig.MaxControls = 10; - arSlave.SlaveConfig.MaxBinaryEvents = 100; - arSlave.SlaveConfig.MaxAnalogEvents = 100; - arSlave.SlaveConfig.MaxCounterEvents = 100; - arSlave.SlaveConfig.UnsolDefaults.PackDelayMS = 200; - arSlave.SlaveConfig.UnsolDefaults.RetryMS = 2000; - - arSlave.SlaveConfig.StaticRsp.BinaryGrpVar.Grp = 1; - arSlave.SlaveConfig.StaticRsp.BinaryGrpVar.Var = 2; - arSlave.SlaveConfig.StaticRsp.AnalogGrpVar.Grp = 30; - arSlave.SlaveConfig.StaticRsp.AnalogGrpVar.Var = 1; - arSlave.SlaveConfig.StaticRsp.CounterGrpVar.Grp = 20; - arSlave.SlaveConfig.StaticRsp.CounterGrpVar.Var = 1; - arSlave.SlaveConfig.StaticRsp.SetpointStatusGrpVar.Grp = 40; - arSlave.SlaveConfig.StaticRsp.SetpointStatusGrpVar.Var = 1; - - arSlave.SlaveConfig.EventRsp.BinaryGrpVar.Grp = 2; - arSlave.SlaveConfig.EventRsp.BinaryGrpVar.Var = 1; - arSlave.SlaveConfig.EventRsp.AnalogGrpVar.Grp = 32; - arSlave.SlaveConfig.EventRsp.AnalogGrpVar.Var = 1; - arSlave.SlaveConfig.EventRsp.CounterGrpVar.Grp = 22; - arSlave.SlaveConfig.EventRsp.CounterGrpVar.Var = 1; - - arSlave.SlaveConfig.TimeIINTask.DoTask = false; - arSlave.SlaveConfig.TimeIINTask.PeriodMS = 30000; - - Configure(arSlave.Stack, true); - } - - void XML_DNP3::Configure(APLXML_DNP::Stack_t& arStack, bool aSlave) - { - arStack.LinkLayer.AckTimeoutMS = 1000; - arStack.LinkLayer.IsMaster = aSlave ? false : true; - arStack.LinkLayer.LocalAddress = aSlave ? 1 : 100; - arStack.LinkLayer.NumRetries = 3; - arStack.LinkLayer.RemoteAddress = aSlave ? 100 : 1; - arStack.LinkLayer.UseConfirmations = false; - - arStack.AppLayer.TimeoutMS = 10000; - arStack.AppLayer.MaxFragSize = apl::dnp::DEFAULT_FRAG_SIZE; - arStack.AppLayer.NumRetries = 3; - } - - std::string DefaultName(const std::string aBase, size_t aCount) - { - std::ostringstream oss; - oss << aBase; - if (aCount < 10) oss << "0"; - oss << aCount; - return oss.str(); - } - - void XML_DNP3::AddDeviceTemplateBinary(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::Binary_t* b = new APLXML_DNP::Binary_t(); - b->ClassGroup = 1; - b->Index = boost::numeric::converter::convert(aIndex); - b->Name = aName; - arCfg.BinaryData.BinaryVector.push_back(b); - } - - void XML_DNP3::AddDeviceTemplateAnalog(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::Analog_t* b = new APLXML_DNP::Analog_t(); - b->ClassGroup = 1; - b->Index = boost::numeric::converter::convert(aIndex); - b->Name = aName; - b->Deadband = 0; - arCfg.AnalogData.AnalogVector.push_back(b); - } - - void XML_DNP3::AddDeviceTemplateCounter(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::Counter_t* b = new APLXML_DNP::Counter_t(); - b->ClassGroup = 1; - b->Index = boost::numeric::converter::convert(aIndex); - b->Name = aName; - arCfg.CounterData.CounterVector.push_back(b); - } - - void XML_DNP3::AddDeviceTemplateControl(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::Control_t* b = new APLXML_DNP::Control_t(); - b->Index = boost::numeric::converter::convert(aIndex); - b->Name = aName; - b->ControlMode = "SBO"; - b->SelectTimeoutMS = 5000; - arCfg.ControlData.ControlVector.push_back(b); - } - - void XML_DNP3::AddDeviceTemplateSetpoint(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::Setpoint_t* b = new APLXML_DNP::Setpoint_t(); - b->Index = boost::numeric::converter::convert(aIndex); - b->Name = aName; - b->ControlMode = "SBO"; - b->SelectTimeoutMS = 5000; - arCfg.SetpointData.SetpointVector.push_back(b); - } - void XML_DNP3::AddDeviceTemplateControlStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::ControlStatus_t* cs = new APLXML_DNP::ControlStatus_t(); - cs->Index = boost::numeric::converter::convert(aIndex); - cs->Name = aName; - arCfg.ControlStatusData.ControlStatusVector.push_back(cs); - } - void XML_DNP3::AddDeviceTemplateSetpointStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) - { - APLXML_DNP::SetpointStatus_t* ss = new APLXML_DNP::SetpointStatus_t(); - ss->Index = boost::numeric::converter::convert(aIndex); - ss->Name = aName; - arCfg.SetpointStatusData.SetpointStatusVector.push_back(ss); - } - - void XML_DNP3::Configure(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aBinaries, size_t aAnalogs, size_t aCounters, size_t aControls, size_t aSetpoints, size_t aControlStatuses, size_t aSetpointStatuses) - { - arCfg.TemplateName = "default"; - - for(size_t i = 0; i < aBinaries; i++){ - AddDeviceTemplateBinary(arCfg, i, DefaultName("binary",i)); - } - for(size_t i = 0; i < aAnalogs; i++){ - AddDeviceTemplateAnalog(arCfg, i, DefaultName("analog",i)); - } - for(size_t i = 0; i < aCounters; i++){ - AddDeviceTemplateCounter(arCfg, i, DefaultName("counter",i)); - } - for(size_t i = 0; i < aControls; i++){ - AddDeviceTemplateControl(arCfg, i, DefaultName("control",i)); - } - for(size_t i = 0; i < aSetpoints; i++){ - AddDeviceTemplateSetpoint(arCfg, i, DefaultName("setpoint",i)); - } - for(size_t i = 0; i < aControlStatuses; i++ ) { - AddDeviceTemplateControlStatus(arCfg, i, DefaultName("controlstatus",i)); - } - for(size_t i = 0; i < aSetpointStatuses; i++ ) { - AddDeviceTemplateSetpointStatus(arCfg, i, DefaultName("setpointstatus",i)); - } - } -}} +#include "XML_DNP3.h" + +#include +#include + +#include + +#include +#include +#include +#include + +namespace apl{ namespace dnp{ + + void XML_DNP3::Configure(APLXML_DNP::Master_t& arMaster, bool aUnsol) + { + arMaster.MasterSettings.TaskRetryMS = 5000; + + arMaster.Unsol.DoTask = aUnsol; + arMaster.Unsol.Enable = aUnsol; + arMaster.Unsol.Class1 = true; + arMaster.Unsol.Class2 = true; + arMaster.Unsol.Class3 = true; + + arMaster.MasterSettings.IntegrityPeriodMS = 60000; + + if(!aUnsol) + { + APLXML_DNP::ExceptionScan_t* pScan = new APLXML_DNP::ExceptionScan_t(); + pScan->Class1 = pScan->Class2 = pScan->Class3 = true; + pScan->PeriodMS = 2000; + arMaster.ScanList.ExceptionScanVector.push_back(pScan); + } + + // Configure the LinkLayer + Configure(arMaster.Stack, false); + } + + void XML_DNP3::Configure(APLXML_DNP::Slave_t& arSlave) + { + //arSlave.SlaveConfig.SlaveConfig.MaxControls = 10; + arSlave.SlaveConfig.MaxBinaryEvents = 100; + arSlave.SlaveConfig.MaxAnalogEvents = 100; + arSlave.SlaveConfig.MaxCounterEvents = 100; + arSlave.SlaveConfig.UnsolDefaults.PackDelayMS = 200; + arSlave.SlaveConfig.UnsolDefaults.RetryMS = 2000; + + arSlave.SlaveConfig.StaticRsp.BinaryGrpVar.Grp = 1; + arSlave.SlaveConfig.StaticRsp.BinaryGrpVar.Var = 2; + arSlave.SlaveConfig.StaticRsp.AnalogGrpVar.Grp = 30; + arSlave.SlaveConfig.StaticRsp.AnalogGrpVar.Var = 1; + arSlave.SlaveConfig.StaticRsp.CounterGrpVar.Grp = 20; + arSlave.SlaveConfig.StaticRsp.CounterGrpVar.Var = 1; + arSlave.SlaveConfig.StaticRsp.SetpointStatusGrpVar.Grp = 40; + arSlave.SlaveConfig.StaticRsp.SetpointStatusGrpVar.Var = 1; + + arSlave.SlaveConfig.EventRsp.BinaryGrpVar.Grp = 2; + arSlave.SlaveConfig.EventRsp.BinaryGrpVar.Var = 1; + arSlave.SlaveConfig.EventRsp.AnalogGrpVar.Grp = 32; + arSlave.SlaveConfig.EventRsp.AnalogGrpVar.Var = 1; + arSlave.SlaveConfig.EventRsp.CounterGrpVar.Grp = 22; + arSlave.SlaveConfig.EventRsp.CounterGrpVar.Var = 1; + + arSlave.SlaveConfig.TimeIINTask.DoTask = false; + arSlave.SlaveConfig.TimeIINTask.PeriodMS = 30000; + + Configure(arSlave.Stack, true); + } + + void XML_DNP3::Configure(APLXML_DNP::Stack_t& arStack, bool aSlave) + { + arStack.LinkLayer.AckTimeoutMS = 1000; + arStack.LinkLayer.IsMaster = aSlave ? false : true; + arStack.LinkLayer.LocalAddress = aSlave ? 1 : 100; + arStack.LinkLayer.NumRetries = 3; + arStack.LinkLayer.RemoteAddress = aSlave ? 100 : 1; + arStack.LinkLayer.UseConfirmations = false; + + arStack.AppLayer.TimeoutMS = 10000; + arStack.AppLayer.MaxFragSize = apl::dnp::DEFAULT_FRAG_SIZE; + arStack.AppLayer.NumRetries = 3; + } + + std::string DefaultName(const std::string aBase, size_t aCount) + { + std::ostringstream oss; + oss << aBase; + if (aCount < 10) oss << "0"; + oss << aCount; + return oss.str(); + } + + void XML_DNP3::AddDeviceTemplateBinary(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::Binary_t* b = new APLXML_DNP::Binary_t(); + b->ClassGroup = 1; + b->Index = boost::numeric::converter::convert(aIndex); + b->Name = aName; + arCfg.BinaryData.BinaryVector.push_back(b); + } + + void XML_DNP3::AddDeviceTemplateAnalog(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::Analog_t* b = new APLXML_DNP::Analog_t(); + b->ClassGroup = 1; + b->Index = boost::numeric::converter::convert(aIndex); + b->Name = aName; + b->Deadband = 0; + arCfg.AnalogData.AnalogVector.push_back(b); + } + + void XML_DNP3::AddDeviceTemplateCounter(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::Counter_t* b = new APLXML_DNP::Counter_t(); + b->ClassGroup = 1; + b->Index = boost::numeric::converter::convert(aIndex); + b->Name = aName; + arCfg.CounterData.CounterVector.push_back(b); + } + + void XML_DNP3::AddDeviceTemplateControl(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::Control_t* b = new APLXML_DNP::Control_t(); + b->Index = boost::numeric::converter::convert(aIndex); + b->Name = aName; + b->ControlMode = "SBO"; + b->SelectTimeoutMS = 5000; + arCfg.ControlData.ControlVector.push_back(b); + } + + void XML_DNP3::AddDeviceTemplateSetpoint(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::Setpoint_t* b = new APLXML_DNP::Setpoint_t(); + b->Index = boost::numeric::converter::convert(aIndex); + b->Name = aName; + b->ControlMode = "SBO"; + b->SelectTimeoutMS = 5000; + arCfg.SetpointData.SetpointVector.push_back(b); + } + void XML_DNP3::AddDeviceTemplateControlStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::ControlStatus_t* cs = new APLXML_DNP::ControlStatus_t(); + cs->Index = boost::numeric::converter::convert(aIndex); + cs->Name = aName; + arCfg.ControlStatusData.ControlStatusVector.push_back(cs); + } + void XML_DNP3::AddDeviceTemplateSetpointStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName) + { + APLXML_DNP::SetpointStatus_t* ss = new APLXML_DNP::SetpointStatus_t(); + ss->Index = boost::numeric::converter::convert(aIndex); + ss->Name = aName; + arCfg.SetpointStatusData.SetpointStatusVector.push_back(ss); + } + + void XML_DNP3::Configure(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aBinaries, size_t aAnalogs, size_t aCounters, size_t aControls, size_t aSetpoints, size_t aControlStatuses, size_t aSetpointStatuses) + { + arCfg.TemplateName = "default"; + + for(size_t i = 0; i < aBinaries; i++){ + AddDeviceTemplateBinary(arCfg, i, DefaultName("binary",i)); + } + for(size_t i = 0; i < aAnalogs; i++){ + AddDeviceTemplateAnalog(arCfg, i, DefaultName("analog",i)); + } + for(size_t i = 0; i < aCounters; i++){ + AddDeviceTemplateCounter(arCfg, i, DefaultName("counter",i)); + } + for(size_t i = 0; i < aControls; i++){ + AddDeviceTemplateControl(arCfg, i, DefaultName("control",i)); + } + for(size_t i = 0; i < aSetpoints; i++){ + AddDeviceTemplateSetpoint(arCfg, i, DefaultName("setpoint",i)); + } + for(size_t i = 0; i < aControlStatuses; i++ ) { + AddDeviceTemplateControlStatus(arCfg, i, DefaultName("controlstatus",i)); + } + for(size_t i = 0; i < aSetpointStatuses; i++ ) { + AddDeviceTemplateSetpointStatus(arCfg, i, DefaultName("setpointstatus",i)); + } + } +}} diff --git a/DNP3XML/XML_DNP3.h b/DNP3XML/XML_DNP3.h index 952241d7..6e3e382b 100644 --- a/DNP3XML/XML_DNP3.h +++ b/DNP3XML/XML_DNP3.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef _XML_DNP3_H_ #define _XML_DNP3_H_ @@ -25,7 +25,7 @@ namespace APLXML_DNP{ class Master_t; class Slave_t; class Stack_t; - class DeviceTemplate_t; + class DeviceTemplate_t; } namespace apl{ namespace dnp{ @@ -43,8 +43,8 @@ namespace apl{ namespace dnp{ static void AddDeviceTemplateCounter(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); static void AddDeviceTemplateControl(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); static void AddDeviceTemplateSetpoint(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); - static void AddDeviceTemplateControlStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); - static void AddDeviceTemplateSetpointStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); + static void AddDeviceTemplateControlStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); + static void AddDeviceTemplateSetpointStatus(APLXML_DNP::DeviceTemplate_t& arCfg, size_t aIndex, std::string aName); }; }} diff --git a/DNP3XML/XML_TestSet.cpp b/DNP3XML/XML_TestSet.cpp index 4be6f0cf..fdecad93 100644 --- a/DNP3XML/XML_TestSet.cpp +++ b/DNP3XML/XML_TestSet.cpp @@ -16,49 +16,49 @@ // specific language governing permissions and limitations // under the License. // -#include "XML_TestSet.h" - -#include -#include - -#include -#include - - -#include -#include - -using namespace apl::dnp; - -namespace apl { - - void XML_TestSet::Configure(APLXML_MTS::MasterTestSet_t& arMasterTest, bool aUseUnsol) - { - arMasterTest.PhysicalLayer = "tcpclient"; - arMasterTest.LogFile = "master_testset.log"; - arMasterTest.Log.Filter = APLXML_Base::LOG_WARNING; - XML_DNP3::Configure(arMasterTest.Master, aUseUnsol); - - xml::XML_APL::AddSerial(arMasterTest.PhysicalLayerList, "serial", "COM1"); - xml::XML_APL::AddTCPClient(arMasterTest.PhysicalLayerList, "tcpclient", "127.0.0.1", 4999); - } - - void XML_TestSet::Configure(APLXML_STS::SlaveTestSet_t& arSlaveTest) - { - arSlaveTest.PhysicalLayer = "tcpserver"; - arSlaveTest.LogFile = "slave_testset.log"; - arSlaveTest.Log.Filter = APLXML_Base::LOG_WARNING; - XML_DNP3::Configure(arSlaveTest.Slave); - - xml::XML_APL::AddSerial(arSlaveTest.PhysicalLayerList, "serial", "COM1"); - xml::XML_APL::AddTCPServer(arSlaveTest.PhysicalLayerList, "tcpserver", 4999); - - arSlaveTest.LogFile = "-"; - arSlaveTest.Remote = false; - arSlaveTest.RemotePort = 4998; - arSlaveTest.LinkCommandStatus = false; - arSlaveTest.StartOnline = false; - } - - -} +#include "XML_TestSet.h" + +#include +#include + +#include +#include + + +#include +#include + +using namespace apl::dnp; + +namespace apl { + + void XML_TestSet::Configure(APLXML_MTS::MasterTestSet_t& arMasterTest, bool aUseUnsol) + { + arMasterTest.PhysicalLayer = "tcpclient"; + arMasterTest.LogFile = "master_testset.log"; + arMasterTest.Log.Filter = APLXML_Base::LOG_WARNING; + XML_DNP3::Configure(arMasterTest.Master, aUseUnsol); + + xml::XML_APL::AddSerial(arMasterTest.PhysicalLayerList, "serial", "COM1"); + xml::XML_APL::AddTCPClient(arMasterTest.PhysicalLayerList, "tcpclient", "127.0.0.1", 4999); + } + + void XML_TestSet::Configure(APLXML_STS::SlaveTestSet_t& arSlaveTest) + { + arSlaveTest.PhysicalLayer = "tcpserver"; + arSlaveTest.LogFile = "slave_testset.log"; + arSlaveTest.Log.Filter = APLXML_Base::LOG_WARNING; + XML_DNP3::Configure(arSlaveTest.Slave); + + xml::XML_APL::AddSerial(arSlaveTest.PhysicalLayerList, "serial", "COM1"); + xml::XML_APL::AddTCPServer(arSlaveTest.PhysicalLayerList, "tcpserver", 4999); + + arSlaveTest.LogFile = "-"; + arSlaveTest.Remote = false; + arSlaveTest.RemotePort = 4998; + arSlaveTest.LinkCommandStatus = false; + arSlaveTest.StartOnline = false; + } + + +} diff --git a/DNP3XML/XML_TestSet.h b/DNP3XML/XML_TestSet.h index 9a4e300c..754a2bd6 100644 --- a/DNP3XML/XML_TestSet.h +++ b/DNP3XML/XML_TestSet.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,36 +6,36 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef _XML_TESTSET_H_ -#define _XML_TESTSET_H_ - -namespace APLXML_MTS{ - class MasterTestSet_t; -} -namespace APLXML_STS{ - class SlaveTestSet_t; -} - -namespace apl{ - - class XML_TestSet - { - public: - static void Configure(APLXML_MTS::MasterTestSet_t& arMasterTest, bool aUseUnsol = false); - static void Configure(APLXML_STS::SlaveTestSet_t& arSlaveTest); - - }; - -} - -#endif +// +#ifndef _XML_TESTSET_H_ +#define _XML_TESTSET_H_ + +namespace APLXML_MTS{ + class MasterTestSet_t; +} +namespace APLXML_STS{ + class SlaveTestSet_t; +} + +namespace apl{ + + class XML_TestSet + { + public: + static void Configure(APLXML_MTS::MasterTestSet_t& arMasterTest, bool aUseUnsol = false); + static void Configure(APLXML_STS::SlaveTestSet_t& arSlaveTest); + + }; + +} + +#endif diff --git a/DNP3XML/XmlToConfig.cpp b/DNP3XML/XmlToConfig.cpp index 9911810c..296f4c73 100644 --- a/DNP3XML/XmlToConfig.cpp +++ b/DNP3XML/XmlToConfig.cpp @@ -16,191 +16,191 @@ // specific language governing permissions and limitations // under the License. // -#include "XmlToConfig.h" - -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace APLXML_Base; - -namespace apl { namespace dnp { - - bool XmlToConfig::Configure(const APLXML_Base::PhysicalLayerList_t& arList, FilterLevel aLevel, AsyncStackManager& arMgr) - { - - for (size_t i = 0; i < arList.TCPClientVector.size(); i++ ) - { - TCPClient_t* pCfg = arList.TCPClientVector[i]; - PhysLayerSettings s(aLevel, pCfg->OpenRetryMS); - arMgr.AddTCPClient(pCfg->Name, s, pCfg->Address, pCfg->Port); - } - for (size_t i = 0; i < arList.TCPServerVector.size(); i++ ) - { - TCPServer_t* pCfg = arList.TCPServerVector[i]; - PhysLayerSettings s(aLevel, pCfg->OpenRetryMS); - arMgr.AddTCPServer(pCfg->Name, s, pCfg->Port); - } - for (size_t i = 0; i < arList.SerialVector.size(); i++ ) - { - Serial_t* pCfg = arList.SerialVector[i]; - PhysLayerSettings s(aLevel, pCfg->OpenRetryMS); - arMgr.AddSerial(pCfg->Name, s, xml::GetSerialSettings(pCfg) ); - } - - return true; - } - - MasterStackConfig XmlToConfig::GetMasterConfig(const APLXML_DNP::Master_t& arCfg) - { - MasterStackConfig cfg; - cfg.app = Convert(arCfg.Stack.AppLayer); - cfg.link = Convert(arCfg.Stack.LinkLayer); - cfg.master = Convert(arCfg); - return cfg; - } - - SlaveStackConfig XmlToConfig::GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const APLXML_DNP::DeviceTemplate_t& arTmp, bool aStartOnline) - { - DeviceTemplate tmp = Convert(arTmp, aStartOnline); - return GetSlaveConfig(arCfg, tmp); - } - - SlaveStackConfig XmlToConfig::GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const DeviceTemplate& arTmp) - { - SlaveStackConfig cfg; - cfg.app = Convert(arCfg.Stack.AppLayer); - cfg.link = Convert(arCfg.Stack.LinkLayer); - cfg.slave = Convert(arCfg.SlaveConfig, arCfg.Stack.AppLayer); - cfg.device = arTmp; - return cfg; - } - - LinkConfig XmlToConfig::Convert(const APLXML_DNP::LinkLayer_t& arLink) - { - LinkConfig cfg(arLink.IsMaster, arLink.UseConfirmations); - cfg.IsMaster = arLink.IsMaster; - cfg.LocalAddr = boost::numeric::converter::convert(arLink.LocalAddress); - cfg.RemoteAddr = boost::numeric::converter::convert(arLink.RemoteAddress); - cfg.Timeout = arLink.AckTimeoutMS; - cfg.UseConfirms = arLink.UseConfirmations; - cfg.NumRetry = boost::numeric::converter::convert(arLink.NumRetries); - return cfg; - } - - AppConfig XmlToConfig::Convert(const APLXML_DNP::AppLayer_t& arCfg) - { - AppConfig cfg; - cfg.FragSize = boost::numeric::converter::convert(arCfg.MaxFragSize); - cfg.RspTimeout = arCfg.TimeoutMS; - cfg.NumRetry = boost::numeric::converter::convert(arCfg.NumRetries); - return cfg; - } - - MasterConfig XmlToConfig::Convert(const APLXML_DNP::Master_t& arCfg) - { - MasterConfig cfg; - cfg.AllowTimeSync = true; - cfg.DoUnsolOnStartup = arCfg.Unsol.DoTask; - cfg.EnableUnsol = arCfg.Unsol.Enable; - cfg.FragSize = arCfg.Stack.AppLayer.MaxFragSize; - cfg.IntegrityRate = arCfg.MasterSettings.IntegrityPeriodMS; - cfg.TaskRetryRate = arCfg.MasterSettings.TaskRetryMS; - cfg.UnsolClassMask = ClassMask::GetMask(arCfg.Unsol.Class1, arCfg.Unsol.Class2, arCfg.Unsol.Class3); - cfg.IntegrityRate = arCfg.MasterSettings.IntegrityPeriodMS; - - std::vector& vec = arCfg.ScanList.ExceptionScanVector; - for(size_t i=0; iClass1, vec[i]->Class2, vec[i]->Class3); - cfg.AddExceptionScan(mask, vec[i]->PeriodMS); - } - return cfg; - } - - SlaveConfig XmlToConfig::Convert(const APLXML_DNP::SlaveConfig_t& arCfg, const APLXML_DNP::AppLayer_t& arApp) - { - SlaveConfig c; - - c.mAllowTimeSync = arCfg.TimeIINTask.DoTask; - c.mTimeSyncPeriod = arCfg.TimeIINTask.PeriodMS; - - c.mUnsolPackDelay = arCfg.UnsolDefaults.PackDelayMS; - c.mUnsolRetryDelay = arCfg.UnsolDefaults.RetryMS; - - c.mStaticBinary = Convert(arCfg.StaticRsp.BinaryGrpVar); - c.mStaticAnalog = Convert(arCfg.StaticRsp.AnalogGrpVar); - c.mStaticCounter = Convert(arCfg.StaticRsp.CounterGrpVar); - c.mStaticSetpointStatus = Convert(arCfg.StaticRsp.SetpointStatusGrpVar); - - c.mEventBinary = Convert(arCfg.EventRsp.BinaryGrpVar); - c.mEventAnalog = Convert(arCfg.EventRsp.AnalogGrpVar); - c.mEventCounter = Convert(arCfg.EventRsp.CounterGrpVar); - - c.mMaxBinaryEvents = arCfg.MaxBinaryEvents; - c.mMaxAnalogEvents = arCfg.MaxAnalogEvents; - c.mMaxCounterEvents = arCfg.MaxCounterEvents; - - c.mMaxControls = 1; - - c.mMaxFragSize = boost::numeric::converter::convert(arApp.MaxFragSize);; - - return c; - } - - GrpVar XmlToConfig::Convert(const APLXML_DNP::GrpVar_t& arCfg) - { - GrpVar gp(arCfg.Grp, arCfg.Var); - return gp; - } - - DeviceTemplate XmlToConfig::Convert(const APLXML_DNP::DeviceTemplate_t& arCfg, bool aStartOnline) - { - size_t numBinary = CalcNumType(arCfg.BinaryData.BinaryVector); - size_t numAnalog = CalcNumType(arCfg.AnalogData.AnalogVector); - size_t numCounter = CalcNumType(arCfg.CounterData.CounterVector); - size_t numControl = CalcNumType(arCfg.ControlData.ControlVector); - size_t numSetpoint = CalcNumType(arCfg.SetpointData.SetpointVector); - size_t numControlStatus = CalcNumType(arCfg.ControlStatusData.ControlStatusVector); - size_t numSetpointStatus = CalcNumType(arCfg.SetpointStatusData.SetpointStatusVector); - - DeviceTemplate t(numBinary, numAnalog, numCounter, numControlStatus, numSetpointStatus, numControl, numSetpoint); - - AddEventPoints(arCfg.BinaryData.BinaryVector, t.mBinary); - AddDeadbandPoints(arCfg.AnalogData.AnalogVector, t.mAnalog); - AddEventPoints(arCfg.CounterData.CounterVector, t.mCounter); - - AddCommandData(arCfg.ControlData.ControlVector, t.mControls); - AddCommandData(arCfg.SetpointData.SetpointVector, t.mSetpoints); - - AddPoints(arCfg.ControlStatusData.ControlStatusVector, t.mControlStatus); - AddPoints(arCfg.SetpointStatusData.SetpointStatusVector, t.mSetpointStatus); - - t.mStartOnline = aStartOnline; - - return t; - } - - CommandModes ConvertMode(const std::string& arMode) - { - if(arMode == "SBO") return CM_SBO_ONLY; - if(arMode == "DO_ONLY") return CM_DO_ONLY; - if(arMode == "SBO_OR_DO") return CM_SBO_OR_DO; - - throw ArgumentException(LOCATION, "invalid command mode"); - } - -}} +#include "XmlToConfig.h" + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace APLXML_Base; + +namespace apl { namespace dnp { + + bool XmlToConfig::Configure(const APLXML_Base::PhysicalLayerList_t& arList, FilterLevel aLevel, AsyncStackManager& arMgr) + { + + for (size_t i = 0; i < arList.TCPClientVector.size(); i++ ) + { + TCPClient_t* pCfg = arList.TCPClientVector[i]; + PhysLayerSettings s(aLevel, pCfg->OpenRetryMS); + arMgr.AddTCPClient(pCfg->Name, s, pCfg->Address, pCfg->Port); + } + for (size_t i = 0; i < arList.TCPServerVector.size(); i++ ) + { + TCPServer_t* pCfg = arList.TCPServerVector[i]; + PhysLayerSettings s(aLevel, pCfg->OpenRetryMS); + arMgr.AddTCPServer(pCfg->Name, s, pCfg->Port); + } + for (size_t i = 0; i < arList.SerialVector.size(); i++ ) + { + Serial_t* pCfg = arList.SerialVector[i]; + PhysLayerSettings s(aLevel, pCfg->OpenRetryMS); + arMgr.AddSerial(pCfg->Name, s, xml::GetSerialSettings(pCfg) ); + } + + return true; + } + + MasterStackConfig XmlToConfig::GetMasterConfig(const APLXML_DNP::Master_t& arCfg) + { + MasterStackConfig cfg; + cfg.app = Convert(arCfg.Stack.AppLayer); + cfg.link = Convert(arCfg.Stack.LinkLayer); + cfg.master = Convert(arCfg); + return cfg; + } + + SlaveStackConfig XmlToConfig::GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const APLXML_DNP::DeviceTemplate_t& arTmp, bool aStartOnline) + { + DeviceTemplate tmp = Convert(arTmp, aStartOnline); + return GetSlaveConfig(arCfg, tmp); + } + + SlaveStackConfig XmlToConfig::GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const DeviceTemplate& arTmp) + { + SlaveStackConfig cfg; + cfg.app = Convert(arCfg.Stack.AppLayer); + cfg.link = Convert(arCfg.Stack.LinkLayer); + cfg.slave = Convert(arCfg.SlaveConfig, arCfg.Stack.AppLayer); + cfg.device = arTmp; + return cfg; + } + + LinkConfig XmlToConfig::Convert(const APLXML_DNP::LinkLayer_t& arLink) + { + LinkConfig cfg(arLink.IsMaster, arLink.UseConfirmations); + cfg.IsMaster = arLink.IsMaster; + cfg.LocalAddr = boost::numeric::converter::convert(arLink.LocalAddress); + cfg.RemoteAddr = boost::numeric::converter::convert(arLink.RemoteAddress); + cfg.Timeout = arLink.AckTimeoutMS; + cfg.UseConfirms = arLink.UseConfirmations; + cfg.NumRetry = boost::numeric::converter::convert(arLink.NumRetries); + return cfg; + } + + AppConfig XmlToConfig::Convert(const APLXML_DNP::AppLayer_t& arCfg) + { + AppConfig cfg; + cfg.FragSize = boost::numeric::converter::convert(arCfg.MaxFragSize); + cfg.RspTimeout = arCfg.TimeoutMS; + cfg.NumRetry = boost::numeric::converter::convert(arCfg.NumRetries); + return cfg; + } + + MasterConfig XmlToConfig::Convert(const APLXML_DNP::Master_t& arCfg) + { + MasterConfig cfg; + cfg.AllowTimeSync = true; + cfg.DoUnsolOnStartup = arCfg.Unsol.DoTask; + cfg.EnableUnsol = arCfg.Unsol.Enable; + cfg.FragSize = arCfg.Stack.AppLayer.MaxFragSize; + cfg.IntegrityRate = arCfg.MasterSettings.IntegrityPeriodMS; + cfg.TaskRetryRate = arCfg.MasterSettings.TaskRetryMS; + cfg.UnsolClassMask = ClassMask::GetMask(arCfg.Unsol.Class1, arCfg.Unsol.Class2, arCfg.Unsol.Class3); + cfg.IntegrityRate = arCfg.MasterSettings.IntegrityPeriodMS; + + std::vector& vec = arCfg.ScanList.ExceptionScanVector; + for(size_t i=0; iClass1, vec[i]->Class2, vec[i]->Class3); + cfg.AddExceptionScan(mask, vec[i]->PeriodMS); + } + return cfg; + } + + SlaveConfig XmlToConfig::Convert(const APLXML_DNP::SlaveConfig_t& arCfg, const APLXML_DNP::AppLayer_t& arApp) + { + SlaveConfig c; + + c.mAllowTimeSync = arCfg.TimeIINTask.DoTask; + c.mTimeSyncPeriod = arCfg.TimeIINTask.PeriodMS; + + c.mUnsolPackDelay = arCfg.UnsolDefaults.PackDelayMS; + c.mUnsolRetryDelay = arCfg.UnsolDefaults.RetryMS; + + c.mStaticBinary = Convert(arCfg.StaticRsp.BinaryGrpVar); + c.mStaticAnalog = Convert(arCfg.StaticRsp.AnalogGrpVar); + c.mStaticCounter = Convert(arCfg.StaticRsp.CounterGrpVar); + c.mStaticSetpointStatus = Convert(arCfg.StaticRsp.SetpointStatusGrpVar); + + c.mEventBinary = Convert(arCfg.EventRsp.BinaryGrpVar); + c.mEventAnalog = Convert(arCfg.EventRsp.AnalogGrpVar); + c.mEventCounter = Convert(arCfg.EventRsp.CounterGrpVar); + + c.mMaxBinaryEvents = arCfg.MaxBinaryEvents; + c.mMaxAnalogEvents = arCfg.MaxAnalogEvents; + c.mMaxCounterEvents = arCfg.MaxCounterEvents; + + c.mMaxControls = 1; + + c.mMaxFragSize = boost::numeric::converter::convert(arApp.MaxFragSize);; + + return c; + } + + GrpVar XmlToConfig::Convert(const APLXML_DNP::GrpVar_t& arCfg) + { + GrpVar gp(arCfg.Grp, arCfg.Var); + return gp; + } + + DeviceTemplate XmlToConfig::Convert(const APLXML_DNP::DeviceTemplate_t& arCfg, bool aStartOnline) + { + size_t numBinary = CalcNumType(arCfg.BinaryData.BinaryVector); + size_t numAnalog = CalcNumType(arCfg.AnalogData.AnalogVector); + size_t numCounter = CalcNumType(arCfg.CounterData.CounterVector); + size_t numControl = CalcNumType(arCfg.ControlData.ControlVector); + size_t numSetpoint = CalcNumType(arCfg.SetpointData.SetpointVector); + size_t numControlStatus = CalcNumType(arCfg.ControlStatusData.ControlStatusVector); + size_t numSetpointStatus = CalcNumType(arCfg.SetpointStatusData.SetpointStatusVector); + + DeviceTemplate t(numBinary, numAnalog, numCounter, numControlStatus, numSetpointStatus, numControl, numSetpoint); + + AddEventPoints(arCfg.BinaryData.BinaryVector, t.mBinary); + AddDeadbandPoints(arCfg.AnalogData.AnalogVector, t.mAnalog); + AddEventPoints(arCfg.CounterData.CounterVector, t.mCounter); + + AddCommandData(arCfg.ControlData.ControlVector, t.mControls); + AddCommandData(arCfg.SetpointData.SetpointVector, t.mSetpoints); + + AddPoints(arCfg.ControlStatusData.ControlStatusVector, t.mControlStatus); + AddPoints(arCfg.SetpointStatusData.SetpointStatusVector, t.mSetpointStatus); + + t.mStartOnline = aStartOnline; + + return t; + } + + CommandModes ConvertMode(const std::string& arMode) + { + if(arMode == "SBO") return CM_SBO_ONLY; + if(arMode == "DO_ONLY") return CM_DO_ONLY; + if(arMode == "SBO_OR_DO") return CM_SBO_OR_DO; + + throw ArgumentException(LOCATION, "invalid command mode"); + } + +}} diff --git a/DNP3XML/XmlToConfig.h b/DNP3XML/XmlToConfig.h index b59d21d1..a660a2f6 100644 --- a/DNP3XML/XmlToConfig.h +++ b/DNP3XML/XmlToConfig.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,123 +6,123 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __XML_TO_CONFIG_H_ -#define __XML_TO_CONFIG_H_ - -#include - - -#include -#include -#include - -#include -#include - -namespace APLXML_DNP{ - class Master_t; - class Slave_t; - class LinkLayer_t; - class AppLayer_t; - class SlaveConfig_t; - class DeviceTemplate_t; - class VTOData_t; - class GrpVar_t; - class Control_t; - class Setpoint_t; -} - -namespace APLXML_Base { - class PhysicalLayerList_t; -} - -namespace apl { namespace dnp { - - struct LinkConfig; - struct AppConfig; - struct MasterConfig; - struct SlaveConfig; - struct VTOConfig; - struct GrpVar; - struct MasterStackConfig; - struct SlaveStackConfig; - class AsyncStackManager; - - class FixedObject; - - - class XmlToConfig - { - public: - - static bool Configure(const APLXML_Base::PhysicalLayerList_t& arList, FilterLevel aLevel, AsyncStackManager& arMgr); - - - static MasterStackConfig GetMasterConfig(const APLXML_DNP::Master_t& arCfg); - static SlaveStackConfig GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const APLXML_DNP::DeviceTemplate_t& arTmp, bool aStartOnline = false); - static SlaveStackConfig GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const DeviceTemplate& arTmp); - - //individual helper functions - static LinkConfig Convert(const APLXML_DNP::LinkLayer_t& arCfg); - static AppConfig Convert(const APLXML_DNP::AppLayer_t& arCfg); - static MasterConfig Convert(const APLXML_DNP::Master_t& arCfg); - static SlaveConfig Convert(const APLXML_DNP::SlaveConfig_t& arCfg, const APLXML_DNP::AppLayer_t& arApp); - static VTOConfig Convert(const APLXML_DNP::VTOData_t& arCfg); - static DeviceTemplate Convert( const APLXML_DNP::DeviceTemplate_t& arCfg, bool aStartOnline = false); - - private: - - static GrpVar Convert(const APLXML_DNP::GrpVar_t& arCfg); - - template - static size_t CalcNumType(const std::vector& arIdxVec) - { - std::set indexSet; - - for(size_t i=0; iIndex); } - if(indexSet.size() > 0) return *indexSet.rbegin()+1; - else return 0; - } - - template - static void AddPoints(const std::vector& arXML, std::vector& arVec) - { - for(size_t i=0; iIndex] = PointRecord(arXML[i]->Name); - } - - template - static void AddEventPoints(const std::vector& arXML, std::vector& arVec) - { - for(size_t i=0; iIndex] = EventPointRecord(arXML[i]->Name, IntToPointClass(arXML[i]->ClassGroup)); - } - - template - static void AddDeadbandPoints(const std::vector& arXML, std::vector& arVec) - { - for(size_t i=0; iIndex] = DeadbandPointRecord(arXML[i]->Name, IntToPointClass(arXML[i]->ClassGroup), arXML[i]->Deadband); - } - - template - static void AddCommandData(const std::vector& arXML, std::vector& arVec) - { - for (size_t i = 0; i < arXML.size(); i++) - arVec[arXML[i]->Index] = ControlRecord(arXML[i]->Name, ConvertMode(arXML[i]->ControlMode), arXML[i]->SelectTimeoutMS); - } - }; - -}} - -#endif +// +#ifndef __XML_TO_CONFIG_H_ +#define __XML_TO_CONFIG_H_ + +#include + + +#include +#include +#include + +#include +#include + +namespace APLXML_DNP{ + class Master_t; + class Slave_t; + class LinkLayer_t; + class AppLayer_t; + class SlaveConfig_t; + class DeviceTemplate_t; + class VTOData_t; + class GrpVar_t; + class Control_t; + class Setpoint_t; +} + +namespace APLXML_Base { + class PhysicalLayerList_t; +} + +namespace apl { namespace dnp { + + struct LinkConfig; + struct AppConfig; + struct MasterConfig; + struct SlaveConfig; + struct VTOConfig; + struct GrpVar; + struct MasterStackConfig; + struct SlaveStackConfig; + class AsyncStackManager; + + class FixedObject; + + + class XmlToConfig + { + public: + + static bool Configure(const APLXML_Base::PhysicalLayerList_t& arList, FilterLevel aLevel, AsyncStackManager& arMgr); + + + static MasterStackConfig GetMasterConfig(const APLXML_DNP::Master_t& arCfg); + static SlaveStackConfig GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const APLXML_DNP::DeviceTemplate_t& arTmp, bool aStartOnline = false); + static SlaveStackConfig GetSlaveConfig(const APLXML_DNP::Slave_t& arCfg, const DeviceTemplate& arTmp); + + //individual helper functions + static LinkConfig Convert(const APLXML_DNP::LinkLayer_t& arCfg); + static AppConfig Convert(const APLXML_DNP::AppLayer_t& arCfg); + static MasterConfig Convert(const APLXML_DNP::Master_t& arCfg); + static SlaveConfig Convert(const APLXML_DNP::SlaveConfig_t& arCfg, const APLXML_DNP::AppLayer_t& arApp); + static VTOConfig Convert(const APLXML_DNP::VTOData_t& arCfg); + static DeviceTemplate Convert( const APLXML_DNP::DeviceTemplate_t& arCfg, bool aStartOnline = false); + + private: + + static GrpVar Convert(const APLXML_DNP::GrpVar_t& arCfg); + + template + static size_t CalcNumType(const std::vector& arIdxVec) + { + std::set indexSet; + + for(size_t i=0; iIndex); } + if(indexSet.size() > 0) return *indexSet.rbegin()+1; + else return 0; + } + + template + static void AddPoints(const std::vector& arXML, std::vector& arVec) + { + for(size_t i=0; iIndex] = PointRecord(arXML[i]->Name); + } + + template + static void AddEventPoints(const std::vector& arXML, std::vector& arVec) + { + for(size_t i=0; iIndex] = EventPointRecord(arXML[i]->Name, IntToPointClass(arXML[i]->ClassGroup)); + } + + template + static void AddDeadbandPoints(const std::vector& arXML, std::vector& arVec) + { + for(size_t i=0; iIndex] = DeadbandPointRecord(arXML[i]->Name, IntToPointClass(arXML[i]->ClassGroup), arXML[i]->Deadband); + } + + template + static void AddCommandData(const std::vector& arXML, std::vector& arVec) + { + for (size_t i = 0; i < arXML.size(); i++) + arVec[arXML[i]->Index] = ControlRecord(arXML[i]->Name, ConvertMode(arXML[i]->ControlMode), arXML[i]->SelectTimeoutMS); + } + }; + +}} + +#endif diff --git a/DNP3XML/rake.project.rb b/DNP3XML/rake.project.rb index 30442bfa..510c1e09 100644 --- a/DNP3XML/rake.project.rb +++ b/DNP3XML/rake.project.rb @@ -16,8 +16,8 @@ # specific language governing permissions and limitations # under the License. # - -$options = { -:target => 'libdnp3xml.a', -:includes => [Boost::get_includes_dir,DEFAULT_INCLUDES] -} + +$options = { +:target => 'libdnp3xml.a', +:includes => [Boost::get_includes_dir,DEFAULT_INCLUDES] +} diff --git a/NOTICE b/NOTICE index c390bf70..570cd4ea 100755 --- a/NOTICE +++ b/NOTICE @@ -1,23 +1,23 @@ -========================================================================= -== NOTICE file corresponding to the section 4 d of == -== the Apache License, Version 2.0, == -== in this case for the Green Energy Corp DNP3 distribution. == -========================================================================= - -This product includes software developed by Green Energy Corp -(http://www.greenenergycorp.com/). - -Please read the LICENSE file present in the root directory of this -distribution. - -Aside from contributions to the Green Energy Corporation DNP3 distribution, this software also -includes: - tinyxml (http://sourceforge.net/projects/tinyxml/) - - Modified source distribution derived from release 2.5.3 - - http://www.opensource.org/licenses/zlib-license.php - -Project requires, not packaged: - * boost version 1.43 or later under the Boost Software License, and - can be downloaded from http://www.boost.org - - +========================================================================= +== NOTICE file corresponding to the section 4 d of == +== the Apache License, Version 2.0, == +== in this case for the Green Energy Corp DNP3 distribution. == +========================================================================= + +This product includes software developed by Green Energy Corp +(http://www.greenenergycorp.com/). + +Please read the LICENSE file present in the root directory of this +distribution. + +Aside from contributions to the Green Energy Corporation DNP3 distribution, this software also +includes: + tinyxml (http://sourceforge.net/projects/tinyxml/) + - Modified source distribution derived from release 2.5.3 + - http://www.opensource.org/licenses/zlib-license.php + +Project requires, not packaged: + * boost version 1.43 or later under the Boost Software License, and + can be downloaded from http://www.boost.org + + diff --git a/README.markdown b/README.markdown index eb45ae72..5403463d 100755 --- a/README.markdown +++ b/README.markdown @@ -1,156 +1,156 @@ -DNP3 library and testset -===================== - - -The DNP3 library and testset is a portable, scalable, and rigorously tested -implementation of the DNP3 (www.dnp.org) protocol stack written in C++ and -provided by Green Energy Corp to the community under the Apache 2.0 license. -The library is optimized for massively parallel front end processor -implementations and slave device simulations, although it has been verified -to perform very well on embedded linux ARM architectures. It includes -a command line master/slave test set. - -The library has been verified under linux, cygwin, and windows. Two build -systems are included: - -- GNU g++ and the rake (ruby make) build system provided. This build system is -verified under ubuntu and cygwin. -- Visual Studio SLN and PROJ files - -The repository is organized as a set of projects of libraries and executables. - -The main libraries are: - -- APL - Portable functionality for things like parsing, physical layers, logging -- APLTestTools - Library of tools/mocks uses for testing -- DNP3 - Protocol library for dnp3 -- Terminal - Extensible library for creating command line driven UI -- DNP3Java - Library generated by swig that wraps the stack with JNI - -The main executable targets are: - -- TestAPL - A test suite for the PSI library -- DNP3Test - A test suite for the DNP3 library -- TerminalTest - A test suite for the Terminal library -- TestSet - A dnp3 command line master/slave test set. - - -# Building Instructions # - -## Common Dependencies for all platforms ## - -Set the TOOLS_HOME environment variable to an appropraite path for installing -tools and libraries. Reasonable choices are C:\Tools or ~/tools. - -- On cygwin/windows this variable is set via: -> ControlPanel->System->Advanced->EnvironmentVariables - -- On Linux systems its common to add the following line to ~/.bashrc -> export TOOLS_HOME=~/tools - -## Configuring CYGWIN ## - -Get a copy of setup.exe from www.cygwin.com. Hold onto setup.exe as you may -need it to install additional packages. - -You will need the following additional packages to build the C++ libraries -and tests. Please be careful to get the correct version if noted below: - -- Web -> wget // used in install scripts to retrieve packages -- Devel -> gcc-g++ // C++ compiler (version 3.4.4, not tested on gcc4x) -- Devel -> cache // C compiler cache for improving recompilation -- Devel -> make // GNU version of make utility -- Devel -> ruby // Scripting language we use it for build scripts -- Devel -> libtool // Shared library generation tool -- Devel -> swig // C/C++ wrapper generator used for Java bindings - -Optional packages: - -- Devel -> doxygen // documentation system for C++ - -Doxygen needs GraphViz. Download and install GraphViz: http://www.graphviz.org/Download_windows.php - -The msi installer will put a program called dot onto your path that doxygen -needs to generate images. - -## Installing ARM CROSS-COMPILER ## - -If you want to build for the Technologic Systems ARM platform, -install the cross-compiler: - -> cd tools/install_scripts/crosstool -> ./install-crosstool.sh - -It is important that this step be completely successfully prior to the -boost installation, as the Boost libraries will be built for ARM as well -as your platform. - -## Install Boost ## - -Install the boost libraries and headers by running the script: - -> cd tools/install_scripts/boost/{VERSION} -> ./install-boost.sh - -This step will take some time as it retrieves the boost package and builds from -source for both your platform and for ARM. - -When the boost version we are using is updated we will update the references in -rakefile.rb and config/boost_*.vsprops to use the new version name and include -updated installers to compile the new version, if after and update the build suddenly -fails with mssing boost include errors errors check that the boost version hasn't -been upgraded recently. - - -## Install Ruby Gems and Rake ## - -RubyGems is a package delivery system for ruby libraries. Follow the -instructions from the RubyGems website to install: - -http://rubygems.org/ - -Rake is a ruby gem. To install rake: - -> gem install rake - -## Install JDK ## - -The Java Developers Kit is used to build Java bindings. Install the Java 6 JDK - -Set the JAVA_HOME directory to the install path of your JDK version. If you -don't want to build java bindings and install the JDK, comment out the -following line from rakefile.rb: - - require 'plugins/swigjava.rb' - -Comment out the dnp3java project from the $projects hash. - -## Building the libraries and tests ## - -Use rake to build. To see a list of targets and their descriptions, type: - -> rake -T - -rake understands dependencies similarly to the GNU make utility. To build and run -the dnp3test executable, type: -> rake dnp3test:run - -Flags not documented by Rake -T: - -- release=true // release mode, compiler optimization and no debug -- arm=true // crosscompile for arm -- SH_VERBOSE=true // print every command that rake issues to the shell - -For example, to build all of the arm libraries and executables, type: -> rake arm=true release=true - -## Generating Documentation ## - -To generate documentation for the stack you need to have doxygen and graphviz (dot) -installed before invoking: - -rake document - -Be patient, this generates hundreds of megs worth of images. - +DNP3 library and testset +===================== + + +The DNP3 library and testset is a portable, scalable, and rigorously tested +implementation of the DNP3 (www.dnp.org) protocol stack written in C++ and +provided by Green Energy Corp to the community under the Apache 2.0 license. +The library is optimized for massively parallel front end processor +implementations and slave device simulations, although it has been verified +to perform very well on embedded linux ARM architectures. It includes +a command line master/slave test set. + +The library has been verified under linux, cygwin, and windows. Two build +systems are included: + +- GNU g++ and the rake (ruby make) build system provided. This build system is +verified under ubuntu and cygwin. +- Visual Studio SLN and PROJ files + +The repository is organized as a set of projects of libraries and executables. + +The main libraries are: + +- APL - Portable functionality for things like parsing, physical layers, logging +- APLTestTools - Library of tools/mocks uses for testing +- DNP3 - Protocol library for dnp3 +- Terminal - Extensible library for creating command line driven UI +- DNP3Java - Library generated by swig that wraps the stack with JNI + +The main executable targets are: + +- TestAPL - A test suite for the PSI library +- DNP3Test - A test suite for the DNP3 library +- TerminalTest - A test suite for the Terminal library +- TestSet - A dnp3 command line master/slave test set. + + +# Building Instructions # + +## Common Dependencies for all platforms ## + +Set the TOOLS_HOME environment variable to an appropraite path for installing +tools and libraries. Reasonable choices are C:\Tools or ~/tools. + +- On cygwin/windows this variable is set via: +> ControlPanel->System->Advanced->EnvironmentVariables + +- On Linux systems its common to add the following line to ~/.bashrc +> export TOOLS_HOME=~/tools + +## Configuring CYGWIN ## + +Get a copy of setup.exe from www.cygwin.com. Hold onto setup.exe as you may +need it to install additional packages. + +You will need the following additional packages to build the C++ libraries +and tests. Please be careful to get the correct version if noted below: + +- Web -> wget // used in install scripts to retrieve packages +- Devel -> gcc-g++ // C++ compiler (version 3.4.4, not tested on gcc4x) +- Devel -> cache // C compiler cache for improving recompilation +- Devel -> make // GNU version of make utility +- Devel -> ruby // Scripting language we use it for build scripts +- Devel -> libtool // Shared library generation tool +- Devel -> swig // C/C++ wrapper generator used for Java bindings + +Optional packages: + +- Devel -> doxygen // documentation system for C++ + +Doxygen needs GraphViz. Download and install GraphViz: http://www.graphviz.org/Download_windows.php + +The msi installer will put a program called dot onto your path that doxygen +needs to generate images. + +## Installing ARM CROSS-COMPILER ## + +If you want to build for the Technologic Systems ARM platform, +install the cross-compiler: + +> cd tools/install_scripts/crosstool +> ./install-crosstool.sh + +It is important that this step be completely successfully prior to the +boost installation, as the Boost libraries will be built for ARM as well +as your platform. + +## Install Boost ## + +Install the boost libraries and headers by running the script: + +> cd tools/install_scripts/boost/{VERSION} +> ./install-boost.sh + +This step will take some time as it retrieves the boost package and builds from +source for both your platform and for ARM. + +When the boost version we are using is updated we will update the references in +rakefile.rb and config/boost_*.vsprops to use the new version name and include +updated installers to compile the new version, if after and update the build suddenly +fails with mssing boost include errors errors check that the boost version hasn't +been upgraded recently. + + +## Install Ruby Gems and Rake ## + +RubyGems is a package delivery system for ruby libraries. Follow the +instructions from the RubyGems website to install: + +http://rubygems.org/ + +Rake is a ruby gem. To install rake: + +> gem install rake + +## Install JDK ## + +The Java Developers Kit is used to build Java bindings. Install the Java 6 JDK + +Set the JAVA_HOME directory to the install path of your JDK version. If you +don't want to build java bindings and install the JDK, comment out the +following line from rakefile.rb: + + require 'plugins/swigjava.rb' + +Comment out the dnp3java project from the $projects hash. + +## Building the libraries and tests ## + +Use rake to build. To see a list of targets and their descriptions, type: + +> rake -T + +rake understands dependencies similarly to the GNU make utility. To build and run +the dnp3test executable, type: +> rake dnp3test:run + +Flags not documented by Rake -T: + +- release=true // release mode, compiler optimization and no debug +- arm=true // crosscompile for arm +- SH_VERBOSE=true // print every command that rake issues to the shell + +For example, to build all of the arm libraries and executables, type: +> rake arm=true release=true + +## Generating Documentation ## + +To generate documentation for the stack you need to have doxygen and graphviz (dot) +installed before invoking: + +rake document + +Be patient, this generates hundreds of megs worth of images. + The html output will be generated in ./docs \ No newline at end of file diff --git a/Terminal/ControlResponseTE.cpp b/Terminal/ControlResponseTE.cpp index 36e96f55..3736dce5 100755 --- a/Terminal/ControlResponseTE.cpp +++ b/Terminal/ControlResponseTE.cpp @@ -1,174 +1,174 @@ -#include "ControlResponseTE.h" - -#include -#include -#include - -namespace apl{ - - CommandResponder :: CommandResponder(Logger* apLogger, bool aLinkStatuses, IDataObserver* apObs) - : - Loggable(apLogger), - mpObs(apObs), - mLinkStatuses(aLinkStatuses) - { - - } - - void CommandResponder :: AcceptCommand(const BinaryOutput& ctrl, size_t i, int aSequence, IResponseAcceptor* apRspAcceptor) - { - CriticalSection c(&mLock); - CommandResponse cr; - cr.mResult = this->HandleControl(ctrl, i); - apRspAcceptor->AcceptResponse(cr, aSequence); - } - - void CommandResponder :: AcceptCommand(const Setpoint& ctrl, size_t i, int aSequence, IResponseAcceptor* apRspAcceptor) - { - CriticalSection c(&mLock); - CommandResponse cr; - cr.mResult = this->HandleControl(ctrl, i); - apRspAcceptor->AcceptResponse(cr, aSequence); - } - - CommandStatus CommandResponder :: HandleControl(const BinaryOutput& aControl, size_t aIndex) - { - CommandStatus cs = CS_TOO_MANY_OPS; - if ( mLinkStatuses && (aControl.GetCode() == CC_LATCH_ON || aControl.GetCode() == CC_LATCH_OFF)) - { - try - { - Transaction t(mpObs); - bool val = aControl.GetCode() == CC_LATCH_ON ? true : false; - mpObs->Update(ControlStatus(val, ControlStatus::ONLINE), aIndex); - cs = CS_SUCCESS; - LOG_BLOCK(LEV_INFO, "Updated ControlStatus "<< aIndex << " with " << val << "." ); - } - catch (Exception& ex) - { - LOG_BLOCK(LEV_WARNING, "Failure trying to update point in response to control. " << ex.GetErrorString()); - cs = CS_NOT_SUPPORTED; - } - } - else - { - cs = GetResponseCode(true, aIndex); - } - LOG_BLOCK(LEV_INFO, "Got Control on "<< aIndex << " with " << ToString(aControl.GetCode()) << " returning " << ToString(cs)); - return cs; - } - - CommandStatus CommandResponder :: HandleControl(const Setpoint& aControl, size_t aIndex) - { - CommandStatus cs = CS_TOO_MANY_OPS; - if ( mLinkStatuses ) - { - try - { - Transaction t(mpObs); - mpObs->Update(SetpointStatus(aControl.GetValue(), SetpointStatus::ONLINE), aIndex); - cs = CS_SUCCESS; - LOG_BLOCK(LEV_INFO, "Updated SetpointStatus "<< aIndex << " with " << aControl.GetValue() << "." ); - } - catch (Exception& ex) - { - LOG_BLOCK(LEV_WARNING, "Failure trying to update point in response to control. " << ex.GetErrorString()); - cs = CS_NOT_SUPPORTED; - } - } - else - { - cs = GetResponseCode(false, aIndex); - } - LOG_BLOCK(LEV_INFO, "Got Setpoint on "<< aIndex << " with " << aControl.GetValue() << " returning " << ToString(cs)); - return cs; - } - - void CommandResponder :: SetResponseCode(bool aType, size_t aIndex, CommandStatus aCode) - { - CriticalSection c(&mLock); - - CommandMap& m = (aType)?mBinaryResponses:mSetpointResponses; - - CommandMap::iterator iter = m.find(aIndex); - - if(iter != m.end()) iter->second = aCode; - else m[aIndex] = aCode; - } - - CommandStatus CommandResponder :: GetResponseCode(bool aType, size_t aIndex) - { - CommandMap& m = (aType) ? mBinaryResponses : mSetpointResponses; - - // check for specific return code for this index. - CommandMap::iterator iter = m.find(aIndex); - if(iter != m.end()) return iter->second; - - return CS_NOT_SUPPORTED; //return default - } - - - ControlResponseTE :: ControlResponseTE(Logger* apLogger, bool aLinkStatuses, IDataObserver* apObs) - : - mHandler(apLogger, aLinkStatuses, apObs) - { - - } - - void ControlResponseTE :: _BindToTerminal(ITerminal* apTerminal) - { - CommandNode cmd; - - cmd.mName = "set response"; - cmd.mUsage = "set response [bo|st|all] [all|#] [code]"; - cmd.mDesc = "Sets the response code we will use to respond to the incoming commands.\nYou can use return code name or index: SUCCESS, TIMEOUT, NO_SELECT, FORMAT_ERROR, NOT_SUPPORTED, ALREADY_ACTIVE, HARDWARE_ERROR, LOCAL, TOO_MANY_OPS, NOT_AUTHORIZED."; - cmd.mHandler = boost::bind(&ControlResponseTE::HandleSetResponse, this, _1); - apTerminal->BindCommand(cmd, cmd.mName); - } - - bool LookupCommandStatus(const std::string& arArg, CommandStatus& arStatus) - { -#define MACRO_CHECK_STRING(name) if(arArg == #name) {arStatus = CS_##name; return true;} - - //this one can't be used in the macro because of a naming collision with the - //terminal macro SUCCESS. - if(arArg == "SUCCESS") {arStatus = CS_SUCCESS; return true;} - MACRO_CHECK_STRING(TIMEOUT); - MACRO_CHECK_STRING(NO_SELECT); - MACRO_CHECK_STRING(FORMAT_ERROR); - MACRO_CHECK_STRING(NOT_SUPPORTED); - MACRO_CHECK_STRING(ALREADY_ACTIVE); - MACRO_CHECK_STRING(HARDWARE_ERROR); - MACRO_CHECK_STRING(LOCAL); - MACRO_CHECK_STRING(TOO_MANY_OPS); - MACRO_CHECK_STRING(NOT_AUTHORIZED); - return false; - } - - retcode ControlResponseTE :: HandleSetResponse(std::vector& arArgs) - { - if(arArgs.size() != 3) return BAD_ARGUMENTS; - - int type; - if(arArgs[0] == "all") type = 2; - else if(arArgs[0] == "bo") type = 0; - else if(arArgs[0] == "st") type = 1; - else return BAD_ARGUMENTS; - - int index; - if(arArgs[1] == "all") index = -1; - else if(!Parsing::Get(arArgs[1], index)) return BAD_ARGUMENTS; - - CommandStatus response; - int temp; - if(Parsing::Get(arArgs[2], temp)){ - response = static_cast(temp); - }else if(!LookupCommandStatus(arArgs[2], response)) return BAD_ARGUMENTS; - - if(type == 0 || type == 2) mHandler.SetResponseCode(true, index, response); - if(type == 1 || type == 2) mHandler.SetResponseCode(false, index, response); - - return SUCCESS; - } - -} +#include "ControlResponseTE.h" + +#include +#include +#include + +namespace apl{ + + CommandResponder :: CommandResponder(Logger* apLogger, bool aLinkStatuses, IDataObserver* apObs) + : + Loggable(apLogger), + mpObs(apObs), + mLinkStatuses(aLinkStatuses) + { + + } + + void CommandResponder :: AcceptCommand(const BinaryOutput& ctrl, size_t i, int aSequence, IResponseAcceptor* apRspAcceptor) + { + CriticalSection c(&mLock); + CommandResponse cr; + cr.mResult = this->HandleControl(ctrl, i); + apRspAcceptor->AcceptResponse(cr, aSequence); + } + + void CommandResponder :: AcceptCommand(const Setpoint& ctrl, size_t i, int aSequence, IResponseAcceptor* apRspAcceptor) + { + CriticalSection c(&mLock); + CommandResponse cr; + cr.mResult = this->HandleControl(ctrl, i); + apRspAcceptor->AcceptResponse(cr, aSequence); + } + + CommandStatus CommandResponder :: HandleControl(const BinaryOutput& aControl, size_t aIndex) + { + CommandStatus cs = CS_TOO_MANY_OPS; + if ( mLinkStatuses && (aControl.GetCode() == CC_LATCH_ON || aControl.GetCode() == CC_LATCH_OFF)) + { + try + { + Transaction t(mpObs); + bool val = aControl.GetCode() == CC_LATCH_ON ? true : false; + mpObs->Update(ControlStatus(val, ControlStatus::ONLINE), aIndex); + cs = CS_SUCCESS; + LOG_BLOCK(LEV_INFO, "Updated ControlStatus "<< aIndex << " with " << val << "." ); + } + catch (Exception& ex) + { + LOG_BLOCK(LEV_WARNING, "Failure trying to update point in response to control. " << ex.GetErrorString()); + cs = CS_NOT_SUPPORTED; + } + } + else + { + cs = GetResponseCode(true, aIndex); + } + LOG_BLOCK(LEV_INFO, "Got Control on "<< aIndex << " with " << ToString(aControl.GetCode()) << " returning " << ToString(cs)); + return cs; + } + + CommandStatus CommandResponder :: HandleControl(const Setpoint& aControl, size_t aIndex) + { + CommandStatus cs = CS_TOO_MANY_OPS; + if ( mLinkStatuses ) + { + try + { + Transaction t(mpObs); + mpObs->Update(SetpointStatus(aControl.GetValue(), SetpointStatus::ONLINE), aIndex); + cs = CS_SUCCESS; + LOG_BLOCK(LEV_INFO, "Updated SetpointStatus "<< aIndex << " with " << aControl.GetValue() << "." ); + } + catch (Exception& ex) + { + LOG_BLOCK(LEV_WARNING, "Failure trying to update point in response to control. " << ex.GetErrorString()); + cs = CS_NOT_SUPPORTED; + } + } + else + { + cs = GetResponseCode(false, aIndex); + } + LOG_BLOCK(LEV_INFO, "Got Setpoint on "<< aIndex << " with " << aControl.GetValue() << " returning " << ToString(cs)); + return cs; + } + + void CommandResponder :: SetResponseCode(bool aType, size_t aIndex, CommandStatus aCode) + { + CriticalSection c(&mLock); + + CommandMap& m = (aType)?mBinaryResponses:mSetpointResponses; + + CommandMap::iterator iter = m.find(aIndex); + + if(iter != m.end()) iter->second = aCode; + else m[aIndex] = aCode; + } + + CommandStatus CommandResponder :: GetResponseCode(bool aType, size_t aIndex) + { + CommandMap& m = (aType) ? mBinaryResponses : mSetpointResponses; + + // check for specific return code for this index. + CommandMap::iterator iter = m.find(aIndex); + if(iter != m.end()) return iter->second; + + return CS_NOT_SUPPORTED; //return default + } + + + ControlResponseTE :: ControlResponseTE(Logger* apLogger, bool aLinkStatuses, IDataObserver* apObs) + : + mHandler(apLogger, aLinkStatuses, apObs) + { + + } + + void ControlResponseTE :: _BindToTerminal(ITerminal* apTerminal) + { + CommandNode cmd; + + cmd.mName = "set response"; + cmd.mUsage = "set response [bo|st|all] [all|#] [code]"; + cmd.mDesc = "Sets the response code we will use to respond to the incoming commands.\nYou can use return code name or index: SUCCESS, TIMEOUT, NO_SELECT, FORMAT_ERROR, NOT_SUPPORTED, ALREADY_ACTIVE, HARDWARE_ERROR, LOCAL, TOO_MANY_OPS, NOT_AUTHORIZED."; + cmd.mHandler = boost::bind(&ControlResponseTE::HandleSetResponse, this, _1); + apTerminal->BindCommand(cmd, cmd.mName); + } + + bool LookupCommandStatus(const std::string& arArg, CommandStatus& arStatus) + { +#define MACRO_CHECK_STRING(name) if(arArg == #name) {arStatus = CS_##name; return true;} + + //this one can't be used in the macro because of a naming collision with the + //terminal macro SUCCESS. + if(arArg == "SUCCESS") {arStatus = CS_SUCCESS; return true;} + MACRO_CHECK_STRING(TIMEOUT); + MACRO_CHECK_STRING(NO_SELECT); + MACRO_CHECK_STRING(FORMAT_ERROR); + MACRO_CHECK_STRING(NOT_SUPPORTED); + MACRO_CHECK_STRING(ALREADY_ACTIVE); + MACRO_CHECK_STRING(HARDWARE_ERROR); + MACRO_CHECK_STRING(LOCAL); + MACRO_CHECK_STRING(TOO_MANY_OPS); + MACRO_CHECK_STRING(NOT_AUTHORIZED); + return false; + } + + retcode ControlResponseTE :: HandleSetResponse(std::vector& arArgs) + { + if(arArgs.size() != 3) return BAD_ARGUMENTS; + + int type; + if(arArgs[0] == "all") type = 2; + else if(arArgs[0] == "bo") type = 0; + else if(arArgs[0] == "st") type = 1; + else return BAD_ARGUMENTS; + + int index; + if(arArgs[1] == "all") index = -1; + else if(!Parsing::Get(arArgs[1], index)) return BAD_ARGUMENTS; + + CommandStatus response; + int temp; + if(Parsing::Get(arArgs[2], temp)){ + response = static_cast(temp); + }else if(!LookupCommandStatus(arArgs[2], response)) return BAD_ARGUMENTS; + + if(type == 0 || type == 2) mHandler.SetResponseCode(true, index, response); + if(type == 1 || type == 2) mHandler.SetResponseCode(false, index, response); + + return SUCCESS; + } + +} diff --git a/Terminal/ControlResponseTE.h b/Terminal/ControlResponseTE.h index 7c97e9ba..0ea4a230 100755 --- a/Terminal/ControlResponseTE.h +++ b/Terminal/ControlResponseTE.h @@ -18,7 +18,7 @@ namespace apl public: CommandResponder(Logger* apLogger, bool aLinkStatuses = false, IDataObserver* apObs = NULL); - + void AcceptCommand(const BinaryOutput&, size_t, int aSequence, IResponseAcceptor* apRspAcceptor); void AcceptCommand(const Setpoint&, size_t, int aSequence, IResponseAcceptor* apRspAcceptor); @@ -44,9 +44,9 @@ namespace apl class ControlResponseTE : public ITerminalExtension { public: - + ControlResponseTE(Logger* apLogger, bool aLinkStatuses = false, IDataObserver* apObs = NULL); - + std::string Name() { return "ControlResponseTE"; } ICommandAcceptor* GetCmdAcceptor() { return &mHandler; } @@ -56,7 +56,7 @@ namespace apl retcode HandleSetResponse(std::vector& arArgs); - CommandResponder mHandler; + CommandResponder mHandler; }; } diff --git a/Terminal/ControlTerminalExtension.h b/Terminal/ControlTerminalExtension.h index cc19ca93..3689db62 100755 --- a/Terminal/ControlTerminalExtension.h +++ b/Terminal/ControlTerminalExtension.h @@ -16,13 +16,13 @@ namespace apl class ControlTerminalExtension : public ITerminalExtension { public: - - ControlTerminalExtension(ICommandAcceptor* apCmdAcceptor) : + + ControlTerminalExtension(ICommandAcceptor* apCmdAcceptor) : mSequence(0), mpCmdAcceptor(apCmdAcceptor), mRspQueue() { - + } std::string Name() { return "ControlTerminalExtension"; } @@ -39,11 +39,11 @@ namespace apl void WaitForResponse(); retcode HandleIssueBO(std::vector& arArgs); retcode HandleIssueST(std::vector& arArgs); - + //implement from ITerminalExtension void _BindToTerminal(ITerminal* apTerminal); - + }; } diff --git a/Terminal/DOTerminalExtension.h b/Terminal/DOTerminalExtension.h index 53e9c078..ccd0dd2e 100755 --- a/Terminal/DOTerminalExtension.h +++ b/Terminal/DOTerminalExtension.h @@ -19,17 +19,17 @@ namespace apl { public: DOTerminalExtension(IDataObserver* apObserver) : mpObserver(apObserver) {} - + virtual ~DOTerminalExtension() {} private: retcode HandleQueueBinary(std::vector& arArgs) - { return HandleQueue(arArgs); } - + { return HandleQueue(arArgs); } + retcode HandleQueueAnalog(std::vector& arArgs) { return HandleQueue(arArgs); } - + retcode HandleQueueCounter(std::vector& arArgs) { return HandleQueue(arArgs); } @@ -37,7 +37,7 @@ namespace apl retcode HandleQueue(std::vector& arArgs); retcode HandleDoTransaction(std::vector& arArgs); IDataObserver* mpObserver; - + //implement from ITerminalExtension void _BindToTerminal(ITerminal* apTerminal); @@ -46,7 +46,7 @@ namespace apl template retcode DOTerminalExtension::HandleQueue(std::vector& arArgs) - { + { size_t index; typename T::ValueType value; size_t quality = AQ_ONLINE; // byte_t is interpreted as a '1' instead of 0x01 @@ -60,13 +60,13 @@ namespace apl break; default: return BAD_ARGUMENTS; - } + } - T p(value, static_cast(quality)); + T p(value, static_cast(quality)); p.SetToNow(); Transaction tr(&mBuffer); mBuffer.Update(p, index); - + return SUCCESS; } } diff --git a/Terminal/FlexibleObserverTerminalExtension.h b/Terminal/FlexibleObserverTerminalExtension.h index 899da3fa..b66348ca 100755 --- a/Terminal/FlexibleObserverTerminalExtension.h +++ b/Terminal/FlexibleObserverTerminalExtension.h @@ -16,7 +16,7 @@ namespace apl { class FlexibleDataObserver; namespace dnp { - + struct ShowRange { enum Type { ST_ALL, ST_BI, ST_AI, ST_C, ST_BOS, ST_SS }; @@ -33,7 +33,7 @@ namespace dnp { class FlexibleObserverTerminalExtension : public ITerminalExtension { public: - + FlexibleObserverTerminalExtension(FlexibleDataObserver* apObserver); FlexibleObserverTerminalExtension(FlexibleDataObserver* apObserver, const DeviceTemplate& arTmp); @@ -61,7 +61,7 @@ namespace dnp { retcode HandleShow(std::vector& arArgs, bool aLogToFile, bool aClearScreenAfter); retcode HandleSetShow(std::vector& arArgs); retcode HandleShowStats(std::vector& arArgs); - + //implement from ITerminalExtension void _BindToTerminal(ITerminal* apTerminal); }; diff --git a/Terminal/LineReader.h b/Terminal/LineReader.h index 1b299ee9..45c2e919 100755 --- a/Terminal/LineReader.h +++ b/Terminal/LineReader.h @@ -17,13 +17,13 @@ class LineReader : public AsyncPhysLayerMonitor, private Uncopyable { public: LineReader(Logger* apLogger, IPhysicalLayerAsync* apPhysical, ITimerSource* apTimerSrc, size_t aBuffSize); - + virtual void AcceptLine(const std::string&) = 0; virtual void _Up() = 0; virtual void _Down() = 0; - + private: - CopyableBuffer mBuffer; + CopyableBuffer mBuffer; size_t mNumBytes; bool mHasCR; diff --git a/Terminal/LogTerminalExtension.h b/Terminal/LogTerminalExtension.h index f69070d5..6ae12bcb 100755 --- a/Terminal/LogTerminalExtension.h +++ b/Terminal/LogTerminalExtension.h @@ -1,76 +1,76 @@ -#ifndef __LOG_TERMINAL_EXTENSION_H_ -#define __LOG_TERMINAL_EXTENSION_H_ - -#include -#include -#include - -#include "TerminalInterfaces.h" - -namespace apl { - -class ITimerSource; -class ITimer; - - class LogTerminalExtension : public ITerminalExtension, public INotifier - { - public: - LogTerminalExtension(EventLog*); - - virtual ~LogTerminalExtension(); - - void RedirectedLine(const std::string&); - - /// Implements INotifier so that we can process new log messages - void Notify(); - - private: - - EventLog* mpLog; - ITimerSource* mpTimerSrc; - - //implement from ITerminalExtension - void _BindToTerminal(ITerminal* apTerminal); - - std::string GetLogString(LogEntry& arEntry); - void ResetActiveColumns(); - void HandleLogTimer(); - - enum LogColumns - { - COL_TIME, - COL_FILTER, - COL_DEVICE, - COL_LOCATION, - COL_MESSAGE - }; - - void StopLoggingToFile(); - - std::vector mActiveColumns; - LogEntryCircularBuffer mBuffer; - MetricBuffer mMetrics; - LogToFile* mpFileLogger; - - //clear - retcode HandleClearScreen(std::vector&); - - //print - retcode HandlePrintLog(std::vector&); - retcode HandlePrintLoggers(std::vector&); - retcode HandlePrintVars(std::vector&); - //run - retcode HandleRunLog(std::vector& arTokens); - //set - retcode HandleSetFilterOrLevel(std::vector& arTokens, bool aSetLevel); - retcode HandleSetLogCol(std::vector& arTokens); - - retcode HandleStartToFileLogging(std::vector& arTokens); - retcode HandleStopToFileLogging(std::vector& arTokens); - - void PrintLog(); - }; -} - -#endif - +#ifndef __LOG_TERMINAL_EXTENSION_H_ +#define __LOG_TERMINAL_EXTENSION_H_ + +#include +#include +#include + +#include "TerminalInterfaces.h" + +namespace apl { + +class ITimerSource; +class ITimer; + + class LogTerminalExtension : public ITerminalExtension, public INotifier + { + public: + LogTerminalExtension(EventLog*); + + virtual ~LogTerminalExtension(); + + void RedirectedLine(const std::string&); + + /// Implements INotifier so that we can process new log messages + void Notify(); + + private: + + EventLog* mpLog; + ITimerSource* mpTimerSrc; + + //implement from ITerminalExtension + void _BindToTerminal(ITerminal* apTerminal); + + std::string GetLogString(LogEntry& arEntry); + void ResetActiveColumns(); + void HandleLogTimer(); + + enum LogColumns + { + COL_TIME, + COL_FILTER, + COL_DEVICE, + COL_LOCATION, + COL_MESSAGE + }; + + void StopLoggingToFile(); + + std::vector mActiveColumns; + LogEntryCircularBuffer mBuffer; + MetricBuffer mMetrics; + LogToFile* mpFileLogger; + + //clear + retcode HandleClearScreen(std::vector&); + + //print + retcode HandlePrintLog(std::vector&); + retcode HandlePrintLoggers(std::vector&); + retcode HandlePrintVars(std::vector&); + //run + retcode HandleRunLog(std::vector& arTokens); + //set + retcode HandleSetFilterOrLevel(std::vector& arTokens, bool aSetLevel); + retcode HandleSetLogCol(std::vector& arTokens); + + retcode HandleStartToFileLogging(std::vector& arTokens); + retcode HandleStopToFileLogging(std::vector& arTokens); + + void PrintLog(); + }; +} + +#endif + diff --git a/Terminal/PhysicalLayerIOStreamAsync.cpp b/Terminal/PhysicalLayerIOStreamAsync.cpp index 4e863aca..c7e98ac3 100755 --- a/Terminal/PhysicalLayerIOStreamAsync.cpp +++ b/Terminal/PhysicalLayerIOStreamAsync.cpp @@ -1,27 +1,27 @@ -#include "PhysicalLayerIOStreamAsync.h" - -#include - -using namespace boost::system; -using namespace std; - -namespace apl { - - PhysicalLayerIOStreamAsync::PhysicalLayerIOStreamAsync(Logger* apLogger, boost::asio::io_service* apService) : - PhysicalLayerSyncProxy(apLogger, apService) - {} - - std::string PhysicalLayerIOStreamAsync::Read() - { - string input; - getline(cin, input); - input.append("\r\n"); - return input; - } - - void PhysicalLayerIOStreamAsync::Write(const std::string& arString) - { - cout << arString; - cout.flush(); - } -} +#include "PhysicalLayerIOStreamAsync.h" + +#include + +using namespace boost::system; +using namespace std; + +namespace apl { + + PhysicalLayerIOStreamAsync::PhysicalLayerIOStreamAsync(Logger* apLogger, boost::asio::io_service* apService) : + PhysicalLayerSyncProxy(apLogger, apService) + {} + + std::string PhysicalLayerIOStreamAsync::Read() + { + string input; + getline(cin, input); + input.append("\r\n"); + return input; + } + + void PhysicalLayerIOStreamAsync::Write(const std::string& arString) + { + cout << arString; + cout.flush(); + } +} diff --git a/Terminal/PhysicalLayerIOStreamAsync.h b/Terminal/PhysicalLayerIOStreamAsync.h index dc769818..509c6c66 100755 --- a/Terminal/PhysicalLayerIOStreamAsync.h +++ b/Terminal/PhysicalLayerIOStreamAsync.h @@ -1,34 +1,34 @@ -#ifndef __PHYSICAL_LAYER_IOSTREAM_ASYNC_H_ -#define __PHYSICAL_LAYER_IOSTREAM_ASYNC_H_ - - -#include "PhysicalLayerSyncProxy.h" - -namespace boost { namespace asio { -class io_service; -}} - -namespace apl -{ - -class Logger; - - /** Simple thread object that allows for non-blocking read of std input. - */ - class PhysicalLayerIOStreamAsync : public PhysicalLayerSyncProxy - { - public: - PhysicalLayerIOStreamAsync(Logger*, boost::asio::io_service*); - - private: - - - //implement virtual members of PhysicalLayerSyncProxy - - std::string Read(); - void Write(const std::string&); - }; -} - -#endif - +#ifndef __PHYSICAL_LAYER_IOSTREAM_ASYNC_H_ +#define __PHYSICAL_LAYER_IOSTREAM_ASYNC_H_ + + +#include "PhysicalLayerSyncProxy.h" + +namespace boost { namespace asio { +class io_service; +}} + +namespace apl +{ + +class Logger; + + /** Simple thread object that allows for non-blocking read of std input. + */ + class PhysicalLayerIOStreamAsync : public PhysicalLayerSyncProxy + { + public: + PhysicalLayerIOStreamAsync(Logger*, boost::asio::io_service*); + + private: + + + //implement virtual members of PhysicalLayerSyncProxy + + std::string Read(); + void Write(const std::string&); + }; +} + +#endif + diff --git a/Terminal/PhysicalLayerSyncProxy.cpp b/Terminal/PhysicalLayerSyncProxy.cpp index 824167cb..b4405cb1 100755 --- a/Terminal/PhysicalLayerSyncProxy.cpp +++ b/Terminal/PhysicalLayerSyncProxy.cpp @@ -1,95 +1,95 @@ -#include -#include "PhysicalLayerSyncProxy.h" - -#include - -using namespace boost::system; -using namespace std; - -namespace apl { - - const boost::system::error_code PhysicalLayerSyncProxy::mSuccessCode(errc::success, get_generic_category()); - const boost::system::error_code PhysicalLayerSyncProxy::mErrorCode(errc::permission_denied, get_generic_category()); - - PhysicalLayerSyncProxy::PhysicalLayerSyncProxy(Logger* apLogger, boost::asio::io_service* apService) : - PhysicalLayerAsyncBase(apLogger), - mpService(apService), - mThread(this) - { - this->Reset(); - mThread.Start(); - } - - void PhysicalLayerSyncProxy::SignalStop() - { - CriticalSection cs(&mWaitLock); - cs.Signal(); - } - - void PhysicalLayerSyncProxy::Reset() - { - mReading = false; - mpBuffer = NULL; - mNumToRead = 0; - mLineQueue.clear(); - } - - void PhysicalLayerSyncProxy::CheckForRead() - { - if(mReading && mLineQueue.size() > 0) { - std::string copy(mLineQueue.front()); - mLineQueue.pop_front(); - size_t len = copy.size(); - size_t min = len > mNumToRead ? mNumToRead : len; - size_t remainder = len - min; - memcpy(mpBuffer, copy.c_str(), min); - if(remainder > 0) { - std::string r(copy.c_str() + mNumToRead, remainder); - mLineQueue.push_front(r); - } - mReading = false; - mpService->post(boost::bind(&PhysicalLayerSyncProxy::OnReadCallback, this, mSuccessCode, mpBuffer, min)); - } - } - - void PhysicalLayerSyncProxy::DoOpen() - { - this->Reset(); - mpService->post(boost::bind(&PhysicalLayerSyncProxy::OnOpenCallback, this, mSuccessCode)); - } - - void PhysicalLayerSyncProxy::DoClose() - { - - } - - void PhysicalLayerSyncProxy::DoAsyncRead(byte_t* apData, size_t aLength) - { - CriticalSection cs(&mWaitLock); - mpBuffer = apData; - mNumToRead = aLength; - mReading = true; - this->CheckForRead(); - if(mReading) cs.Signal(); //wake up the thread to go and get more data from stdin - } - - void PhysicalLayerSyncProxy::DoAsyncWrite(const byte_t* apData, size_t aLength) - { - const char* pBuff = reinterpret_cast(apData); - string s(pBuff, aLength); - this->Write(s); - mpService->post(boost::bind(&PhysicalLayerSyncProxy::OnWriteCallback, this, mSuccessCode, aLength)); - } - - void PhysicalLayerSyncProxy::Run() - { - while(!IsExitRequested()) { - CriticalSection cs(&mWaitLock); - if( !mReading ) cs.Wait(); - if( mReading ) { - mLineQueue.push_back(this->Read()); - this->CheckForRead(); - } - } - } -} +#include +#include "PhysicalLayerSyncProxy.h" + +#include + +using namespace boost::system; +using namespace std; + +namespace apl { + + const boost::system::error_code PhysicalLayerSyncProxy::mSuccessCode(errc::success, get_generic_category()); + const boost::system::error_code PhysicalLayerSyncProxy::mErrorCode(errc::permission_denied, get_generic_category()); + + PhysicalLayerSyncProxy::PhysicalLayerSyncProxy(Logger* apLogger, boost::asio::io_service* apService) : + PhysicalLayerAsyncBase(apLogger), + mpService(apService), + mThread(this) + { + this->Reset(); + mThread.Start(); + } + + void PhysicalLayerSyncProxy::SignalStop() + { + CriticalSection cs(&mWaitLock); + cs.Signal(); + } + + void PhysicalLayerSyncProxy::Reset() + { + mReading = false; + mpBuffer = NULL; + mNumToRead = 0; + mLineQueue.clear(); + } + + void PhysicalLayerSyncProxy::CheckForRead() + { + if(mReading && mLineQueue.size() > 0) { + std::string copy(mLineQueue.front()); + mLineQueue.pop_front(); + size_t len = copy.size(); + size_t min = len > mNumToRead ? mNumToRead : len; + size_t remainder = len - min; + memcpy(mpBuffer, copy.c_str(), min); + if(remainder > 0) { + std::string r(copy.c_str() + mNumToRead, remainder); + mLineQueue.push_front(r); + } + mReading = false; + mpService->post(boost::bind(&PhysicalLayerSyncProxy::OnReadCallback, this, mSuccessCode, mpBuffer, min)); + } + } + + void PhysicalLayerSyncProxy::DoOpen() + { + this->Reset(); + mpService->post(boost::bind(&PhysicalLayerSyncProxy::OnOpenCallback, this, mSuccessCode)); + } + + void PhysicalLayerSyncProxy::DoClose() + { + + } + + void PhysicalLayerSyncProxy::DoAsyncRead(byte_t* apData, size_t aLength) + { + CriticalSection cs(&mWaitLock); + mpBuffer = apData; + mNumToRead = aLength; + mReading = true; + this->CheckForRead(); + if(mReading) cs.Signal(); //wake up the thread to go and get more data from stdin + } + + void PhysicalLayerSyncProxy::DoAsyncWrite(const byte_t* apData, size_t aLength) + { + const char* pBuff = reinterpret_cast(apData); + string s(pBuff, aLength); + this->Write(s); + mpService->post(boost::bind(&PhysicalLayerSyncProxy::OnWriteCallback, this, mSuccessCode, aLength)); + } + + void PhysicalLayerSyncProxy::Run() + { + while(!IsExitRequested()) { + CriticalSection cs(&mWaitLock); + if( !mReading ) cs.Wait(); + if( mReading ) { + mLineQueue.push_back(this->Read()); + this->CheckForRead(); + } + } + } +} diff --git a/Terminal/PhysicalLayerSyncProxy.h b/Terminal/PhysicalLayerSyncProxy.h index f2884e3b..6f8e8177 100755 --- a/Terminal/PhysicalLayerSyncProxy.h +++ b/Terminal/PhysicalLayerSyncProxy.h @@ -1,68 +1,68 @@ -#ifndef __PHYSICAL_LAYER_SYNC_PROXY_H_ -#define __PHYSICAL_LAYER_SYNC_PROXY_H_ - -#include -#include -#include -#include - -#include -#include -#include - -namespace boost { namespace asio { -class io_service; -}} - -namespace apl { - -class Logger; - - /** Simple thread object that allows for non-blocking read of std input. - */ - class PhysicalLayerSyncProxy : public PhysicalLayerAsyncBase, private Threadable - { - public: - PhysicalLayerSyncProxy(Logger*, boost::asio::io_service*); - - void DoOpen(); - void DoClose(); - void DoAsyncRead(byte_t*, size_t); - void DoAsyncWrite(const byte_t*, size_t); - - static const boost::system::error_code mSuccessCode; - static const boost::system::error_code mErrorCode; - - protected: - - /// Blocking read defined in base class - virtual std::string Read() = 0; - - /// Blocking write defined in base class - virtual void Write(const std::string&) = 0; - - - - private: - - void SignalStop(); - - void Run(); - void Reset(); - void CheckForRead(); - - boost::asio::io_service* mpService; - - bool mReading; - size_t mNumToRead; - byte_t* mpBuffer; - - SigLock mWaitLock; - std::deque mLineQueue; - Thread mThread; - - }; -} - -#endif - +#ifndef __PHYSICAL_LAYER_SYNC_PROXY_H_ +#define __PHYSICAL_LAYER_SYNC_PROXY_H_ + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace asio { +class io_service; +}} + +namespace apl { + +class Logger; + + /** Simple thread object that allows for non-blocking read of std input. + */ + class PhysicalLayerSyncProxy : public PhysicalLayerAsyncBase, private Threadable + { + public: + PhysicalLayerSyncProxy(Logger*, boost::asio::io_service*); + + void DoOpen(); + void DoClose(); + void DoAsyncRead(byte_t*, size_t); + void DoAsyncWrite(const byte_t*, size_t); + + static const boost::system::error_code mSuccessCode; + static const boost::system::error_code mErrorCode; + + protected: + + /// Blocking read defined in base class + virtual std::string Read() = 0; + + /// Blocking write defined in base class + virtual void Write(const std::string&) = 0; + + + + private: + + void SignalStop(); + + void Run(); + void Reset(); + void CheckForRead(); + + boost::asio::io_service* mpService; + + bool mReading; + size_t mNumToRead; + byte_t* mpBuffer; + + SigLock mWaitLock; + std::deque mLineQueue; + Thread mThread; + + }; +} + +#endif + diff --git a/Terminal/Terminal.h b/Terminal/Terminal.h index c9555e92..e63a5696 100755 --- a/Terminal/Terminal.h +++ b/Terminal/Terminal.h @@ -16,15 +16,15 @@ namespace apl { class IPhysicalLayerAsync; class ITimerSource; class ITimer; - + /** A threadable class for interacting with communication stacks. */ class Terminal : private LineReader, public ITerminal - { + { public: - + Terminal(Logger* apLogger, IPhysicalLayerAsync* apPhysical, ITimerSource* apTimerSrc, const std::string& arBanner = "Terminal", bool aIOMode = false, bool aHoldTimer = true); - + void BindCommand(const CommandNode& arNode, const std::string &arFullCommand); void AddExtension(ITerminalExtension* apExtension) @@ -35,19 +35,19 @@ class ITimer; void AcceptLine(const std::string& arLine); void _Up(); void _Down(); - + retcode ProcessLine(const std::string& arLine); void Post(const ExpirationHandler& arHandler); void SetRedirect(const RedirectFunc&); void ClearRedirect(); - + void _OnSendSuccess(); void _OnSendFailure(); void Init() { this->Start(); } - void Shutdown() { + void Shutdown() { if(mpInfiniteTimer) mpInfiniteTimer->Cancel(); this->Stop(); } @@ -59,32 +59,32 @@ class ITimer; void QueueSendRecursive(const std::string& arData); void CheckForSend(); - + std::deque mSendQueue; CopyableBuffer mSendBuffer; - + //The hierarchical map of commands and callbacks TokenNode mCmdRoot; IPhysicalLayerAsync* mpPhysical; ITimerSource* mpTimerSrc; - + ITimer* mpInfiniteTimer; void Null(); - std::string mBanner; + std::string mBanner; bool mIOMode; RedirectFunc mRedirectFunc; retcode HandleDefault(std::vector& arTokens); - retcode HandleHelp(std::vector& arTokens); + retcode HandleHelp(std::vector& arTokens); retcode HandleQuit(std::vector& ); retcode HandleBye(std::vector& ); retcode HandleEcho(std::vector& ); - + void InitCmdHandlers(); //initialize the command handlers - + void SendPrompt(); - + // private helper functions void PrintSubCommands(const std::string& arCmdName, const std::vector& arSubCmds); void PrintClearScreen(); diff --git a/Terminal/Terminal.vcproj b/Terminal/Terminal.vcproj index b1af16b3..88c4140e 100755 --- a/Terminal/Terminal.vcproj +++ b/Terminal/Terminal.vcproj @@ -1,247 +1,247 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Terminal/TerminalInterfaces.h b/Terminal/TerminalInterfaces.h index 14b10ad3..ea387843 100755 --- a/Terminal/TerminalInterfaces.h +++ b/Terminal/TerminalInterfaces.h @@ -87,8 +87,8 @@ namespace apl virtual ~ITerminal() {} - virtual void BindCommand(const CommandNode& arNode, const std::string &arFullCommand) = 0; - virtual void QueueSend(const std::string& arData, bool aLog = true) = 0; + virtual void BindCommand(const CommandNode& arNode, const std::string &arFullCommand) = 0; + virtual void QueueSend(const std::string& arData, bool aLog = true) = 0; virtual void SetRedirect(const RedirectFunc&) = 0; virtual void ClearRedirect() = 0; virtual void Post(const ExpirationHandler& arHandler) = 0; @@ -103,11 +103,11 @@ namespace apl ITerminalExtension() : mpTerminal(NULL) {} virtual ~ITerminalExtension() {} - + void BindToTerminal(ITerminal* apTerminal) - { - assert(apTerminal != NULL); - assert(mpTerminal == NULL); + { + assert(apTerminal != NULL); + assert(mpTerminal == NULL); mpTerminal = apTerminal; this->_BindToTerminal(apTerminal); } @@ -117,23 +117,23 @@ namespace apl mpTerminal->Post(arHandler); } - void SetRedirect(const RedirectFunc& arRedirect) + void SetRedirect(const RedirectFunc& arRedirect) { mpTerminal->SetRedirect(arRedirect); } - void ClearRedirect() + void ClearRedirect() { mpTerminal->ClearRedirect(); } protected: - void Send(const std::string& arData, bool aClearSrc = false) - { - assert(mpTerminal != NULL); + void Send(const std::string& arData, bool aClearSrc = false) + { + assert(mpTerminal != NULL); mpTerminal->QueueSend(arData, aClearSrc); - } + } private: diff --git a/Terminal/TokenNode.h b/Terminal/TokenNode.h index 0facc307..73ec5df3 100755 --- a/Terminal/TokenNode.h +++ b/Terminal/TokenNode.h @@ -15,19 +15,19 @@ namespace apl public: - TokenNode(T aValue) + TokenNode(T aValue) : mHasDefault(true), mValue(aValue) { - + } - TokenNode() + TokenNode() : mHasDefault(false) { - + } ~TokenNode() @@ -65,7 +65,7 @@ namespace apl mMap[arToken] = pToken; return pToken; } - + void SetValue(T aValue) { @@ -78,17 +78,17 @@ namespace apl typename TokenMap::iterator i = mMap.begin(); for(; i != mMap.end(); i++) arNames.push_back(i->first); } - + private: bool mHasDefault; T mValue; - + TokenMap mMap; - + }; } diff --git a/Terminal/rake.project.rb b/Terminal/rake.project.rb index fa3a26c5..79d7c2d8 100755 --- a/Terminal/rake.project.rb +++ b/Terminal/rake.project.rb @@ -1,5 +1,5 @@ - -$options = { -:target => 'libterminal.a', -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES] -} + +$options = { +:target => 'libterminal.a', +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES] +} diff --git a/TerminalTest/TerminalTest.vcproj b/TerminalTest/TerminalTest.vcproj index 75248e8f..ba1c76f8 100755 --- a/TerminalTest/TerminalTest.vcproj +++ b/TerminalTest/TerminalTest.vcproj @@ -1,203 +1,203 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TerminalTest/TestPhysicalLayerSyncProxy.cpp b/TerminalTest/TestPhysicalLayerSyncProxy.cpp index 31da18c4..426e970d 100755 --- a/TerminalTest/TestPhysicalLayerSyncProxy.cpp +++ b/TerminalTest/TestPhysicalLayerSyncProxy.cpp @@ -1,97 +1,97 @@ -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -using namespace apl; -using namespace boost; - -class SyncProxyTestObject : public LogTester, public AsyncTestObjectASIO, public PhysicalLayerSyncProxy -{ - public: - SyncProxyTestObject(FilterLevel aLevel, bool aImmediate = false) : - LogTester(aImmediate), - AsyncTestObjectASIO(), - PhysicalLayerSyncProxy(mLog.GetLogger(aLevel, "SyncProxy"), this->GetService()), - adapter(mLog.GetLogger(aLevel, "Adapter"), this, false), - upper(mLog.GetLogger(aLevel, "Upper")) - { - adapter.SetUpperLayer(&upper); - } - - std::string Read() - { - CriticalSection cs(&mQueueLock); - while(mReadQueue.size() == 0) cs.Wait(); - std::string ret = mReadQueue.front(); - mReadQueue.pop_front(); - return ret; - } - - void Write(const std::string&) - { - - } - - void Push(const std::string& s) - { - CriticalSection cs(&mQueueLock); - mReadQueue.push_back(s); - cs.Signal(); - } - - apl::LowerLayerToPhysAdapter adapter; - apl::MockUpperLayer upper; - - private: - - SigLock mQueueLock; - std::deque mReadQueue; -}; - -BOOST_AUTO_TEST_SUITE(PhysicalLayerSyncProxy) - - - BOOST_AUTO_TEST_CASE(Init) - { - SyncProxyTestObject t(LEV_INFO); - } - - BOOST_AUTO_TEST_CASE(OpenReadWrite) - { - SyncProxyTestObject t(LEV_INFO); - MockUpperLayer::State s; - BOOST_REQUIRE(t.upper.StateEquals(s)); - t.AsyncOpen(); ++s.mNumLayerUp; - t.ProceedUntil(boost::bind(&MockUpperLayer::StateEquals, &t.upper, s)); - - t.adapter.StartRead(); - t.Push("foo"); - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::BufferEqualsString, &t.upper, "foo"))); - - t.Push("bar"); - t.adapter.StartRead(); - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::BufferEqualsString, &t.upper, "foobar"))); - - t.upper.SendDown("00"); ++s.mSuccessCnt; - t.ProceedUntil(boost::bind(&MockUpperLayer::StateEquals, &t.upper, s)); - - t.AsyncClose(); ++s.mNumLayerDown; - t.ProceedUntil(boost::bind(&MockUpperLayer::StateEquals, &t.upper, s)); - } - - - -BOOST_AUTO_TEST_SUITE_END() - +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +using namespace apl; +using namespace boost; + +class SyncProxyTestObject : public LogTester, public AsyncTestObjectASIO, public PhysicalLayerSyncProxy +{ + public: + SyncProxyTestObject(FilterLevel aLevel, bool aImmediate = false) : + LogTester(aImmediate), + AsyncTestObjectASIO(), + PhysicalLayerSyncProxy(mLog.GetLogger(aLevel, "SyncProxy"), this->GetService()), + adapter(mLog.GetLogger(aLevel, "Adapter"), this, false), + upper(mLog.GetLogger(aLevel, "Upper")) + { + adapter.SetUpperLayer(&upper); + } + + std::string Read() + { + CriticalSection cs(&mQueueLock); + while(mReadQueue.size() == 0) cs.Wait(); + std::string ret = mReadQueue.front(); + mReadQueue.pop_front(); + return ret; + } + + void Write(const std::string&) + { + + } + + void Push(const std::string& s) + { + CriticalSection cs(&mQueueLock); + mReadQueue.push_back(s); + cs.Signal(); + } + + apl::LowerLayerToPhysAdapter adapter; + apl::MockUpperLayer upper; + + private: + + SigLock mQueueLock; + std::deque mReadQueue; +}; + +BOOST_AUTO_TEST_SUITE(PhysicalLayerSyncProxy) + + + BOOST_AUTO_TEST_CASE(Init) + { + SyncProxyTestObject t(LEV_INFO); + } + + BOOST_AUTO_TEST_CASE(OpenReadWrite) + { + SyncProxyTestObject t(LEV_INFO); + MockUpperLayer::State s; + BOOST_REQUIRE(t.upper.StateEquals(s)); + t.AsyncOpen(); ++s.mNumLayerUp; + t.ProceedUntil(boost::bind(&MockUpperLayer::StateEquals, &t.upper, s)); + + t.adapter.StartRead(); + t.Push("foo"); + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::BufferEqualsString, &t.upper, "foo"))); + + t.Push("bar"); + t.adapter.StartRead(); + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::BufferEqualsString, &t.upper, "foobar"))); + + t.upper.SendDown("00"); ++s.mSuccessCnt; + t.ProceedUntil(boost::bind(&MockUpperLayer::StateEquals, &t.upper, s)); + + t.AsyncClose(); ++s.mNumLayerDown; + t.ProceedUntil(boost::bind(&MockUpperLayer::StateEquals, &t.upper, s)); + } + + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/TerminalTest/TestTerminal.cpp b/TerminalTest/TestTerminal.cpp index acf93db2..fb439f50 100755 --- a/TerminalTest/TestTerminal.cpp +++ b/TerminalTest/TestTerminal.cpp @@ -1,174 +1,174 @@ -#define BOOST_TEST_MODULE terminal -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -using namespace boost; -using namespace std; -using namespace apl; - - - -/* -tests that does a pretty stupid run through the Terminal UI commands to make sure -that everything is still functioning. This is not really intended to be a full validation -just a sanity check to make sure all the functionality has been run and an easy fast way -to develop new functionality. -*/ -BOOST_AUTO_TEST_SUITE(UISuite) - -bool SendAndTest(MockPhysicalLayerAsyncTS* apLayer, std::string aCmd, std::string aSearchString) -{ - aCmd.append("\r\n"); - apLayer->WriteToLayer(reinterpret_cast(aCmd.c_str()), aCmd.length()); - apLayer->Advance(); - return apLayer->BufferContains(aSearchString); -} - -void TestCommandParsing(MockPhysicalLayerAsyncTS* apLayer){ - //check that a bad command string is parsed and ignored correclty - BOOST_REQUIRE(SendAndTest(apLayer, "badCommand", "Unrecognized")); - - //check that a valid command with a space before or after the string is ignored - BOOST_REQUIRE(SendAndTest(apLayer, "help print ", "log")); - BOOST_REQUIRE(SendAndTest(apLayer, " help print", "log")); - - //test that 2 lines recieved at once are both processed - BOOST_REQUIRE(SendAndTest(apLayer, "help\r\nhelp print", "log")); - - //generate a big long string that should flood the Readline() buffer. - byte_t tooBigBuff[1100]; - for(int i=0; i < 1100; ++i) tooBigBuff[i] = '0' + (i%10); - string tooBigString((char*)tooBigBuff, 1100); - //add onto the end of the string a valid command we can check the output of - tooBigString.append("\r\nprint log"); -} - -void TestHelpCommands(MockPhysicalLayerAsyncTS* apLayer){ - //test that help generates a big usage text screen. - BOOST_REQUIRE(SendAndTest(apLayer, "help", "usage")); - //test that we have atleast some subtopics for print - BOOST_REQUIRE(SendAndTest(apLayer, "help print", "log")); - //make sure we get a usefull error message for a missing subtopic - BOOST_REQUIRE(SendAndTest(apLayer, "help print faketopic", "No topic found")); - //see that we appear to get the list of registered devices - BOOST_REQUIRE(SendAndTest(apLayer, "help print loggers", "registered logger")); - - //check that we get a list of sub commands (log should be one) - BOOST_REQUIRE(SendAndTest(apLayer, "help run", "log")); - - //shows that atleast filter is a subcommand of set - BOOST_REQUIRE(SendAndTest(apLayer, "help set", "filter")); - //check that the help string is approriate for set filter - BOOST_REQUIRE(SendAndTest(apLayer, "help set filter", "filters")); - //check that the help string is approriate for set col - BOOST_REQUIRE(SendAndTest(apLayer, "help set logcol", "column order")); - - //check that a bad subcommand generates the usage message. - BOOST_REQUIRE(SendAndTest(apLayer, "print loggers NotARealDevice", "usage: ")); - - //test that a "clear screen" command ilicits a "form feed" that clears the screen. - BOOST_REQUIRE(SendAndTest(apLayer, "clear screen", "\f")); -} - -void TestPrintCommands(MockPhysicalLayerAsyncTS* apLayer, Logger* apLogger){ - //check that our new device is in the list - BOOST_REQUIRE(SendAndTest(apLayer, "print loggers", "TestDevice")); - - //Log a string and see that it appears in the print log command - apLogger->Log(LEV_ERROR,LOCATION,"TestLogOutput"); - BOOST_REQUIRE(SendAndTest(apLayer, "print log", "TestLogOutput")); - - //log another string and make sure that it is displayed if we ask for jsut the TestDevice - apLogger->Log(LEV_ERROR,LOCATION,"TestOutputOnly"); - BOOST_REQUIRE(SendAndTest(apLayer, "print log TestDevice", "TestOutputOnly")); -} - -void TestSetCommands(MockPhysicalLayerAsyncTS* apLayer){ - //test that the help string is correct - BOOST_REQUIRE(SendAndTest(apLayer, "set logcol", "usage: ")); - //test that we stop the user from having the same column more that once - BOOST_REQUIRE(SendAndTest(apLayer, "set logcol tt", "more than once")); - //check that bad column names are thrown out. - BOOST_REQUIRE(SendAndTest(apLayer, "set logcol x", "Unrecognized log column")); - //make sure a valid string is allowed - BOOST_REQUIRE(SendAndTest(apLayer, "set logcol fldm", ">")); - - //test the help string - BOOST_REQUIRE(SendAndTest(apLayer, "set filter", "usage: ")); - - //test that we cant have both all and none - BOOST_REQUIRE(SendAndTest(apLayer, "set filter an", "Couldn't parse")); - //test that we cant have both all and anything else - BOOST_REQUIRE(SendAndTest(apLayer, "set filter ad", "Couldn't parse")); - //check that a bad filter is ignored - BOOST_REQUIRE(SendAndTest(apLayer, "set filter x", "Couldn't parse")); - //test that all works - BOOST_REQUIRE(SendAndTest(apLayer, "set filter a", ">")); - //test that none works - BOOST_REQUIRE(SendAndTest(apLayer, "set filter n", ">")); - //test that setting all of the filters manually works - BOOST_REQUIRE(SendAndTest(apLayer, "set filter dciwev", ">")); - - //leave it set to all to error only - BOOST_REQUIRE(SendAndTest(apLayer, "set filter e", ">")); - - //make sure it ignores attempts to set filters on bad devieces - BOOST_REQUIRE(SendAndTest(apLayer, "set filter dciwev BadDevice", "Unrecognized device")); - //check that it works for a good device - BOOST_REQUIRE(SendAndTest(apLayer, "set filter dciwev TestDevice", ">")); -} - -void TestRunCommands(MockPhysicalLayerAsyncTS* apLayer, Logger* apLogger){ - //put an entry into the log that we will pickup on RunLog so we see something - apLogger->Log(LEV_ERROR,LOCATION,"TestOutputOnRun"); - - //do the run command, notice I adedd a \r\n which forces a second line of input to be ready - //immediateley to break the "run" cycle after a single iteration (this is necessary since the - //parser is expecting ">" which we don't get during a "run" command. - BOOST_REQUIRE(SendAndTest(apLayer, "run log\r\n", "TestOutputOnRun")); -} - -BOOST_AUTO_TEST_CASE(TerminalInteractions) -{ - //prepare the terminal on a "non-standard" port - EventLog log; - Logger* pLoggerA = log.GetLogger(LEV_INTERPRET, "Terminal"); - - MockTimerSource mts; - MockPhysicalLayerAsyncTS phys(log.GetLogger(LEV_INTERPRET, "Phys"), &mts); - - LogTerminalExtension lte(&log); - Terminal trm(pLoggerA, &phys, &mts, "Test Terminal", false, false); - trm.AddExtension(<e); - trm.Init(); - - BOOST_REQUIRE(mts.DispatchOne()); - - //add a "device" to the logger so we can test the devices behavior - Logger* logger = log.GetLogger(LEV_ERROR,"TestDevice"); - - TestCommandParsing(&phys); - TestHelpCommands(&phys); - TestPrintCommands(&phys, logger); - - TestSetCommands(&phys); - TestRunCommands(&phys, logger); - - trm.Shutdown(); -} - -BOOST_AUTO_TEST_SUITE_END() - +#define BOOST_TEST_MODULE terminal +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +using namespace boost; +using namespace std; +using namespace apl; + + + +/* +tests that does a pretty stupid run through the Terminal UI commands to make sure +that everything is still functioning. This is not really intended to be a full validation +just a sanity check to make sure all the functionality has been run and an easy fast way +to develop new functionality. +*/ +BOOST_AUTO_TEST_SUITE(UISuite) + +bool SendAndTest(MockPhysicalLayerAsyncTS* apLayer, std::string aCmd, std::string aSearchString) +{ + aCmd.append("\r\n"); + apLayer->WriteToLayer(reinterpret_cast(aCmd.c_str()), aCmd.length()); + apLayer->Advance(); + return apLayer->BufferContains(aSearchString); +} + +void TestCommandParsing(MockPhysicalLayerAsyncTS* apLayer){ + //check that a bad command string is parsed and ignored correclty + BOOST_REQUIRE(SendAndTest(apLayer, "badCommand", "Unrecognized")); + + //check that a valid command with a space before or after the string is ignored + BOOST_REQUIRE(SendAndTest(apLayer, "help print ", "log")); + BOOST_REQUIRE(SendAndTest(apLayer, " help print", "log")); + + //test that 2 lines recieved at once are both processed + BOOST_REQUIRE(SendAndTest(apLayer, "help\r\nhelp print", "log")); + + //generate a big long string that should flood the Readline() buffer. + byte_t tooBigBuff[1100]; + for(int i=0; i < 1100; ++i) tooBigBuff[i] = '0' + (i%10); + string tooBigString((char*)tooBigBuff, 1100); + //add onto the end of the string a valid command we can check the output of + tooBigString.append("\r\nprint log"); +} + +void TestHelpCommands(MockPhysicalLayerAsyncTS* apLayer){ + //test that help generates a big usage text screen. + BOOST_REQUIRE(SendAndTest(apLayer, "help", "usage")); + //test that we have atleast some subtopics for print + BOOST_REQUIRE(SendAndTest(apLayer, "help print", "log")); + //make sure we get a usefull error message for a missing subtopic + BOOST_REQUIRE(SendAndTest(apLayer, "help print faketopic", "No topic found")); + //see that we appear to get the list of registered devices + BOOST_REQUIRE(SendAndTest(apLayer, "help print loggers", "registered logger")); + + //check that we get a list of sub commands (log should be one) + BOOST_REQUIRE(SendAndTest(apLayer, "help run", "log")); + + //shows that atleast filter is a subcommand of set + BOOST_REQUIRE(SendAndTest(apLayer, "help set", "filter")); + //check that the help string is approriate for set filter + BOOST_REQUIRE(SendAndTest(apLayer, "help set filter", "filters")); + //check that the help string is approriate for set col + BOOST_REQUIRE(SendAndTest(apLayer, "help set logcol", "column order")); + + //check that a bad subcommand generates the usage message. + BOOST_REQUIRE(SendAndTest(apLayer, "print loggers NotARealDevice", "usage: ")); + + //test that a "clear screen" command ilicits a "form feed" that clears the screen. + BOOST_REQUIRE(SendAndTest(apLayer, "clear screen", "\f")); +} + +void TestPrintCommands(MockPhysicalLayerAsyncTS* apLayer, Logger* apLogger){ + //check that our new device is in the list + BOOST_REQUIRE(SendAndTest(apLayer, "print loggers", "TestDevice")); + + //Log a string and see that it appears in the print log command + apLogger->Log(LEV_ERROR,LOCATION,"TestLogOutput"); + BOOST_REQUIRE(SendAndTest(apLayer, "print log", "TestLogOutput")); + + //log another string and make sure that it is displayed if we ask for jsut the TestDevice + apLogger->Log(LEV_ERROR,LOCATION,"TestOutputOnly"); + BOOST_REQUIRE(SendAndTest(apLayer, "print log TestDevice", "TestOutputOnly")); +} + +void TestSetCommands(MockPhysicalLayerAsyncTS* apLayer){ + //test that the help string is correct + BOOST_REQUIRE(SendAndTest(apLayer, "set logcol", "usage: ")); + //test that we stop the user from having the same column more that once + BOOST_REQUIRE(SendAndTest(apLayer, "set logcol tt", "more than once")); + //check that bad column names are thrown out. + BOOST_REQUIRE(SendAndTest(apLayer, "set logcol x", "Unrecognized log column")); + //make sure a valid string is allowed + BOOST_REQUIRE(SendAndTest(apLayer, "set logcol fldm", ">")); + + //test the help string + BOOST_REQUIRE(SendAndTest(apLayer, "set filter", "usage: ")); + + //test that we cant have both all and none + BOOST_REQUIRE(SendAndTest(apLayer, "set filter an", "Couldn't parse")); + //test that we cant have both all and anything else + BOOST_REQUIRE(SendAndTest(apLayer, "set filter ad", "Couldn't parse")); + //check that a bad filter is ignored + BOOST_REQUIRE(SendAndTest(apLayer, "set filter x", "Couldn't parse")); + //test that all works + BOOST_REQUIRE(SendAndTest(apLayer, "set filter a", ">")); + //test that none works + BOOST_REQUIRE(SendAndTest(apLayer, "set filter n", ">")); + //test that setting all of the filters manually works + BOOST_REQUIRE(SendAndTest(apLayer, "set filter dciwev", ">")); + + //leave it set to all to error only + BOOST_REQUIRE(SendAndTest(apLayer, "set filter e", ">")); + + //make sure it ignores attempts to set filters on bad devieces + BOOST_REQUIRE(SendAndTest(apLayer, "set filter dciwev BadDevice", "Unrecognized device")); + //check that it works for a good device + BOOST_REQUIRE(SendAndTest(apLayer, "set filter dciwev TestDevice", ">")); +} + +void TestRunCommands(MockPhysicalLayerAsyncTS* apLayer, Logger* apLogger){ + //put an entry into the log that we will pickup on RunLog so we see something + apLogger->Log(LEV_ERROR,LOCATION,"TestOutputOnRun"); + + //do the run command, notice I adedd a \r\n which forces a second line of input to be ready + //immediateley to break the "run" cycle after a single iteration (this is necessary since the + //parser is expecting ">" which we don't get during a "run" command. + BOOST_REQUIRE(SendAndTest(apLayer, "run log\r\n", "TestOutputOnRun")); +} + +BOOST_AUTO_TEST_CASE(TerminalInteractions) +{ + //prepare the terminal on a "non-standard" port + EventLog log; + Logger* pLoggerA = log.GetLogger(LEV_INTERPRET, "Terminal"); + + MockTimerSource mts; + MockPhysicalLayerAsyncTS phys(log.GetLogger(LEV_INTERPRET, "Phys"), &mts); + + LogTerminalExtension lte(&log); + Terminal trm(pLoggerA, &phys, &mts, "Test Terminal", false, false); + trm.AddExtension(<e); + trm.Init(); + + BOOST_REQUIRE(mts.DispatchOne()); + + //add a "device" to the logger so we can test the devices behavior + Logger* logger = log.GetLogger(LEV_ERROR,"TestDevice"); + + TestCommandParsing(&phys); + TestHelpCommands(&phys); + TestPrintCommands(&phys, logger); + + TestSetCommands(&phys); + TestRunCommands(&phys, logger); + + trm.Shutdown(); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/TerminalTest/rake.project.rb b/TerminalTest/rake.project.rb index ef45da0f..7487c571 100755 --- a/TerminalTest/rake.project.rb +++ b/TerminalTest/rake.project.rb @@ -1,7 +1,7 @@ - -$options = { -:target => 'terminaltest.exe', -:project_libs => [:terminal, :apltesttools, :apl], -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -:libs => Boost::get_static_libs + $PLATFORM_LIBS -} + +$options = { +:target => 'terminaltest.exe', +:project_libs => [:terminal, :apltesttools, :apl], +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +:libs => Boost::get_static_libs + $PLATFORM_LIBS +} diff --git a/TestAPL/AsyncPhysBaseTest.cpp b/TestAPL/AsyncPhysBaseTest.cpp index ec998817..40f8e58a 100644 --- a/TestAPL/AsyncPhysBaseTest.cpp +++ b/TestAPL/AsyncPhysBaseTest.cpp @@ -16,22 +16,22 @@ // specific language governing permissions and limitations // under the License. // -#include "AsyncPhysBaseTest.h" - - - -namespace apl { - -AsyncPhysBaseTest::AsyncPhysBaseTest(FilterLevel aLevel, bool aImmediate) : -LogTester(aImmediate), -phys(mLog.GetLogger(aLevel, "phys")), -adapter(mLog.GetLogger(aLevel, "adapter"), &phys, false), -upper(mLog.GetLogger(aLevel, "upper")) -{ - adapter.SetUpperLayer(&upper); -} - - -} - - +#include "AsyncPhysBaseTest.h" + + + +namespace apl { + +AsyncPhysBaseTest::AsyncPhysBaseTest(FilterLevel aLevel, bool aImmediate) : +LogTester(aImmediate), +phys(mLog.GetLogger(aLevel, "phys")), +adapter(mLog.GetLogger(aLevel, "adapter"), &phys, false), +upper(mLog.GetLogger(aLevel, "upper")) +{ + adapter.SetUpperLayer(&upper); +} + + +} + + diff --git a/TestAPL/AsyncPhysBaseTest.h b/TestAPL/AsyncPhysBaseTest.h index 13a345c7..8fbe4cc8 100644 --- a/TestAPL/AsyncPhysBaseTest.h +++ b/TestAPL/AsyncPhysBaseTest.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,37 +6,37 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_PHYS_BASE_TEST_H_ -#define __ASYNC_PHYS_BASE_TEST_H_ - -#include - -#include -#include -#include - -namespace apl { - -class AsyncPhysBaseTest : public LogTester -{ - public: - AsyncPhysBaseTest(FilterLevel aLevel = LEV_INFO, bool aImmediate = false); - - MockPhysicalLayerAsync phys; - LowerLayerToPhysAdapter adapter; - MockUpperLayer upper; -}; - -} - -#endif +// +#ifndef __ASYNC_PHYS_BASE_TEST_H_ +#define __ASYNC_PHYS_BASE_TEST_H_ + +#include + +#include +#include +#include + +namespace apl { + +class AsyncPhysBaseTest : public LogTester +{ + public: + AsyncPhysBaseTest(FilterLevel aLevel = LEV_INFO, bool aImmediate = false); + + MockPhysicalLayerAsync phys; + LowerLayerToPhysAdapter adapter; + MockUpperLayer upper; +}; + +} + +#endif diff --git a/TestAPL/AsyncPhysTestObject.cpp b/TestAPL/AsyncPhysTestObject.cpp index c2934188..b20d6577 100644 --- a/TestAPL/AsyncPhysTestObject.cpp +++ b/TestAPL/AsyncPhysTestObject.cpp @@ -16,55 +16,55 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "AsyncPhysTestObject.h" - -#include -#include - -using namespace std; - -namespace apl { - -AsyncPhysTestObject::AsyncPhysTestObject(FilterLevel aLevel, bool aImmediate, bool aAutoRead) : -AsyncTestObjectASIO(), -LogTester(aImmediate), -mTCPClient(mLog.GetLogger(aLevel,"TCPClient"), this->GetService(), "127.0.0.1", 50000), -mTCPServer(mLog.GetLogger(aLevel,"TCPSever"), this->GetService(), 50000), -mClientAdapter(mLog.GetLogger(aLevel,"ClientAdapter"), &mTCPClient, aAutoRead), -mServerAdapter(mLog.GetLogger(aLevel,"ServerAdapter"), &mTCPServer, aAutoRead), -mClientUpper(mLog.GetLogger(aLevel,"MockUpperClient")), -mServerUpper(mLog.GetLogger(aLevel,"MockUpperServer")) -{ - mClientAdapter.SetUpperLayer(&mClientUpper); - mServerAdapter.SetUpperLayer(&mServerUpper); -} - -AsyncLoopback::AsyncLoopback(Logger* apLogger, IPhysicalLayerAsync* apPhys, ITimerSource* apTimerSrc, FilterLevel aLevel, bool aImmediate) : -Loggable(apLogger), -AsyncPhysLayerMonitor(apLogger, apPhys, apTimerSrc, 5000), -mRead(1024), -mWrite(mRead) -{ - -} - -void AsyncLoopback::StartRead() -{ - mpPhys->AsyncRead(mRead, mRead.Size()); -} - -void AsyncLoopback::_OnReceive(const apl::byte_t* apData, size_t aNumBytes) -{ - if(mpPhys->CanWrite()) { - memcpy(mWrite, mRead, aNumBytes); - mpPhys->AsyncWrite(mWrite, aNumBytes); - } - this->StartRead(); -} - -void AsyncLoopback::Up(void) { this->StartRead(); } - - - +#include +#include "AsyncPhysTestObject.h" + +#include +#include + +using namespace std; + +namespace apl { + +AsyncPhysTestObject::AsyncPhysTestObject(FilterLevel aLevel, bool aImmediate, bool aAutoRead) : +AsyncTestObjectASIO(), +LogTester(aImmediate), +mTCPClient(mLog.GetLogger(aLevel,"TCPClient"), this->GetService(), "127.0.0.1", 50000), +mTCPServer(mLog.GetLogger(aLevel,"TCPSever"), this->GetService(), 50000), +mClientAdapter(mLog.GetLogger(aLevel,"ClientAdapter"), &mTCPClient, aAutoRead), +mServerAdapter(mLog.GetLogger(aLevel,"ServerAdapter"), &mTCPServer, aAutoRead), +mClientUpper(mLog.GetLogger(aLevel,"MockUpperClient")), +mServerUpper(mLog.GetLogger(aLevel,"MockUpperServer")) +{ + mClientAdapter.SetUpperLayer(&mClientUpper); + mServerAdapter.SetUpperLayer(&mServerUpper); +} + +AsyncLoopback::AsyncLoopback(Logger* apLogger, IPhysicalLayerAsync* apPhys, ITimerSource* apTimerSrc, FilterLevel aLevel, bool aImmediate) : +Loggable(apLogger), +AsyncPhysLayerMonitor(apLogger, apPhys, apTimerSrc, 5000), +mRead(1024), +mWrite(mRead) +{ + +} + +void AsyncLoopback::StartRead() +{ + mpPhys->AsyncRead(mRead, mRead.Size()); +} + +void AsyncLoopback::_OnReceive(const apl::byte_t* apData, size_t aNumBytes) +{ + if(mpPhys->CanWrite()) { + memcpy(mWrite, mRead, aNumBytes); + mpPhys->AsyncWrite(mWrite, aNumBytes); + } + this->StartRead(); +} + +void AsyncLoopback::Up(void) { this->StartRead(); } + + + } \ No newline at end of file diff --git a/TestAPL/AsyncPhysTestObject.h b/TestAPL/AsyncPhysTestObject.h index bf32e55f..d960cde9 100644 --- a/TestAPL/AsyncPhysTestObject.h +++ b/TestAPL/AsyncPhysTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,70 +6,70 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __ASYNC_PHYS_TEST_OBJECT_H_ -#define __ASYNC_PHYS_TEST_OBJECT_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace apl { - - class AsyncPhysTestObject : public AsyncTestObjectASIO, public LogTester - { - public: - AsyncPhysTestObject(FilterLevel aLevel = LEV_INFO, bool aImmediate = false, bool aAutoRead = true); - - private: - Logger* mpLogger; - - public: - PhysicalLayerAsyncTCPClient mTCPClient; - PhysicalLayerAsyncTCPServer mTCPServer; - - LowerLayerToPhysAdapter mClientAdapter; - LowerLayerToPhysAdapter mServerAdapter; - - MockUpperLayer mClientUpper; - MockUpperLayer mServerUpper; - }; - - class AsyncLoopback : public AsyncPhysLayerMonitor - { - public: - AsyncLoopback(Logger*, IPhysicalLayerAsync*, ITimerSource*, FilterLevel aLevel = LEV_INFO, bool aImmediate = false); - - private: - - CopyableBuffer mRead; - CopyableBuffer mWrite; - - void _OnReceive(const apl::byte_t *,size_t); - void _OnSendSuccess(void){} - void _OnSendFailure(void){} - - void Up(void); - void Down(void) {} - - void StartRead(); - }; - -} - -#endif +// +#ifndef __ASYNC_PHYS_TEST_OBJECT_H_ +#define __ASYNC_PHYS_TEST_OBJECT_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace apl { + + class AsyncPhysTestObject : public AsyncTestObjectASIO, public LogTester + { + public: + AsyncPhysTestObject(FilterLevel aLevel = LEV_INFO, bool aImmediate = false, bool aAutoRead = true); + + private: + Logger* mpLogger; + + public: + PhysicalLayerAsyncTCPClient mTCPClient; + PhysicalLayerAsyncTCPServer mTCPServer; + + LowerLayerToPhysAdapter mClientAdapter; + LowerLayerToPhysAdapter mServerAdapter; + + MockUpperLayer mClientUpper; + MockUpperLayer mServerUpper; + }; + + class AsyncLoopback : public AsyncPhysLayerMonitor + { + public: + AsyncLoopback(Logger*, IPhysicalLayerAsync*, ITimerSource*, FilterLevel aLevel = LEV_INFO, bool aImmediate = false); + + private: + + CopyableBuffer mRead; + CopyableBuffer mWrite; + + void _OnReceive(const apl::byte_t *,size_t); + void _OnSendSuccess(void){} + void _OnSendFailure(void){} + + void Up(void); + void Down(void) {} + + void StartRead(); + }; + +} + +#endif diff --git a/TestAPL/AsyncSerialTestObject.h b/TestAPL/AsyncSerialTestObject.h index 94427460..5e234f02 100644 --- a/TestAPL/AsyncSerialTestObject.h +++ b/TestAPL/AsyncSerialTestObject.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,16 +6,16 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// +// #ifndef __ASYNC_SERIAL_TEST_OBJECT_H_ #define __ASYNC_SERIAL_TEST_OBJECT_H_ @@ -34,7 +34,7 @@ namespace apl { public: AsyncSerialTestObject(SerialSettings cfg, FilterLevel aLevel = LEV_INFO, bool aImmediate = false); virtual ~AsyncSerialTestObject() {} - + private: Logger* mpLogger; diff --git a/TestAPL/TestAPL.vcproj b/TestAPL/TestAPL.vcproj index 184582b6..6934e53c 100755 --- a/TestAPL/TestAPL.vcproj +++ b/TestAPL/TestAPL.vcproj @@ -1,372 +1,372 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestAPL/TestASIO.cpp b/TestAPL/TestASIO.cpp index 5fe0fab6..9f899371 100644 --- a/TestAPL/TestASIO.cpp +++ b/TestAPL/TestASIO.cpp @@ -16,51 +16,51 @@ // specific language governing permissions and limitations // under the License. // -#include - -#include -#include -#include -#include -#include - - -#include - -using namespace std; -using namespace boost; -using namespace boost::asio; -using namespace boost::system; -using namespace apl; - - - void AssertCanceled(bool* apFlag, const boost::system::error_code& ec) - { - if(ec) *apFlag = true; - } - - void Cancel(deadline_timer* aptimer) - { - aptimer->cancel(); - } - - BOOST_AUTO_TEST_SUITE(TestBoostASIO) - - BOOST_AUTO_TEST_CASE(TimerCancel) - { - bool flag = false; - - io_service io; - deadline_timer t1(io, posix_time::seconds(0)); - deadline_timer t2(io, posix_time::seconds(1000)); - - t1.async_wait(bind(Cancel, &t2)); - t2.async_wait(bind(AssertCanceled, &flag, _1)); - - io.run(); - - BOOST_REQUIRE(flag); - } - - BOOST_AUTO_TEST_SUITE_END() - +#include + +#include +#include +#include +#include +#include + + +#include + +using namespace std; +using namespace boost; +using namespace boost::asio; +using namespace boost::system; +using namespace apl; + + + void AssertCanceled(bool* apFlag, const boost::system::error_code& ec) + { + if(ec) *apFlag = true; + } + + void Cancel(deadline_timer* aptimer) + { + aptimer->cancel(); + } + + BOOST_AUTO_TEST_SUITE(TestBoostASIO) + + BOOST_AUTO_TEST_CASE(TimerCancel) + { + bool flag = false; + + io_service io; + deadline_timer t1(io, posix_time::seconds(0)); + deadline_timer t2(io, posix_time::seconds(1000)); + + t1.async_wait(bind(Cancel, &t2)); + t2.async_wait(bind(AssertCanceled, &flag, _1)); + + io.run(); + + BOOST_REQUIRE(flag); + } + + BOOST_AUTO_TEST_SUITE_END() + diff --git a/TestAPL/TestAsyncTask.cpp b/TestAPL/TestAsyncTask.cpp index d3a71941..11dea8cf 100644 --- a/TestAPL/TestAsyncTask.cpp +++ b/TestAPL/TestAsyncTask.cpp @@ -16,250 +16,250 @@ // specific language governing permissions and limitations // under the License. // -#include - - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -using namespace apl; -using namespace boost; -using namespace boost::posix_time; - - - -class MockTaskHandler -{ - public: - - TaskHandler GetHandler() - { return bind(&MockTaskHandler::OnTask, this, _1); } - - size_t Size() { return mTasks.size(); } - - ITaskCompletion* Front() - { - return (Size() > 0) ? mTasks.front() : NULL; - } - - void Pop() - { - mTasks.pop_front(); - } - - void Complete(bool aSuccess) - { - ITaskCompletion* p = mTasks.front(); - Pop(); - p->OnComplete(aSuccess); - } - - private: - - std::deque mTasks; - - void OnTask(ITaskCompletion* apTask) { mTasks.push_back(apTask); } -}; - -BOOST_AUTO_TEST_SUITE(AsyncTaskSuite) - -BOOST_AUTO_TEST_CASE(DependencyAnalysis) -{ - MockTaskHandler mth; - MockTimerSource mts; - AsyncTaskScheduler ats(&mts); - - AsyncTaskGroup* pGroup = ats.NewGroup(); - - AsyncTaskBase* pT1 = pGroup->Add(1000, 1000, 0, mth.GetHandler()); - AsyncTaskBase* pT2 = pGroup->Add(1000, 1000, 0, mth.GetHandler()); - AsyncTaskBase* pT3 = pGroup->Add(1000, 1000, 0, mth.GetHandler()); - - // try self-assignemt - BOOST_REQUIRE_THROW(pT1->AddDependency(pT1), ArgumentException); - - BOOST_REQUIRE(!pT2->IsDependency(pT1)); - pT2->AddDependency(pT1); - BOOST_REQUIRE(pT2->IsDependency(pT1)); - - BOOST_REQUIRE(!pT3->IsDependency(pT2)); - pT3->AddDependency(pT2); - BOOST_REQUIRE(pT3->IsDependency(pT2)); - - //check that dependencies are transitive - BOOST_REQUIRE(pT3->IsDependency(pT1)); - - //try to create some circular dependencies - BOOST_REQUIRE_THROW(pT1->AddDependency(pT2), ArgumentException); - BOOST_REQUIRE_THROW(pT1->AddDependency(pT3), ArgumentException); -} - -BOOST_AUTO_TEST_CASE(ContinousTask) -{ - MockTaskHandler mth; - MockTimerSource mts; - AsyncTaskScheduler ats(&mts); - - AsyncTaskGroup* pGroup = ats.NewGroup(); - - AsyncTaskContinuous* pT1 = pGroup->AddContinuous(0, mth.GetHandler()); - AsyncTaskBase* pT2 = pGroup->Add(1000, 1000, 1, mth.GetHandler()); - - pT1->Enable(); - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); - pGroup->Enable(); - mth.Complete(true); - - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); - mth.Complete(true); - - for(size_t i=0; i<5; ++i) { - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); - mth.Complete(true); - } - - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); - pT1->Disable(); - - - - -} - -/// Two groups that execute independently of one another -BOOST_AUTO_TEST_CASE(DecoupledGroupsMode) -{ - MockTaskHandler mth; - MockTimerSource mts; - AsyncTaskScheduler ats(&mts); - - AsyncTaskGroup* pGroup1 = ats.NewGroup(); - AsyncTaskGroup* pGroup2 = ats.NewGroup(); - - AsyncTaskBase* pT1 = pGroup1->Add(1000, 1000, 0, mth.GetHandler()); - AsyncTaskBase* pT2 = pGroup2->Add(1000, 1000, 0, mth.GetHandler()); - - pGroup1->Enable(); - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - pGroup2->Enable(); - - BOOST_REQUIRE_EQUAL(mth.Size(), 2); - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); - mth.Pop(); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); -} - -BOOST_AUTO_TEST_CASE(NonPeriodic) -{ - MockTaskHandler mth; - MockTimerSource mts; - MockTimeSource fake_time; - AsyncTaskScheduler ats(&mts, &fake_time); - - AsyncTaskGroup* pGroup = ats.NewGroup(); - fake_time.SetToNow(); - - AsyncTaskBase* pT1 = pGroup->Add(-1, 100, 0, mth.GetHandler()); //non-periodic task - AsyncTaskBase* pT2 = pGroup->Add(2000, 100, 0, mth.GetHandler()); - - pGroup->Enable(); - - //complete both the tasks - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); - mth.Complete(true); - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); - mth.Complete(true); - - // a timer should be registered for the next periodic task execution - BOOST_REQUIRE_EQUAL(mts.NumActive(), 1); - BOOST_REQUIRE_EQUAL(mth.Size(), 0); - fake_time.Advance(2000); - BOOST_REQUIRE(mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); -} - - -BOOST_AUTO_TEST_CASE(PriorityBreaksTies) -{ - MockTaskHandler mth; - MockTimerSource mts; - AsyncTaskScheduler ats(&mts); - - AsyncTaskGroup* pGroup = ats.NewGroup(); - - pGroup->Add(100, 100, 0, mth.GetHandler()); - AsyncTaskBase* pT2 = pGroup->Add(100, 100, 1, mth.GetHandler()); // higher priority - - pGroup->Enable(); - - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); -} - -BOOST_AUTO_TEST_CASE(DependenciesEnforced) -{ - MockTaskHandler mth; - MockTimerSource mts; - AsyncTaskScheduler ats(&mts); - - AsyncTaskGroup* pGroup = ats.NewGroup(); - AsyncTaskBase* pT1 = pGroup->Add(100, 100, 0, mth.GetHandler()); - AsyncTaskBase* pT2 = pGroup->Add(100, 100, 0, mth.GetHandler()); - - pT1->AddDependency(pT2); // T1 depends on T2 - - pGroup->Enable(); - - BOOST_REQUIRE_EQUAL(mth.Size(), 1); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); -} - -BOOST_AUTO_TEST_CASE(TimerUsage) -{ - MockTaskHandler mth; - MockTimerSource mts; - MockTimeSource fake_time; - AsyncTaskScheduler ats(&mts, &fake_time); - - fake_time.SetToNow(); - - AsyncTaskGroup* pGroup = ats.NewGroup(); - AsyncTaskBase* pT1 = pGroup->Add(1000, 100, 0, mth.GetHandler()); - AsyncTaskBase* pT2 = pGroup->Add(1500, 100, 0, mth.GetHandler()); - - pGroup->Enable(); - - // complete the two periodic tasks - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); mth.Complete(true); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); mth.Complete(true); - - //if you disptach the call back early, nothing should happen except a new timer - BOOST_REQUIRE(mts.DispatchOne()); - - fake_time.Advance(1001); - BOOST_REQUIRE(mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(mth.Front(), pT1); mth.Complete(true); - - fake_time.Advance(500); - BOOST_REQUIRE(mts.DispatchOne()); - BOOST_REQUIRE_EQUAL(mth.Front(), pT2); mth.Complete(true); -} - -BOOST_AUTO_TEST_SUITE_END() +#include + + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using namespace apl; +using namespace boost; +using namespace boost::posix_time; + + + +class MockTaskHandler +{ + public: + + TaskHandler GetHandler() + { return bind(&MockTaskHandler::OnTask, this, _1); } + + size_t Size() { return mTasks.size(); } + + ITaskCompletion* Front() + { + return (Size() > 0) ? mTasks.front() : NULL; + } + + void Pop() + { + mTasks.pop_front(); + } + + void Complete(bool aSuccess) + { + ITaskCompletion* p = mTasks.front(); + Pop(); + p->OnComplete(aSuccess); + } + + private: + + std::deque mTasks; + + void OnTask(ITaskCompletion* apTask) { mTasks.push_back(apTask); } +}; + +BOOST_AUTO_TEST_SUITE(AsyncTaskSuite) + +BOOST_AUTO_TEST_CASE(DependencyAnalysis) +{ + MockTaskHandler mth; + MockTimerSource mts; + AsyncTaskScheduler ats(&mts); + + AsyncTaskGroup* pGroup = ats.NewGroup(); + + AsyncTaskBase* pT1 = pGroup->Add(1000, 1000, 0, mth.GetHandler()); + AsyncTaskBase* pT2 = pGroup->Add(1000, 1000, 0, mth.GetHandler()); + AsyncTaskBase* pT3 = pGroup->Add(1000, 1000, 0, mth.GetHandler()); + + // try self-assignemt + BOOST_REQUIRE_THROW(pT1->AddDependency(pT1), ArgumentException); + + BOOST_REQUIRE(!pT2->IsDependency(pT1)); + pT2->AddDependency(pT1); + BOOST_REQUIRE(pT2->IsDependency(pT1)); + + BOOST_REQUIRE(!pT3->IsDependency(pT2)); + pT3->AddDependency(pT2); + BOOST_REQUIRE(pT3->IsDependency(pT2)); + + //check that dependencies are transitive + BOOST_REQUIRE(pT3->IsDependency(pT1)); + + //try to create some circular dependencies + BOOST_REQUIRE_THROW(pT1->AddDependency(pT2), ArgumentException); + BOOST_REQUIRE_THROW(pT1->AddDependency(pT3), ArgumentException); +} + +BOOST_AUTO_TEST_CASE(ContinousTask) +{ + MockTaskHandler mth; + MockTimerSource mts; + AsyncTaskScheduler ats(&mts); + + AsyncTaskGroup* pGroup = ats.NewGroup(); + + AsyncTaskContinuous* pT1 = pGroup->AddContinuous(0, mth.GetHandler()); + AsyncTaskBase* pT2 = pGroup->Add(1000, 1000, 1, mth.GetHandler()); + + pT1->Enable(); + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); + pGroup->Enable(); + mth.Complete(true); + + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); + mth.Complete(true); + + for(size_t i=0; i<5; ++i) { + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); + mth.Complete(true); + } + + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); + pT1->Disable(); + + + + +} + +/// Two groups that execute independently of one another +BOOST_AUTO_TEST_CASE(DecoupledGroupsMode) +{ + MockTaskHandler mth; + MockTimerSource mts; + AsyncTaskScheduler ats(&mts); + + AsyncTaskGroup* pGroup1 = ats.NewGroup(); + AsyncTaskGroup* pGroup2 = ats.NewGroup(); + + AsyncTaskBase* pT1 = pGroup1->Add(1000, 1000, 0, mth.GetHandler()); + AsyncTaskBase* pT2 = pGroup2->Add(1000, 1000, 0, mth.GetHandler()); + + pGroup1->Enable(); + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + pGroup2->Enable(); + + BOOST_REQUIRE_EQUAL(mth.Size(), 2); + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); + mth.Pop(); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); +} + +BOOST_AUTO_TEST_CASE(NonPeriodic) +{ + MockTaskHandler mth; + MockTimerSource mts; + MockTimeSource fake_time; + AsyncTaskScheduler ats(&mts, &fake_time); + + AsyncTaskGroup* pGroup = ats.NewGroup(); + fake_time.SetToNow(); + + AsyncTaskBase* pT1 = pGroup->Add(-1, 100, 0, mth.GetHandler()); //non-periodic task + AsyncTaskBase* pT2 = pGroup->Add(2000, 100, 0, mth.GetHandler()); + + pGroup->Enable(); + + //complete both the tasks + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); + mth.Complete(true); + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); + mth.Complete(true); + + // a timer should be registered for the next periodic task execution + BOOST_REQUIRE_EQUAL(mts.NumActive(), 1); + BOOST_REQUIRE_EQUAL(mth.Size(), 0); + fake_time.Advance(2000); + BOOST_REQUIRE(mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); +} + + +BOOST_AUTO_TEST_CASE(PriorityBreaksTies) +{ + MockTaskHandler mth; + MockTimerSource mts; + AsyncTaskScheduler ats(&mts); + + AsyncTaskGroup* pGroup = ats.NewGroup(); + + pGroup->Add(100, 100, 0, mth.GetHandler()); + AsyncTaskBase* pT2 = pGroup->Add(100, 100, 1, mth.GetHandler()); // higher priority + + pGroup->Enable(); + + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); +} + +BOOST_AUTO_TEST_CASE(DependenciesEnforced) +{ + MockTaskHandler mth; + MockTimerSource mts; + AsyncTaskScheduler ats(&mts); + + AsyncTaskGroup* pGroup = ats.NewGroup(); + AsyncTaskBase* pT1 = pGroup->Add(100, 100, 0, mth.GetHandler()); + AsyncTaskBase* pT2 = pGroup->Add(100, 100, 0, mth.GetHandler()); + + pT1->AddDependency(pT2); // T1 depends on T2 + + pGroup->Enable(); + + BOOST_REQUIRE_EQUAL(mth.Size(), 1); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); +} + +BOOST_AUTO_TEST_CASE(TimerUsage) +{ + MockTaskHandler mth; + MockTimerSource mts; + MockTimeSource fake_time; + AsyncTaskScheduler ats(&mts, &fake_time); + + fake_time.SetToNow(); + + AsyncTaskGroup* pGroup = ats.NewGroup(); + AsyncTaskBase* pT1 = pGroup->Add(1000, 100, 0, mth.GetHandler()); + AsyncTaskBase* pT2 = pGroup->Add(1500, 100, 0, mth.GetHandler()); + + pGroup->Enable(); + + // complete the two periodic tasks + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); mth.Complete(true); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); mth.Complete(true); + + //if you disptach the call back early, nothing should happen except a new timer + BOOST_REQUIRE(mts.DispatchOne()); + + fake_time.Advance(1001); + BOOST_REQUIRE(mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(mth.Front(), pT1); mth.Complete(true); + + fake_time.Advance(500); + BOOST_REQUIRE(mts.DispatchOne()); + BOOST_REQUIRE_EQUAL(mth.Front(), pT2); mth.Complete(true); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestCastLongLongDouble.cpp b/TestAPL/TestCastLongLongDouble.cpp index 867e3e40..da297896 100644 --- a/TestAPL/TestCastLongLongDouble.cpp +++ b/TestAPL/TestCastLongLongDouble.cpp @@ -16,94 +16,94 @@ // specific language governing permissions and limitations // under the License. // - - -/* -The tests in this file deal with the casting Int64 to double problems on the ARM device compiling with GCC. -A manual method is included that gets around the problem as well. -*/ - -#include -#include -#include -#include "math.h" -#include -#include - -#include - -using namespace apl; - - - - BOOST_AUTO_TEST_SUITE(Casting) - template - T2 TestCast(T1 input){ - return static_cast(input); - } - - template - bool IsEqual(T1 a, T1 b){ - return a == b; - } - - template <> - bool IsEqual(double a, double b){ - double diff = a - b; - if(diff < 0) diff = -diff; - return diff <= 1e-5; - } - - template <> - bool IsEqual(float a, float b){ - float diff = a - b; - if(diff < 0) diff = -diff; - return diff <= 1e-5; - } - -#define CHECK_CAST(t1, t2, a, b)\ - {t2 amod = TestCast(a);\ - if(!IsEqual(amod,(b))){\ - std::ostringstream oss; \ - oss << (#t1)<< "->" << (#t2) << " doesn't cast correctly: " << (amod) << " != " << (b); \ - std::cout << "Failure: " << oss.str() << std::endl;\ - }} - - - BOOST_AUTO_TEST_CASE(Casting){ - CHECK_CAST(double,int,1000.0,1000); - CHECK_CAST(double,float,1001.0,1001.0f); - CHECK_CAST(double,long,1002.0,1002); - //these 2 tests fail on the arm device and fail strangley, there - //is definatley something weird going on here, probably because - //the 64 bit long long is the same size as a double so just gets - //shifted into the double strangley. This means that the results - //of an operation can be different if the casting is done and the - //result is stored to memory or if the value stays in a register - //(as an intermediate calculation value), very nasty. - CHECK_CAST(double,int_64_t,1003.0,1003); - - CHECK_CAST(int_64_t,double,1004,1004.0); - - CHECK_CAST(double,float,1012.0,1012.0f); - CHECK_CAST(int_64_t,double,1006,1006.0); - - CHECK_CAST(int,double,1007,1007.0); - CHECK_CAST(long,double,1008,1008.0); - CHECK_CAST(int,float,1009,1009.0f); - - CHECK_CAST(float,int_64_t,1010.0f,1010); - CHECK_CAST(float,int,1011.0f,1011); - - CHECK_CAST(int_64_t,double,4294967296LL,4294967296.0); - CHECK_CAST(double,int_64_t,4294967296.0,4294967296LL); - - } - - BOOST_AUTO_TEST_CASE(ManualConversion){ - - BOOST_REQUIRE_FLOAT_EQUAL(4294967296.0,SafeCastInt64ToDouble(4294967296LL)); - BOOST_REQUIRE_FLOAT_EQUAL(4398046511104.00,SafeCastInt64ToDouble(4398046511104LL)); - - } - BOOST_AUTO_TEST_SUITE_END() + + +/* +The tests in this file deal with the casting Int64 to double problems on the ARM device compiling with GCC. +A manual method is included that gets around the problem as well. +*/ + +#include +#include +#include +#include "math.h" +#include +#include + +#include + +using namespace apl; + + + + BOOST_AUTO_TEST_SUITE(Casting) + template + T2 TestCast(T1 input){ + return static_cast(input); + } + + template + bool IsEqual(T1 a, T1 b){ + return a == b; + } + + template <> + bool IsEqual(double a, double b){ + double diff = a - b; + if(diff < 0) diff = -diff; + return diff <= 1e-5; + } + + template <> + bool IsEqual(float a, float b){ + float diff = a - b; + if(diff < 0) diff = -diff; + return diff <= 1e-5; + } + +#define CHECK_CAST(t1, t2, a, b)\ + {t2 amod = TestCast(a);\ + if(!IsEqual(amod,(b))){\ + std::ostringstream oss; \ + oss << (#t1)<< "->" << (#t2) << " doesn't cast correctly: " << (amod) << " != " << (b); \ + std::cout << "Failure: " << oss.str() << std::endl;\ + }} + + + BOOST_AUTO_TEST_CASE(Casting){ + CHECK_CAST(double,int,1000.0,1000); + CHECK_CAST(double,float,1001.0,1001.0f); + CHECK_CAST(double,long,1002.0,1002); + //these 2 tests fail on the arm device and fail strangley, there + //is definatley something weird going on here, probably because + //the 64 bit long long is the same size as a double so just gets + //shifted into the double strangley. This means that the results + //of an operation can be different if the casting is done and the + //result is stored to memory or if the value stays in a register + //(as an intermediate calculation value), very nasty. + CHECK_CAST(double,int_64_t,1003.0,1003); + + CHECK_CAST(int_64_t,double,1004,1004.0); + + CHECK_CAST(double,float,1012.0,1012.0f); + CHECK_CAST(int_64_t,double,1006,1006.0); + + CHECK_CAST(int,double,1007,1007.0); + CHECK_CAST(long,double,1008,1008.0); + CHECK_CAST(int,float,1009,1009.0f); + + CHECK_CAST(float,int_64_t,1010.0f,1010); + CHECK_CAST(float,int,1011.0f,1011); + + CHECK_CAST(int_64_t,double,4294967296LL,4294967296.0); + CHECK_CAST(double,int_64_t,4294967296.0,4294967296LL); + + } + + BOOST_AUTO_TEST_CASE(ManualConversion){ + + BOOST_REQUIRE_FLOAT_EQUAL(4294967296.0,SafeCastInt64ToDouble(4294967296LL)); + BOOST_REQUIRE_FLOAT_EQUAL(4398046511104.00,SafeCastInt64ToDouble(4398046511104LL)); + + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestCommandQueue.cpp b/TestAPL/TestCommandQueue.cpp index 88253634..e7cb7a20 100644 --- a/TestAPL/TestCommandQueue.cpp +++ b/TestAPL/TestCommandQueue.cpp @@ -16,109 +16,109 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include -#include - -using namespace apl; - - - - - BOOST_AUTO_TEST_SUITE(CommandQueueSuite) - BOOST_AUTO_TEST_CASE(SimpleWriteAndRead){ - CommandQueue cq; - - BinaryOutput bo; - bo.mRawCode = CC_LATCH_ON; - - cq.AcceptCommand(bo,3,4, NULL); - - BOOST_REQUIRE_EQUAL(cq.Next(), CT_BINARY_OUTPUT); - - BinaryOutput bo2; - bo2.mRawCode = CC_LATCH_OFF; - CommandData info; - - cq.Read(bo2, info); - - BOOST_REQUIRE_EQUAL(cq.Next(), CT_NONE); - - BOOST_REQUIRE_EQUAL(info.mIndex, 3); - BOOST_REQUIRE_EQUAL(info.mSequence, 4); - BOOST_REQUIRE_EQUAL(bo2.mRawCode, CC_LATCH_ON); - } - - BOOST_AUTO_TEST_CASE(ExecuteCommand){ - CommandQueue cq; - MockCommandHandler mh; - MockResponseAcceptor mr; - - cq.AcceptCommand(BinaryOutput(CC_PULSE), 0, 0, &mr); - BOOST_REQUIRE_EQUAL(cq.Size(), 1); - cq.ExecuteCommand(&mh); - BOOST_REQUIRE_EQUAL(cq.Size(), 0); - BOOST_REQUIRE_EQUAL(mh.num_bo, 1); - BOOST_REQUIRE_EQUAL(mh.num_sp, 0); - BOOST_REQUIRE_EQUAL(mr.NumResponses(), 1); - - cq.AcceptCommand(Setpoint(0), 0, 0, &mr); - BOOST_REQUIRE_EQUAL(cq.Size(), 1); - cq.ExecuteCommand(&mh); - BOOST_REQUIRE_EQUAL(cq.Size(), 0); - BOOST_REQUIRE_EQUAL(mh.num_bo, 1); - BOOST_REQUIRE_EQUAL(mh.num_sp, 1); - BOOST_REQUIRE_EQUAL(mr.NumResponses(), 2); - - BOOST_REQUIRE_EQUAL(mr.PopResponse().Response.mResult, CS_SUCCESS); - } - - BOOST_AUTO_TEST_CASE(OrderMaintained){ - CommandQueue cq; - size_t testLength = 100; - for(size_t i=0; i < testLength; i++){ - int type = rand()%3; - int seq = static_cast(i); - if(type == 0){ - BinaryOutput bo; - bo.mRawCode = (i%2 == 0) ? CC_LATCH_ON : CC_LATCH_OFF; - bo.mCount = (byte_t)i%255; - cq.AcceptCommand(bo,i,seq, NULL); - } - else{ - Setpoint st; - st.SetValue(static_cast(i)); - cq.AcceptCommand(st,i,seq, NULL); - } - } - for(size_t i=0; i < testLength; i++){ - CommandTypes type = cq.Next(); - CommandData info; - switch(type){ - case CT_BINARY_OUTPUT: - { - BinaryOutput bo; - cq.Read(bo, info); - BOOST_REQUIRE_EQUAL(bo.mCount, i); - }break; - case CT_SETPOINT: - { - Setpoint st; - cq.Read(st, info); - BOOST_REQUIRE_EQUAL(st.GetIntValue(), (int)i); - }break; - case CT_NONE: - BOOST_REQUIRE(false); - } - BOOST_REQUIRE_EQUAL(info.mIndex, i); - BOOST_REQUIRE_EQUAL(info.mSequence, (int)i); - - } - BOOST_REQUIRE_EQUAL(cq.Next(), CT_NONE); - } - BOOST_AUTO_TEST_SUITE_END() - - +#include +#include + +#include +#include +#include + +using namespace apl; + + + + + BOOST_AUTO_TEST_SUITE(CommandQueueSuite) + BOOST_AUTO_TEST_CASE(SimpleWriteAndRead){ + CommandQueue cq; + + BinaryOutput bo; + bo.mRawCode = CC_LATCH_ON; + + cq.AcceptCommand(bo,3,4, NULL); + + BOOST_REQUIRE_EQUAL(cq.Next(), CT_BINARY_OUTPUT); + + BinaryOutput bo2; + bo2.mRawCode = CC_LATCH_OFF; + CommandData info; + + cq.Read(bo2, info); + + BOOST_REQUIRE_EQUAL(cq.Next(), CT_NONE); + + BOOST_REQUIRE_EQUAL(info.mIndex, 3); + BOOST_REQUIRE_EQUAL(info.mSequence, 4); + BOOST_REQUIRE_EQUAL(bo2.mRawCode, CC_LATCH_ON); + } + + BOOST_AUTO_TEST_CASE(ExecuteCommand){ + CommandQueue cq; + MockCommandHandler mh; + MockResponseAcceptor mr; + + cq.AcceptCommand(BinaryOutput(CC_PULSE), 0, 0, &mr); + BOOST_REQUIRE_EQUAL(cq.Size(), 1); + cq.ExecuteCommand(&mh); + BOOST_REQUIRE_EQUAL(cq.Size(), 0); + BOOST_REQUIRE_EQUAL(mh.num_bo, 1); + BOOST_REQUIRE_EQUAL(mh.num_sp, 0); + BOOST_REQUIRE_EQUAL(mr.NumResponses(), 1); + + cq.AcceptCommand(Setpoint(0), 0, 0, &mr); + BOOST_REQUIRE_EQUAL(cq.Size(), 1); + cq.ExecuteCommand(&mh); + BOOST_REQUIRE_EQUAL(cq.Size(), 0); + BOOST_REQUIRE_EQUAL(mh.num_bo, 1); + BOOST_REQUIRE_EQUAL(mh.num_sp, 1); + BOOST_REQUIRE_EQUAL(mr.NumResponses(), 2); + + BOOST_REQUIRE_EQUAL(mr.PopResponse().Response.mResult, CS_SUCCESS); + } + + BOOST_AUTO_TEST_CASE(OrderMaintained){ + CommandQueue cq; + size_t testLength = 100; + for(size_t i=0; i < testLength; i++){ + int type = rand()%3; + int seq = static_cast(i); + if(type == 0){ + BinaryOutput bo; + bo.mRawCode = (i%2 == 0) ? CC_LATCH_ON : CC_LATCH_OFF; + bo.mCount = (byte_t)i%255; + cq.AcceptCommand(bo,i,seq, NULL); + } + else{ + Setpoint st; + st.SetValue(static_cast(i)); + cq.AcceptCommand(st,i,seq, NULL); + } + } + for(size_t i=0; i < testLength; i++){ + CommandTypes type = cq.Next(); + CommandData info; + switch(type){ + case CT_BINARY_OUTPUT: + { + BinaryOutput bo; + cq.Read(bo, info); + BOOST_REQUIRE_EQUAL(bo.mCount, i); + }break; + case CT_SETPOINT: + { + Setpoint st; + cq.Read(st, info); + BOOST_REQUIRE_EQUAL(st.GetIntValue(), (int)i); + }break; + case CT_NONE: + BOOST_REQUIRE(false); + } + BOOST_REQUIRE_EQUAL(info.mIndex, i); + BOOST_REQUIRE_EQUAL(info.mSequence, (int)i); + + } + BOOST_REQUIRE_EQUAL(cq.Next(), CT_NONE); + } + BOOST_AUTO_TEST_SUITE_END() + + diff --git a/TestAPL/TestCommandTypes.cpp b/TestAPL/TestCommandTypes.cpp index 9c686435..72be0976 100644 --- a/TestAPL/TestCommandTypes.cpp +++ b/TestAPL/TestCommandTypes.cpp @@ -16,104 +16,104 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include - -using namespace apl; - - - template - void OptimalTypeTest(T val, SetpointEncodingType correct) - { - Setpoint sp(val); - BOOST_REQUIRE_EQUAL(correct, sp.GetOptimalEncodingType()); - } - - template - void AutoTypeTest(T val, SetpointEncodingType correct) - { - Setpoint sp; sp.SetValue(val); - BOOST_REQUIRE_EQUAL(sp.GetValue(), val); - BOOST_REQUIRE_EQUAL(correct, sp.GetEncodingType()); - } - BOOST_AUTO_TEST_SUITE(CommandTypesSuite) - - BOOST_AUTO_TEST_CASE(SetpointSet) { - AutoTypeTest(0.01, SPET_AUTO_DOUBLE); - } - BOOST_AUTO_TEST_CASE(SetpointSetInt) { - AutoTypeTest(5, SPET_AUTO_INT); - } - BOOST_AUTO_TEST_CASE(OptimalFloat) { - OptimalTypeTest(100.0, SPET_FLOAT); - } - BOOST_AUTO_TEST_CASE(OptimalDouble) { - OptimalTypeTest(std::numeric_limits::max()*100.0, SPET_DOUBLE); - } - BOOST_AUTO_TEST_CASE(OptimalInt16) { - OptimalTypeTest(55, SPET_INT16); - } - BOOST_AUTO_TEST_CASE(OptimalInt32) { - OptimalTypeTest(80000, SPET_INT32); - } - - - BOOST_AUTO_TEST_CASE(ByteToCommand) { - BOOST_REQUIRE_EQUAL(CS_SUCCESS, ByteToCommandStatus(0)); - BOOST_REQUIRE_EQUAL(CS_TIMEOUT, ByteToCommandStatus(1)); - BOOST_REQUIRE_EQUAL(CS_NO_SELECT, ByteToCommandStatus(2)); - BOOST_REQUIRE_EQUAL(CS_FORMAT_ERROR, ByteToCommandStatus(3)); - BOOST_REQUIRE_EQUAL(CS_NOT_SUPPORTED, ByteToCommandStatus(4)); - BOOST_REQUIRE_EQUAL(CS_ALREADY_ACTIVE, ByteToCommandStatus(5)); - BOOST_REQUIRE_EQUAL(CS_HARDWARE_ERROR, ByteToCommandStatus(6)); - BOOST_REQUIRE_EQUAL(CS_LOCAL, ByteToCommandStatus(7)); - BOOST_REQUIRE_EQUAL(CS_TOO_MANY_OPS, ByteToCommandStatus(8)); - BOOST_REQUIRE_EQUAL(CS_NOT_AUTHORIZED, ByteToCommandStatus(9)); - } - - BOOST_AUTO_TEST_CASE(CommandToString) { - BOOST_REQUIRE_EQUAL("CS_SUCCESS", ToString(CS_SUCCESS)); - BOOST_REQUIRE_EQUAL("CS_TIMEOUT", ToString(CS_TIMEOUT)); - BOOST_REQUIRE_EQUAL("CS_NO_SELECT", ToString(CS_NO_SELECT)); - BOOST_REQUIRE_EQUAL("CS_FORMAT_ERROR", ToString(CS_FORMAT_ERROR)); - BOOST_REQUIRE_EQUAL("CS_NOT_SUPPORTED", ToString(CS_NOT_SUPPORTED)); - BOOST_REQUIRE_EQUAL("CS_ALREADY_ACTIVE", ToString(CS_ALREADY_ACTIVE)); - BOOST_REQUIRE_EQUAL("CS_HARDWARE_ERROR", ToString(CS_HARDWARE_ERROR)); - BOOST_REQUIRE_EQUAL("CS_LOCAL", ToString(CS_LOCAL)); - BOOST_REQUIRE_EQUAL("CS_TOO_MANY_OPS", ToString(CS_TOO_MANY_OPS)); - BOOST_REQUIRE_EQUAL("CS_NOT_AUTHORIZED", ToString(CS_NOT_AUTHORIZED)); - BOOST_REQUIRE_EQUAL("Unknown", ToString(CS_UNDEFINED)); - } - - BOOST_AUTO_TEST_CASE(ByteToControl) { - BOOST_REQUIRE_EQUAL(CC_NULL, ByteToControlCode(0)); - BOOST_REQUIRE_EQUAL(CC_PULSE, ByteToControlCode(0x01)); - BOOST_REQUIRE_EQUAL(CC_LATCH_ON, ByteToControlCode(0x03)); - BOOST_REQUIRE_EQUAL(CC_LATCH_OFF, ByteToControlCode(0x04)); - BOOST_REQUIRE_EQUAL(CC_PULSE_CLOSE, ByteToControlCode(0x41)); - BOOST_REQUIRE_EQUAL(CC_PULSE_TRIP, ByteToControlCode(0x81)); - BOOST_REQUIRE_EQUAL(CC_UNDEFINED, ByteToControlCode(0xFF)); - } - - BOOST_AUTO_TEST_CASE(ControlToString) { - BOOST_REQUIRE_EQUAL("CC_NULL", ToString(CC_NULL)); - BOOST_REQUIRE_EQUAL("CC_PULSE", ToString(CC_PULSE)); - BOOST_REQUIRE_EQUAL("CC_LATCH_ON", ToString(CC_LATCH_ON)); - BOOST_REQUIRE_EQUAL("CC_LATCH_OFF", ToString(CC_LATCH_OFF)); - BOOST_REQUIRE_EQUAL("CC_PULSE_CLOSE", ToString(CC_PULSE_CLOSE)); - BOOST_REQUIRE_EQUAL("CC_PULSE_TRIP", ToString(CC_PULSE_TRIP)); - BOOST_REQUIRE_EQUAL("Unknown", ToString(CC_UNDEFINED)); - } - - BOOST_AUTO_TEST_CASE(CommandTypeToString) { - BOOST_REQUIRE_EQUAL("BinaryOutput", ToString(CT_BINARY_OUTPUT)); - BOOST_REQUIRE_EQUAL("Setpoint", ToString(CT_SETPOINT)); - BOOST_REQUIRE_EQUAL("Unknown", ToString(CT_NONE)); - } - - BOOST_AUTO_TEST_SUITE_END() - - +#include +#include + +#include +#include + +using namespace apl; + + + template + void OptimalTypeTest(T val, SetpointEncodingType correct) + { + Setpoint sp(val); + BOOST_REQUIRE_EQUAL(correct, sp.GetOptimalEncodingType()); + } + + template + void AutoTypeTest(T val, SetpointEncodingType correct) + { + Setpoint sp; sp.SetValue(val); + BOOST_REQUIRE_EQUAL(sp.GetValue(), val); + BOOST_REQUIRE_EQUAL(correct, sp.GetEncodingType()); + } + BOOST_AUTO_TEST_SUITE(CommandTypesSuite) + + BOOST_AUTO_TEST_CASE(SetpointSet) { + AutoTypeTest(0.01, SPET_AUTO_DOUBLE); + } + BOOST_AUTO_TEST_CASE(SetpointSetInt) { + AutoTypeTest(5, SPET_AUTO_INT); + } + BOOST_AUTO_TEST_CASE(OptimalFloat) { + OptimalTypeTest(100.0, SPET_FLOAT); + } + BOOST_AUTO_TEST_CASE(OptimalDouble) { + OptimalTypeTest(std::numeric_limits::max()*100.0, SPET_DOUBLE); + } + BOOST_AUTO_TEST_CASE(OptimalInt16) { + OptimalTypeTest(55, SPET_INT16); + } + BOOST_AUTO_TEST_CASE(OptimalInt32) { + OptimalTypeTest(80000, SPET_INT32); + } + + + BOOST_AUTO_TEST_CASE(ByteToCommand) { + BOOST_REQUIRE_EQUAL(CS_SUCCESS, ByteToCommandStatus(0)); + BOOST_REQUIRE_EQUAL(CS_TIMEOUT, ByteToCommandStatus(1)); + BOOST_REQUIRE_EQUAL(CS_NO_SELECT, ByteToCommandStatus(2)); + BOOST_REQUIRE_EQUAL(CS_FORMAT_ERROR, ByteToCommandStatus(3)); + BOOST_REQUIRE_EQUAL(CS_NOT_SUPPORTED, ByteToCommandStatus(4)); + BOOST_REQUIRE_EQUAL(CS_ALREADY_ACTIVE, ByteToCommandStatus(5)); + BOOST_REQUIRE_EQUAL(CS_HARDWARE_ERROR, ByteToCommandStatus(6)); + BOOST_REQUIRE_EQUAL(CS_LOCAL, ByteToCommandStatus(7)); + BOOST_REQUIRE_EQUAL(CS_TOO_MANY_OPS, ByteToCommandStatus(8)); + BOOST_REQUIRE_EQUAL(CS_NOT_AUTHORIZED, ByteToCommandStatus(9)); + } + + BOOST_AUTO_TEST_CASE(CommandToString) { + BOOST_REQUIRE_EQUAL("CS_SUCCESS", ToString(CS_SUCCESS)); + BOOST_REQUIRE_EQUAL("CS_TIMEOUT", ToString(CS_TIMEOUT)); + BOOST_REQUIRE_EQUAL("CS_NO_SELECT", ToString(CS_NO_SELECT)); + BOOST_REQUIRE_EQUAL("CS_FORMAT_ERROR", ToString(CS_FORMAT_ERROR)); + BOOST_REQUIRE_EQUAL("CS_NOT_SUPPORTED", ToString(CS_NOT_SUPPORTED)); + BOOST_REQUIRE_EQUAL("CS_ALREADY_ACTIVE", ToString(CS_ALREADY_ACTIVE)); + BOOST_REQUIRE_EQUAL("CS_HARDWARE_ERROR", ToString(CS_HARDWARE_ERROR)); + BOOST_REQUIRE_EQUAL("CS_LOCAL", ToString(CS_LOCAL)); + BOOST_REQUIRE_EQUAL("CS_TOO_MANY_OPS", ToString(CS_TOO_MANY_OPS)); + BOOST_REQUIRE_EQUAL("CS_NOT_AUTHORIZED", ToString(CS_NOT_AUTHORIZED)); + BOOST_REQUIRE_EQUAL("Unknown", ToString(CS_UNDEFINED)); + } + + BOOST_AUTO_TEST_CASE(ByteToControl) { + BOOST_REQUIRE_EQUAL(CC_NULL, ByteToControlCode(0)); + BOOST_REQUIRE_EQUAL(CC_PULSE, ByteToControlCode(0x01)); + BOOST_REQUIRE_EQUAL(CC_LATCH_ON, ByteToControlCode(0x03)); + BOOST_REQUIRE_EQUAL(CC_LATCH_OFF, ByteToControlCode(0x04)); + BOOST_REQUIRE_EQUAL(CC_PULSE_CLOSE, ByteToControlCode(0x41)); + BOOST_REQUIRE_EQUAL(CC_PULSE_TRIP, ByteToControlCode(0x81)); + BOOST_REQUIRE_EQUAL(CC_UNDEFINED, ByteToControlCode(0xFF)); + } + + BOOST_AUTO_TEST_CASE(ControlToString) { + BOOST_REQUIRE_EQUAL("CC_NULL", ToString(CC_NULL)); + BOOST_REQUIRE_EQUAL("CC_PULSE", ToString(CC_PULSE)); + BOOST_REQUIRE_EQUAL("CC_LATCH_ON", ToString(CC_LATCH_ON)); + BOOST_REQUIRE_EQUAL("CC_LATCH_OFF", ToString(CC_LATCH_OFF)); + BOOST_REQUIRE_EQUAL("CC_PULSE_CLOSE", ToString(CC_PULSE_CLOSE)); + BOOST_REQUIRE_EQUAL("CC_PULSE_TRIP", ToString(CC_PULSE_TRIP)); + BOOST_REQUIRE_EQUAL("Unknown", ToString(CC_UNDEFINED)); + } + + BOOST_AUTO_TEST_CASE(CommandTypeToString) { + BOOST_REQUIRE_EQUAL("BinaryOutput", ToString(CT_BINARY_OUTPUT)); + BOOST_REQUIRE_EQUAL("Setpoint", ToString(CT_SETPOINT)); + BOOST_REQUIRE_EQUAL("Unknown", ToString(CT_NONE)); + } + + BOOST_AUTO_TEST_SUITE_END() + + diff --git a/TestAPL/TestLocks.cpp b/TestAPL/TestLocks.cpp index 2518843e..1d65ab81 100644 --- a/TestAPL/TestLocks.cpp +++ b/TestAPL/TestLocks.cpp @@ -16,203 +16,203 @@ // specific language governing permissions and limitations // under the License. // - -#include -#include -#include -#include -#include -#include - -using namespace apl; - - - - -class MockThreadable : public Threadable -{ - public: - MockThreadable(SigLock* apLock) : mpLock(apLock){} - private: - SigLock* mpLock; - void Run() - { - //just acquire and signal - mpLock->Lock(); - mpLock->Signal(); - mpLock->Unlock(); - } - - std::string Description() const { return "MockThreadable"; } -}; - -class DoubleLocker : public Threadable -{ - public: - DoubleLocker (SigLock* apLock) : mpLock(apLock){} - private: - SigLock* mpLock; - void Run() - { - //just acquire and signal - mpLock->Lock(); - mpLock->Lock(); - mpLock->Unlock(); - } -}; - - BOOST_AUTO_TEST_SUITE(OSSpecificTests) - - BOOST_AUTO_TEST_CASE(CriticalSection) - { - SigLock lock; - apl::CriticalSection cs(&lock); - } - - BOOST_AUTO_TEST_CASE(CriticalSectionEarlyEnd) - { - SigLock lock; - - apl::CriticalSection cs(&lock); - cs.End(); - } - - BOOST_AUTO_TEST_CASE(TimedWaitFailure) - { - SigLock lock; - - lock.Lock(); - bool wake = lock.TimedWait(0); - lock.Unlock(); - - BOOST_REQUIRE(!wake); - } - - BOOST_AUTO_TEST_CASE(TimedWaitSuccess) - { - SigLock lock; - MockThreadable threadable(&lock); - Thread thread(&threadable); - lock.Lock(); - thread.Start(); - bool wake = lock.TimedWait(10000); - lock.Unlock(); - thread.WaitForStop(); - - BOOST_REQUIRE(wake); - } - - /* - BOOST_AUTO_TEST_CASE(DoubleLocking) - { - Lock lock; - DoubleLocker dl(&lock); - Thread thread(&dl); - thread.Start(); - thread.WaitForStop(); - - lock.Lock(); - lock.Unlock(); - } - */ - - /* Deprecated - This test will fail an assertion in ~Lock() now. - BOOST_AUTO_TEST_CASE(DestructionWhileLocked){ - //create a lock - Lock* plock = new Lock(); - // get the lock on it - plock->Lock(); - //make sure that it doesn't explode if that lock is deleted while locked. - delete plock; - } - */ - - BOOST_AUTO_TEST_CASE(EventLockTests) - { - EventLock ec; - // Signal(), Broadcast() and GetEvents() all require being locked so we lock over the whole test - ec.Lock(); - // test that before any events have been signaled the value is all bits set - // this forces client code to check all sources at least once - BOOST_REQUIRE_EQUAL(ec.GetEvents(),static_cast(~0)); - ec.Unlock(); - - //test that a signal registers the correct event - ec.SignalEvent(1); - - ec.Lock(); - // test that the evnt was recived (non destructivley) - BOOST_REQUIRE_EQUAL(ec.GetEvents(false),1); - // make sure the non-destructive GetEvents left the event with the same value - BOOST_REQUIRE_EQUAL(ec.GetEvents(),1); - // make sure the regular destructive GetEvents() call cleared the event buffer. - BOOST_REQUIRE_EQUAL(ec.GetEvents(),0); - ec.Unlock(); - - //make sure that a brodcast works like a signal - ec.BroadcastEvent(1); - - ec.Lock(); - BOOST_REQUIRE_EQUAL(ec.GetEvents(),1); - ec.Unlock(); - - // make sure that multiple events are all stored and reported correctly. - ec.SignalEvent(1); - ec.SignalEvent(1<<1); - ec.SignalEvent(1<<2); - ec.SignalEvent(1<<3); - - ec.Lock(); - //should be the OR of the 4 lowest bits = 0xf - BOOST_REQUIRE_EQUAL(ec.GetEvents(),0xf); - ec.Unlock(); - } - - BOOST_AUTO_TEST_CASE(Notifier) - { - EventLock ec; - ec.Lock(); - ec.GetEvents(); //when an event lock is initialized it is set to !0 - ec.Unlock(); - - - int m1 = 1 << 2; - int m2 = 1 << 4; - //create a pair of EventLocks that use the same event counter - INotifier* pNot1 = ec.GetNotifier(m1); - INotifier* pNot2 = ec.GetNotifier(m2); - - pNot1->Notify(); - - ec.Lock(); - BOOST_REQUIRE_EQUAL(ec.GetEvents(), m1); - ec.Unlock(); - - pNot2->Notify(); - - ec.Lock(); - BOOST_REQUIRE_EQUAL(ec.GetEvents(), m2); - ec.Unlock(); - - pNot1->Notify(); - pNot2->Notify(); - - ec.Lock(); - BOOST_REQUIRE_EQUAL(ec.GetEvents(), m1 | m2); - ec.Unlock(); - } - BOOST_AUTO_TEST_CASE(MaxLocks) - { - std::vector locks; - for(int i =0; i < 1000; i++){ - locks.push_back(new SigLock()); - } - for(int i =1000-1; i >= 0; i--){ - delete (locks)[i]; - locks.pop_back(); - } - } - - BOOST_AUTO_TEST_SUITE_END() - - + +#include +#include +#include +#include +#include +#include + +using namespace apl; + + + + +class MockThreadable : public Threadable +{ + public: + MockThreadable(SigLock* apLock) : mpLock(apLock){} + private: + SigLock* mpLock; + void Run() + { + //just acquire and signal + mpLock->Lock(); + mpLock->Signal(); + mpLock->Unlock(); + } + + std::string Description() const { return "MockThreadable"; } +}; + +class DoubleLocker : public Threadable +{ + public: + DoubleLocker (SigLock* apLock) : mpLock(apLock){} + private: + SigLock* mpLock; + void Run() + { + //just acquire and signal + mpLock->Lock(); + mpLock->Lock(); + mpLock->Unlock(); + } +}; + + BOOST_AUTO_TEST_SUITE(OSSpecificTests) + + BOOST_AUTO_TEST_CASE(CriticalSection) + { + SigLock lock; + apl::CriticalSection cs(&lock); + } + + BOOST_AUTO_TEST_CASE(CriticalSectionEarlyEnd) + { + SigLock lock; + + apl::CriticalSection cs(&lock); + cs.End(); + } + + BOOST_AUTO_TEST_CASE(TimedWaitFailure) + { + SigLock lock; + + lock.Lock(); + bool wake = lock.TimedWait(0); + lock.Unlock(); + + BOOST_REQUIRE(!wake); + } + + BOOST_AUTO_TEST_CASE(TimedWaitSuccess) + { + SigLock lock; + MockThreadable threadable(&lock); + Thread thread(&threadable); + lock.Lock(); + thread.Start(); + bool wake = lock.TimedWait(10000); + lock.Unlock(); + thread.WaitForStop(); + + BOOST_REQUIRE(wake); + } + + /* + BOOST_AUTO_TEST_CASE(DoubleLocking) + { + Lock lock; + DoubleLocker dl(&lock); + Thread thread(&dl); + thread.Start(); + thread.WaitForStop(); + + lock.Lock(); + lock.Unlock(); + } + */ + + /* Deprecated - This test will fail an assertion in ~Lock() now. + BOOST_AUTO_TEST_CASE(DestructionWhileLocked){ + //create a lock + Lock* plock = new Lock(); + // get the lock on it + plock->Lock(); + //make sure that it doesn't explode if that lock is deleted while locked. + delete plock; + } + */ + + BOOST_AUTO_TEST_CASE(EventLockTests) + { + EventLock ec; + // Signal(), Broadcast() and GetEvents() all require being locked so we lock over the whole test + ec.Lock(); + // test that before any events have been signaled the value is all bits set + // this forces client code to check all sources at least once + BOOST_REQUIRE_EQUAL(ec.GetEvents(),static_cast(~0)); + ec.Unlock(); + + //test that a signal registers the correct event + ec.SignalEvent(1); + + ec.Lock(); + // test that the evnt was recived (non destructivley) + BOOST_REQUIRE_EQUAL(ec.GetEvents(false),1); + // make sure the non-destructive GetEvents left the event with the same value + BOOST_REQUIRE_EQUAL(ec.GetEvents(),1); + // make sure the regular destructive GetEvents() call cleared the event buffer. + BOOST_REQUIRE_EQUAL(ec.GetEvents(),0); + ec.Unlock(); + + //make sure that a brodcast works like a signal + ec.BroadcastEvent(1); + + ec.Lock(); + BOOST_REQUIRE_EQUAL(ec.GetEvents(),1); + ec.Unlock(); + + // make sure that multiple events are all stored and reported correctly. + ec.SignalEvent(1); + ec.SignalEvent(1<<1); + ec.SignalEvent(1<<2); + ec.SignalEvent(1<<3); + + ec.Lock(); + //should be the OR of the 4 lowest bits = 0xf + BOOST_REQUIRE_EQUAL(ec.GetEvents(),0xf); + ec.Unlock(); + } + + BOOST_AUTO_TEST_CASE(Notifier) + { + EventLock ec; + ec.Lock(); + ec.GetEvents(); //when an event lock is initialized it is set to !0 + ec.Unlock(); + + + int m1 = 1 << 2; + int m2 = 1 << 4; + //create a pair of EventLocks that use the same event counter + INotifier* pNot1 = ec.GetNotifier(m1); + INotifier* pNot2 = ec.GetNotifier(m2); + + pNot1->Notify(); + + ec.Lock(); + BOOST_REQUIRE_EQUAL(ec.GetEvents(), m1); + ec.Unlock(); + + pNot2->Notify(); + + ec.Lock(); + BOOST_REQUIRE_EQUAL(ec.GetEvents(), m2); + ec.Unlock(); + + pNot1->Notify(); + pNot2->Notify(); + + ec.Lock(); + BOOST_REQUIRE_EQUAL(ec.GetEvents(), m1 | m2); + ec.Unlock(); + } + BOOST_AUTO_TEST_CASE(MaxLocks) + { + std::vector locks; + for(int i =0; i < 1000; i++){ + locks.push_back(new SigLock()); + } + for(int i =1000-1; i >= 0; i--){ + delete (locks)[i]; + locks.pop_back(); + } + } + + BOOST_AUTO_TEST_SUITE_END() + + diff --git a/TestAPL/TestLog.cpp b/TestAPL/TestLog.cpp index 6165ec2d..64a0c8ab 100644 --- a/TestAPL/TestLog.cpp +++ b/TestAPL/TestLog.cpp @@ -16,137 +16,137 @@ // specific language governing permissions and limitations // under the License. // - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace boost; -using namespace std; -using namespace apl; - - -#ifdef GetMessage -//to deal with that stupid windows GetMessageA define. -#undef GetMessage -#endif - - - - BOOST_AUTO_TEST_SUITE(LogTest) - - BOOST_AUTO_TEST_CASE( LogLifetimeTest ) - { - size_t aCount = 100; - EventLog log; - LogEntryCircularBuffer buff; - log.AddLogSubscriber(&buff); - Logger* pLogger = log.GetLogger(LEV_DEBUG, "LogTest"); - - for ( size_t i = 0; i < aCount; i++ ) - { - pLogger->Log( apl::LEV_DEBUG, "Test test test test", "Test message" ); - } - - BOOST_REQUIRE_EQUAL( buff.Count(), aCount ); - - LogEntry entry; - for ( size_t i = 0; i < aCount; i++ ) - { - BOOST_REQUIRE(buff.ReadLog(entry)); - BOOST_REQUIRE_EQUAL( buff.Count(), aCount - i - 1); - } - BOOST_REQUIRE_EQUAL( buff.Count(), 0 ); - - } - - BOOST_AUTO_TEST_CASE( LogEntryParamsTest ) - { - EventLog log; - LogEntryCircularBuffer buff; - log.AddLogSubscriber(&buff); - Logger* pLogger = log.GetLogger(LEV_DEBUG, "LogTest"); - - BOOST_REQUIRE_EQUAL(buff.Count(), 0); - pLogger->Log( LEV_DEBUG, "LogEntryParamsTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 1); - - LogEntry entry; - BOOST_REQUIRE(buff.ReadLog(entry)); - - BOOST_REQUIRE_EQUAL( entry.GetFilterLevel(), LEV_DEBUG ); - BOOST_REQUIRE_EQUAL( entry.GetLocation(), "LogEntryParamsTest" ); - BOOST_REQUIRE_EQUAL( entry.GetMessage(), "MessageMessage" ); - BOOST_REQUIRE_EQUAL( entry.GetErrorCode(), 5 ); - BOOST_REQUIRE_EQUAL( entry.GetDeviceName(), "LogTest"); - } - - BOOST_AUTO_TEST_CASE( LogLevelTest ) - { - EventLog log; - LogEntryCircularBuffer buff; - log.AddLogSubscriber(&buff); - Logger* pLogger = log.GetLogger(LEV_INTERPRET, "LogTest"); - - BOOST_REQUIRE_EQUAL(buff.Count(), 0); - pLogger->Log( LEV_INFO, "LogLevelTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 1); - pLogger->Log( LEV_INTERPRET, "LogLevelTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 2); - pLogger->Log( LEV_COMM, "LogLevelTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 2); - } - - BOOST_AUTO_TEST_CASE( LogSubLevelTest ) - { - EventLog log; - LogEntryCircularBuffer buff; - log.AddLogSubscriber(&buff); - Logger* pLogger = log.GetLogger(LEV_DEBUG, "LogTest")->GetSubLogger("LogTestSub", LEV_INTERPRET); - - BOOST_REQUIRE_EQUAL(buff.Count(), 0); - pLogger->Log( LEV_INFO, "LogLevelTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 1); - pLogger->Log( LEV_INTERPRET, "LogLevelTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 2); - pLogger->Log( LEV_COMM, "LogLevelTest", "MessageMessage", 5 ); - BOOST_REQUIRE_EQUAL(buff.Count(), 2); - } - - BOOST_AUTO_TEST_CASE( LogErrorCounting) - { - apl::LogTester log(false); - Logger* pLogger = log.GetLog().GetLogger(LEV_DEBUG, "test1"); - pLogger->Log( LEV_DEBUG, "LogEntryParamsTest", "MessageMessage", 5 ); - - BOOST_REQUIRE_EQUAL(log.NextErrorCode(), 5); - BOOST_REQUIRE_EQUAL(log.NextErrorCode(), -1); - } - - BOOST_AUTO_TEST_SUITE_END() - - BOOST_AUTO_TEST_SUITE(LogToFileSuite) - - BOOST_AUTO_TEST_CASE(AddRemove){ - - { - EventLog log; - LogToFile file(&log, "unittest.log"); - Logger* pLogger = log.GetLogger(LEV_DEBUG, "test1"); - pLogger->Log( apl::LEV_DEBUG, "Test test test test", "Test message" ); - } - - ifstream inFile("unittest.log"); - std::string s; - inFile >> s; - BOOST_REQUIRE(s.find("Test test") != 0); - - } - - BOOST_AUTO_TEST_SUITE_END() + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; +using namespace apl; + + +#ifdef GetMessage +//to deal with that stupid windows GetMessageA define. +#undef GetMessage +#endif + + + + BOOST_AUTO_TEST_SUITE(LogTest) + + BOOST_AUTO_TEST_CASE( LogLifetimeTest ) + { + size_t aCount = 100; + EventLog log; + LogEntryCircularBuffer buff; + log.AddLogSubscriber(&buff); + Logger* pLogger = log.GetLogger(LEV_DEBUG, "LogTest"); + + for ( size_t i = 0; i < aCount; i++ ) + { + pLogger->Log( apl::LEV_DEBUG, "Test test test test", "Test message" ); + } + + BOOST_REQUIRE_EQUAL( buff.Count(), aCount ); + + LogEntry entry; + for ( size_t i = 0; i < aCount; i++ ) + { + BOOST_REQUIRE(buff.ReadLog(entry)); + BOOST_REQUIRE_EQUAL( buff.Count(), aCount - i - 1); + } + BOOST_REQUIRE_EQUAL( buff.Count(), 0 ); + + } + + BOOST_AUTO_TEST_CASE( LogEntryParamsTest ) + { + EventLog log; + LogEntryCircularBuffer buff; + log.AddLogSubscriber(&buff); + Logger* pLogger = log.GetLogger(LEV_DEBUG, "LogTest"); + + BOOST_REQUIRE_EQUAL(buff.Count(), 0); + pLogger->Log( LEV_DEBUG, "LogEntryParamsTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 1); + + LogEntry entry; + BOOST_REQUIRE(buff.ReadLog(entry)); + + BOOST_REQUIRE_EQUAL( entry.GetFilterLevel(), LEV_DEBUG ); + BOOST_REQUIRE_EQUAL( entry.GetLocation(), "LogEntryParamsTest" ); + BOOST_REQUIRE_EQUAL( entry.GetMessage(), "MessageMessage" ); + BOOST_REQUIRE_EQUAL( entry.GetErrorCode(), 5 ); + BOOST_REQUIRE_EQUAL( entry.GetDeviceName(), "LogTest"); + } + + BOOST_AUTO_TEST_CASE( LogLevelTest ) + { + EventLog log; + LogEntryCircularBuffer buff; + log.AddLogSubscriber(&buff); + Logger* pLogger = log.GetLogger(LEV_INTERPRET, "LogTest"); + + BOOST_REQUIRE_EQUAL(buff.Count(), 0); + pLogger->Log( LEV_INFO, "LogLevelTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 1); + pLogger->Log( LEV_INTERPRET, "LogLevelTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 2); + pLogger->Log( LEV_COMM, "LogLevelTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 2); + } + + BOOST_AUTO_TEST_CASE( LogSubLevelTest ) + { + EventLog log; + LogEntryCircularBuffer buff; + log.AddLogSubscriber(&buff); + Logger* pLogger = log.GetLogger(LEV_DEBUG, "LogTest")->GetSubLogger("LogTestSub", LEV_INTERPRET); + + BOOST_REQUIRE_EQUAL(buff.Count(), 0); + pLogger->Log( LEV_INFO, "LogLevelTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 1); + pLogger->Log( LEV_INTERPRET, "LogLevelTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 2); + pLogger->Log( LEV_COMM, "LogLevelTest", "MessageMessage", 5 ); + BOOST_REQUIRE_EQUAL(buff.Count(), 2); + } + + BOOST_AUTO_TEST_CASE( LogErrorCounting) + { + apl::LogTester log(false); + Logger* pLogger = log.GetLog().GetLogger(LEV_DEBUG, "test1"); + pLogger->Log( LEV_DEBUG, "LogEntryParamsTest", "MessageMessage", 5 ); + + BOOST_REQUIRE_EQUAL(log.NextErrorCode(), 5); + BOOST_REQUIRE_EQUAL(log.NextErrorCode(), -1); + } + + BOOST_AUTO_TEST_SUITE_END() + + BOOST_AUTO_TEST_SUITE(LogToFileSuite) + + BOOST_AUTO_TEST_CASE(AddRemove){ + + { + EventLog log; + LogToFile file(&log, "unittest.log"); + Logger* pLogger = log.GetLogger(LEV_DEBUG, "test1"); + pLogger->Log( apl::LEV_DEBUG, "Test test test test", "Test message" ); + } + + ifstream inFile("unittest.log"); + std::string s; + inFile >> s; + BOOST_REQUIRE(s.find("Test test") != 0); + + } + + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestMisc.cpp b/TestAPL/TestMisc.cpp index e3f6998c..d3ecf871 100644 --- a/TestAPL/TestMisc.cpp +++ b/TestAPL/TestMisc.cpp @@ -16,44 +16,44 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - - -#include -#include - -#include - -using namespace apl; - - -BOOST_AUTO_TEST_SUITE(MiscTest) - - BOOST_AUTO_TEST_CASE(ToUpperCase) - { - string test("lower case"); - apl::toUpperCase(test); - BOOST_REQUIRE_EQUAL(test, "LOWER CASE"); - - string test2("UPPPER case"); - apl::toUpperCase(test2); - BOOST_REQUIRE_EQUAL(test2, "UPPPER CASE"); - - string test3("123456789abcDEF"); - apl::toUpperCase(test3); - BOOST_REQUIRE_EQUAL(test3, "123456789ABCDEF"); - } - -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + + +#include +#include + +#include + +using namespace apl; + + +BOOST_AUTO_TEST_SUITE(MiscTest) + + BOOST_AUTO_TEST_CASE(ToUpperCase) + { + string test("lower case"); + apl::toUpperCase(test); + BOOST_REQUIRE_EQUAL(test, "LOWER CASE"); + + string test2("UPPPER case"); + apl::toUpperCase(test2); + BOOST_REQUIRE_EQUAL(test2, "UPPPER CASE"); + + string test3("123456789abcDEF"); + apl::toUpperCase(test3); + BOOST_REQUIRE_EQUAL(test3, "123456789ABCDEF"); + } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestPackingUnpacking.cpp b/TestAPL/TestPackingUnpacking.cpp index b43aa194..417c1025 100644 --- a/TestAPL/TestPackingUnpacking.cpp +++ b/TestAPL/TestPackingUnpacking.cpp @@ -16,149 +16,149 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - - -#include -#include -#include -#include - -#include - -using namespace std; -using namespace apl; -using namespace std; - -template -bool TestReadWrite(typename T::Type aValue) -{ - byte_t data[2*T::Size]; - for(size_t i=0; i -bool TestReadWriteDouble(typename T::Type aValue) -{ - ByteStr data(2*T::Size); - - for(size_t i=0; i -bool TestFloatParsing(std::string aHex, typename T::Type aValue) -{ - HexSequence hs(aHex); - size_t type_size = sizeof(typename T::Type); - BOOST_REQUIRE_EQUAL(hs.Size(), type_size); - - ByteStr buff(2*type_size); - - for(size_t i=0; i("20 74 85 2F C7 2B A2 C0", -2.3258890344E3)); - - BOOST_REQUIRE(TestFloatParsing("00 00 00 00 64 89 67 41", 12340000.0)); - BOOST_REQUIRE(TestFloatParsing("00 00 00 00 00 00 34 C0", -20.0)); - BOOST_REQUIRE(TestFloatParsing("8F 81 9C 95 2D F9 64 BB", -13.879E-23)); - BOOST_REQUIRE(TestFloatParsing("00 00 00 00 00 00 59 40", 100.0)); - } - - BOOST_AUTO_TEST_CASE(SinglePacking) - { - BOOST_REQUIRE(TestFloatParsing("20 4B 3C 4B", 12340000.0f)); - BOOST_REQUIRE(TestFloatParsing("6D C9 27 9B", -13.879E-23f)); - BOOST_REQUIRE(TestFloatParsing("00 00 A0 C1", -20.0)); - } - - BOOST_AUTO_TEST_CASE(DoubleFloat) - { - BOOST_REQUIRE(TestReadWriteDouble(0)); - BOOST_REQUIRE(TestReadWriteDouble(-100000)); - BOOST_REQUIRE(TestReadWriteDouble(-2.3258890344E3)); - BOOST_REQUIRE(TestReadWriteDouble(1E20)); - BOOST_REQUIRE(TestReadWriteDouble(100.0)); - } - - BOOST_AUTO_TEST_CASE(SingleFloat) - { - BOOST_REQUIRE(TestReadWriteDouble(0.0f)); - BOOST_REQUIRE(TestReadWriteDouble(-100000.0f)); - BOOST_REQUIRE(TestReadWriteDouble(-2.3258890344E3f)); - BOOST_REQUIRE(TestReadWriteDouble(1E20f)); - BOOST_REQUIRE(TestReadWriteDouble(100.0f)); - } - - BOOST_AUTO_TEST_CASE(UInt8) - { - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(123)); - BOOST_REQUIRE(TestReadWrite(255)); - } - - BOOST_AUTO_TEST_CASE(UInt16LE) - { - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(123)); - BOOST_REQUIRE(TestReadWrite(65535)); - } - - BOOST_AUTO_TEST_CASE(Int16LE) - { - BOOST_REQUIRE(TestReadWrite(-32768)); - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(32767)); - } - - BOOST_AUTO_TEST_CASE(UInt32LE) - { - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(123)); - BOOST_REQUIRE(TestReadWrite(4294967295UL)); - } - - BOOST_AUTO_TEST_CASE(Int32LE) - { - BOOST_REQUIRE(TestReadWrite(0x80000000)); - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(0x7fffffff)); - } - - BOOST_AUTO_TEST_CASE(UInt48LE) - { - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(123)); - BOOST_REQUIRE(TestReadWrite(281474976710655LL)); - } - - BOOST_AUTO_TEST_CASE(UInt64BE) - { - BOOST_REQUIRE(TestReadWrite(0)); - BOOST_REQUIRE(TestReadWrite(123)); - BOOST_REQUIRE(TestReadWrite(5000000000ULL)); - } - - BOOST_AUTO_TEST_SUITE_END() +#include +#include + + +#include +#include +#include +#include + +#include + +using namespace std; +using namespace apl; +using namespace std; + +template +bool TestReadWrite(typename T::Type aValue) +{ + byte_t data[2*T::Size]; + for(size_t i=0; i +bool TestReadWriteDouble(typename T::Type aValue) +{ + ByteStr data(2*T::Size); + + for(size_t i=0; i +bool TestFloatParsing(std::string aHex, typename T::Type aValue) +{ + HexSequence hs(aHex); + size_t type_size = sizeof(typename T::Type); + BOOST_REQUIRE_EQUAL(hs.Size(), type_size); + + ByteStr buff(2*type_size); + + for(size_t i=0; i("20 74 85 2F C7 2B A2 C0", -2.3258890344E3)); + + BOOST_REQUIRE(TestFloatParsing("00 00 00 00 64 89 67 41", 12340000.0)); + BOOST_REQUIRE(TestFloatParsing("00 00 00 00 00 00 34 C0", -20.0)); + BOOST_REQUIRE(TestFloatParsing("8F 81 9C 95 2D F9 64 BB", -13.879E-23)); + BOOST_REQUIRE(TestFloatParsing("00 00 00 00 00 00 59 40", 100.0)); + } + + BOOST_AUTO_TEST_CASE(SinglePacking) + { + BOOST_REQUIRE(TestFloatParsing("20 4B 3C 4B", 12340000.0f)); + BOOST_REQUIRE(TestFloatParsing("6D C9 27 9B", -13.879E-23f)); + BOOST_REQUIRE(TestFloatParsing("00 00 A0 C1", -20.0)); + } + + BOOST_AUTO_TEST_CASE(DoubleFloat) + { + BOOST_REQUIRE(TestReadWriteDouble(0)); + BOOST_REQUIRE(TestReadWriteDouble(-100000)); + BOOST_REQUIRE(TestReadWriteDouble(-2.3258890344E3)); + BOOST_REQUIRE(TestReadWriteDouble(1E20)); + BOOST_REQUIRE(TestReadWriteDouble(100.0)); + } + + BOOST_AUTO_TEST_CASE(SingleFloat) + { + BOOST_REQUIRE(TestReadWriteDouble(0.0f)); + BOOST_REQUIRE(TestReadWriteDouble(-100000.0f)); + BOOST_REQUIRE(TestReadWriteDouble(-2.3258890344E3f)); + BOOST_REQUIRE(TestReadWriteDouble(1E20f)); + BOOST_REQUIRE(TestReadWriteDouble(100.0f)); + } + + BOOST_AUTO_TEST_CASE(UInt8) + { + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(123)); + BOOST_REQUIRE(TestReadWrite(255)); + } + + BOOST_AUTO_TEST_CASE(UInt16LE) + { + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(123)); + BOOST_REQUIRE(TestReadWrite(65535)); + } + + BOOST_AUTO_TEST_CASE(Int16LE) + { + BOOST_REQUIRE(TestReadWrite(-32768)); + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(32767)); + } + + BOOST_AUTO_TEST_CASE(UInt32LE) + { + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(123)); + BOOST_REQUIRE(TestReadWrite(4294967295UL)); + } + + BOOST_AUTO_TEST_CASE(Int32LE) + { + BOOST_REQUIRE(TestReadWrite(0x80000000)); + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(0x7fffffff)); + } + + BOOST_AUTO_TEST_CASE(UInt48LE) + { + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(123)); + BOOST_REQUIRE(TestReadWrite(281474976710655LL)); + } + + BOOST_AUTO_TEST_CASE(UInt64BE) + { + BOOST_REQUIRE(TestReadWrite(0)); + BOOST_REQUIRE(TestReadWrite(123)); + BOOST_REQUIRE(TestReadWrite(5000000000ULL)); + } + + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestParsing.cpp b/TestAPL/TestParsing.cpp index 5e343b16..32924f81 100644 --- a/TestAPL/TestParsing.cpp +++ b/TestAPL/TestParsing.cpp @@ -16,40 +16,40 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include - - -BOOST_AUTO_TEST_SUITE(Parsing) - -BOOST_AUTO_TEST_CASE(Bool) -{ - bool val; - BOOST_REQUIRE(apl::Parsing::Get("true", val)); - BOOST_REQUIRE(val); - BOOST_REQUIRE(apl::Parsing::Get("false", val)); - BOOST_REQUIRE_FALSE(val); - BOOST_REQUIRE_FALSE(apl::Parsing::Get("foo", val)); -} - -BOOST_AUTO_TEST_CASE(Int) -{ - int val; - BOOST_REQUIRE(apl::Parsing::Get("123", val)); - BOOST_REQUIRE_EQUAL(val, 123); - BOOST_REQUIRE(apl::Parsing::Get("-123", val)); - BOOST_REQUIRE_EQUAL(val, -123); - BOOST_REQUIRE_FALSE(apl::Parsing::Get("foo", val)); -} - -BOOST_AUTO_TEST_CASE(Positive) -{ - int val; - BOOST_REQUIRE(apl::Parsing::GetPositive("123", val)); - BOOST_REQUIRE_EQUAL(val, 123); - BOOST_REQUIRE_FALSE(apl::Parsing::GetPositive("-123", val)); -} - -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include + + +BOOST_AUTO_TEST_SUITE(Parsing) + +BOOST_AUTO_TEST_CASE(Bool) +{ + bool val; + BOOST_REQUIRE(apl::Parsing::Get("true", val)); + BOOST_REQUIRE(val); + BOOST_REQUIRE(apl::Parsing::Get("false", val)); + BOOST_REQUIRE_FALSE(val); + BOOST_REQUIRE_FALSE(apl::Parsing::Get("foo", val)); +} + +BOOST_AUTO_TEST_CASE(Int) +{ + int val; + BOOST_REQUIRE(apl::Parsing::Get("123", val)); + BOOST_REQUIRE_EQUAL(val, 123); + BOOST_REQUIRE(apl::Parsing::Get("-123", val)); + BOOST_REQUIRE_EQUAL(val, -123); + BOOST_REQUIRE_FALSE(apl::Parsing::Get("foo", val)); +} + +BOOST_AUTO_TEST_CASE(Positive) +{ + int val; + BOOST_REQUIRE(apl::Parsing::GetPositive("123", val)); + BOOST_REQUIRE_EQUAL(val, 123); + BOOST_REQUIRE_FALSE(apl::Parsing::GetPositive("-123", val)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestPhysicalLayerAsyncBase.cpp b/TestAPL/TestPhysicalLayerAsyncBase.cpp index 17fe9fb0..a18eebb8 100644 --- a/TestAPL/TestPhysicalLayerAsyncBase.cpp +++ b/TestAPL/TestPhysicalLayerAsyncBase.cpp @@ -16,137 +16,137 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include "AsyncPhysBaseTest.h" - -#include - -using namespace apl; - - - - BOOST_AUTO_TEST_SUITE(PhysicalLayerAsyncBaseSuite) - BOOST_AUTO_TEST_CASE(ClosedState) { - AsyncPhysBaseTest t; - byte_t buff; - - BOOST_REQUIRE_THROW(t.phys.AsyncClose(), InvalidStateException); - BOOST_REQUIRE_THROW(t.upper.SendDown("00"), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.AsyncRead(&buff, 1), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalSendFailure(), InvalidStateException); - - } - - BOOST_AUTO_TEST_CASE(OpenCloseNotification) { - AsyncPhysBaseTest t; - const size_t NUM = 3; - - for(size_t i=1; i<=NUM; ++i) { - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerUp,i); - t.phys.AsyncClose(); - - BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalSendFailure(), InvalidStateException); - - BOOST_REQUIRE_EQUAL(t.phys.NumClose(), i); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, i); - } - } - - BOOST_AUTO_TEST_CASE(ReadState) { - AsyncPhysBaseTest t; - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - t.adapter.StartRead(); //start a read - - BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalSendSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalSendFailure(), InvalidStateException); - - t.phys.TriggerRead("00"); - t.upper.BufferEquals("00"); - } - - BOOST_AUTO_TEST_CASE(CloseWhileReading) { - AsyncPhysBaseTest t; - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - t.adapter.StartRead(); - - t.phys.AsyncClose(); - BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); //layer shouldn't go down until the outstanding read comes back - t.phys.SignalReadFailure(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); - } - - BOOST_AUTO_TEST_CASE(WriteState) { - AsyncPhysBaseTest t; - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - - t.upper.SendDown("00"); - BOOST_REQUIRE_EQUAL(t.phys.Size(), 1); - - BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.TriggerRead(""), InvalidStateException); - BOOST_REQUIRE_THROW(t.phys.SignalReadFailure(), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(CloseWhileWriting) { - AsyncPhysBaseTest t; - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - - t.upper.SendDown("00"); - t.phys.AsyncClose(); - BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); //layer shouldn't go down until the outstanding write comes back - t.phys.SignalSendFailure(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); - } - - BOOST_AUTO_TEST_CASE(CloseWhileReadingWriting) { - AsyncPhysBaseTest t; - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - - t.upper.SendDown("00"); - t.adapter.StartRead(); - t.phys.AsyncClose(); - BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); - t.phys.SignalSendFailure(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); - t.phys.SignalReadFailure(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); - } - - BOOST_AUTO_TEST_CASE(CloseWhileWritingReading) { - AsyncPhysBaseTest t; - t.phys.AsyncOpen(); - t.phys.SignalOpenSuccess(); - - t.upper.SendDown("00"); - t.adapter.StartRead(); - t.phys.AsyncClose(); - BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); - t.phys.SignalReadFailure(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); - t.phys.SignalSendFailure(); - BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); - } - BOOST_AUTO_TEST_SUITE_END() - +#include +#include + +#include "AsyncPhysBaseTest.h" + +#include + +using namespace apl; + + + + BOOST_AUTO_TEST_SUITE(PhysicalLayerAsyncBaseSuite) + BOOST_AUTO_TEST_CASE(ClosedState) { + AsyncPhysBaseTest t; + byte_t buff; + + BOOST_REQUIRE_THROW(t.phys.AsyncClose(), InvalidStateException); + BOOST_REQUIRE_THROW(t.upper.SendDown("00"), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.AsyncRead(&buff, 1), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalSendFailure(), InvalidStateException); + + } + + BOOST_AUTO_TEST_CASE(OpenCloseNotification) { + AsyncPhysBaseTest t; + const size_t NUM = 3; + + for(size_t i=1; i<=NUM; ++i) { + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerUp,i); + t.phys.AsyncClose(); + + BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalSendFailure(), InvalidStateException); + + BOOST_REQUIRE_EQUAL(t.phys.NumClose(), i); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, i); + } + } + + BOOST_AUTO_TEST_CASE(ReadState) { + AsyncPhysBaseTest t; + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + t.adapter.StartRead(); //start a read + + BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalSendSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalSendFailure(), InvalidStateException); + + t.phys.TriggerRead("00"); + t.upper.BufferEquals("00"); + } + + BOOST_AUTO_TEST_CASE(CloseWhileReading) { + AsyncPhysBaseTest t; + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + t.adapter.StartRead(); + + t.phys.AsyncClose(); + BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); //layer shouldn't go down until the outstanding read comes back + t.phys.SignalReadFailure(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); + } + + BOOST_AUTO_TEST_CASE(WriteState) { + AsyncPhysBaseTest t; + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + + t.upper.SendDown("00"); + BOOST_REQUIRE_EQUAL(t.phys.Size(), 1); + + BOOST_REQUIRE_THROW(t.phys.SignalOpenFailure(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalOpenSuccess(), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.TriggerRead(""), InvalidStateException); + BOOST_REQUIRE_THROW(t.phys.SignalReadFailure(), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(CloseWhileWriting) { + AsyncPhysBaseTest t; + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + + t.upper.SendDown("00"); + t.phys.AsyncClose(); + BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); //layer shouldn't go down until the outstanding write comes back + t.phys.SignalSendFailure(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); + } + + BOOST_AUTO_TEST_CASE(CloseWhileReadingWriting) { + AsyncPhysBaseTest t; + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + + t.upper.SendDown("00"); + t.adapter.StartRead(); + t.phys.AsyncClose(); + BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); + t.phys.SignalSendFailure(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); + t.phys.SignalReadFailure(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); + } + + BOOST_AUTO_TEST_CASE(CloseWhileWritingReading) { + AsyncPhysBaseTest t; + t.phys.AsyncOpen(); + t.phys.SignalOpenSuccess(); + + t.upper.SendDown("00"); + t.adapter.StartRead(); + t.phys.AsyncClose(); + BOOST_REQUIRE_EQUAL(t.phys.NumClose(), 1); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); + t.phys.SignalReadFailure(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 0); + t.phys.SignalSendFailure(); + BOOST_REQUIRE_EQUAL(t.upper.GetState().mNumLayerDown, 1); + } + BOOST_AUTO_TEST_SUITE_END() + diff --git a/TestAPL/TestPhysicalLayerAsyncSerial.cpp b/TestAPL/TestPhysicalLayerAsyncSerial.cpp index ae9c8de7..919b8cc8 100644 --- a/TestAPL/TestPhysicalLayerAsyncSerial.cpp +++ b/TestAPL/TestPhysicalLayerAsyncSerial.cpp @@ -16,49 +16,49 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "AsyncSerialTestObject.h" - -#include -#include -#include - -#include -#include -#include -#include - -using namespace apl; -using namespace boost; - - - -//run the tests on arm to give us some protection - BOOST_AUTO_TEST_SUITE(PhysicalLayerSerialSuite) -#ifdef SERIAL_PORT - - BOOST_AUTO_TEST_CASE(TestSendReceiveLoopback) - { - SerialSettings s; - s.mDevice = TOSTRING(SERIAL_PORT); - s.mBaud = 9600; - s.mDataBits = 8; - s.mStopBits = 1; - s.mParity = PAR_NONE; - s.mFlowType = FLOW_NONE; - - AsyncSerialTestObject t(s); - - t.mPort.AsyncOpen(); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mUpper))); - - ByteStr b(4096, 0); - t.mUpper.SendDown(b, b.Size()); - - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::SizeEquals, &t.mUpper, b.Size()))); - } - -#endif - - BOOST_AUTO_TEST_SUITE_END() - +#include +#include "AsyncSerialTestObject.h" + +#include +#include +#include + +#include +#include +#include +#include + +using namespace apl; +using namespace boost; + + + +//run the tests on arm to give us some protection + BOOST_AUTO_TEST_SUITE(PhysicalLayerSerialSuite) +#ifdef SERIAL_PORT + + BOOST_AUTO_TEST_CASE(TestSendReceiveLoopback) + { + SerialSettings s; + s.mDevice = TOSTRING(SERIAL_PORT); + s.mBaud = 9600; + s.mDataBits = 8; + s.mStopBits = 1; + s.mParity = PAR_NONE; + s.mFlowType = FLOW_NONE; + + AsyncSerialTestObject t(s); + + t.mPort.AsyncOpen(); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mUpper))); + + ByteStr b(4096, 0); + t.mUpper.SendDown(b, b.Size()); + + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::SizeEquals, &t.mUpper, b.Size()))); + } + +#endif + + BOOST_AUTO_TEST_SUITE_END() + diff --git a/TestAPL/TestPhysicalLayerAsyncTCP.cpp b/TestAPL/TestPhysicalLayerAsyncTCP.cpp index 86c9553a..cca51d27 100644 --- a/TestAPL/TestPhysicalLayerAsyncTCP.cpp +++ b/TestAPL/TestPhysicalLayerAsyncTCP.cpp @@ -16,179 +16,179 @@ // specific language governing permissions and limitations // under the License. // -#include -#include "AsyncPhysTestObject.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -using namespace apl; -using namespace boost; - - -BOOST_AUTO_TEST_SUITE(PhysicalLayerAsyncTCPSuite) - - BOOST_AUTO_TEST_CASE(TestStateClosed) - { - AsyncPhysTestObject t(LEV_INFO, false); - - byte_t buff[100]; - - // Test that reads/writes of length 0 throw ArgumentException - BOOST_REQUIRE_THROW(t.mTCPClient.AsyncWrite(buff,0), ArgumentException); - BOOST_REQUIRE_THROW(t.mTCPClient.AsyncRead(buff,0), ArgumentException); - - //Test that in the closed state we get the proper invalid state exceptions - BOOST_REQUIRE_THROW(t.mTCPClient.AsyncWrite(buff,100), InvalidStateException); - BOOST_REQUIRE_THROW(t.mTCPClient.AsyncRead(buff,100), InvalidStateException); - BOOST_REQUIRE_THROW(t.mTCPClient.AsyncClose(), InvalidStateException); - } - - BOOST_AUTO_TEST_CASE(ClientConnectionRejected) - { - AsyncPhysTestObject t(LEV_INFO, false); - - BOOST_REQUIRE_EQUAL(t.mClientAdapter.GetNumOpenFailure(), 0); - - for(size_t i=0; i<2; ++i) { - t.mTCPClient.AsyncOpen(); - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&LowerLayerToPhysAdapter::OpenFailureEquals, &t.mClientAdapter, i+1))); - } - } - - BOOST_AUTO_TEST_CASE(ClientConnectionCanceled) - { - AsyncPhysTestObject t(LEV_INFO, false); - - for(size_t i=0; i<2; ++i) { - t.mTCPClient.AsyncOpen(); - t.mTCPClient.AsyncClose(); - - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&LowerLayerToPhysAdapter::OpenFailureEquals, &t.mClientAdapter, i+1))); - } - } - - BOOST_AUTO_TEST_CASE(ServerAcceptCanceled) - { - AsyncPhysTestObject t(LEV_INFO, false); - - for(size_t i=0; i<2; ++i) { - t.mTCPServer.AsyncOpen(); - t.mTCPServer.AsyncClose(); - - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&LowerLayerToPhysAdapter::OpenFailureEquals, &t.mServerAdapter, i+1))); - } - } - - BOOST_AUTO_TEST_CASE(ConnectDisconnect) - { - AsyncPhysTestObject t(LEV_INFO, false); - - for(size_t i=0; i< 10; ++i) { - - t.mTCPServer.AsyncOpen(); - t.mTCPClient.AsyncOpen(); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); - - //Check that since reads are outstanding, you only have to stop 1/2 of the connection - if( (i%2) == 0 ) t.mTCPServer.AsyncClose(); - else t.mTCPClient.AsyncClose(); - BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); - BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); - } - } - - BOOST_AUTO_TEST_CASE(TestSendShutdown) - { - AsyncPhysTestObject t(LEV_INFO, false); - - t.mTCPServer.AsyncOpen(); - t.mTCPClient.AsyncOpen(); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); - - ByteStr bs(1024, 77); //give some interesting seed value to make sure bytes are correctly written - t.mClientUpper.SendDown(bs.Buffer(), bs.Size()); - - t.mTCPClient.AsyncClose(); - BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); - BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); - } - - BOOST_AUTO_TEST_CASE(TwoWaySend) - { - const size_t SEND_SIZE = 1 << 20; // 1 MB - - AsyncPhysTestObject t(LEV_INFO, false); - - t.mTCPServer.AsyncOpen(); - t.mTCPClient.AsyncOpen(); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); - BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); - - //both layers are now up and reading, start them both writing - ByteStr bs(SEND_SIZE, 77); //give some interesting seed value to make sure bytes are correctly written - t.mClientUpper.SendDown(bs.Buffer(), bs.Size()); - t.mServerUpper.SendDown(bs.Buffer(), bs.Size()); - - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::SizeEquals, &t.mServerUpper, SEND_SIZE))); - BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::SizeEquals, &t.mClientUpper, SEND_SIZE))); - - BOOST_REQUIRE(t.mClientUpper.BufferEquals(bs.Buffer(), bs.Size())); - BOOST_REQUIRE(t.mServerUpper.BufferEquals(bs.Buffer(), bs.Size())); - - t.mTCPServer.AsyncClose(); //stop one side - BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); - BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); - } - -#ifndef ARM - - BOOST_AUTO_TEST_CASE(Loopback) - { - EventLog logserver; - boost::asio::io_service loopservice; - TimerSourceASIO timer_src(&loopservice); - PhysicalLayerAsyncTCPServer server(logserver.GetLogger(LEV_INFO, "server"), &loopservice, 30000); - AsyncLoopback t(logserver.GetLogger(LEV_INFO, "loopback"), &server, &timer_src, LEV_WARNING, false); - IOServiceThread iost(&loopservice); - t.Start(); - iost.Start(); - - EventLog log; - Logger* logger = log.GetLogger(LEV_DEBUG, "client"); - AsyncTestObjectASIO test; - PhysicalLayerAsyncTCPClient client(logger, test.GetService(), "127.0.0.1", 30000); - LowerLayerToPhysAdapter adapter(logger, &client); - MockUpperLayer upper(logger); - adapter.SetUpperLayer(&upper); - - client.AsyncOpen(); - BOOST_REQUIRE(test.ProceedUntil(boost::bind(&MockUpperLayer::IsLowerLayerUp, &upper))); - - for(size_t i=0; i<1000; ++i) { - upper.SendDown("01 02 03"); - BOOST_REQUIRE(test.ProceedUntil(boost::bind(&MockUpperLayer::BufferEquals, &upper, "01 02 03"))); - BOOST_REQUIRE(test.ProceedUntil(boost::bind(&MockUpperLayer::CountersEqual, &upper, 1, 0))); - upper.ClearBuffer(); - upper.Reset(); - } - } - -#endif - - -BOOST_AUTO_TEST_SUITE_END() - +#include +#include "AsyncPhysTestObject.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace apl; +using namespace boost; + + +BOOST_AUTO_TEST_SUITE(PhysicalLayerAsyncTCPSuite) + + BOOST_AUTO_TEST_CASE(TestStateClosed) + { + AsyncPhysTestObject t(LEV_INFO, false); + + byte_t buff[100]; + + // Test that reads/writes of length 0 throw ArgumentException + BOOST_REQUIRE_THROW(t.mTCPClient.AsyncWrite(buff,0), ArgumentException); + BOOST_REQUIRE_THROW(t.mTCPClient.AsyncRead(buff,0), ArgumentException); + + //Test that in the closed state we get the proper invalid state exceptions + BOOST_REQUIRE_THROW(t.mTCPClient.AsyncWrite(buff,100), InvalidStateException); + BOOST_REQUIRE_THROW(t.mTCPClient.AsyncRead(buff,100), InvalidStateException); + BOOST_REQUIRE_THROW(t.mTCPClient.AsyncClose(), InvalidStateException); + } + + BOOST_AUTO_TEST_CASE(ClientConnectionRejected) + { + AsyncPhysTestObject t(LEV_INFO, false); + + BOOST_REQUIRE_EQUAL(t.mClientAdapter.GetNumOpenFailure(), 0); + + for(size_t i=0; i<2; ++i) { + t.mTCPClient.AsyncOpen(); + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&LowerLayerToPhysAdapter::OpenFailureEquals, &t.mClientAdapter, i+1))); + } + } + + BOOST_AUTO_TEST_CASE(ClientConnectionCanceled) + { + AsyncPhysTestObject t(LEV_INFO, false); + + for(size_t i=0; i<2; ++i) { + t.mTCPClient.AsyncOpen(); + t.mTCPClient.AsyncClose(); + + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&LowerLayerToPhysAdapter::OpenFailureEquals, &t.mClientAdapter, i+1))); + } + } + + BOOST_AUTO_TEST_CASE(ServerAcceptCanceled) + { + AsyncPhysTestObject t(LEV_INFO, false); + + for(size_t i=0; i<2; ++i) { + t.mTCPServer.AsyncOpen(); + t.mTCPServer.AsyncClose(); + + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&LowerLayerToPhysAdapter::OpenFailureEquals, &t.mServerAdapter, i+1))); + } + } + + BOOST_AUTO_TEST_CASE(ConnectDisconnect) + { + AsyncPhysTestObject t(LEV_INFO, false); + + for(size_t i=0; i< 10; ++i) { + + t.mTCPServer.AsyncOpen(); + t.mTCPClient.AsyncOpen(); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); + + //Check that since reads are outstanding, you only have to stop 1/2 of the connection + if( (i%2) == 0 ) t.mTCPServer.AsyncClose(); + else t.mTCPClient.AsyncClose(); + BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); + BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); + } + } + + BOOST_AUTO_TEST_CASE(TestSendShutdown) + { + AsyncPhysTestObject t(LEV_INFO, false); + + t.mTCPServer.AsyncOpen(); + t.mTCPClient.AsyncOpen(); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); + + ByteStr bs(1024, 77); //give some interesting seed value to make sure bytes are correctly written + t.mClientUpper.SendDown(bs.Buffer(), bs.Size()); + + t.mTCPClient.AsyncClose(); + BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); + BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); + } + + BOOST_AUTO_TEST_CASE(TwoWaySend) + { + const size_t SEND_SIZE = 1 << 20; // 1 MB + + AsyncPhysTestObject t(LEV_INFO, false); + + t.mTCPServer.AsyncOpen(); + t.mTCPClient.AsyncOpen(); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); + BOOST_REQUIRE(t.ProceedUntil(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); + + //both layers are now up and reading, start them both writing + ByteStr bs(SEND_SIZE, 77); //give some interesting seed value to make sure bytes are correctly written + t.mClientUpper.SendDown(bs.Buffer(), bs.Size()); + t.mServerUpper.SendDown(bs.Buffer(), bs.Size()); + + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::SizeEquals, &t.mServerUpper, SEND_SIZE))); + BOOST_REQUIRE(t.ProceedUntil(boost::bind(&MockUpperLayer::SizeEquals, &t.mClientUpper, SEND_SIZE))); + + BOOST_REQUIRE(t.mClientUpper.BufferEquals(bs.Buffer(), bs.Size())); + BOOST_REQUIRE(t.mServerUpper.BufferEquals(bs.Buffer(), bs.Size())); + + t.mTCPServer.AsyncClose(); //stop one side + BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mServerUpper))); + BOOST_REQUIRE(t.ProceedUntilFalse(bind(&MockUpperLayer::IsLowerLayerUp, &t.mClientUpper))); + } + +#ifndef ARM + + BOOST_AUTO_TEST_CASE(Loopback) + { + EventLog logserver; + boost::asio::io_service loopservice; + TimerSourceASIO timer_src(&loopservice); + PhysicalLayerAsyncTCPServer server(logserver.GetLogger(LEV_INFO, "server"), &loopservice, 30000); + AsyncLoopback t(logserver.GetLogger(LEV_INFO, "loopback"), &server, &timer_src, LEV_WARNING, false); + IOServiceThread iost(&loopservice); + t.Start(); + iost.Start(); + + EventLog log; + Logger* logger = log.GetLogger(LEV_DEBUG, "client"); + AsyncTestObjectASIO test; + PhysicalLayerAsyncTCPClient client(logger, test.GetService(), "127.0.0.1", 30000); + LowerLayerToPhysAdapter adapter(logger, &client); + MockUpperLayer upper(logger); + adapter.SetUpperLayer(&upper); + + client.AsyncOpen(); + BOOST_REQUIRE(test.ProceedUntil(boost::bind(&MockUpperLayer::IsLowerLayerUp, &upper))); + + for(size_t i=0; i<1000; ++i) { + upper.SendDown("01 02 03"); + BOOST_REQUIRE(test.ProceedUntil(boost::bind(&MockUpperLayer::BufferEquals, &upper, "01 02 03"))); + BOOST_REQUIRE(test.ProceedUntil(boost::bind(&MockUpperLayer::CountersEqual, &upper, 1, 0))); + upper.ClearBuffer(); + upper.Reset(); + } + } + +#endif + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/TestAPL/TestQualityMasks.cpp b/TestAPL/TestQualityMasks.cpp index be617a72..97d0bedd 100644 --- a/TestAPL/TestQualityMasks.cpp +++ b/TestAPL/TestQualityMasks.cpp @@ -16,22 +16,22 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include - -BOOST_AUTO_TEST_SUITE(QualityMasks) - -BOOST_AUTO_TEST_CASE(ToString) - { - BOOST_REQUIRE_EQUAL(apl::BinaryQualToString(0), ""); - - BOOST_REQUIRE_NOT_EQUAL(apl::BinaryQualToString(~0).find("LocalForced"), std::string::npos); - BOOST_REQUIRE_NOT_EQUAL(apl::CounterQualToString(~0).find("CommLost"), std::string::npos); - BOOST_REQUIRE_NOT_EQUAL(apl::AnalogQualToString(~0).find("OverRange"), std::string::npos); - BOOST_REQUIRE_NOT_EQUAL(apl::ControlStatusQualToString(~0).find("Online"), std::string::npos); - BOOST_REQUIRE_NOT_EQUAL(apl::SetpointStatusQualToString(~0).find("Restart"), std::string::npos); - } - -BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include + +BOOST_AUTO_TEST_SUITE(QualityMasks) + +BOOST_AUTO_TEST_CASE(ToString) + { + BOOST_REQUIRE_EQUAL(apl::BinaryQualToString(0), ""); + + BOOST_REQUIRE_NOT_EQUAL(apl::BinaryQualToString(~0).find("LocalForced"), std::string::npos); + BOOST_REQUIRE_NOT_EQUAL(apl::CounterQualToString(~0).find("CommLost"), std::string::npos); + BOOST_REQUIRE_NOT_EQUAL(apl::AnalogQualToString(~0).find("OverRange"), std::string::npos); + BOOST_REQUIRE_NOT_EQUAL(apl::ControlStatusQualToString(~0).find("Online"), std::string::npos); + BOOST_REQUIRE_NOT_EQUAL(apl::SetpointStatusQualToString(~0).find("Restart"), std::string::npos); + } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestShiftableBuffer.cpp b/TestAPL/TestShiftableBuffer.cpp index f471ffe1..a405d71e 100644 --- a/TestAPL/TestShiftableBuffer.cpp +++ b/TestAPL/TestShiftableBuffer.cpp @@ -16,138 +16,138 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include - -using namespace apl; - - - - BOOST_AUTO_TEST_SUITE(ShiftableBufferSuite) - BOOST_AUTO_TEST_CASE(ConstructDestruct) - { - ShiftableBuffer b(100); - } - - BOOST_AUTO_TEST_CASE(InitialState) - { - ShiftableBuffer b(100); - - BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 0); - BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 100); - BOOST_REQUIRE_EQUAL(b.ReadBuff(), b.WriteBuff()); - - BOOST_REQUIRE_THROW(b.AdvanceWrite(101), ArgumentException); - BOOST_REQUIRE_THROW(b.AdvanceRead(1), ArgumentException); - } - - BOOST_AUTO_TEST_CASE(ReadingWriting) - { - ShiftableBuffer b(100); - - b.AdvanceWrite(40); - BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 60); - BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 40); - - b.AdvanceWrite(60); - BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 0); - BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 100); - - b.AdvanceRead(30); - BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 0); - BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 70); - - b.AdvanceRead(70); - BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 0); - BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 0); - } - - BOOST_AUTO_TEST_CASE(Shifting) - { - ShiftableBuffer b(100); - - //initialize buffer to all zeros - for(size_t i=0; i +#include + +#include +#include + +using namespace apl; + + + + BOOST_AUTO_TEST_SUITE(ShiftableBufferSuite) + BOOST_AUTO_TEST_CASE(ConstructDestruct) + { + ShiftableBuffer b(100); + } + + BOOST_AUTO_TEST_CASE(InitialState) + { + ShiftableBuffer b(100); + + BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 0); + BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 100); + BOOST_REQUIRE_EQUAL(b.ReadBuff(), b.WriteBuff()); + + BOOST_REQUIRE_THROW(b.AdvanceWrite(101), ArgumentException); + BOOST_REQUIRE_THROW(b.AdvanceRead(1), ArgumentException); + } + + BOOST_AUTO_TEST_CASE(ReadingWriting) + { + ShiftableBuffer b(100); + + b.AdvanceWrite(40); + BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 60); + BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 40); + + b.AdvanceWrite(60); + BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 0); + BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 100); + + b.AdvanceRead(30); + BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 0); + BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 70); + + b.AdvanceRead(70); + BOOST_REQUIRE_EQUAL(b.NumWriteBytes(), 0); + BOOST_REQUIRE_EQUAL(b.NumReadBytes(), 0); + } + + BOOST_AUTO_TEST_CASE(Shifting) + { + ShiftableBuffer b(100); + + //initialize buffer to all zeros + for(size_t i=0; i -#include - -#include -#include - -#include -#include -#include - -using namespace std; -using namespace apl; - - - - BOOST_AUTO_TEST_SUITE(SyncVarSuite) - BOOST_AUTO_TEST_CASE(TestStartupNoChange) - { - SyncVar val(0); - BOOST_REQUIRE_FALSE(val.ChangeSinceRead()); - } - - BOOST_AUTO_TEST_CASE(TestChange) - { - SyncVar val(0); - - val.Set(0); - BOOST_REQUIRE_FALSE(val.ChangeSinceRead()); - - val.Set(1); - BOOST_REQUIRE(val.ChangeSinceRead()); - - BOOST_REQUIRE_EQUAL(1, val.Get()); - BOOST_REQUIRE_FALSE(val.ChangeSinceRead()); - } - - BOOST_AUTO_TEST_CASE(TestNotification) - { - EventLock el; - Notifier n(4, &el); - SyncVar val(0); - val.AddObserver(&n); - - { - CriticalSection cs(&el); - el.GetEvents(); - } - - { - //This should not cause a deadlock b/c the SynvVar should not try to notify b/c the value doesn't change - CriticalSection cs(&el); - val.Set(0); - BOOST_REQUIRE_EQUAL(0, el.GetEvents()); - } - - val.Set(1); - - { - CriticalSection cs(&el); - BOOST_REQUIRE_EQUAL(4, el.GetEvents()); - BOOST_REQUIRE_EQUAL(0, el.GetEvents()); - } - } - - BOOST_AUTO_TEST_SUITE_END()//end suite - +#include +#include + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace apl; + + + + BOOST_AUTO_TEST_SUITE(SyncVarSuite) + BOOST_AUTO_TEST_CASE(TestStartupNoChange) + { + SyncVar val(0); + BOOST_REQUIRE_FALSE(val.ChangeSinceRead()); + } + + BOOST_AUTO_TEST_CASE(TestChange) + { + SyncVar val(0); + + val.Set(0); + BOOST_REQUIRE_FALSE(val.ChangeSinceRead()); + + val.Set(1); + BOOST_REQUIRE(val.ChangeSinceRead()); + + BOOST_REQUIRE_EQUAL(1, val.Get()); + BOOST_REQUIRE_FALSE(val.ChangeSinceRead()); + } + + BOOST_AUTO_TEST_CASE(TestNotification) + { + EventLock el; + Notifier n(4, &el); + SyncVar val(0); + val.AddObserver(&n); + + { + CriticalSection cs(&el); + el.GetEvents(); + } + + { + //This should not cause a deadlock b/c the SynvVar should not try to notify b/c the value doesn't change + CriticalSection cs(&el); + val.Set(0); + BOOST_REQUIRE_EQUAL(0, el.GetEvents()); + } + + val.Set(1); + + { + CriticalSection cs(&el); + BOOST_REQUIRE_EQUAL(4, el.GetEvents()); + BOOST_REQUIRE_EQUAL(0, el.GetEvents()); + } + } + + BOOST_AUTO_TEST_SUITE_END()//end suite + diff --git a/TestAPL/TestThreading.cpp b/TestAPL/TestThreading.cpp index 9fe16bf0..30e09ef7 100644 --- a/TestAPL/TestThreading.cpp +++ b/TestAPL/TestThreading.cpp @@ -16,268 +16,268 @@ // specific language governing permissions and limitations // under the License. // -#include -#include -#include -#include -#include - -using namespace std; - -#include -#include -#include -using namespace apl; - - - BOOST_AUTO_TEST_SUITE(OSSpecificTests) - class WaitOnLock : public Threadable{ - public: - WaitOnLock(SigLock* apCountLock , INotifier* apNotifier, Logger* apLogger, string aName): - mWaiting(false), mpNotifier(apNotifier), mpCount(apCountLock), mpLogger(apLogger), mThreadName(aName) - { - //auto start the thread. - mpThread = new Thread(this); - - mpThread->Start(); - //use the startLock to syncronize with the about to start thread. - mStartLock.Lock(); - //block until the thread has actually started - if(!mWaiting){ - mStartLock.Wait(); - } - mStartLock.Unlock(); - }; - ~WaitOnLock(){ - //shut the loop down. - mpThread->RequestStop(); - mpCount->Lock(); - while(mWaiting){ - mpCount->Broadcast(); - mpCount->TimedWait(50); - } - mpCount->Unlock(); - mpThread->WaitForStop(); - delete mpThread; - } - - std::string Description() const { return "WaitOnLock"; } - - void Run(){ - //while we aren't quitting wait on the lock and count ticks. - mpCount->Lock(); - //we use the startlock to make sure that this thread has gotten the count - //lock so we know that the order the threads make it into the Wait() call is - //the fifo order we expect - mStartLock.Lock(); - mWaiting = true; - mpLogger->Log(LEV_DEBUG,mThreadName,"About to wait"); - //rewake the constuctor - mStartLock.Signal(); - mStartLock.Unlock(); - while(!this->IsExitRequested()){ - //wait for notifies from the proxy, count them - mpCount->Wait(); - //mpLogger->Log(LEV_DEBUG,L_PHYSICAL,mThreadName,"Woken, signaling event"); - mpNotifier->Notify(); - } - //inform the destructor that the loop has died - mWaiting = false; - - //do one last notify to handle case where last thread got RequestThread after - //it had signaled but before it had gotten back to the wait condition. - mpNotifier->Notify(); - - - //unlock the main lock so other threads can exit - mpCount->Unlock(); - - }; - bool mWaiting; - //the event lock we use to notify the main thread that we have been woken - INotifier* mpNotifier; - //the "main" lock that we are going to wait on to verify FiFo behavior - SigLock* mpCount; - //an internal lock we use to make sure the thread is running before we return from the constuctor. - SigLock mStartLock; - Logger* mpLogger; - string mThreadName; - Thread* mpThread; - }; - void AddCount(int_64_t aEvent, int *aCounts, int aSlots){ - int_64_t m = 1; - int bit; - for(bit=0; bit < aSlots; bit++){ - if(aEvent == (m << bit))break; - } - BOOST_REQUIRE(bit != aSlots); - aCounts[bit]++; - } - bool CheckCount(int* aCounts, int aSlots, Logger* apLogger, bool aDisplay){ - int aMax=-1; - int aMin=100; - for(int i=0; i < aSlots; i++){ - if(aMax < aCounts[i]) aMax = aCounts[i]; - if(aMin > aCounts[i]) aMin = aCounts[i]; - } - if(aMax - aMin > 2 && aDisplay){ - ostringstream oss; - oss << "One Thread too far ahead Min = " << aMin << " max =" << aMax; - apLogger->Log(LEV_EVENT,"AddCount",oss.str()); - return false; - } - return true; - } - void TestFifoOrder(int numThreads, EventLog* apLog){ - //create a name for the error messages - ostringstream oss; - oss << "Fifo:" << numThreads; - string testName = oss.str(); - - bool notFifo = false; - //create the bit mask which is what the event counter should - //look like when all the threads have fired - int_64_t allThreadsMask = 1; - allThreadsMask = (allThreadsMask<Lock(); - ec->GetEvents(); //clear the default !0 - ec->Unlock(); - - Logger* pLogger = apLog->GetLogger(LEV_EVENT, "TestThreading"); - - std::vector threads; - int *counts = new int[numThreads]; - for(int i=0; i < numThreads; i++){ - //create a name for the thread - ostringstream oss; - oss << "Thread:" << i; - //create and start a new listening thread with the mask 1 << i - threads.push_back(new WaitOnLock(lock,ec->GetNotifier(EventLock::Get64BitMask(i)), apLog->GetLogger(LEV_WARNING, oss.str()),oss.str())); - //check that the thread is in the waiting state - BOOST_REQUIRE_EQUAL(threads[i]->mWaiting,true); - counts[i] = 0; - } - //lock the event counter - ec->Lock(); - //run through the entire order a few times to make sure the scheduling is fair - for(int i=0; i < numThreads*7; i++){ - //mod is the thread that should be getting fired this time. - int mod = i%numThreads; - - //make sure the event counter is empty - BOOST_REQUIRE_EQUAL(ec->GetEvents(),0); - pLogger->Log(LEV_DEBUG,testName,"Master about to Signal"); - //unlcok the event counter (so the other thread can get access) - ec->Unlock(); - //lock and signal the other thread (which means it will wake up and signal an event) - lock->Lock(); - lock->Signal(); - lock->Unlock(); - //relock the event counter and then get the ready events - ec->Lock(); - if(ec->GetEvents(false) == 0){ - //if there are no ready events wait until the signal happens that an event occured - ec->Wait(); - } - pLogger->Log(LEV_DEBUG,testName,"Master got woken"); - //calculate the mask the current thread should have. - int_64_t mask = EventLock::Get64BitMask(mod); - //get the value of the event counter. - int_64_t count = ec->GetEvents(); - AddCount(count, counts, numThreads); - //make sure we got what we expected - if(count != mask){ - ostringstream oss; - oss << mask << " Mask != count " << count << " iter =" << (i/numThreads) << " mod = " << mod; - pLogger->Log(LEV_DEBUG,testName,oss.str()); - notFifo = true; - } - if(mod == numThreads-1){ - CheckCount(counts, numThreads,pLogger,false); - } - } - //no longer asserting its FIFO since it isn't really FIFO when other things are happening - CheckCount(counts,numThreads,pLogger,true); - //unlock the event counter so the threads can shut quickly - ec->Unlock(); - - pLogger->Log(LEV_DEBUG,testName,"StoppingAll"); - for(int i=0; i < numThreads; i++){ - //set all the threads to have: Threadable::mIsExitRequested set to true - threads[i]->mpThread->RequestStop(); - } - - //make sure none of our threads have quit early - ec->Lock(); - BOOST_REQUIRE_EQUAL( ec->GetEvents(false),0); - ec->Unlock(); - - pLogger->Log(LEV_DEBUG,testName,"Broadcast"); - //wake up all the threads, they will all signal an event as they terminate - lock->Lock(); - lock->Broadcast(); - lock->Unlock(); - //delete all the threads (also blocks until they all complete) - for(size_t i=0; i < threads.size(); i++){ - delete (threads)[i]; - } - //make sure that all the threads have quit - ec->Lock(); - BOOST_REQUIRE_EQUAL( ec->GetEvents(false),allThreadsMask); - ec->Unlock(); - - //cleanup, if there were any threads waiting on these locks this would fail - delete lock; - delete ec; - delete[] counts; - } - - BOOST_AUTO_TEST_CASE(FifoOnLocks5) - { - EventLog log; - TestFifoOrder(5, &log); - } - BOOST_AUTO_TEST_CASE(FifoOnLocks15) - { - EventLog log; - TestFifoOrder(15, &log); - } - BOOST_AUTO_TEST_CASE(FifoOnLocks63) - { - EventLog log; - TestFifoOrder(63, &log); - } - - void AssuredSleep(int millis){ - StopWatch t; - Thread::SleepFor(millis,true); - BOOST_REQUIRE(t.Elapsed() >= millis); - } - BOOST_AUTO_TEST_CASE(EnsuredSleepFor) - { - AssuredSleep(1); - AssuredSleep(2); - AssuredSleep(9); - AssuredSleep(100); //added this b/c it would have yielded ridiculous results on Linux when there was a bug - } - - /*//test is deprecated, proper shutdown will ensure this doesn't happen, - BOOST_AUTO_TEST_CASE(DestructionWhileBeingWaitedOn) - { - MAKE_LOG(); - Lock* lock = new Lock(); - EventLock* ec = new EventLock(); - WaitOnLock thread(lock,new EventLock(ec,1),apLogger,"test"); - // will cause assertion failure, can't do it! - // delete lock; - CLEAN_LOG(); - - } - */ - BOOST_AUTO_TEST_SUITE_END() +#include +#include +#include +#include +#include + +using namespace std; + +#include +#include +#include +using namespace apl; + + + BOOST_AUTO_TEST_SUITE(OSSpecificTests) + class WaitOnLock : public Threadable{ + public: + WaitOnLock(SigLock* apCountLock , INotifier* apNotifier, Logger* apLogger, string aName): + mWaiting(false), mpNotifier(apNotifier), mpCount(apCountLock), mpLogger(apLogger), mThreadName(aName) + { + //auto start the thread. + mpThread = new Thread(this); + + mpThread->Start(); + //use the startLock to syncronize with the about to start thread. + mStartLock.Lock(); + //block until the thread has actually started + if(!mWaiting){ + mStartLock.Wait(); + } + mStartLock.Unlock(); + }; + ~WaitOnLock(){ + //shut the loop down. + mpThread->RequestStop(); + mpCount->Lock(); + while(mWaiting){ + mpCount->Broadcast(); + mpCount->TimedWait(50); + } + mpCount->Unlock(); + mpThread->WaitForStop(); + delete mpThread; + } + + std::string Description() const { return "WaitOnLock"; } + + void Run(){ + //while we aren't quitting wait on the lock and count ticks. + mpCount->Lock(); + //we use the startlock to make sure that this thread has gotten the count + //lock so we know that the order the threads make it into the Wait() call is + //the fifo order we expect + mStartLock.Lock(); + mWaiting = true; + mpLogger->Log(LEV_DEBUG,mThreadName,"About to wait"); + //rewake the constuctor + mStartLock.Signal(); + mStartLock.Unlock(); + while(!this->IsExitRequested()){ + //wait for notifies from the proxy, count them + mpCount->Wait(); + //mpLogger->Log(LEV_DEBUG,L_PHYSICAL,mThreadName,"Woken, signaling event"); + mpNotifier->Notify(); + } + //inform the destructor that the loop has died + mWaiting = false; + + //do one last notify to handle case where last thread got RequestThread after + //it had signaled but before it had gotten back to the wait condition. + mpNotifier->Notify(); + + + //unlock the main lock so other threads can exit + mpCount->Unlock(); + + }; + bool mWaiting; + //the event lock we use to notify the main thread that we have been woken + INotifier* mpNotifier; + //the "main" lock that we are going to wait on to verify FiFo behavior + SigLock* mpCount; + //an internal lock we use to make sure the thread is running before we return from the constuctor. + SigLock mStartLock; + Logger* mpLogger; + string mThreadName; + Thread* mpThread; + }; + void AddCount(int_64_t aEvent, int *aCounts, int aSlots){ + int_64_t m = 1; + int bit; + for(bit=0; bit < aSlots; bit++){ + if(aEvent == (m << bit))break; + } + BOOST_REQUIRE(bit != aSlots); + aCounts[bit]++; + } + bool CheckCount(int* aCounts, int aSlots, Logger* apLogger, bool aDisplay){ + int aMax=-1; + int aMin=100; + for(int i=0; i < aSlots; i++){ + if(aMax < aCounts[i]) aMax = aCounts[i]; + if(aMin > aCounts[i]) aMin = aCounts[i]; + } + if(aMax - aMin > 2 && aDisplay){ + ostringstream oss; + oss << "One Thread too far ahead Min = " << aMin << " max =" << aMax; + apLogger->Log(LEV_EVENT,"AddCount",oss.str()); + return false; + } + return true; + } + void TestFifoOrder(int numThreads, EventLog* apLog){ + //create a name for the error messages + ostringstream oss; + oss << "Fifo:" << numThreads; + string testName = oss.str(); + + bool notFifo = false; + //create the bit mask which is what the event counter should + //look like when all the threads have fired + int_64_t allThreadsMask = 1; + allThreadsMask = (allThreadsMask<Lock(); + ec->GetEvents(); //clear the default !0 + ec->Unlock(); + + Logger* pLogger = apLog->GetLogger(LEV_EVENT, "TestThreading"); + + std::vector threads; + int *counts = new int[numThreads]; + for(int i=0; i < numThreads; i++){ + //create a name for the thread + ostringstream oss; + oss << "Thread:" << i; + //create and start a new listening thread with the mask 1 << i + threads.push_back(new WaitOnLock(lock,ec->GetNotifier(EventLock::Get64BitMask(i)), apLog->GetLogger(LEV_WARNING, oss.str()),oss.str())); + //check that the thread is in the waiting state + BOOST_REQUIRE_EQUAL(threads[i]->mWaiting,true); + counts[i] = 0; + } + //lock the event counter + ec->Lock(); + //run through the entire order a few times to make sure the scheduling is fair + for(int i=0; i < numThreads*7; i++){ + //mod is the thread that should be getting fired this time. + int mod = i%numThreads; + + //make sure the event counter is empty + BOOST_REQUIRE_EQUAL(ec->GetEvents(),0); + pLogger->Log(LEV_DEBUG,testName,"Master about to Signal"); + //unlcok the event counter (so the other thread can get access) + ec->Unlock(); + //lock and signal the other thread (which means it will wake up and signal an event) + lock->Lock(); + lock->Signal(); + lock->Unlock(); + //relock the event counter and then get the ready events + ec->Lock(); + if(ec->GetEvents(false) == 0){ + //if there are no ready events wait until the signal happens that an event occured + ec->Wait(); + } + pLogger->Log(LEV_DEBUG,testName,"Master got woken"); + //calculate the mask the current thread should have. + int_64_t mask = EventLock::Get64BitMask(mod); + //get the value of the event counter. + int_64_t count = ec->GetEvents(); + AddCount(count, counts, numThreads); + //make sure we got what we expected + if(count != mask){ + ostringstream oss; + oss << mask << " Mask != count " << count << " iter =" << (i/numThreads) << " mod = " << mod; + pLogger->Log(LEV_DEBUG,testName,oss.str()); + notFifo = true; + } + if(mod == numThreads-1){ + CheckCount(counts, numThreads,pLogger,false); + } + } + //no longer asserting its FIFO since it isn't really FIFO when other things are happening + CheckCount(counts,numThreads,pLogger,true); + //unlock the event counter so the threads can shut quickly + ec->Unlock(); + + pLogger->Log(LEV_DEBUG,testName,"StoppingAll"); + for(int i=0; i < numThreads; i++){ + //set all the threads to have: Threadable::mIsExitRequested set to true + threads[i]->mpThread->RequestStop(); + } + + //make sure none of our threads have quit early + ec->Lock(); + BOOST_REQUIRE_EQUAL( ec->GetEvents(false),0); + ec->Unlock(); + + pLogger->Log(LEV_DEBUG,testName,"Broadcast"); + //wake up all the threads, they will all signal an event as they terminate + lock->Lock(); + lock->Broadcast(); + lock->Unlock(); + //delete all the threads (also blocks until they all complete) + for(size_t i=0; i < threads.size(); i++){ + delete (threads)[i]; + } + //make sure that all the threads have quit + ec->Lock(); + BOOST_REQUIRE_EQUAL( ec->GetEvents(false),allThreadsMask); + ec->Unlock(); + + //cleanup, if there were any threads waiting on these locks this would fail + delete lock; + delete ec; + delete[] counts; + } + + BOOST_AUTO_TEST_CASE(FifoOnLocks5) + { + EventLog log; + TestFifoOrder(5, &log); + } + BOOST_AUTO_TEST_CASE(FifoOnLocks15) + { + EventLog log; + TestFifoOrder(15, &log); + } + BOOST_AUTO_TEST_CASE(FifoOnLocks63) + { + EventLog log; + TestFifoOrder(63, &log); + } + + void AssuredSleep(int millis){ + StopWatch t; + Thread::SleepFor(millis,true); + BOOST_REQUIRE(t.Elapsed() >= millis); + } + BOOST_AUTO_TEST_CASE(EnsuredSleepFor) + { + AssuredSleep(1); + AssuredSleep(2); + AssuredSleep(9); + AssuredSleep(100); //added this b/c it would have yielded ridiculous results on Linux when there was a bug + } + + /*//test is deprecated, proper shutdown will ensure this doesn't happen, + BOOST_AUTO_TEST_CASE(DestructionWhileBeingWaitedOn) + { + MAKE_LOG(); + Lock* lock = new Lock(); + EventLock* ec = new EventLock(); + WaitOnLock thread(lock,new EventLock(ec,1),apLogger,"test"); + // will cause assertion failure, can't do it! + // delete lock; + CLEAN_LOG(); + + } + */ + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestTime.cpp b/TestAPL/TestTime.cpp index de645219..13a540ef 100644 --- a/TestAPL/TestTime.cpp +++ b/TestAPL/TestTime.cpp @@ -16,315 +16,315 @@ // specific language governing permissions and limitations // under the License. // -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - - -#include -#include -#include - -using namespace std; -using namespace apl; - - - BOOST_AUTO_TEST_SUITE(TimeTest) - BOOST_AUTO_TEST_CASE(CustomPTimeToString) - { - ptime t = time_from_string("2008-07-01 12:00:00.100"); - string out = ToNormalizedString(t); - string expected("2008-Jul-01 12:00:00.100"); - - BOOST_REQUIRE_EQUAL(out, expected); - - t = time_from_string("2008-07-01 2:01:27.000"); - out = ToNormalizedString(t); - expected = "2008-Jul-01 02:01:27.000"; - - BOOST_REQUIRE_EQUAL(out, expected); - } - - BOOST_AUTO_TEST_CASE(Sleep) - { - int sleeps[4] = {25,50,75,100}; - - for(int i=0; i< 4; i++) - { - Time start; - Thread::SleepFor(sleeps[i]+10,true); - Time end; - - millis_t interval = Time::CalcDeltaMS(end, start); - - //std::cout << "Start: " << start.GetTimeString() << endl; - //std::cout << "End: " << end.GetTimeString() << endl; - //std::cout << interval << std::endl; - BOOST_REQUIRE(interval >= sleeps[i]); - } - } - - BOOST_AUTO_TEST_CASE(TimeConstruction) - { - for(int i=0; i<1000; i++) - Time t; - } - - BOOST_AUTO_TEST_CASE(ReadSystemTime) - { - Time t; //default value is NOW - int sleepTime = 2000; - Thread::SleepFor(sleepTime,true); //let's sleep for a few seconds - int_64_t elapsed = t.GetElapsedMS(); //now let's verify that close to this amount of time has elapsed - - BOOST_REQUIRE(elapsed >= sleepTime); - } - BOOST_AUTO_TEST_CASE(CheckInstantElapsed) - { - Time t; - - int_64_t diff = t.GetElapsedMS(); - - BOOST_REQUIRE_EQUAL( diff , 0 ); - } - BOOST_AUTO_TEST_CASE(CheckMonotononicallyIncreasing) - { - //check that subsequent calls to GetElapsed() allways return increasing numbers - Time t; - int_64_t lastElapsed = t.GetElapsedMS(); - int_64_t elapsed; - - for(int i =0; i < 200; i++){ - for(int j=0; j < 1000; j++){ - elapsed = t.GetElapsedMS(); - if(elapsed < lastElapsed){ - ostringstream oss; - oss << "Time Elapsed didn't increase " << elapsed << " < " << lastElapsed; - std::cout << oss.str() << std::endl; - BOOST_REQUIRE(elapsed >= lastElapsed); - }else{ - lastElapsed = elapsed; - } - } - } - } - - BOOST_AUTO_TEST_CASE(SetTime) - { - Time t; - int_64_t time = t.GetValueMS(); - t.SetTo(t.GetValueMS()+5000); //set to five seconds in the future - - time = t.GetValueMS() - time; - - BOOST_REQUIRE_EQUAL(time, 5000); - } - - BOOST_AUTO_TEST_CASE(AddTime) - { - Time t; - int_64_t time = t.GetValueMS(); - t.AddMS(5000); - - time = t.GetValueMS() - time; - - BOOST_REQUIRE_EQUAL(time, 5000); - } - - BOOST_AUTO_TEST_CASE(Operators) - { - Time t1(1000); - Time t2(900); - - BOOST_REQUIRE(t2 < t1); - BOOST_REQUIRE( !(t1= t2 ); - - BOOST_REQUIRE(t1 == t1); - BOOST_REQUIRE(t2 == t2); - BOOST_REQUIRE(t1 <= t1); - BOOST_REQUIRE(t2 <= t2); - BOOST_REQUIRE(t1 >= t1); - BOOST_REQUIRE(t2 >= t2); - - } - - BOOST_AUTO_TEST_CASE(MaxMin) - { - Time tmin = Time::Min; - Time tmax = Time::Max; - - BOOST_REQUIRE(tmin < tmax); - BOOST_REQUIRE(tmax > tmin); - BOOST_REQUIRE(tmin <= tmax); - BOOST_REQUIRE(tmax >= tmin); - BOOST_REQUIRE( !(tmin == tmax) ); - BOOST_REQUIRE(tmin == tmin); - BOOST_REQUIRE(tmax == tmax); - } - BOOST_AUTO_TEST_SUITE_END() - - BOOST_AUTO_TEST_SUITE(TimeoutTests) - BOOST_AUTO_TEST_CASE(AllParams){ - //create a timeout of 1 millisecond - Timeout to(1); - - //check that the timeout starts out unexpired - BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); - BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); - - //sleep for atleast 1 milli - Thread::SleepFor(1, true); - - //make sure that it is still unexpired since we have overridden - //the "UpdateTimeout" to false which means it won't believe it - //has expired even though enough time has passed - BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); - BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); - - //once we call IsExpired(true) it will update its remaining time - //and therefore think it is expired - BOOST_REQUIRE_EQUAL(to.IsExpired(true), true); - BOOST_REQUIRE_EQUAL(to.Remaining(false), 0); - - //we will reset the timeout to another millisecond - to.Reset(1); - - //check that the reset worked and its unexpired - BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); - BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); - - //sleep long enough to trip the state - Thread::SleepFor(1, true); - - //check that its symettric if we call to.Remaing(true) it - //will return 0 and isexpired will return true - BOOST_REQUIRE_EQUAL(to.Remaining(true), 0); - BOOST_REQUIRE_EQUAL(to.IsExpired(false), true); - } - - BOOST_AUTO_TEST_CASE(DefaultArguments){ - //create a timeout of 1 millisecond - Timeout to(1); - - //check that its not expired - BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); - BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); - - //sleep for a mill - Thread::SleepFor(1, true); - - //check that the remaining still says 1 - BOOST_REQUIRE_EQUAL(to.Remaining(), 1); - - //check that once we ask if it is expired it tells us we are and have no time remaining. - BOOST_REQUIRE_EQUAL(to.IsExpired(), true); - BOOST_REQUIRE_EQUAL(to.Remaining(), 0); - } - - BOOST_AUTO_TEST_CASE(ExampleLoop){ - StopWatch t; - Timeout to(250); - - do{ - Thread::SleepFor(rand()%to.Remaining()); - }while(!to.IsExpired()); - - BOOST_REQUIRE(t.Elapsed() >= 250); - } - - BOOST_AUTO_TEST_SUITE_END() - - BOOST_AUTO_TEST_SUITE(StopWatchTests) - - BOOST_AUTO_TEST_CASE(BasicTest){ - StopWatch sw; - - //show that the stopwatch start at 0 (may be 1 almost instantly in current implementation) - BOOST_REQUIRE(sw.Elapsed(false) <= 1); - - //sleep for 5 millis - Thread::SleepFor(5, true); - - //make sure the stopwatch recorded atleast 5 millis elapsed (override default bool) - BOOST_REQUIRE(sw.Elapsed(false) >= 5); - - //check that the value wasn't reset and that if aReset==true the next call restarts - //the stopwatch - BOOST_REQUIRE(sw.Elapsed(true) >= 5); - BOOST_REQUIRE(sw.Elapsed(false) <= 1); - - //sleep again - Thread::SleepFor(5, true); - - //check that the elapsed time is correct - BOOST_REQUIRE(sw.Elapsed(false) >= 5); - - //restart the stopwatch and make sure that the elapsed time gets back to 0 - sw.Restart(); - BOOST_REQUIRE(sw.Elapsed(false) <= 1); - } - - BOOST_AUTO_TEST_CASE(ExampleUsage){ - StopWatch sw; - Thread::SleepFor(5); //should take 5 mills but may take less - millis_t sleep1 = sw.Elapsed(); //automatic restart of stopwatch (like a split) - Thread::SleepFor(5, true); //will take atleast 5 mills - millis_t sleep2 = sw.Elapsed(); //should be around 5 millis - BOOST_REQUIRE(sleep1 >= 0); - BOOST_REQUIRE(sleep2 >= 0); - } - - BOOST_AUTO_TEST_SUITE_END() - - BOOST_AUTO_TEST_SUITE(TimeStampTests) - BOOST_AUTO_TEST_CASE(TimeStampOperations){ - //get current time stamp - TimeStamp_t now = TimeStamp::GetTimeStamp(); - - //get a timestamp for 2 milliseconds in the future - TimeStamp_t laterGuess = TimeStamp::GetTimeStamp(2); - - //actually sleep for 2 milliseconds - Thread::SleepFor(2,true); - - //get another timestamp - TimeStamp_t later = TimeStamp::GetTimeStamp(); - - //check that it is a difference of 2 milliseconds from our original stamp - millis_t difference = later - now; - BOOST_REQUIRE(difference >= 2); - - //check that is equal to our "future" stamp - millis_t difference2 = laterGuess - later; - BOOST_REQUIRE(difference > difference2); - } - - BOOST_AUTO_TEST_SUITE_END() - - BOOST_AUTO_TEST_SUITE(TimeManagerTests) - BOOST_AUTO_TEST_CASE(TimeSourceSystemOffsetTest) { - - TimeSourceSystemOffset time; - millis_t base = time.GetTime(); - time.SetTime(base+5000); - BOOST_REQUIRE(time.GetTime() >= base+5000); - } - BOOST_AUTO_TEST_CASE(TimeSourceSystemOffsetTestNeg) { - - TimeSourceSystemOffset time; - millis_t base = time.GetTime(); - time.SetTime(base-5000); - BOOST_REQUIRE(time.GetTime() >= base-5000); - } - BOOST_AUTO_TEST_SUITE_END() +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +#include +#include +#include + +using namespace std; +using namespace apl; + + + BOOST_AUTO_TEST_SUITE(TimeTest) + BOOST_AUTO_TEST_CASE(CustomPTimeToString) + { + ptime t = time_from_string("2008-07-01 12:00:00.100"); + string out = ToNormalizedString(t); + string expected("2008-Jul-01 12:00:00.100"); + + BOOST_REQUIRE_EQUAL(out, expected); + + t = time_from_string("2008-07-01 2:01:27.000"); + out = ToNormalizedString(t); + expected = "2008-Jul-01 02:01:27.000"; + + BOOST_REQUIRE_EQUAL(out, expected); + } + + BOOST_AUTO_TEST_CASE(Sleep) + { + int sleeps[4] = {25,50,75,100}; + + for(int i=0; i< 4; i++) + { + Time start; + Thread::SleepFor(sleeps[i]+10,true); + Time end; + + millis_t interval = Time::CalcDeltaMS(end, start); + + //std::cout << "Start: " << start.GetTimeString() << endl; + //std::cout << "End: " << end.GetTimeString() << endl; + //std::cout << interval << std::endl; + BOOST_REQUIRE(interval >= sleeps[i]); + } + } + + BOOST_AUTO_TEST_CASE(TimeConstruction) + { + for(int i=0; i<1000; i++) + Time t; + } + + BOOST_AUTO_TEST_CASE(ReadSystemTime) + { + Time t; //default value is NOW + int sleepTime = 2000; + Thread::SleepFor(sleepTime,true); //let's sleep for a few seconds + int_64_t elapsed = t.GetElapsedMS(); //now let's verify that close to this amount of time has elapsed + + BOOST_REQUIRE(elapsed >= sleepTime); + } + BOOST_AUTO_TEST_CASE(CheckInstantElapsed) + { + Time t; + + int_64_t diff = t.GetElapsedMS(); + + BOOST_REQUIRE_EQUAL( diff , 0 ); + } + BOOST_AUTO_TEST_CASE(CheckMonotononicallyIncreasing) + { + //check that subsequent calls to GetElapsed() allways return increasing numbers + Time t; + int_64_t lastElapsed = t.GetElapsedMS(); + int_64_t elapsed; + + for(int i =0; i < 200; i++){ + for(int j=0; j < 1000; j++){ + elapsed = t.GetElapsedMS(); + if(elapsed < lastElapsed){ + ostringstream oss; + oss << "Time Elapsed didn't increase " << elapsed << " < " << lastElapsed; + std::cout << oss.str() << std::endl; + BOOST_REQUIRE(elapsed >= lastElapsed); + }else{ + lastElapsed = elapsed; + } + } + } + } + + BOOST_AUTO_TEST_CASE(SetTime) + { + Time t; + int_64_t time = t.GetValueMS(); + t.SetTo(t.GetValueMS()+5000); //set to five seconds in the future + + time = t.GetValueMS() - time; + + BOOST_REQUIRE_EQUAL(time, 5000); + } + + BOOST_AUTO_TEST_CASE(AddTime) + { + Time t; + int_64_t time = t.GetValueMS(); + t.AddMS(5000); + + time = t.GetValueMS() - time; + + BOOST_REQUIRE_EQUAL(time, 5000); + } + + BOOST_AUTO_TEST_CASE(Operators) + { + Time t1(1000); + Time t2(900); + + BOOST_REQUIRE(t2 < t1); + BOOST_REQUIRE( !(t1= t2 ); + + BOOST_REQUIRE(t1 == t1); + BOOST_REQUIRE(t2 == t2); + BOOST_REQUIRE(t1 <= t1); + BOOST_REQUIRE(t2 <= t2); + BOOST_REQUIRE(t1 >= t1); + BOOST_REQUIRE(t2 >= t2); + + } + + BOOST_AUTO_TEST_CASE(MaxMin) + { + Time tmin = Time::Min; + Time tmax = Time::Max; + + BOOST_REQUIRE(tmin < tmax); + BOOST_REQUIRE(tmax > tmin); + BOOST_REQUIRE(tmin <= tmax); + BOOST_REQUIRE(tmax >= tmin); + BOOST_REQUIRE( !(tmin == tmax) ); + BOOST_REQUIRE(tmin == tmin); + BOOST_REQUIRE(tmax == tmax); + } + BOOST_AUTO_TEST_SUITE_END() + + BOOST_AUTO_TEST_SUITE(TimeoutTests) + BOOST_AUTO_TEST_CASE(AllParams){ + //create a timeout of 1 millisecond + Timeout to(1); + + //check that the timeout starts out unexpired + BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); + BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); + + //sleep for atleast 1 milli + Thread::SleepFor(1, true); + + //make sure that it is still unexpired since we have overridden + //the "UpdateTimeout" to false which means it won't believe it + //has expired even though enough time has passed + BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); + BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); + + //once we call IsExpired(true) it will update its remaining time + //and therefore think it is expired + BOOST_REQUIRE_EQUAL(to.IsExpired(true), true); + BOOST_REQUIRE_EQUAL(to.Remaining(false), 0); + + //we will reset the timeout to another millisecond + to.Reset(1); + + //check that the reset worked and its unexpired + BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); + BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); + + //sleep long enough to trip the state + Thread::SleepFor(1, true); + + //check that its symettric if we call to.Remaing(true) it + //will return 0 and isexpired will return true + BOOST_REQUIRE_EQUAL(to.Remaining(true), 0); + BOOST_REQUIRE_EQUAL(to.IsExpired(false), true); + } + + BOOST_AUTO_TEST_CASE(DefaultArguments){ + //create a timeout of 1 millisecond + Timeout to(1); + + //check that its not expired + BOOST_REQUIRE_EQUAL(to.IsExpired(false), false); + BOOST_REQUIRE_EQUAL(to.Remaining(false), 1); + + //sleep for a mill + Thread::SleepFor(1, true); + + //check that the remaining still says 1 + BOOST_REQUIRE_EQUAL(to.Remaining(), 1); + + //check that once we ask if it is expired it tells us we are and have no time remaining. + BOOST_REQUIRE_EQUAL(to.IsExpired(), true); + BOOST_REQUIRE_EQUAL(to.Remaining(), 0); + } + + BOOST_AUTO_TEST_CASE(ExampleLoop){ + StopWatch t; + Timeout to(250); + + do{ + Thread::SleepFor(rand()%to.Remaining()); + }while(!to.IsExpired()); + + BOOST_REQUIRE(t.Elapsed() >= 250); + } + + BOOST_AUTO_TEST_SUITE_END() + + BOOST_AUTO_TEST_SUITE(StopWatchTests) + + BOOST_AUTO_TEST_CASE(BasicTest){ + StopWatch sw; + + //show that the stopwatch start at 0 (may be 1 almost instantly in current implementation) + BOOST_REQUIRE(sw.Elapsed(false) <= 1); + + //sleep for 5 millis + Thread::SleepFor(5, true); + + //make sure the stopwatch recorded atleast 5 millis elapsed (override default bool) + BOOST_REQUIRE(sw.Elapsed(false) >= 5); + + //check that the value wasn't reset and that if aReset==true the next call restarts + //the stopwatch + BOOST_REQUIRE(sw.Elapsed(true) >= 5); + BOOST_REQUIRE(sw.Elapsed(false) <= 1); + + //sleep again + Thread::SleepFor(5, true); + + //check that the elapsed time is correct + BOOST_REQUIRE(sw.Elapsed(false) >= 5); + + //restart the stopwatch and make sure that the elapsed time gets back to 0 + sw.Restart(); + BOOST_REQUIRE(sw.Elapsed(false) <= 1); + } + + BOOST_AUTO_TEST_CASE(ExampleUsage){ + StopWatch sw; + Thread::SleepFor(5); //should take 5 mills but may take less + millis_t sleep1 = sw.Elapsed(); //automatic restart of stopwatch (like a split) + Thread::SleepFor(5, true); //will take atleast 5 mills + millis_t sleep2 = sw.Elapsed(); //should be around 5 millis + BOOST_REQUIRE(sleep1 >= 0); + BOOST_REQUIRE(sleep2 >= 0); + } + + BOOST_AUTO_TEST_SUITE_END() + + BOOST_AUTO_TEST_SUITE(TimeStampTests) + BOOST_AUTO_TEST_CASE(TimeStampOperations){ + //get current time stamp + TimeStamp_t now = TimeStamp::GetTimeStamp(); + + //get a timestamp for 2 milliseconds in the future + TimeStamp_t laterGuess = TimeStamp::GetTimeStamp(2); + + //actually sleep for 2 milliseconds + Thread::SleepFor(2,true); + + //get another timestamp + TimeStamp_t later = TimeStamp::GetTimeStamp(); + + //check that it is a difference of 2 milliseconds from our original stamp + millis_t difference = later - now; + BOOST_REQUIRE(difference >= 2); + + //check that is equal to our "future" stamp + millis_t difference2 = laterGuess - later; + BOOST_REQUIRE(difference > difference2); + } + + BOOST_AUTO_TEST_SUITE_END() + + BOOST_AUTO_TEST_SUITE(TimeManagerTests) + BOOST_AUTO_TEST_CASE(TimeSourceSystemOffsetTest) { + + TimeSourceSystemOffset time; + millis_t base = time.GetTime(); + time.SetTime(base+5000); + BOOST_REQUIRE(time.GetTime() >= base+5000); + } + BOOST_AUTO_TEST_CASE(TimeSourceSystemOffsetTestNeg) { + + TimeSourceSystemOffset time; + millis_t base = time.GetTime(); + time.SetTime(base-5000); + BOOST_REQUIRE(time.GetTime() >= base-5000); + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestTimers.cpp b/TestAPL/TestTimers.cpp index 366780a0..2e656cbd 100644 --- a/TestAPL/TestTimers.cpp +++ b/TestAPL/TestTimers.cpp @@ -16,134 +16,134 @@ // specific language governing permissions and limitations // under the License. // -#include -#include -#include - - -#include -#include -#include - -#include -#include - -using namespace std; -using namespace apl; - - - class MockTimerHandler - { - public: - MockTimerHandler() : mCount(0) - {} - - void OnExpiration() { ++mCount; } - size_t GetCount() { return mCount; } - - private: - size_t mCount; - }; - - class MonotonicReceiver : private Threadable - { - public: - MonotonicReceiver(boost::asio::io_service* apSrv) : - mLast(-1), - mNum(0), - mMonotonic(true), - mpSrv(apSrv), - mThread(this) - {} - - void Receive(int aVal) { - if(aVal <= mLast) mMonotonic = false; - ++mNum; - mLast = aVal; - } - - bool IsMonotonic() { return mMonotonic; } - int Num() { return mNum; } - - void Start() { mThread.Start(); } - void Stop() { mThread.WaitForStop(); } - - private: - - int mLast; - int mNum; - bool mMonotonic; - - boost::asio::io_service* mpSrv; - - void Run() { mpSrv->run(); } - - Thread mThread; - }; - - BOOST_AUTO_TEST_SUITE(Timers) - BOOST_AUTO_TEST_CASE(TestOrderedDispatch) - { - const int NUM = 10000; - - boost::asio::io_service srv; - TimerSourceASIO ts(&srv); - MonotonicReceiver rcv(&srv); - - for(int i=0; iCancel(); - BOOST_REQUIRE_EQUAL(1, srv.run_one()); - BOOST_REQUIRE_EQUAL(0, mth.GetCount()); - ITimer* pT2 = ts.Start(1, boost::bind(&MockTimerHandler::OnExpiration, &mth)); - BOOST_REQUIRE_EQUAL(pT1, pT2); - } - - - BOOST_AUTO_TEST_CASE(MultipleOutstanding) - { - MockTimerHandler mth1; - MockTimerHandler mth2; - boost::asio::io_service srv; - TimerSourceASIO ts(&srv); - ITimer* pT1 = ts.Start(0, boost::bind(&MockTimerHandler::OnExpiration, &mth1)); - ITimer* pT2 = ts.Start(100, boost::bind(&MockTimerHandler::OnExpiration, &mth2)); - - BOOST_REQUIRE_NOT_EQUAL(pT1, pT2); - - BOOST_REQUIRE_EQUAL(1, srv.run_one()); - BOOST_REQUIRE_EQUAL(1, mth1.GetCount()); - BOOST_REQUIRE_EQUAL(0, mth2.GetCount()); - - BOOST_REQUIRE_EQUAL(1, srv.run_one()); - BOOST_REQUIRE_EQUAL(1, mth1.GetCount()); - BOOST_REQUIRE_EQUAL(1, mth2.GetCount()); - } - - BOOST_AUTO_TEST_SUITE_END() +#include +#include +#include + + +#include +#include +#include + +#include +#include + +using namespace std; +using namespace apl; + + + class MockTimerHandler + { + public: + MockTimerHandler() : mCount(0) + {} + + void OnExpiration() { ++mCount; } + size_t GetCount() { return mCount; } + + private: + size_t mCount; + }; + + class MonotonicReceiver : private Threadable + { + public: + MonotonicReceiver(boost::asio::io_service* apSrv) : + mLast(-1), + mNum(0), + mMonotonic(true), + mpSrv(apSrv), + mThread(this) + {} + + void Receive(int aVal) { + if(aVal <= mLast) mMonotonic = false; + ++mNum; + mLast = aVal; + } + + bool IsMonotonic() { return mMonotonic; } + int Num() { return mNum; } + + void Start() { mThread.Start(); } + void Stop() { mThread.WaitForStop(); } + + private: + + int mLast; + int mNum; + bool mMonotonic; + + boost::asio::io_service* mpSrv; + + void Run() { mpSrv->run(); } + + Thread mThread; + }; + + BOOST_AUTO_TEST_SUITE(Timers) + BOOST_AUTO_TEST_CASE(TestOrderedDispatch) + { + const int NUM = 10000; + + boost::asio::io_service srv; + TimerSourceASIO ts(&srv); + MonotonicReceiver rcv(&srv); + + for(int i=0; iCancel(); + BOOST_REQUIRE_EQUAL(1, srv.run_one()); + BOOST_REQUIRE_EQUAL(0, mth.GetCount()); + ITimer* pT2 = ts.Start(1, boost::bind(&MockTimerHandler::OnExpiration, &mth)); + BOOST_REQUIRE_EQUAL(pT1, pT2); + } + + + BOOST_AUTO_TEST_CASE(MultipleOutstanding) + { + MockTimerHandler mth1; + MockTimerHandler mth2; + boost::asio::io_service srv; + TimerSourceASIO ts(&srv); + ITimer* pT1 = ts.Start(0, boost::bind(&MockTimerHandler::OnExpiration, &mth1)); + ITimer* pT2 = ts.Start(100, boost::bind(&MockTimerHandler::OnExpiration, &mth2)); + + BOOST_REQUIRE_NOT_EQUAL(pT1, pT2); + + BOOST_REQUIRE_EQUAL(1, srv.run_one()); + BOOST_REQUIRE_EQUAL(1, mth1.GetCount()); + BOOST_REQUIRE_EQUAL(0, mth2.GetCount()); + + BOOST_REQUIRE_EQUAL(1, srv.run_one()); + BOOST_REQUIRE_EQUAL(1, mth1.GetCount()); + BOOST_REQUIRE_EQUAL(1, mth2.GetCount()); + } + + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestTypes.cpp b/TestAPL/TestTypes.cpp index 5f1cc3fa..3e73894a 100644 --- a/TestAPL/TestTypes.cpp +++ b/TestAPL/TestTypes.cpp @@ -16,52 +16,52 @@ // specific language governing permissions and limitations // under the License. // -#define BOOST_TEST_MODULE apl -#include - -#include -#include - -using namespace std; -using namespace apl; - -#undef max -#undef min - -template -void TestType(T min, T max, size_t aBytes) -{ - BOOST_CHECK_EQUAL(sizeof(T), aBytes); - - T val = min; - T limit = numeric_limits::min(); - BOOST_CHECK_EQUAL(val, limit); - - val = max; - limit = numeric_limits::max(); - BOOST_CHECK_EQUAL(val, limit); -} - -BOOST_AUTO_TEST_SUITE(TestTypes) - - BOOST_AUTO_TEST_CASE( UByte ) - { - TestType(0,255,1); - } - - BOOST_AUTO_TEST_CASE( Int16 ) - { TestType(-32768, 32767, 2); } - - BOOST_AUTO_TEST_CASE( UInt16 ) - { TestType(0,65535,2); } - - BOOST_AUTO_TEST_CASE( Int32 ) - { TestType(0x80000000, 2147483647L, 4); } - - BOOST_AUTO_TEST_CASE( UInt32 ) - { TestType(0, 4294967295UL, 4); } - - BOOST_AUTO_TEST_CASE( Int64) - { TestType(0x8000000000000000LL, 9223372036854775807LL, 8); } - -BOOST_AUTO_TEST_SUITE_END() +#define BOOST_TEST_MODULE apl +#include + +#include +#include + +using namespace std; +using namespace apl; + +#undef max +#undef min + +template +void TestType(T min, T max, size_t aBytes) +{ + BOOST_CHECK_EQUAL(sizeof(T), aBytes); + + T val = min; + T limit = numeric_limits::min(); + BOOST_CHECK_EQUAL(val, limit); + + val = max; + limit = numeric_limits::max(); + BOOST_CHECK_EQUAL(val, limit); +} + +BOOST_AUTO_TEST_SUITE(TestTypes) + + BOOST_AUTO_TEST_CASE( UByte ) + { + TestType(0,255,1); + } + + BOOST_AUTO_TEST_CASE( Int16 ) + { TestType(-32768, 32767, 2); } + + BOOST_AUTO_TEST_CASE( UInt16 ) + { TestType(0,65535,2); } + + BOOST_AUTO_TEST_CASE( Int32 ) + { TestType(0x80000000, 2147483647L, 4); } + + BOOST_AUTO_TEST_CASE( UInt32 ) + { TestType(0, 4294967295UL, 4); } + + BOOST_AUTO_TEST_CASE( Int64) + { TestType(0x8000000000000000LL, 9223372036854775807LL, 8); } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestUtil.cpp b/TestAPL/TestUtil.cpp index b27ff8f9..605bb97c 100644 --- a/TestAPL/TestUtil.cpp +++ b/TestAPL/TestUtil.cpp @@ -16,65 +16,65 @@ // specific language governing permissions and limitations // under the License. // -#include -#include - -#include -#include - -using namespace std; -using namespace apl; - - - BOOST_AUTO_TEST_SUITE(UtilSuite) - template - void TestHex(const std::string& aHex, byte_t* aCompareBytes, size_t aCount) - { - HexSequence hs(aHex); - - BOOST_REQUIRE(hs.Size() <= N); - - BOOST_REQUIRE_EQUAL(hs.Size(), aCount ); - for ( size_t i = 0; i < aCount; i++ ) - BOOST_REQUIRE_EQUAL(hs[i], aCompareBytes[i]); - } - - BOOST_AUTO_TEST_CASE(HexToBytes2TestSmall) - { - byte_t values[] = { 0xAF, 0x23 }; - TestHex<2>( "AF23", values, 2 ); - } - BOOST_AUTO_TEST_CASE(HexToBytes2Test64) - { - byte_t values[] = { 0x13, 0xA2, 0x00, 0x40, 0x56, 0x1D, 0x08 }; - TestHex<7>( "13A20040561D08", values, 7 ); - } - - BOOST_AUTO_TEST_CASE(HexToBytes2Test64TooBig) - { - byte_t values[] = { 0x13, 0xA2, 0x00, 0x40, 0x56, 0x1D, 0x08 }; - TestHex<8>( "13A20040561D08", values, 7 ); - } - - - BOOST_AUTO_TEST_CASE(HexToBytes2Test64Hole) - { - byte_t values[] = { 0x13, 0xA2, 0x00, 0x40, 0x56, 0x1D, 0x08 }; - TestHex<8>( "13A200 40561 D08", values, 7 ); - } - - /* - BOOST_AUTO_TEST_CASE(HexToUInt64) - { - uint_64_t val = apl::HexToUInt64( "13A20040561D08" ); - BOOST_REQUIRE_EQUAL( val, 5526146520587528ULL ); - } - - BOOST_AUTO_TEST_CASE(HexToUInt64null) - { - uint_64_t val = apl::HexToUInt64( "" ); - BOOST_REQUIRE_EQUAL( val, 0 ); - } - */ - - BOOST_AUTO_TEST_SUITE_END() +#include +#include + +#include +#include + +using namespace std; +using namespace apl; + + + BOOST_AUTO_TEST_SUITE(UtilSuite) + template + void TestHex(const std::string& aHex, byte_t* aCompareBytes, size_t aCount) + { + HexSequence hs(aHex); + + BOOST_REQUIRE(hs.Size() <= N); + + BOOST_REQUIRE_EQUAL(hs.Size(), aCount ); + for ( size_t i = 0; i < aCount; i++ ) + BOOST_REQUIRE_EQUAL(hs[i], aCompareBytes[i]); + } + + BOOST_AUTO_TEST_CASE(HexToBytes2TestSmall) + { + byte_t values[] = { 0xAF, 0x23 }; + TestHex<2>( "AF23", values, 2 ); + } + BOOST_AUTO_TEST_CASE(HexToBytes2Test64) + { + byte_t values[] = { 0x13, 0xA2, 0x00, 0x40, 0x56, 0x1D, 0x08 }; + TestHex<7>( "13A20040561D08", values, 7 ); + } + + BOOST_AUTO_TEST_CASE(HexToBytes2Test64TooBig) + { + byte_t values[] = { 0x13, 0xA2, 0x00, 0x40, 0x56, 0x1D, 0x08 }; + TestHex<8>( "13A20040561D08", values, 7 ); + } + + + BOOST_AUTO_TEST_CASE(HexToBytes2Test64Hole) + { + byte_t values[] = { 0x13, 0xA2, 0x00, 0x40, 0x56, 0x1D, 0x08 }; + TestHex<8>( "13A200 40561 D08", values, 7 ); + } + + /* + BOOST_AUTO_TEST_CASE(HexToUInt64) + { + uint_64_t val = apl::HexToUInt64( "13A20040561D08" ); + BOOST_REQUIRE_EQUAL( val, 5526146520587528ULL ); + } + + BOOST_AUTO_TEST_CASE(HexToUInt64null) + { + uint_64_t val = apl::HexToUInt64( "" ); + BOOST_REQUIRE_EQUAL( val, 0 ); + } + */ + + BOOST_AUTO_TEST_SUITE_END() diff --git a/TestAPL/TestXmlBinding.cpp b/TestAPL/TestXmlBinding.cpp index aca660d8..f397df56 100644 --- a/TestAPL/TestXmlBinding.cpp +++ b/TestAPL/TestXmlBinding.cpp @@ -16,117 +16,117 @@ // specific language governing permissions and limitations // under the License. // -#include - - -#include -#include -#include -#include -#include -#include - -using namespace apl; - - -BOOST_AUTO_TEST_SUITE(XmlTests) - - - BOOST_AUTO_TEST_CASE(ParseInt){ - TiXmlElement testNode("Test"); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "100"), 100); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "123456789"), 123456789); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "-100"), -100); - - //dont do implit casting to int - BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, "-1.00"), apl::Exception); - //dont read a string as int - BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, "abcasdasd"), apl::Exception); - //empty string where an int should fail - BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, ""), apl::Exception); - - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "2147483647"), 2147483647); - BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, "2147483648"), apl::Exception); - } - BOOST_AUTO_TEST_CASE(WriteInt){ - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_int(100), "100"); - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_int(-1), "-1"); - } - BOOST_AUTO_TEST_CASE(ParseBool){ - TiXmlElement testNode("Test"); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_bool(&testNode, "true"), true); - //can only use "true" and "false" any other casing is an error. - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "TRUE"), apl::Exception); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "True"), apl::Exception); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "tRue"), apl::Exception); - - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_bool(&testNode, "false"), false); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "FALSE"), apl::Exception); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "False"), apl::Exception); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "faLse"), apl::Exception); - - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "0"), apl::Exception); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "1"), apl::Exception); - BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, ""), apl::Exception); - } - BOOST_AUTO_TEST_CASE(WriteBool){ - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_bool(true), "true"); - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_bool(false), "false"); - } - BOOST_AUTO_TEST_CASE(ParseDouble){ - TiXmlElement testNode("Test"); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "100"), 100); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "3.1456"), 3.1456); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100."), -100); - - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0e-7"), -1.0e-5); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0E-7"), -1.0e-5); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "2147483648"), 2147483648UL); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0E4"), -1.0e6); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0E+4"), -1.0e6); - } - BOOST_AUTO_TEST_CASE(WriteDouble){ - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_double(55), "55"); - } - BOOST_AUTO_TEST_CASE(ParseString){ - TiXmlElement testNode("Test"); - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_string(&testNode, "qwertyuiop"), "qwertyuiop"); - - //consider an empty string to be a valid string - BOOST_CHECK_EQUAL(IXMLDataBound::FromString_string(&testNode, ""), ""); - } - BOOST_AUTO_TEST_CASE(WriteString){ - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_string("qwertyuiop"), "qwertyuiop"); - BOOST_CHECK_EQUAL(IXMLDataBound::ToString_string(""), ""); - } - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(SingleNodeSuite) - - BOOST_AUTO_TEST_CASE(SaveAndLoad){ - EventLog log; - SingleNodeSaver s("TestSingle.tiny.xml", log.GetLogger(LEV_DEBUG, "SingleNode")); - APLXML_Base::TCPServer_t node; - - node.Name = "HelloWorld"; - node.Port = 1000; - - BOOST_CHECK(s.SaveNode(node)); - - APLXML_Base::TCPServer_t node2; - BOOST_CHECK(s.LoadNode(node2)); - - BOOST_CHECK_EQUAL(node2.Name, "HelloWorld"); - BOOST_CHECK_EQUAL(node2.Port, 1000); - } - BOOST_AUTO_TEST_CASE(LoadFails){ - EventLog log; - SingleNodeSaver s("TestSingleFailure.tiny.xml", log.GetLogger(LEV_DEBUG, "SingleNode")); - APLXML_Base::Serial_t node; - - BOOST_CHECK_EQUAL(s.LoadNode(node), false); - } - -BOOST_AUTO_TEST_SUITE_END() - +#include + + +#include +#include +#include +#include +#include +#include + +using namespace apl; + + +BOOST_AUTO_TEST_SUITE(XmlTests) + + + BOOST_AUTO_TEST_CASE(ParseInt){ + TiXmlElement testNode("Test"); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "100"), 100); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "123456789"), 123456789); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "-100"), -100); + + //dont do implit casting to int + BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, "-1.00"), apl::Exception); + //dont read a string as int + BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, "abcasdasd"), apl::Exception); + //empty string where an int should fail + BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, ""), apl::Exception); + + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_int(&testNode, "2147483647"), 2147483647); + BOOST_CHECK_THROW(IXMLDataBound::FromString_int(&testNode, "2147483648"), apl::Exception); + } + BOOST_AUTO_TEST_CASE(WriteInt){ + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_int(100), "100"); + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_int(-1), "-1"); + } + BOOST_AUTO_TEST_CASE(ParseBool){ + TiXmlElement testNode("Test"); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_bool(&testNode, "true"), true); + //can only use "true" and "false" any other casing is an error. + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "TRUE"), apl::Exception); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "True"), apl::Exception); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "tRue"), apl::Exception); + + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_bool(&testNode, "false"), false); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "FALSE"), apl::Exception); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "False"), apl::Exception); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "faLse"), apl::Exception); + + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "0"), apl::Exception); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, "1"), apl::Exception); + BOOST_CHECK_THROW(IXMLDataBound::FromString_bool(&testNode, ""), apl::Exception); + } + BOOST_AUTO_TEST_CASE(WriteBool){ + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_bool(true), "true"); + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_bool(false), "false"); + } + BOOST_AUTO_TEST_CASE(ParseDouble){ + TiXmlElement testNode("Test"); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "100"), 100); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "3.1456"), 3.1456); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100."), -100); + + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0e-7"), -1.0e-5); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0E-7"), -1.0e-5); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "2147483648"), 2147483648UL); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0E4"), -1.0e6); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_double(&testNode, "-100.0E+4"), -1.0e6); + } + BOOST_AUTO_TEST_CASE(WriteDouble){ + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_double(55), "55"); + } + BOOST_AUTO_TEST_CASE(ParseString){ + TiXmlElement testNode("Test"); + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_string(&testNode, "qwertyuiop"), "qwertyuiop"); + + //consider an empty string to be a valid string + BOOST_CHECK_EQUAL(IXMLDataBound::FromString_string(&testNode, ""), ""); + } + BOOST_AUTO_TEST_CASE(WriteString){ + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_string("qwertyuiop"), "qwertyuiop"); + BOOST_CHECK_EQUAL(IXMLDataBound::ToString_string(""), ""); + } + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(SingleNodeSuite) + + BOOST_AUTO_TEST_CASE(SaveAndLoad){ + EventLog log; + SingleNodeSaver s("TestSingle.tiny.xml", log.GetLogger(LEV_DEBUG, "SingleNode")); + APLXML_Base::TCPServer_t node; + + node.Name = "HelloWorld"; + node.Port = 1000; + + BOOST_CHECK(s.SaveNode(node)); + + APLXML_Base::TCPServer_t node2; + BOOST_CHECK(s.LoadNode(node2)); + + BOOST_CHECK_EQUAL(node2.Name, "HelloWorld"); + BOOST_CHECK_EQUAL(node2.Port, 1000); + } + BOOST_AUTO_TEST_CASE(LoadFails){ + EventLog log; + SingleNodeSaver s("TestSingleFailure.tiny.xml", log.GetLogger(LEV_DEBUG, "SingleNode")); + APLXML_Base::Serial_t node; + + BOOST_CHECK_EQUAL(s.LoadNode(node), false); + } + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/TestAPL/rake.project.rb b/TestAPL/rake.project.rb index e00b3c49..919d941c 100644 --- a/TestAPL/rake.project.rb +++ b/TestAPL/rake.project.rb @@ -16,10 +16,10 @@ # specific language governing permissions and limitations # under the License. # - -$options = { -:target => 'testapl.exe', -:project_libs => [:xmlbindings, :tinyxml, :aplxml, :apltesttools, :apl], -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -:libs => Boost::get_static_libs + $PLATFORM_LIBS -} + +$options = { +:target => 'testapl.exe', +:project_libs => [:xmlbindings, :tinyxml, :aplxml, :apltesttools, :apl], +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +:libs => Boost::get_static_libs + $PLATFORM_LIBS +} diff --git a/TestSet/StackHelpers.cpp b/TestSet/StackHelpers.cpp index 1c3c9d91..b7c080ae 100644 --- a/TestSet/StackHelpers.cpp +++ b/TestSet/StackHelpers.cpp @@ -16,76 +16,76 @@ // specific language governing permissions and limitations // under the License. // -#include "StackHelpers.h" - -#include -#include -#include - -#include -#include -#include - -#include - -using namespace APLXML_Base; - -namespace apl { namespace dnp { - -IPhysicalLayerAsync* FGetTerminalPhys(Logger* apLogger, boost::asio::io_service* apSrv, bool aRemote, apl::uint_16_t aRemotePort) -{ - if (aRemote) return PhysicalLayerFactory::FGetTCPServerAsync(aRemotePort, apSrv, apLogger); - else return new PhysicalLayerIOStreamAsync(apLogger, apSrv); -} - -StackBase::StackBase(const APLXML_Base::PhysicalLayerList_t& arList, FilterLevel aLevel, const std::string& arLogFile, bool aRemote, apl::uint_16_t aRemotePort) : - log(), - logToFile(&log, arLogFile), - pTermLogger(log.GetLogger(aLevel, "terminal")), - mService(), - mTermThread(mService.Get()), - mTimerSrc(mService.Get()), - pTermPhys(FGetTerminalPhys(pTermLogger, mTermThread.GetService(), aRemote, aRemotePort)), - lte(&log), - trm(pTermLogger, pTermPhys.get(), &mTimerSrc, "Test Set Terminal (DNP)", true), - mgr(log.GetLogger(aLevel, "dnp")) -{ - trm.AddExtension(<e); - XmlToConfig::Configure(arList, aLevel, mgr); -} - -void StackBase::Run() { - mgr.Start(); - trm.Init(); - mTermThread.Run(); //blocking - - mTermThread.Stop(); -} - - -SlaveXMLStack::SlaveXMLStack(APLXML_STS::SlaveTestSet_t* pCfg, FilterLevel aLevel) : - StackBase(pCfg->PhysicalLayerList, aLevel, pCfg->LogFile, pCfg->Remote, pCfg->RemotePort), +#include "StackHelpers.h" + +#include +#include +#include + +#include +#include +#include + +#include + +using namespace APLXML_Base; + +namespace apl { namespace dnp { + +IPhysicalLayerAsync* FGetTerminalPhys(Logger* apLogger, boost::asio::io_service* apSrv, bool aRemote, apl::uint_16_t aRemotePort) +{ + if (aRemote) return PhysicalLayerFactory::FGetTCPServerAsync(aRemotePort, apSrv, apLogger); + else return new PhysicalLayerIOStreamAsync(apLogger, apSrv); +} + +StackBase::StackBase(const APLXML_Base::PhysicalLayerList_t& arList, FilterLevel aLevel, const std::string& arLogFile, bool aRemote, apl::uint_16_t aRemotePort) : + log(), + logToFile(&log, arLogFile), + pTermLogger(log.GetLogger(aLevel, "terminal")), + mService(), + mTermThread(mService.Get()), + mTimerSrc(mService.Get()), + pTermPhys(FGetTerminalPhys(pTermLogger, mTermThread.GetService(), aRemote, aRemotePort)), + lte(&log), + trm(pTermLogger, pTermPhys.get(), &mTimerSrc, "Test Set Terminal (DNP)", true), + mgr(log.GetLogger(aLevel, "dnp")) +{ + trm.AddExtension(<e); + XmlToConfig::Configure(arList, aLevel, mgr); +} + +void StackBase::Run() { + mgr.Start(); + trm.Init(); + mTermThread.Run(); //blocking + + mTermThread.Stop(); +} + + +SlaveXMLStack::SlaveXMLStack(APLXML_STS::SlaveTestSet_t* pCfg, FilterLevel aLevel) : + StackBase(pCfg->PhysicalLayerList, aLevel, pCfg->LogFile, pCfg->Remote, pCfg->RemotePort), pObs(mgr.AddSlave(pCfg->PhysicalLayer, "sts", aLevel, crte.GetCmdAcceptor(), XmlToConfig::GetSlaveConfig(pCfg->Slave, pCfg->DeviceTemplate, pCfg->StartOnline))), - crte(log.GetLogger(LEV_INTERPRET, "Incoming Controls"), pCfg->LinkCommandStatus, pObs), - dote(pObs) -{ - trm.AddExtension(&dote); - trm.AddExtension(&crte); -} - - -MasterXMLStack::MasterXMLStack(APLXML_MTS::MasterTestSet_t* pCfg, FilterLevel aLevel) : -StackBase(pCfg->PhysicalLayerList, aLevel, pCfg->LogFile), -fdo(), -accept(mgr.AddMaster(pCfg->PhysicalLayer, "mts", aLevel, &fdo, XmlToConfig::GetMasterConfig(pCfg->Master))), -cte(accept), -fte(&fdo) -{ - trm.AddExtension(&fte); - trm.AddExtension(&cte); -} - - - -}} - + crte(log.GetLogger(LEV_INTERPRET, "Incoming Controls"), pCfg->LinkCommandStatus, pObs), + dote(pObs) +{ + trm.AddExtension(&dote); + trm.AddExtension(&crte); +} + + +MasterXMLStack::MasterXMLStack(APLXML_MTS::MasterTestSet_t* pCfg, FilterLevel aLevel) : +StackBase(pCfg->PhysicalLayerList, aLevel, pCfg->LogFile), +fdo(), +accept(mgr.AddMaster(pCfg->PhysicalLayer, "mts", aLevel, &fdo, XmlToConfig::GetMasterConfig(pCfg->Master))), +cte(accept), +fte(&fdo) +{ + trm.AddExtension(&fte); + trm.AddExtension(&cte); +} + + + +}} + diff --git a/TestSet/StackHelpers.h b/TestSet/StackHelpers.h index 9b367c5c..911804fd 100644 --- a/TestSet/StackHelpers.h +++ b/TestSet/StackHelpers.h @@ -1,4 +1,4 @@ -// +// // Licensed to Green Energy Corp (www.greenenergycorp.com) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information @@ -6,97 +6,97 @@ // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// -#ifndef __STACK_HELPERS_H_ -#define __STACK_HELPERS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -namespace apl { namespace dnp { - -class StackBase -{ -public: - StackBase(const APLXML_Base::PhysicalLayerList_t&, FilterLevel aLevel, const std::string& arLogFile = "-", bool aRemote = false, apl::uint_16_t aRemotePort = 4998); - - void Run(); - -protected: - - EventLog log; - LogToFile logToFile; - Logger* pTermLogger; - - IOService mService; - IOServiceThread mTermThread; - TimerSourceASIO mTimerSrc; - auto_ptr pTermPhys; - - LogTerminalExtension lte; - - Terminal trm; - AsyncStackManager mgr; - -}; - -class SlaveXMLStack : public StackBase -{ -public: - SlaveXMLStack(APLXML_STS::SlaveTestSet_t* pCfg, FilterLevel aLevel); - - IDataObserver* GetDataObs() { return pObs; } - -private: - - IDataObserver* pObs; - ControlResponseTE crte; - DOTerminalExtension dote; -}; - -class MasterXMLStack : public StackBase -{ -public: - MasterXMLStack(APLXML_MTS::MasterTestSet_t* pCfg, FilterLevel aLevel); - - ICommandAcceptor* GetCmdAcceptor() { return accept; } - -private: - FlexibleDataObserver fdo; - ICommandAcceptor* accept; - ControlTerminalExtension cte; - FlexibleObserverTerminalExtension fte; -}; - - -}} - -#endif +// +#ifndef __STACK_HELPERS_H_ +#define __STACK_HELPERS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace apl { namespace dnp { + +class StackBase +{ +public: + StackBase(const APLXML_Base::PhysicalLayerList_t&, FilterLevel aLevel, const std::string& arLogFile = "-", bool aRemote = false, apl::uint_16_t aRemotePort = 4998); + + void Run(); + +protected: + + EventLog log; + LogToFile logToFile; + Logger* pTermLogger; + + IOService mService; + IOServiceThread mTermThread; + TimerSourceASIO mTimerSrc; + auto_ptr pTermPhys; + + LogTerminalExtension lte; + + Terminal trm; + AsyncStackManager mgr; + +}; + +class SlaveXMLStack : public StackBase +{ +public: + SlaveXMLStack(APLXML_STS::SlaveTestSet_t* pCfg, FilterLevel aLevel); + + IDataObserver* GetDataObs() { return pObs; } + +private: + + IDataObserver* pObs; + ControlResponseTE crte; + DOTerminalExtension dote; +}; + +class MasterXMLStack : public StackBase +{ +public: + MasterXMLStack(APLXML_MTS::MasterTestSet_t* pCfg, FilterLevel aLevel); + + ICommandAcceptor* GetCmdAcceptor() { return accept; } + +private: + FlexibleDataObserver fdo; + ICommandAcceptor* accept; + ControlTerminalExtension cte; + FlexibleObserverTerminalExtension fte; +}; + + +}} + +#endif diff --git a/TestSet/TestSet.vcproj b/TestSet/TestSet.vcproj index bd361cf2..30fc315b 100755 --- a/TestSet/TestSet.vcproj +++ b/TestSet/TestSet.vcproj @@ -1,226 +1,226 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestSet/rake.project.rb b/TestSet/rake.project.rb index c9bd6ed2..eebf702b 100644 --- a/TestSet/rake.project.rb +++ b/TestSet/rake.project.rb @@ -16,10 +16,10 @@ # specific language governing permissions and limitations # under the License. # - -$options = { -:target => 'testset.exe', -:project_libs => [:terminal, :xmlbindings, :dnp3xml, :dnp3, :tinyxml, :aplxml, :apl], -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], -:libs => Boost::get_static_libs + $PLATFORM_LIBS -} + +$options = { +:target => 'testset.exe', +:project_libs => [:terminal, :xmlbindings, :dnp3xml, :dnp3, :tinyxml, :aplxml, :apl], +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES], +:libs => Boost::get_static_libs + $PLATFORM_LIBS +} diff --git a/TestSet/tmw_test.rb b/TestSet/tmw_test.rb index ffc9f593..aa97aef1 100644 --- a/TestSet/tmw_test.rb +++ b/TestSet/tmw_test.rb @@ -16,57 +16,57 @@ # specific language governing permissions and limitations # under the License. # - -require 'rexml/document' -include REXML - -return -1 unless ARGV.count >= 7 - -s_confirms = ARGV[0] -app_conf_timeout = ARGV[1] -unsol_allowed = ARGV[2] -unsol_retry_period = ARGV[3] -unsol_offline_delay = ARGV[4] -tx_frag_size = ARGV[5] -self_address = ARGV[6] - -test_msg = ARGV[7] if ARGV.count >= 8 -test_msg ||= "" - -#puts "SCONFIRMS: " + s_confirms -#puts "APPCONFTIMEOUT: " + app_conf_timeout -#puts "UNSOLALLOWED: " + unsol_allowed -#puts "UNSOLRETRYPER: " + unsol_retry_period -#puts "UNSOLOFFLINEDELAY: " + unsol_offline_delay -#puts "TXFRAGSIZE: " + tx_frag_size -#puts "SELFADDRESS: " + self_address -#puts "Test: " + test_msg - - -file = File.open("C:\\code\\DNP\\TestSet\\tmw_template.xml") -doc = Document.new file - -doc.elements.each("//LinkLayer") do |link| - link.attributes["UseConfirmations"] = (s_confirms == "always") ? "true" : "false" -end - -doc.elements.each("//AppLayer") do |app| - app.attributes["ConfTimeoutMS"] = app_conf_timeout > unsol_retry_period ? app_conf_timeout : unsol_retry_period - app.attributes["MaxFragmentSize"] = tx_frag_size -end - -doc.elements.each("//UnsolDefaults") do |app| - app.attributes["UnsolEnabled"] = unsol_allowed - #app.attributes["DoClass1"] = unsol_allowed - #app.attributes["DoClass2"] = unsol_allowed - #app.attributes["DoClass3"] = unsol_allowed - app.attributes["RetryMS"] = 0 -end - -filename = "C:/code/DNP/TestSet/temp_slave.xml" -outfile = File.new(filename, "w+") -doc.write outfile -outfile.close - -puts filename - + +require 'rexml/document' +include REXML + +return -1 unless ARGV.count >= 7 + +s_confirms = ARGV[0] +app_conf_timeout = ARGV[1] +unsol_allowed = ARGV[2] +unsol_retry_period = ARGV[3] +unsol_offline_delay = ARGV[4] +tx_frag_size = ARGV[5] +self_address = ARGV[6] + +test_msg = ARGV[7] if ARGV.count >= 8 +test_msg ||= "" + +#puts "SCONFIRMS: " + s_confirms +#puts "APPCONFTIMEOUT: " + app_conf_timeout +#puts "UNSOLALLOWED: " + unsol_allowed +#puts "UNSOLRETRYPER: " + unsol_retry_period +#puts "UNSOLOFFLINEDELAY: " + unsol_offline_delay +#puts "TXFRAGSIZE: " + tx_frag_size +#puts "SELFADDRESS: " + self_address +#puts "Test: " + test_msg + + +file = File.open("C:\\code\\DNP\\TestSet\\tmw_template.xml") +doc = Document.new file + +doc.elements.each("//LinkLayer") do |link| + link.attributes["UseConfirmations"] = (s_confirms == "always") ? "true" : "false" +end + +doc.elements.each("//AppLayer") do |app| + app.attributes["ConfTimeoutMS"] = app_conf_timeout > unsol_retry_period ? app_conf_timeout : unsol_retry_period + app.attributes["MaxFragmentSize"] = tx_frag_size +end + +doc.elements.each("//UnsolDefaults") do |app| + app.attributes["UnsolEnabled"] = unsol_allowed + #app.attributes["DoClass1"] = unsol_allowed + #app.attributes["DoClass2"] = unsol_allowed + #app.attributes["DoClass3"] = unsol_allowed + app.attributes["RetryMS"] = 0 +end + +filename = "C:/code/DNP/TestSet/temp_slave.xml" +outfile = File.new(filename, "w+") +doc.write outfile +outfile.close + +puts filename + diff --git a/TestSetInstaller/TestSetInstaller.vdproj b/TestSetInstaller/TestSetInstaller.vdproj index 957d5acf..c727fbd3 100755 --- a/TestSetInstaller/TestSetInstaller.vdproj +++ b/TestSetInstaller/TestSetInstaller.vdproj @@ -1,961 +1,961 @@ -"DeployProject" -{ -"VSVersion" = "3:800" -"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}" -"IsWebType" = "8:FALSE" -"ProjectName" = "8:TestSetInstaller" -"LanguageId" = "3:1033" -"CodePage" = "3:1252" -"UILanguageId" = "3:1033" -"SccProjectName" = "8:" -"SccLocalPath" = "8:" -"SccAuxPath" = "8:" -"SccProvider" = "8:" - "Hierarchy" - { - "Entry" - { - "MsmKey" = "8:_06639457B6034CBBBA61FF62C542015A" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_26684E6E2AE44D038E2A3EEF56421EB0" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_515D6B07AD824454B6DDFD3AD33D108E" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_5EDC4D3604BB4DB29C7408531072F8C9" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_6A312EAB7E9140DC81E3439C767051CA" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_81D00EDA021FC53443A8A4E552FBC39E" - "OwnerKey" = "8:_6A312EAB7E9140DC81E3439C767051CA" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - } - "Configurations" - { - "Debug" - { - "DisplayName" = "8:Debug" - "IsDebugOnly" = "11:TRUE" - "IsReleaseOnly" = "11:FALSE" - "OutputFilename" = "8:Debug\\TestSetInstaller.msi" - "PackageFilesAs" = "3:2" - "PackageFileSize" = "3:-2147483648" - "CabType" = "3:1" - "Compression" = "3:2" - "SignOutput" = "11:FALSE" - "CertificateFile" = "8:" - "PrivateKeyFile" = "8:" - "TimeStampServer" = "8:" - "InstallerBootstrapper" = "3:2" - "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" - { - "Enabled" = "11:TRUE" - "PromptEnabled" = "11:TRUE" - "PrerequisitesLocation" = "2:1" - "Url" = "8:" - "ComponentsUrl" = "8:" - "Items" - { - } - } - } - "Release" - { - "DisplayName" = "8:Release" - "IsDebugOnly" = "11:FALSE" - "IsReleaseOnly" = "11:TRUE" - "OutputFilename" = "8:Release\\TestSetInstaller.msi" - "PackageFilesAs" = "3:2" - "PackageFileSize" = "3:-2147483648" - "CabType" = "3:1" - "Compression" = "3:2" - "SignOutput" = "11:FALSE" - "CertificateFile" = "8:" - "PrivateKeyFile" = "8:" - "TimeStampServer" = "8:" - "InstallerBootstrapper" = "3:2" - "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" - { - "Enabled" = "11:TRUE" - "PromptEnabled" = "11:TRUE" - "PrerequisitesLocation" = "2:1" - "Url" = "8:" - "ComponentsUrl" = "8:" - "Items" - { - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.2.0" - { - "Name" = "8:.NET Framework 2.0" - "ProductCode" = "8:Microsoft.Net.Framework.2.0" - } - "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Visual.C++.8.0.x86" - { - "Name" = "8:Visual C++ Runtime Libraries (x86)" - "ProductCode" = "8:Microsoft.Visual.C++.8.0.x86" - } - } - } - } - } - "Deployable" - { - "CustomAction" - { - } - "DefaultFeature" - { - "Name" = "8:DefaultFeature" - "Title" = "8:" - "Description" = "8:" - } - "ExternalPersistence" - { - "LaunchCondition" - { - } - } - "File" - { - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_06639457B6034CBBBA61FF62C542015A" - { - "SourcePath" = "8:icons\\square_dnp_48.ico" - "TargetName" = "8:square_dnp_48.ico" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - } - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_26684E6E2AE44D038E2A3EEF56421EB0" - { - "SourcePath" = "8:icons\\square_dnp_16.ico" - "TargetName" = "8:square_dnp_16.ico" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - } - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_515D6B07AD824454B6DDFD3AD33D108E" - { - "SourcePath" = "8:icons\\square_dnp_32.ico" - "TargetName" = "8:square_dnp_32.ico" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - } - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5EDC4D3604BB4DB29C7408531072F8C9" - { - "SourcePath" = "8:EULA.rtf" - "TargetName" = "8:EULA.rtf" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - } - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_81D00EDA021FC53443A8A4E552FBC39E" - { - "SourcePath" = "8:MSWSOCK.dll" - "TargetName" = "8:MSWSOCK.dll" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:TRUE" - "IsDependency" = "11:TRUE" - "IsolateTo" = "8:" - } - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_96C0F18DB7814CE0834AADB9EA6D5317" - { - "SourcePath" = "8:icons\\dnp_banner.bmp" - "TargetName" = "8:dnp_banner.bmp" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - } - } - "FileType" - { - } - "Folder" - { - "{1525181F-901A-416C-8A58-119130FE478E}:_8F841B0A78D146FBB45B22F00219430A" - { - "Name" = "8:#1916" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:DesktopFolder" - "Folders" - { - } - } - "{3C67513D-01DD-4637-8A68-80971EB9504F}:_9C472356ABDA4F198CFB74D8416F04A0" - { - "DefaultLocation" = "8:[ProgramFilesFolder]\\dnp3" - "Name" = "8:#1925" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:TARGETDIR" - "Folders" - { - } - } - "{1525181F-901A-416C-8A58-119130FE478E}:_A632BDD9E7B1465FBA07B58404E70B73" - { - "Name" = "8:#1919" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:ProgramMenuFolder" - "Folders" - { - "{9EF0B969-E518-4E46-987F-47570745A589}:_314E7AD011F54D158D9A53847B2F7C24" - { - "Name" = "8:DNP3" - "AlwaysCreate" = "11:FALSE" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Property" = "8:_DD8FD499F42E4F688B3243499993E326" - "Folders" - { - } - } - } - } - } - "LaunchCondition" - { - } - "Locator" - { - } - "MsiBootstrapper" - { - "LangId" = "3:1033" - } - "Product" - { - "Name" = "8:Microsoft Visual Studio" - "ProductName" = "8:DNP3 Test Set" - "ProductCode" = "8:{73C3B9AD-3CC6-498E-873B-F1CF59C08F52}" - "PackageCode" = "8:{5BABDAB5-78C5-4CCD-A866-05F0E720ED64}" - "UpgradeCode" = "8:{F07912E9-9BAF-4F92-ADE2-8C169AAFB16E}" - "RestartWWWService" = "11:FALSE" - "RemovePreviousVersions" = "11:TRUE" - "DetectNewerInstalledVersion" = "11:TRUE" - "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:0.9.0" - "Manufacturer" = "8:http://code.google.com/p/dnp3/" - "ARPHELPTELEPHONE" = "8:" - "ARPHELPLINK" = "8:" - "Title" = "8:DNP3 Test Set" - "Subject" = "8:" - "ARPCONTACT" = "8:http://code.google.com/p/dnp3/" - "Keywords" = "8:" - "ARPCOMMENTS" = "8:slave/master testset for DNP3" - "ARPURLINFOABOUT" = "8:http://code.google.com/p/dnp3/" - "ARPPRODUCTICON" = "8:_515D6B07AD824454B6DDFD3AD33D108E" - "ARPIconIndex" = "3:0" - "SearchPath" = "8:" - "UseSystemSearchPath" = "11:TRUE" - "TargetPlatform" = "3:0" - "PreBuildEvent" = "8:" - "PostBuildEvent" = "8:" - "RunPostBuildEvent" = "3:0" - } - "Registry" - { - "HKLM" - { - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_4FE400D340A84B67BC6738B996A4A15E" - { - "Name" = "8:Software" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_E8FA755AA89B42D5A81A14A6C69461AE" - { - "Name" = "8:[Manufacturer]" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - } - "Values" - { - } - } - } - "Values" - { - } - } - } - } - "HKCU" - { - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_22DAE4A623834619BBE687449728DD4E" - { - "Name" = "8:Software" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_DB11A180B58B4B7FBAFF9F9D24C50D98" - { - "Name" = "8:[Manufacturer]" - "Condition" = "8:" - "AlwaysCreate" = "11:FALSE" - "DeleteAtUninstall" = "11:FALSE" - "Transitive" = "11:FALSE" - "Keys" - { - } - "Values" - { - } - } - } - "Values" - { - } - } - } - } - "HKCR" - { - "Keys" - { - } - } - "HKU" - { - "Keys" - { - } - } - "HKPU" - { - "Keys" - { - } - } - } - "Sequences" - { - } - "Shortcut" - { - "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_1DAB0809F27C4B81B1997BC45E3AD2E5" - { - "Name" = "8:Default DNP3 Slave" - "Arguments" = "8:-S -E" - "Description" = "8:" - "ShowCmd" = "3:1" - "IconIndex" = "3:0" - "Transitive" = "11:FALSE" - "Target" = "8:_6A312EAB7E9140DC81E3439C767051CA" - "Folder" = "8:_314E7AD011F54D158D9A53847B2F7C24" - "WorkingFolder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Icon" = "8:_515D6B07AD824454B6DDFD3AD33D108E" - "Feature" = "8:" - } - "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_AD05C05D5426462590DC0DB7BAEB7438" - { - "Name" = "8:Default DNP3 Master" - "Arguments" = "8:-E" - "Description" = "8:" - "ShowCmd" = "3:1" - "IconIndex" = "3:0" - "Transitive" = "11:FALSE" - "Target" = "8:_6A312EAB7E9140DC81E3439C767051CA" - "Folder" = "8:_314E7AD011F54D158D9A53847B2F7C24" - "WorkingFolder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Icon" = "8:_515D6B07AD824454B6DDFD3AD33D108E" - "Feature" = "8:" - } - } - "UserInterface" - { - "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_5EDDAA81AC194B739DB755D4CB235AF5" - { - "UseDynamicProperties" = "11:FALSE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdUserInterface.wim" - } - "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_7545D2C8BD9E4A729FCD009559BC9AF2" - { - "UseDynamicProperties" = "11:FALSE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdBasicDialogs.wim" - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_896015AE9F3D4A609EDDE42B31F9A621" - { - "Name" = "8:#1902" - "Sequence" = "3:2" - "Attributes" = "3:3" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E12FA6B600164EFA8D8E145EAC8BC2D7" - { - "Sequence" = "3:100" - "DisplayName" = "8:Finished" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminFinishedDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_984E55F9C41542F5997B3DEF0EDD9574" - { - "Name" = "8:#1901" - "Sequence" = "3:1" - "Attributes" = "3:2" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E80188B8A3DB4293B74D956B7398901F" - { - "Sequence" = "3:100" - "DisplayName" = "8:Progress" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdProgressDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:2" - "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "UsePlugInResources" = "11:TRUE" - } - "ShowProgress" - { - "Name" = "8:ShowProgress" - "DisplayName" = "8:#1009" - "Description" = "8:#1109" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_9AF0CE6EB420404D8553B32F52349022" - { - "Name" = "8:#1902" - "Sequence" = "3:1" - "Attributes" = "3:3" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_70CAEF35449E41F5A3D0D509CC137675" - { - "Sequence" = "3:100" - "DisplayName" = "8:Finished" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdFinishedDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:2" - "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "UsePlugInResources" = "11:TRUE" - } - "UpdateText" - { - "Name" = "8:UpdateText" - "DisplayName" = "8:#1058" - "Description" = "8:#1158" - "Type" = "3:15" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1258" - "DefaultValue" = "8:#1258" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_9B9E35E304644F1193DA93527B21746D" - { - "Name" = "8:#1901" - "Sequence" = "3:2" - "Attributes" = "3:2" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_3F076F46A3C845D09DD79C51283C6AF6" - { - "Sequence" = "3:100" - "DisplayName" = "8:Progress" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminProgressDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "ShowProgress" - { - "Name" = "8:ShowProgress" - "DisplayName" = "8:#1009" - "Description" = "8:#1109" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_A187D886E7BE465895B80C64363D79AF" - { - "Name" = "8:#1900" - "Sequence" = "3:2" - "Attributes" = "3:1" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2428CBCEED5A4DCBBB60C562834793D1" - { - "Sequence" = "3:100" - "DisplayName" = "8:Welcome" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminWelcomeDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - "CopyrightWarning" - { - "Name" = "8:CopyrightWarning" - "DisplayName" = "8:#1002" - "Description" = "8:#1102" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1202" - "DefaultValue" = "8:#1202" - "UsePlugInResources" = "11:TRUE" - } - "Welcome" - { - "Name" = "8:Welcome" - "DisplayName" = "8:#1003" - "Description" = "8:#1103" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1203" - "DefaultValue" = "8:#1203" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_3E8859E1D80E475E9645379489717419" - { - "Sequence" = "3:200" - "DisplayName" = "8:Installation Folder" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminFolderDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C4B153C0756047A48D547F257B547E73" - { - "Sequence" = "3:300" - "DisplayName" = "8:Confirm Installation" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdAdminConfirmDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_B42CAD5283D04270B48992102056F975" - { - "Name" = "8:#1900" - "Sequence" = "3:1" - "Attributes" = "3:1" - "Dialogs" - { - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_5FDD084C0DA24CA88619039BD7B619AB" - { - "Sequence" = "3:110" - "DisplayName" = "8:License Agreement" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdLicenseDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:2" - "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "UsePlugInResources" = "11:TRUE" - } - "EulaText" - { - "Name" = "8:EulaText" - "DisplayName" = "8:#1008" - "Description" = "8:#1108" - "Type" = "3:6" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:2" - "Value" = "8:_5EDC4D3604BB4DB29C7408531072F8C9" - "UsePlugInResources" = "11:TRUE" - } - "Sunken" - { - "Name" = "8:Sunken" - "DisplayName" = "8:#1007" - "Description" = "8:#1107" - "Type" = "3:5" - "ContextData" = "8:4;True=4;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:4" - "DefaultValue" = "3:4" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_63ED1C7021EB4E9E88F8465775A58DBA" - { - "Sequence" = "3:300" - "DisplayName" = "8:Confirm Installation" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdConfirmDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:2" - "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7CF0EF327B7649228CAB0EF54E44F7F0" - { - "Sequence" = "3:200" - "DisplayName" = "8:Installation Folder" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdFolderDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:2" - "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "UsePlugInResources" = "11:TRUE" - } - "InstallAllUsersVisible" - { - "Name" = "8:InstallAllUsersVisible" - "DisplayName" = "8:#1059" - "Description" = "8:#1159" - "Type" = "3:5" - "ContextData" = "8:1;True=1;False=0" - "Attributes" = "3:0" - "Setting" = "3:0" - "Value" = "3:1" - "DefaultValue" = "3:1" - "UsePlugInResources" = "11:TRUE" - } - } - } - "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_BC43C8BA151A46E6B68FF34DD5F7E9A6" - { - "Sequence" = "3:100" - "DisplayName" = "8:Welcome" - "UseDynamicProperties" = "11:TRUE" - "IsDependency" = "11:FALSE" - "SourcePath" = "8:\\VsdWelcomeDlg.wid" - "Properties" - { - "BannerBitmap" - { - "Name" = "8:BannerBitmap" - "DisplayName" = "8:#1001" - "Description" = "8:#1101" - "Type" = "3:8" - "ContextData" = "8:Bitmap" - "Attributes" = "3:4" - "Setting" = "3:2" - "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" - "UsePlugInResources" = "11:TRUE" - } - "CopyrightWarning" - { - "Name" = "8:CopyrightWarning" - "DisplayName" = "8:#1002" - "Description" = "8:#1102" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:1" - "Value" = "8:#1202" - "DefaultValue" = "8:#1202" - "UsePlugInResources" = "11:TRUE" - } - "Welcome" - { - "Name" = "8:Welcome" - "DisplayName" = "8:#1003" - "Description" = "8:#1103" - "Type" = "3:3" - "ContextData" = "8:" - "Attributes" = "3:0" - "Setting" = "3:2" - "Value" = "8:The installer will guide you through the steps required to install [Title] on your computer." - "DefaultValue" = "8:#1203" - "UsePlugInResources" = "11:TRUE" - } - } - } - } - } - } - "MergeModule" - { - } - "ProjectOutput" - { - "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_6A312EAB7E9140DC81E3439C767051CA" - { - "SourcePath" = "8:..\\TestSet\\Release\\TestSet.exe" - "TargetName" = "8:" - "Tag" = "8:" - "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - "ProjectOutputGroupRegister" = "3:1" - "OutputConfiguration" = "8:" - "OutputGroupCanonicalName" = "8:Built" - "OutputProjectGuid" = "8:{DE526D6F-CE9C-47E4-8783-12344FDBF581}" - "ShowKeyOutput" = "11:TRUE" - "ExcludeFilters" - { - } - } - } - } -} +"DeployProject" +{ +"VSVersion" = "3:800" +"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}" +"IsWebType" = "8:FALSE" +"ProjectName" = "8:TestSetInstaller" +"LanguageId" = "3:1033" +"CodePage" = "3:1252" +"UILanguageId" = "3:1033" +"SccProjectName" = "8:" +"SccLocalPath" = "8:" +"SccAuxPath" = "8:" +"SccProvider" = "8:" + "Hierarchy" + { + "Entry" + { + "MsmKey" = "8:_06639457B6034CBBBA61FF62C542015A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_26684E6E2AE44D038E2A3EEF56421EB0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_515D6B07AD824454B6DDFD3AD33D108E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5EDC4D3604BB4DB29C7408531072F8C9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6A312EAB7E9140DC81E3439C767051CA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_81D00EDA021FC53443A8A4E552FBC39E" + "OwnerKey" = "8:_6A312EAB7E9140DC81E3439C767051CA" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + } + "Configurations" + { + "Debug" + { + "DisplayName" = "8:Debug" + "IsDebugOnly" = "11:TRUE" + "IsReleaseOnly" = "11:FALSE" + "OutputFilename" = "8:Debug\\TestSetInstaller.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" + { + "Enabled" = "11:TRUE" + "PromptEnabled" = "11:TRUE" + "PrerequisitesLocation" = "2:1" + "Url" = "8:" + "ComponentsUrl" = "8:" + "Items" + { + } + } + } + "Release" + { + "DisplayName" = "8:Release" + "IsDebugOnly" = "11:FALSE" + "IsReleaseOnly" = "11:TRUE" + "OutputFilename" = "8:Release\\TestSetInstaller.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" + { + "Enabled" = "11:TRUE" + "PromptEnabled" = "11:TRUE" + "PrerequisitesLocation" = "2:1" + "Url" = "8:" + "ComponentsUrl" = "8:" + "Items" + { + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.2.0" + { + "Name" = "8:.NET Framework 2.0" + "ProductCode" = "8:Microsoft.Net.Framework.2.0" + } + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Visual.C++.8.0.x86" + { + "Name" = "8:Visual C++ Runtime Libraries (x86)" + "ProductCode" = "8:Microsoft.Visual.C++.8.0.x86" + } + } + } + } + } + "Deployable" + { + "CustomAction" + { + } + "DefaultFeature" + { + "Name" = "8:DefaultFeature" + "Title" = "8:" + "Description" = "8:" + } + "ExternalPersistence" + { + "LaunchCondition" + { + } + } + "File" + { + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_06639457B6034CBBBA61FF62C542015A" + { + "SourcePath" = "8:icons\\square_dnp_48.ico" + "TargetName" = "8:square_dnp_48.ico" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_26684E6E2AE44D038E2A3EEF56421EB0" + { + "SourcePath" = "8:icons\\square_dnp_16.ico" + "TargetName" = "8:square_dnp_16.ico" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_515D6B07AD824454B6DDFD3AD33D108E" + { + "SourcePath" = "8:icons\\square_dnp_32.ico" + "TargetName" = "8:square_dnp_32.ico" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5EDC4D3604BB4DB29C7408531072F8C9" + { + "SourcePath" = "8:EULA.rtf" + "TargetName" = "8:EULA.rtf" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_81D00EDA021FC53443A8A4E552FBC39E" + { + "SourcePath" = "8:MSWSOCK.dll" + "TargetName" = "8:MSWSOCK.dll" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_96C0F18DB7814CE0834AADB9EA6D5317" + { + "SourcePath" = "8:icons\\dnp_banner.bmp" + "TargetName" = "8:dnp_banner.bmp" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + } + "FileType" + { + } + "Folder" + { + "{1525181F-901A-416C-8A58-119130FE478E}:_8F841B0A78D146FBB45B22F00219430A" + { + "Name" = "8:#1916" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:DesktopFolder" + "Folders" + { + } + } + "{3C67513D-01DD-4637-8A68-80971EB9504F}:_9C472356ABDA4F198CFB74D8416F04A0" + { + "DefaultLocation" = "8:[ProgramFilesFolder]\\dnp3" + "Name" = "8:#1925" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:TARGETDIR" + "Folders" + { + } + } + "{1525181F-901A-416C-8A58-119130FE478E}:_A632BDD9E7B1465FBA07B58404E70B73" + { + "Name" = "8:#1919" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:ProgramMenuFolder" + "Folders" + { + "{9EF0B969-E518-4E46-987F-47570745A589}:_314E7AD011F54D158D9A53847B2F7C24" + { + "Name" = "8:DNP3" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_DD8FD499F42E4F688B3243499993E326" + "Folders" + { + } + } + } + } + } + "LaunchCondition" + { + } + "Locator" + { + } + "MsiBootstrapper" + { + "LangId" = "3:1033" + } + "Product" + { + "Name" = "8:Microsoft Visual Studio" + "ProductName" = "8:DNP3 Test Set" + "ProductCode" = "8:{73C3B9AD-3CC6-498E-873B-F1CF59C08F52}" + "PackageCode" = "8:{5BABDAB5-78C5-4CCD-A866-05F0E720ED64}" + "UpgradeCode" = "8:{F07912E9-9BAF-4F92-ADE2-8C169AAFB16E}" + "RestartWWWService" = "11:FALSE" + "RemovePreviousVersions" = "11:TRUE" + "DetectNewerInstalledVersion" = "11:TRUE" + "InstallAllUsers" = "11:FALSE" + "ProductVersion" = "8:0.9.0" + "Manufacturer" = "8:http://code.google.com/p/dnp3/" + "ARPHELPTELEPHONE" = "8:" + "ARPHELPLINK" = "8:" + "Title" = "8:DNP3 Test Set" + "Subject" = "8:" + "ARPCONTACT" = "8:http://code.google.com/p/dnp3/" + "Keywords" = "8:" + "ARPCOMMENTS" = "8:slave/master testset for DNP3" + "ARPURLINFOABOUT" = "8:http://code.google.com/p/dnp3/" + "ARPPRODUCTICON" = "8:_515D6B07AD824454B6DDFD3AD33D108E" + "ARPIconIndex" = "3:0" + "SearchPath" = "8:" + "UseSystemSearchPath" = "11:TRUE" + "TargetPlatform" = "3:0" + "PreBuildEvent" = "8:" + "PostBuildEvent" = "8:" + "RunPostBuildEvent" = "3:0" + } + "Registry" + { + "HKLM" + { + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_4FE400D340A84B67BC6738B996A4A15E" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_E8FA755AA89B42D5A81A14A6C69461AE" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCU" + { + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_22DAE4A623834619BBE687449728DD4E" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_DB11A180B58B4B7FBAFF9F9D24C50D98" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCR" + { + "Keys" + { + } + } + "HKU" + { + "Keys" + { + } + } + "HKPU" + { + "Keys" + { + } + } + } + "Sequences" + { + } + "Shortcut" + { + "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_1DAB0809F27C4B81B1997BC45E3AD2E5" + { + "Name" = "8:Default DNP3 Slave" + "Arguments" = "8:-S -E" + "Description" = "8:" + "ShowCmd" = "3:1" + "IconIndex" = "3:0" + "Transitive" = "11:FALSE" + "Target" = "8:_6A312EAB7E9140DC81E3439C767051CA" + "Folder" = "8:_314E7AD011F54D158D9A53847B2F7C24" + "WorkingFolder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Icon" = "8:_515D6B07AD824454B6DDFD3AD33D108E" + "Feature" = "8:" + } + "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_AD05C05D5426462590DC0DB7BAEB7438" + { + "Name" = "8:Default DNP3 Master" + "Arguments" = "8:-E" + "Description" = "8:" + "ShowCmd" = "3:1" + "IconIndex" = "3:0" + "Transitive" = "11:FALSE" + "Target" = "8:_6A312EAB7E9140DC81E3439C767051CA" + "Folder" = "8:_314E7AD011F54D158D9A53847B2F7C24" + "WorkingFolder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Icon" = "8:_515D6B07AD824454B6DDFD3AD33D108E" + "Feature" = "8:" + } + } + "UserInterface" + { + "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_5EDDAA81AC194B739DB755D4CB235AF5" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdUserInterface.wim" + } + "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_7545D2C8BD9E4A729FCD009559BC9AF2" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdBasicDialogs.wim" + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_896015AE9F3D4A609EDDE42B31F9A621" + { + "Name" = "8:#1902" + "Sequence" = "3:2" + "Attributes" = "3:3" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E12FA6B600164EFA8D8E145EAC8BC2D7" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_984E55F9C41542F5997B3DEF0EDD9574" + { + "Name" = "8:#1901" + "Sequence" = "3:1" + "Attributes" = "3:2" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E80188B8A3DB4293B74D956B7398901F" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:2" + "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_9AF0CE6EB420404D8553B32F52349022" + { + "Name" = "8:#1902" + "Sequence" = "3:1" + "Attributes" = "3:3" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_70CAEF35449E41F5A3D0D509CC137675" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:2" + "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "UsePlugInResources" = "11:TRUE" + } + "UpdateText" + { + "Name" = "8:UpdateText" + "DisplayName" = "8:#1058" + "Description" = "8:#1158" + "Type" = "3:15" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1258" + "DefaultValue" = "8:#1258" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_9B9E35E304644F1193DA93527B21746D" + { + "Name" = "8:#1901" + "Sequence" = "3:2" + "Attributes" = "3:2" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_3F076F46A3C845D09DD79C51283C6AF6" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_A187D886E7BE465895B80C64363D79AF" + { + "Name" = "8:#1900" + "Sequence" = "3:2" + "Attributes" = "3:1" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2428CBCEED5A4DCBBB60C562834793D1" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_3E8859E1D80E475E9645379489717419" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C4B153C0756047A48D547F257B547E73" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_B42CAD5283D04270B48992102056F975" + { + "Name" = "8:#1900" + "Sequence" = "3:1" + "Attributes" = "3:1" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_5FDD084C0DA24CA88619039BD7B619AB" + { + "Sequence" = "3:110" + "DisplayName" = "8:License Agreement" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdLicenseDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:2" + "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "UsePlugInResources" = "11:TRUE" + } + "EulaText" + { + "Name" = "8:EulaText" + "DisplayName" = "8:#1008" + "Description" = "8:#1108" + "Type" = "3:6" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:_5EDC4D3604BB4DB29C7408531072F8C9" + "UsePlugInResources" = "11:TRUE" + } + "Sunken" + { + "Name" = "8:Sunken" + "DisplayName" = "8:#1007" + "Description" = "8:#1107" + "Type" = "3:5" + "ContextData" = "8:4;True=4;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:4" + "DefaultValue" = "3:4" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_63ED1C7021EB4E9E88F8465775A58DBA" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:2" + "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7CF0EF327B7649228CAB0EF54E44F7F0" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:2" + "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "UsePlugInResources" = "11:TRUE" + } + "InstallAllUsersVisible" + { + "Name" = "8:InstallAllUsersVisible" + "DisplayName" = "8:#1059" + "Description" = "8:#1159" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_BC43C8BA151A46E6B68FF34DD5F7E9A6" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:2" + "Value" = "8:_96C0F18DB7814CE0834AADB9EA6D5317" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:The installer will guide you through the steps required to install [Title] on your computer." + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + } + "MergeModule" + { + } + "ProjectOutput" + { + "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_6A312EAB7E9140DC81E3439C767051CA" + { + "SourcePath" = "8:..\\TestSet\\Release\\TestSet.exe" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_9C472356ABDA4F198CFB74D8416F04A0" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{DE526D6F-CE9C-47E4-8783-12344FDBF581}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + } + } + } +} diff --git a/XMLBindings/APLXML_Base.cpp b/XMLBindings/APLXML_Base.cpp index d15d5de9..9712d801 100755 --- a/XMLBindings/APLXML_Base.cpp +++ b/XMLBindings/APLXML_Base.cpp @@ -1,10 +1,10 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#include "APLXML_Base.h" +*/ +#include "APLXML_Base.h" using namespace std; -namespace APLXML_Base { +namespace APLXML_Base { BaudRateEnum FromString_BaudRateEnum(TiXmlNode* apParent, const char* aValue) { if(aValue != NULL && strcmp(aValue,"1200") == 0) return BAUDRATE_1200; if(aValue != NULL && strcmp(aValue,"1800") == 0) return BAUDRATE_1800; @@ -38,7 +38,7 @@ string ToString_BaudRateEnum(BaudRateEnum aValue) { oss << "Bad Enum value " << aValue << " for type BaudRateEnum"; throw apl::Exception(LOCATION, oss.str()); }; - + DBitsEnum FromString_DBitsEnum(TiXmlNode* apParent, const char* aValue) { if(aValue != NULL && strcmp(aValue,"DATABITS_7") == 0) return DATABITS_7; if(aValue != NULL && strcmp(aValue,"DATABITS_8") == 0) return DATABITS_8; @@ -56,7 +56,7 @@ string ToString_DBitsEnum(DBitsEnum aValue) { oss << "Bad Enum value " << aValue << " for type DBitsEnum"; throw apl::Exception(LOCATION, oss.str()); }; - + FlowControlEnum FromString_FlowControlEnum(TiXmlNode* apParent, const char* aValue) { if(aValue != NULL && strcmp(aValue,"FLOW_NONE") == 0) return FLOW_NONE; if(aValue != NULL && strcmp(aValue,"FLOW_HARDWARE") == 0) return FLOW_HARDWARE; @@ -76,7 +76,7 @@ string ToString_FlowControlEnum(FlowControlEnum aValue) { oss << "Bad Enum value " << aValue << " for type FlowControlEnum"; throw apl::Exception(LOCATION, oss.str()); }; - + LogLevelEnum FromString_LogLevelEnum(TiXmlNode* apParent, const char* aValue) { if(aValue != NULL && strcmp(aValue,"LOG_DEBUG") == 0) return LOG_DEBUG; if(aValue != NULL && strcmp(aValue,"LOG_COMM") == 0) return LOG_COMM; @@ -104,7 +104,7 @@ string ToString_LogLevelEnum(LogLevelEnum aValue) { oss << "Bad Enum value " << aValue << " for type LogLevelEnum"; throw apl::Exception(LOCATION, oss.str()); }; - + ParityEnum FromString_ParityEnum(TiXmlNode* apParent, const char* aValue) { if(aValue != NULL && strcmp(aValue,"PARITY_NONE") == 0) return PARITY_NONE; if(aValue != NULL && strcmp(aValue,"PARITY_EVEN") == 0) return PARITY_EVEN; @@ -124,7 +124,7 @@ string ToString_ParityEnum(ParityEnum aValue) { oss << "Bad Enum value " << aValue << " for type ParityEnum"; throw apl::Exception(LOCATION, oss.str()); }; - + void PhysicalLayerDescriptor_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("PhysicalLayerDescriptor",pNode->Type() == TiXmlNode::ELEMENT); @@ -146,7 +146,7 @@ void PhysicalLayerDescriptor_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bo pEm->SetAttribute("Name", ToString_string(Name)); pEm->SetAttribute("OpenRetryMS", ToString_int(OpenRetryMS)); }; - + StopBitsEnum FromString_StopBitsEnum(TiXmlNode* apParent, const char* aValue) { if(aValue != NULL && strcmp(aValue,"STOPBITS_0") == 0) return STOPBITS_0; if(aValue != NULL && strcmp(aValue,"STOPBITS_1") == 0) return STOPBITS_1; @@ -166,7 +166,7 @@ string ToString_StopBitsEnum(StopBitsEnum aValue) { oss << "Bad Enum value " << aValue << " for type StopBitsEnum"; throw apl::Exception(LOCATION, oss.str()); }; - + void TCPClient_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("TCPClient",pNode->Type() == TiXmlNode::ELEMENT); @@ -190,7 +190,7 @@ void TCPClient_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVali pEm->SetAttribute("Address", ToString_string(Address)); pEm->SetAttribute("Port", ToString_int(Port)); }; - + void TCPServer_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("TCPServer",pNode->Type() == TiXmlNode::ELEMENT); @@ -212,7 +212,7 @@ void TCPServer_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVali this->APLXML_Base::PhysicalLayerDescriptor_t::toXml(pEm, false, aIgnoreValid); pEm->SetAttribute("Port", ToString_int(Port)); }; - + void Log_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Log",pNode->Type() == TiXmlNode::ELEMENT); @@ -232,7 +232,7 @@ void Log_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ } pEm->SetAttribute("Filter", ToString_LogLevelEnum(Filter)); }; - + void Serial_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Serial",pNode->Type() == TiXmlNode::ELEMENT); @@ -264,7 +264,7 @@ void Serial_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ pEm->SetAttribute("StopBits", ToString_StopBitsEnum(StopBits)); pEm->SetAttribute("FlowControl", ToString_FlowControlEnum(FlowControl)); }; - + PhysicalLayerList_t::PhysicalLayerList_t(): TCPServer("TCPServer"), TCPServerVector(TCPServer.collection), TCPClient("TCPClient"), TCPClientVector(TCPClient.collection), @@ -293,5 +293,5 @@ void PhysicalLayerList_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIg TCPClient.toXml(pEm, true, aIgnoreValid); Serial.toXml(pEm, true, aIgnoreValid); }; - -} + +} diff --git a/XMLBindings/APLXML_Base.h b/XMLBindings/APLXML_Base.h index 99b78ad7..f1f6a4c4 100755 --- a/XMLBindings/APLXML_Base.h +++ b/XMLBindings/APLXML_Base.h @@ -1,144 +1,144 @@ -/* ****************************** - GENERATED CONTENT DO NOT ALTER! -********************************* -*/ -#ifndef _APLXML_BASE_H_ -#define _APLXML_BASE_H_ -#include -using namespace std; -namespace APLXML_Base { -enum BaudRateEnum { - BAUDRATE_1200, - BAUDRATE_1800, - BAUDRATE_2400, - BAUDRATE_4800, - BAUDRATE_9600, - BAUDRATE_19200, - BAUDRATE_38400, - BAUDRATE_57600, - BAUDRATE_115200, - BAUDRATE_230400, -}; - BaudRateEnum FromString_BaudRateEnum(TiXmlNode* apParent, const char* aValue); - string ToString_BaudRateEnum(BaudRateEnum aValue); - -enum DBitsEnum { - DATABITS_7, - DATABITS_8, -}; - DBitsEnum FromString_DBitsEnum(TiXmlNode* apParent, const char* aValue); - string ToString_DBitsEnum(DBitsEnum aValue); - -enum FlowControlEnum { - FLOW_NONE, - FLOW_HARDWARE, - FLOW_XONXOFF, -}; - FlowControlEnum FromString_FlowControlEnum(TiXmlNode* apParent, const char* aValue); - string ToString_FlowControlEnum(FlowControlEnum aValue); - -enum LogLevelEnum { - LOG_DEBUG, - LOG_COMM, - LOG_INTERPRET, - LOG_INFO, - LOG_WARNING, - LOG_ERROR, - LOG_EVENT, -}; - LogLevelEnum FromString_LogLevelEnum(TiXmlNode* apParent, const char* aValue); - string ToString_LogLevelEnum(LogLevelEnum aValue); - -enum ParityEnum { - PARITY_NONE, - PARITY_EVEN, - PARITY_ODD, -}; - ParityEnum FromString_ParityEnum(TiXmlNode* apParent, const char* aValue); - string ToString_ParityEnum(ParityEnum aValue); - -class PhysicalLayerDescriptor_t : public IXMLDataBound { -public: - void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); - void fromXml(TiXmlNode* pNode); - string Name; - int OpenRetryMS; -}; -enum StopBitsEnum { - STOPBITS_0, - STOPBITS_1, - STOPBITS_2, -}; - StopBitsEnum FromString_StopBitsEnum(TiXmlNode* apParent, const char* aValue); - string ToString_StopBitsEnum(StopBitsEnum aValue); - -class TCPClient_t : public APLXML_Base::PhysicalLayerDescriptor_t{ -public: - void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); - void fromXml(TiXmlNode* pNode); - string Address; - int Port; -}; -class TCPServer_t : public APLXML_Base::PhysicalLayerDescriptor_t{ -public: - void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); - void fromXml(TiXmlNode* pNode); - int Port; -}; -class Log_t : public IXMLDataBound { -public: - void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); - void fromXml(TiXmlNode* pNode); - LogLevelEnum Filter; -}; -class Serial_t : public APLXML_Base::PhysicalLayerDescriptor_t{ -public: - void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); - void fromXml(TiXmlNode* pNode); - string Device; - BaudRateEnum BaudRate; - ParityEnum Parity; - DBitsEnum DBits; - StopBitsEnum StopBits; - FlowControlEnum FlowControl; -}; -#ifdef SWIG -} -%template(Serial_c) std::vector; -namespace APLXML_Base{ -#endif -#ifdef SWIG -} -%template(TCPClient_c) std::vector; -namespace APLXML_Base{ -#endif -#ifdef SWIG -} -%template(TCPServer_c) std::vector; -namespace APLXML_Base{ -#endif -class PhysicalLayerList_t : public IXMLDataBound { -public: - void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); - void fromXml(TiXmlNode* pNode); - PhysicalLayerList_t(); - -#ifdef SWIG -%immutable TCPServerVector; -#endif - private: collectedType < TCPServer_t > TCPServer; - public: vector < TCPServer_t* >& TCPServerVector; -#ifdef SWIG -%immutable TCPClientVector; -#endif - private: collectedType < TCPClient_t > TCPClient; - public: vector < TCPClient_t* >& TCPClientVector; -#ifdef SWIG -%immutable SerialVector; -#endif - private: collectedType < Serial_t > Serial; - public: vector < Serial_t* >& SerialVector; -}; -} -#endif - +/* ****************************** + GENERATED CONTENT DO NOT ALTER! +********************************* +*/ +#ifndef _APLXML_BASE_H_ +#define _APLXML_BASE_H_ +#include +using namespace std; +namespace APLXML_Base { +enum BaudRateEnum { + BAUDRATE_1200, + BAUDRATE_1800, + BAUDRATE_2400, + BAUDRATE_4800, + BAUDRATE_9600, + BAUDRATE_19200, + BAUDRATE_38400, + BAUDRATE_57600, + BAUDRATE_115200, + BAUDRATE_230400, +}; + BaudRateEnum FromString_BaudRateEnum(TiXmlNode* apParent, const char* aValue); + string ToString_BaudRateEnum(BaudRateEnum aValue); + +enum DBitsEnum { + DATABITS_7, + DATABITS_8, +}; + DBitsEnum FromString_DBitsEnum(TiXmlNode* apParent, const char* aValue); + string ToString_DBitsEnum(DBitsEnum aValue); + +enum FlowControlEnum { + FLOW_NONE, + FLOW_HARDWARE, + FLOW_XONXOFF, +}; + FlowControlEnum FromString_FlowControlEnum(TiXmlNode* apParent, const char* aValue); + string ToString_FlowControlEnum(FlowControlEnum aValue); + +enum LogLevelEnum { + LOG_DEBUG, + LOG_COMM, + LOG_INTERPRET, + LOG_INFO, + LOG_WARNING, + LOG_ERROR, + LOG_EVENT, +}; + LogLevelEnum FromString_LogLevelEnum(TiXmlNode* apParent, const char* aValue); + string ToString_LogLevelEnum(LogLevelEnum aValue); + +enum ParityEnum { + PARITY_NONE, + PARITY_EVEN, + PARITY_ODD, +}; + ParityEnum FromString_ParityEnum(TiXmlNode* apParent, const char* aValue); + string ToString_ParityEnum(ParityEnum aValue); + +class PhysicalLayerDescriptor_t : public IXMLDataBound { +public: + void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); + void fromXml(TiXmlNode* pNode); + string Name; + int OpenRetryMS; +}; +enum StopBitsEnum { + STOPBITS_0, + STOPBITS_1, + STOPBITS_2, +}; + StopBitsEnum FromString_StopBitsEnum(TiXmlNode* apParent, const char* aValue); + string ToString_StopBitsEnum(StopBitsEnum aValue); + +class TCPClient_t : public APLXML_Base::PhysicalLayerDescriptor_t{ +public: + void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); + void fromXml(TiXmlNode* pNode); + string Address; + int Port; +}; +class TCPServer_t : public APLXML_Base::PhysicalLayerDescriptor_t{ +public: + void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); + void fromXml(TiXmlNode* pNode); + int Port; +}; +class Log_t : public IXMLDataBound { +public: + void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); + void fromXml(TiXmlNode* pNode); + LogLevelEnum Filter; +}; +class Serial_t : public APLXML_Base::PhysicalLayerDescriptor_t{ +public: + void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); + void fromXml(TiXmlNode* pNode); + string Device; + BaudRateEnum BaudRate; + ParityEnum Parity; + DBitsEnum DBits; + StopBitsEnum StopBits; + FlowControlEnum FlowControl; +}; +#ifdef SWIG +} +%template(Serial_c) std::vector; +namespace APLXML_Base{ +#endif +#ifdef SWIG +} +%template(TCPClient_c) std::vector; +namespace APLXML_Base{ +#endif +#ifdef SWIG +} +%template(TCPServer_c) std::vector; +namespace APLXML_Base{ +#endif +class PhysicalLayerList_t : public IXMLDataBound { +public: + void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); + void fromXml(TiXmlNode* pNode); + PhysicalLayerList_t(); + +#ifdef SWIG +%immutable TCPServerVector; +#endif + private: collectedType < TCPServer_t > TCPServer; + public: vector < TCPServer_t* >& TCPServerVector; +#ifdef SWIG +%immutable TCPClientVector; +#endif + private: collectedType < TCPClient_t > TCPClient; + public: vector < TCPClient_t* >& TCPClientVector; +#ifdef SWIG +%immutable SerialVector; +#endif + private: collectedType < Serial_t > Serial; + public: vector < Serial_t* >& SerialVector; +}; +} +#endif + diff --git a/XMLBindings/APLXML_DNP.cpp b/XMLBindings/APLXML_DNP.cpp index ac280aed..6c70984d 100755 --- a/XMLBindings/APLXML_DNP.cpp +++ b/XMLBindings/APLXML_DNP.cpp @@ -1,10 +1,10 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#include "APLXML_DNP.h" +*/ +#include "APLXML_DNP.h" using namespace std; -namespace APLXML_DNP { +namespace APLXML_DNP { void Analog_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Analog",pNode->Type() == TiXmlNode::ELEMENT); @@ -30,7 +30,7 @@ void Analog_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ pEm->SetAttribute("ClassGroup", ToString_int(ClassGroup)); pEm->SetAttribute("Deadband", ToString_int(Deadband)); }; - + AnalogData_t::AnalogData_t(): Analog("Analog"), AnalogVector(Analog.collection){}; void AnalogData_t :: fromXml(TiXmlNode* pNode){ @@ -53,7 +53,7 @@ void AnalogData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVal } Analog.toXml(pEm, true, aIgnoreValid); }; - + void AppLayer_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("AppLayer",pNode->Type() == TiXmlNode::ELEMENT); @@ -77,7 +77,7 @@ void AppLayer_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid pEm->SetAttribute("MaxFragSize", ToString_int(MaxFragSize)); pEm->SetAttribute("NumRetries", ToString_int(NumRetries)); }; - + void Binary_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Binary",pNode->Type() == TiXmlNode::ELEMENT); @@ -101,7 +101,7 @@ void Binary_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ pEm->SetAttribute("Name", ToString_string(Name)); pEm->SetAttribute("ClassGroup", ToString_int(ClassGroup)); }; - + BinaryData_t::BinaryData_t(): Binary("Binary"), BinaryVector(Binary.collection){}; void BinaryData_t :: fromXml(TiXmlNode* pNode){ @@ -124,7 +124,7 @@ void BinaryData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVal } Binary.toXml(pEm, true, aIgnoreValid); }; - + void Control_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Control",pNode->Type() == TiXmlNode::ELEMENT); @@ -150,7 +150,7 @@ void Control_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid) pEm->SetAttribute("ControlMode", ToString_string(ControlMode)); pEm->SetAttribute("SelectTimeoutMS", ToString_int(SelectTimeoutMS)); }; - + ControlData_t::ControlData_t(): Control("Control"), ControlVector(Control.collection){}; void ControlData_t :: fromXml(TiXmlNode* pNode){ @@ -173,7 +173,7 @@ void ControlData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVa } Control.toXml(pEm, true, aIgnoreValid); }; - + void ControlStatus_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("ControlStatus",pNode->Type() == TiXmlNode::ELEMENT); @@ -195,7 +195,7 @@ void ControlStatus_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnore pEm->SetAttribute("Index", ToString_int(Index)); pEm->SetAttribute("Name", ToString_string(Name)); }; - + ControlStatusData_t::ControlStatusData_t(): ControlStatus("ControlStatus"), ControlStatusVector(ControlStatus.collection){}; void ControlStatusData_t :: fromXml(TiXmlNode* pNode){ @@ -218,7 +218,7 @@ void ControlStatusData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIg } ControlStatus.toXml(pEm, true, aIgnoreValid); }; - + void Counter_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Counter",pNode->Type() == TiXmlNode::ELEMENT); @@ -242,7 +242,7 @@ void Counter_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid) pEm->SetAttribute("ClassGroup", ToString_int(ClassGroup)); pEm->SetAttribute("Name", ToString_string(Name)); }; - + CounterData_t::CounterData_t(): Counter("Counter"), CounterVector(Counter.collection){}; void CounterData_t :: fromXml(TiXmlNode* pNode){ @@ -265,7 +265,7 @@ void CounterData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVa } Counter.toXml(pEm, true, aIgnoreValid); }; - + void ExceptionScan_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("ExceptionScan",pNode->Type() == TiXmlNode::ELEMENT); @@ -291,7 +291,7 @@ void ExceptionScan_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnore pEm->SetAttribute("Class3", ToString_bool(Class3)); pEm->SetAttribute("PeriodMS", ToString_int(PeriodMS)); }; - + void GrpVar_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("GrpVar",pNode->Type() == TiXmlNode::ELEMENT); @@ -313,7 +313,7 @@ void GrpVar_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ pEm->SetAttribute("Grp", ToString_int(Grp)); pEm->SetAttribute("Var", ToString_int(Var)); }; - + void LinkLayer_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("LinkLayer",pNode->Type() == TiXmlNode::ELEMENT); @@ -343,7 +343,7 @@ void LinkLayer_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVali pEm->SetAttribute("AckTimeoutMS", ToString_int(AckTimeoutMS)); pEm->SetAttribute("NumRetries", ToString_int(NumRetries)); }; - + void MasterSettings_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("MasterSettings",pNode->Type() == TiXmlNode::ELEMENT); @@ -367,7 +367,7 @@ void MasterSettings_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnor pEm->SetAttribute("TaskRetryMS", ToString_int(TaskRetryMS)); pEm->SetAttribute("IntegrityPeriodMS", ToString_int(IntegrityPeriodMS)); }; - + ScanList_t::ScanList_t(): ExceptionScan("ExceptionScan"), ExceptionScanVector(ExceptionScan.collection){}; void ScanList_t :: fromXml(TiXmlNode* pNode){ @@ -390,7 +390,7 @@ void ScanList_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid } ExceptionScan.toXml(pEm, true, aIgnoreValid); }; - + void Setpoint_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Setpoint",pNode->Type() == TiXmlNode::ELEMENT); @@ -416,7 +416,7 @@ void Setpoint_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid pEm->SetAttribute("ControlMode", ToString_string(ControlMode)); pEm->SetAttribute("SelectTimeoutMS", ToString_int(SelectTimeoutMS)); }; - + SetpointData_t::SetpointData_t(): Setpoint("Setpoint"), SetpointVector(Setpoint.collection){}; void SetpointData_t :: fromXml(TiXmlNode* pNode){ @@ -439,7 +439,7 @@ void SetpointData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreV } Setpoint.toXml(pEm, true, aIgnoreValid); }; - + void SetpointStatus_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("SetpointStatus",pNode->Type() == TiXmlNode::ELEMENT); @@ -461,7 +461,7 @@ void SetpointStatus_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnor pEm->SetAttribute("Index", ToString_int(Index)); pEm->SetAttribute("Name", ToString_string(Name)); }; - + SetpointStatusData_t::SetpointStatusData_t(): SetpointStatus("SetpointStatus"), SetpointStatusVector(SetpointStatus.collection){}; void SetpointStatusData_t :: fromXml(TiXmlNode* pNode){ @@ -484,7 +484,7 @@ void SetpointStatusData_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aI } SetpointStatus.toXml(pEm, true, aIgnoreValid); }; - + void SetpointStatusGrpVar_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("SetpointStatusGrpVar",pNode->Type() == TiXmlNode::ELEMENT); @@ -504,7 +504,7 @@ void SetpointStatusGrpVar_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool } this->APLXML_DNP::GrpVar_t::toXml(pEm, false, aIgnoreValid); }; - + void Stack_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Stack",pNode->Type() == TiXmlNode::ELEMENT); @@ -526,7 +526,7 @@ void Stack_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ LinkLayer.toXml(pEm, true, aIgnoreValid); AppLayer.toXml(pEm, true, aIgnoreValid); }; - + void TimeIINTask_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("TimeIINTask",pNode->Type() == TiXmlNode::ELEMENT); @@ -548,7 +548,7 @@ void TimeIINTask_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVa pEm->SetAttribute("DoTask", ToString_bool(DoTask)); pEm->SetAttribute("PeriodMS", ToString_int(PeriodMS)); }; - + void Unsol_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Unsol",pNode->Type() == TiXmlNode::ELEMENT); @@ -576,7 +576,7 @@ void Unsol_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ pEm->SetAttribute("Class2", ToString_bool(Class2)); pEm->SetAttribute("Class3", ToString_bool(Class3)); }; - + void UnsolDefaults_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("UnsolDefaults",pNode->Type() == TiXmlNode::ELEMENT); @@ -604,7 +604,7 @@ void UnsolDefaults_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnore pEm->SetAttribute("PackDelayMS", ToString_int(PackDelayMS)); pEm->SetAttribute("RetryMS", ToString_int(RetryMS)); }; - + void AnalogGrpVar_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("AnalogGrpVar",pNode->Type() == TiXmlNode::ELEMENT); @@ -624,7 +624,7 @@ void AnalogGrpVar_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreV } this->APLXML_DNP::GrpVar_t::toXml(pEm, false, aIgnoreValid); }; - + void BinaryGrpVar_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("BinaryGrpVar",pNode->Type() == TiXmlNode::ELEMENT); @@ -644,7 +644,7 @@ void BinaryGrpVar_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreV } this->APLXML_DNP::GrpVar_t::toXml(pEm, false, aIgnoreValid); }; - + void CounterGrpVar_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("CounterGrpVar",pNode->Type() == TiXmlNode::ELEMENT); @@ -664,7 +664,7 @@ void CounterGrpVar_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnore } this->APLXML_DNP::GrpVar_t::toXml(pEm, false, aIgnoreValid); }; - + void DeviceTemplate_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("DeviceTemplate",pNode->Type() == TiXmlNode::ELEMENT); @@ -698,7 +698,7 @@ void DeviceTemplate_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnor SetpointData.toXml(pEm, true, aIgnoreValid); ControlData.toXml(pEm, true, aIgnoreValid); }; - + void EventRsp_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("EventRsp",pNode->Type() == TiXmlNode::ELEMENT); @@ -722,7 +722,7 @@ void EventRsp_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid AnalogGrpVar.toXml(pEm, true, aIgnoreValid); CounterGrpVar.toXml(pEm, true, aIgnoreValid); }; - + void Master_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Master",pNode->Type() == TiXmlNode::ELEMENT); @@ -748,7 +748,7 @@ void Master_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ ScanList.toXml(pEm, true, aIgnoreValid); Unsol.toXml(pEm, true, aIgnoreValid); }; - + void StaticRsp_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("StaticRsp",pNode->Type() == TiXmlNode::ELEMENT); @@ -774,7 +774,7 @@ void StaticRsp_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVali CounterGrpVar.toXml(pEm, true, aIgnoreValid); SetpointStatusGrpVar.toXml(pEm, true, aIgnoreValid); }; - + void SlaveConfig_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("SlaveConfig",pNode->Type() == TiXmlNode::ELEMENT); @@ -806,7 +806,7 @@ void SlaveConfig_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreVa TimeIINTask.toXml(pEm, true, aIgnoreValid); UnsolDefaults.toXml(pEm, true, aIgnoreValid); }; - + void Slave_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("Slave",pNode->Type() == TiXmlNode::ELEMENT); @@ -828,5 +828,5 @@ void Slave_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid){ Stack.toXml(pEm, true, aIgnoreValid); SlaveConfig.toXml(pEm, true, aIgnoreValid); }; - -} + +} diff --git a/XMLBindings/APLXML_DNP.h b/XMLBindings/APLXML_DNP.h index f3294d2b..43587393 100755 --- a/XMLBindings/APLXML_DNP.h +++ b/XMLBindings/APLXML_DNP.h @@ -1,12 +1,12 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#ifndef _APLXML_DNP_H_ -#define _APLXML_DNP_H_ -#include +*/ +#ifndef _APLXML_DNP_H_ +#define _APLXML_DNP_H_ +#include using namespace std; -namespace APLXML_DNP { +namespace APLXML_DNP { class Analog_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -15,7 +15,7 @@ class Analog_t : public IXMLDataBound { string Name; int ClassGroup; int Deadband; -}; +}; #ifdef SWIG } %template(Analog_c) std::vector; @@ -32,7 +32,7 @@ class AnalogData_t : public IXMLDataBound { #endif private: collectedType < Analog_t > Analog; public: vector < Analog_t* >& AnalogVector; -}; +}; class AppLayer_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -40,7 +40,7 @@ class AppLayer_t : public IXMLDataBound { int TimeoutMS; int MaxFragSize; int NumRetries; -}; +}; class Binary_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -48,7 +48,7 @@ class Binary_t : public IXMLDataBound { int Index; string Name; int ClassGroup; -}; +}; #ifdef SWIG } %template(Binary_c) std::vector; @@ -65,7 +65,7 @@ class BinaryData_t : public IXMLDataBound { #endif private: collectedType < Binary_t > Binary; public: vector < Binary_t* >& BinaryVector; -}; +}; class Control_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -74,7 +74,7 @@ class Control_t : public IXMLDataBound { string Name; string ControlMode; int SelectTimeoutMS; -}; +}; #ifdef SWIG } %template(Control_c) std::vector; @@ -91,14 +91,14 @@ class ControlData_t : public IXMLDataBound { #endif private: collectedType < Control_t > Control; public: vector < Control_t* >& ControlVector; -}; +}; class ControlStatus_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); int Index; string Name; -}; +}; #ifdef SWIG } %template(ControlStatus_c) std::vector; @@ -115,7 +115,7 @@ class ControlStatusData_t : public IXMLDataBound { #endif private: collectedType < ControlStatus_t > ControlStatus; public: vector < ControlStatus_t* >& ControlStatusVector; -}; +}; class Counter_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -123,7 +123,7 @@ class Counter_t : public IXMLDataBound { int Index; int ClassGroup; string Name; -}; +}; #ifdef SWIG } %template(Counter_c) std::vector; @@ -140,7 +140,7 @@ class CounterData_t : public IXMLDataBound { #endif private: collectedType < Counter_t > Counter; public: vector < Counter_t* >& CounterVector; -}; +}; class ExceptionScan_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -149,14 +149,14 @@ class ExceptionScan_t : public IXMLDataBound { bool Class2; bool Class3; int PeriodMS; -}; +}; class GrpVar_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); int Grp; int Var; -}; +}; class LinkLayer_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -167,7 +167,7 @@ class LinkLayer_t : public IXMLDataBound { bool UseConfirmations; int AckTimeoutMS; int NumRetries; -}; +}; class MasterSettings_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -175,7 +175,7 @@ class MasterSettings_t : public IXMLDataBound { bool AllowTimeSync; int TaskRetryMS; int IntegrityPeriodMS; -}; +}; #ifdef SWIG } %template(ExceptionScan_c) std::vector; @@ -192,7 +192,7 @@ class ScanList_t : public IXMLDataBound { #endif private: collectedType < ExceptionScan_t > ExceptionScan; public: vector < ExceptionScan_t* >& ExceptionScanVector; -}; +}; class Setpoint_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -201,7 +201,7 @@ class Setpoint_t : public IXMLDataBound { string Name; string ControlMode; int SelectTimeoutMS; -}; +}; #ifdef SWIG } %template(Setpoint_c) std::vector; @@ -218,14 +218,14 @@ class SetpointData_t : public IXMLDataBound { #endif private: collectedType < Setpoint_t > Setpoint; public: vector < Setpoint_t* >& SetpointVector; -}; +}; class SetpointStatus_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); int Index; string Name; -}; +}; #ifdef SWIG } %template(SetpointStatus_c) std::vector; @@ -242,12 +242,12 @@ class SetpointStatusData_t : public IXMLDataBound { #endif private: collectedType < SetpointStatus_t > SetpointStatus; public: vector < SetpointStatus_t* >& SetpointStatusVector; -}; +}; class SetpointStatusGrpVar_t : public APLXML_DNP::GrpVar_t{ public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); -}; +}; class Stack_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -260,14 +260,14 @@ class Stack_t : public IXMLDataBound { %immutable AppLayer; #endif AppLayer_t AppLayer; -}; +}; class TimeIINTask_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); bool DoTask; int PeriodMS; -}; +}; class Unsol_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -277,7 +277,7 @@ class Unsol_t : public IXMLDataBound { bool Class1; bool Class2; bool Class3; -}; +}; class UnsolDefaults_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -287,22 +287,22 @@ class UnsolDefaults_t : public IXMLDataBound { bool DoClass3; int PackDelayMS; int RetryMS; -}; +}; class AnalogGrpVar_t : public APLXML_DNP::GrpVar_t{ public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); -}; +}; class BinaryGrpVar_t : public APLXML_DNP::GrpVar_t{ public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); -}; +}; class CounterGrpVar_t : public APLXML_DNP::GrpVar_t{ public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); void fromXml(TiXmlNode* pNode); -}; +}; class DeviceTemplate_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -336,7 +336,7 @@ class DeviceTemplate_t : public IXMLDataBound { %immutable ControlData; #endif ControlData_t ControlData; -}; +}; class EventRsp_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -353,7 +353,7 @@ class EventRsp_t : public IXMLDataBound { %immutable CounterGrpVar; #endif CounterGrpVar_t CounterGrpVar; -}; +}; class Master_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -374,7 +374,7 @@ class Master_t : public IXMLDataBound { %immutable Unsol; #endif Unsol_t Unsol; -}; +}; class StaticRsp_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -395,7 +395,7 @@ class StaticRsp_t : public IXMLDataBound { %immutable SetpointStatusGrpVar; #endif SetpointStatusGrpVar_t SetpointStatusGrpVar; -}; +}; class SlaveConfig_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -419,7 +419,7 @@ class SlaveConfig_t : public IXMLDataBound { %immutable UnsolDefaults; #endif UnsolDefaults_t UnsolDefaults; -}; +}; class Slave_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -432,7 +432,7 @@ class Slave_t : public IXMLDataBound { %immutable SlaveConfig; #endif SlaveConfig_t SlaveConfig; -}; +}; } #endif - + diff --git a/XMLBindings/APLXML_MTS.cpp b/XMLBindings/APLXML_MTS.cpp index b37732cd..f3416b92 100755 --- a/XMLBindings/APLXML_MTS.cpp +++ b/XMLBindings/APLXML_MTS.cpp @@ -1,10 +1,10 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#include "APLXML_MTS.h" +*/ +#include "APLXML_MTS.h" using namespace std; -namespace APLXML_MTS { +namespace APLXML_MTS { void MasterTestSet_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("MasterTestSet",pNode->Type() == TiXmlNode::ELEMENT); @@ -32,5 +32,5 @@ void MasterTestSet_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnore Master.toXml(pEm, true, aIgnoreValid); PhysicalLayerList.toXml(pEm, true, aIgnoreValid); }; - -} + +} diff --git a/XMLBindings/APLXML_MTS.h b/XMLBindings/APLXML_MTS.h index f004a63a..e38aa575 100755 --- a/XMLBindings/APLXML_MTS.h +++ b/XMLBindings/APLXML_MTS.h @@ -1,14 +1,14 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#ifndef _APLXML_MTS_H_ -#define _APLXML_MTS_H_ -#include -#include -#include +*/ +#ifndef _APLXML_MTS_H_ +#define _APLXML_MTS_H_ +#include +#include +#include using namespace std; -namespace APLXML_MTS { +namespace APLXML_MTS { class MasterTestSet_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -27,7 +27,7 @@ class MasterTestSet_t : public IXMLDataBound { %immutable PhysicalLayerList; #endif APLXML_Base::PhysicalLayerList_t PhysicalLayerList; -}; +}; } #endif - + diff --git a/XMLBindings/APLXML_STS.cpp b/XMLBindings/APLXML_STS.cpp index 5de8a7ee..b23478b8 100755 --- a/XMLBindings/APLXML_STS.cpp +++ b/XMLBindings/APLXML_STS.cpp @@ -1,10 +1,10 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#include "APLXML_STS.h" +*/ +#include "APLXML_STS.h" using namespace std; -namespace APLXML_STS { +namespace APLXML_STS { void SlaveTestSet_t :: fromXml(TiXmlNode* pNode){ if(pNode == NULL)return; XML_CHECK("SlaveTestSet",pNode->Type() == TiXmlNode::ELEMENT); @@ -42,5 +42,5 @@ void SlaveTestSet_t :: toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreV DeviceTemplate.toXml(pEm, true, aIgnoreValid); PhysicalLayerList.toXml(pEm, true, aIgnoreValid); }; - -} + +} diff --git a/XMLBindings/APLXML_STS.h b/XMLBindings/APLXML_STS.h index 065abb60..a40d483c 100755 --- a/XMLBindings/APLXML_STS.h +++ b/XMLBindings/APLXML_STS.h @@ -1,14 +1,14 @@ /* ****************************** GENERATED CONTENT DO NOT ALTER! ********************************* -*/ -#ifndef _APLXML_STS_H_ -#define _APLXML_STS_H_ -#include -#include -#include +*/ +#ifndef _APLXML_STS_H_ +#define _APLXML_STS_H_ +#include +#include +#include using namespace std; -namespace APLXML_STS { +namespace APLXML_STS { class SlaveTestSet_t : public IXMLDataBound { public: void toXml(TiXmlNode* pParent, bool aCreateNode, bool aIgnoreValid); @@ -35,7 +35,7 @@ class SlaveTestSet_t : public IXMLDataBound { %immutable PhysicalLayerList; #endif APLXML_Base::PhysicalLayerList_t PhysicalLayerList; -}; +}; } #endif - + diff --git a/XMLBindings/XMLBindings.vcproj b/XMLBindings/XMLBindings.vcproj index 5648482f..b3f2defa 100755 --- a/XMLBindings/XMLBindings.vcproj +++ b/XMLBindings/XMLBindings.vcproj @@ -1,187 +1,187 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XMLBindings/rake.project.rb b/XMLBindings/rake.project.rb index ca92536e..2261bc3a 100755 --- a/XMLBindings/rake.project.rb +++ b/XMLBindings/rake.project.rb @@ -1,5 +1,5 @@ - -$options = { -:target => 'libxmlbindings.a', -:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES] -} + +$options = { +:target => 'libxmlbindings.a', +:includes => [Boost::get_includes_dir, DEFAULT_INCLUDES] +} diff --git a/config/boost_includes.vsprops b/config/boost_includes.vsprops index e0f89ee7..a1be1696 100755 --- a/config/boost_includes.vsprops +++ b/config/boost_includes.vsprops @@ -1,11 +1,11 @@ - - - - + + + + diff --git a/config/boost_lib.vsprops b/config/boost_lib.vsprops index 7c2fd386..89e1104f 100755 --- a/config/boost_lib.vsprops +++ b/config/boost_lib.vsprops @@ -1,11 +1,11 @@ - - - - + + + + diff --git a/config/local_dir.vsprops b/config/local_dir.vsprops index 31e567c7..94cc2ca9 100755 --- a/config/local_dir.vsprops +++ b/config/local_dir.vsprops @@ -1,11 +1,11 @@ - - - - + + + + diff --git a/config/output_dirs.vsprops b/config/output_dirs.vsprops index 4a8a574b..b1b6b0a2 100755 --- a/config/output_dirs.vsprops +++ b/config/output_dirs.vsprops @@ -1,9 +1,9 @@ - - - + + + diff --git a/rakefile.rb b/rakefile.rb index 1ae51fda..7897062b 100755 --- a/rakefile.rb +++ b/rakefile.rb @@ -1,82 +1,82 @@ - -$: << './tools/rake_build_system' #make sure this rakefile can see all the build system files - -ENV['BOOST_VERSION']='boost_1_43' - -require 'rake/clean' - -require 'rake.environment.rb' # this sets up a slew of environment constants -require 'plugins/rake.cpp.rb' # this provides the facilities for declaring C++ style builds -require 'plugins/rake.boost.rb' # provides location and names of the boost libraries -require 'plugins/rake.swigjava.rb' # provides helpers for creating cpp/java bindings using swig -require 'plugins/rake.source.rb' # provides licensing helpers - -DEFAULT_INCLUDES << __FILE__.pathmap('%d') - -#format is name => options, :dir is required -$projects = { -:apl => {:dir => 'APL' }, -:testapl => {:dir => 'TestAPL'}, -:apltesttools => {:dir => 'APLTestTools'}, -:dnp3 => {:dir => 'DNP3'}, -:dnp3xml => {:dir => 'DNP3XML'}, -:xmlbindings => {:dir => 'XMLBindings'}, -:dnp3test => {:dir => 'DNP3Test'}, -:testset => {:dir => 'TestSet'}, -:tinyxml => {:dir => 'tinyxml'}, -:aplxml => {:dir => 'APLXML'}, -:terminal => {:dir => 'Terminal'}, -:terminaltest => {:dir => 'TerminalTest'}, -:dnp3java => {:dir => 'DNP3Java'}, -} - -add_projects($projects) #removes projects that are not valid for $hw_os - -SOURCE_PROJECTS = [:apl, :testapl, :apltesttools, :dnp3, :dnp3test, :dnp3xml, :aplxml, :testset] -SOURCE_DIRS = SOURCE_PROJECTS.collect { |p| $projects[p][:dir] } - -desc 'Generate doxygen html docs for the project' -task :document do - `doxygen ./config/doxygen.config` -end - -desc 'Generate a sloccount report for the project' -task :sloccount do - dirs = SOURCE_DIRS + ['tools/rake_build_system'] - `sloccount --wide --details #{dirs.join(' ')} > sloccount.sc` -end - -desc "Create a jar with the embedded shared library" -task "dnp3java:package" => ["dnp3java:build"] do - dir = $projects[:dnp3java][:dir] - sh "javac ./#{dir}/jar/org/psi/dnp3/*.java" - sh "jar cvf ./#{dir}/dnp3java.jar -C ./#{dir}/jar ." -end - -desc "Deploy the shared library to the system lib directory" -task "dnp3java:install" => ["dnp3java:build"] do - sh "rake dnp3java:copytarget['/usr/lib','libdnp3java.so',true]" -end - -namespace :license do - - license_dirs = SOURCE_DIRS << 'External\build_system' - - license_types = { - :cpp => {:exts => ['.cpp','.h'], :comment => '// '}, - :ruby => {:exts => ['.rb'], :comment => '# '}, - } - - extensions = license_types.collect { |k,v| v[:exts] }.join('/') - - desc "add the licensing file to all #{extensions}" - task :add do - license_types.each { |key,options| add_license(license_dirs, options, 'FILE_LICENSE') } - end - - desc "remove the licensing file from all #{extensions}" - task :remove do - license_types.each { |key,options| remove_license(license_dirs, options, 'FILE_LICENSE') } - end - + +$: << './tools/rake_build_system' #make sure this rakefile can see all the build system files + +ENV['BOOST_VERSION']='boost_1_43' + +require 'rake/clean' + +require 'rake.environment.rb' # this sets up a slew of environment constants +require 'plugins/rake.cpp.rb' # this provides the facilities for declaring C++ style builds +require 'plugins/rake.boost.rb' # provides location and names of the boost libraries +require 'plugins/rake.swigjava.rb' # provides helpers for creating cpp/java bindings using swig +require 'plugins/rake.source.rb' # provides licensing helpers + +DEFAULT_INCLUDES << __FILE__.pathmap('%d') + +#format is name => options, :dir is required +$projects = { +:apl => {:dir => 'APL' }, +:testapl => {:dir => 'TestAPL'}, +:apltesttools => {:dir => 'APLTestTools'}, +:dnp3 => {:dir => 'DNP3'}, +:dnp3xml => {:dir => 'DNP3XML'}, +:xmlbindings => {:dir => 'XMLBindings'}, +:dnp3test => {:dir => 'DNP3Test'}, +:testset => {:dir => 'TestSet'}, +:tinyxml => {:dir => 'tinyxml'}, +:aplxml => {:dir => 'APLXML'}, +:terminal => {:dir => 'Terminal'}, +:terminaltest => {:dir => 'TerminalTest'}, +:dnp3java => {:dir => 'DNP3Java'}, +} + +add_projects($projects) #removes projects that are not valid for $hw_os + +SOURCE_PROJECTS = [:apl, :testapl, :apltesttools, :dnp3, :dnp3test, :dnp3xml, :aplxml, :testset] +SOURCE_DIRS = SOURCE_PROJECTS.collect { |p| $projects[p][:dir] } + +desc 'Generate doxygen html docs for the project' +task :document do + `doxygen ./config/doxygen.config` +end + +desc 'Generate a sloccount report for the project' +task :sloccount do + dirs = SOURCE_DIRS + ['tools/rake_build_system'] + `sloccount --wide --details #{dirs.join(' ')} > sloccount.sc` +end + +desc "Create a jar with the embedded shared library" +task "dnp3java:package" => ["dnp3java:build"] do + dir = $projects[:dnp3java][:dir] + sh "javac ./#{dir}/jar/org/psi/dnp3/*.java" + sh "jar cvf ./#{dir}/dnp3java.jar -C ./#{dir}/jar ." +end + +desc "Deploy the shared library to the system lib directory" +task "dnp3java:install" => ["dnp3java:build"] do + sh "rake dnp3java:copytarget['/usr/lib','libdnp3java.so',true]" +end + +namespace :license do + + license_dirs = SOURCE_DIRS << 'External\build_system' + + license_types = { + :cpp => {:exts => ['.cpp','.h'], :comment => '// '}, + :ruby => {:exts => ['.rb'], :comment => '# '}, + } + + extensions = license_types.collect { |k,v| v[:exts] }.join('/') + + desc "add the licensing file to all #{extensions}" + task :add do + license_types.each { |key,options| add_license(license_dirs, options, 'FILE_LICENSE') } + end + + desc "remove the licensing file from all #{extensions}" + task :remove do + license_types.each { |key,options| remove_license(license_dirs, options, 'FILE_LICENSE') } + end + end \ No newline at end of file diff --git a/tinyxml/rake.project.rb b/tinyxml/rake.project.rb index fb16f9e2..3730c032 100755 --- a/tinyxml/rake.project.rb +++ b/tinyxml/rake.project.rb @@ -1,5 +1,5 @@ -#setup the psi project -$options = { -:target => 'libtinyxml.a', -:includes => [DEFAULT_INCLUDES] -} +#setup the psi project +$options = { +:target => 'libtinyxml.a', +:includes => [DEFAULT_INCLUDES] +} diff --git a/tinyxml/tinystr.h b/tinyxml/tinystr.h index 3c2aa9d5..d4fc3d76 100755 --- a/tinyxml/tinystr.h +++ b/tinyxml/tinystr.h @@ -238,7 +238,7 @@ class TiXmlString // to the normal allocation, although use an 'int' for systems // that are overly picky about structure alignment. const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); rep_ = reinterpret_cast( new int[ intsNeeded ] ); rep_->str[ rep_->size = sz ] = '\0'; diff --git a/tinyxml/tinyxml.cpp b/tinyxml/tinyxml.cpp index cbe03795..fd510674 100755 --- a/tinyxml/tinyxml.cpp +++ b/tinyxml/tinyxml.cpp @@ -1,1920 +1,1920 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* - * THIS FILE WAS ALTERED BY Sam Hendley, 7. November 2007. - * - * - added Boolean querying functions - * - added USE_STL preprocessor macro - */ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::DOCUMENT ) - { - delete node; - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( replaceThis->parent != this ) - return 0; - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -void TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return &node->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const char* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s ); - } - else { - *i = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const std::string* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s->c_str() ); - } - else { - *i = 0; - } - } - return s; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const char* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s ); - } - else { - *d = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const std::string* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s->c_str() ); - } - else { - *d = 0; - } - } - return s; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} - -int TiXmlElement::QueryBoolAttribute( const char* name, bool* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryBoolValue( ival ); -} - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryBoolAttribute( const std::string& name, bool* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryBoolValue( ival ); -} -#endif - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - char buf[64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); - #else - sprintf( buf, "%d", val ); - #endif - SetAttribute( name, buf ); -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - std::ostringstream oss; - oss << val; - SetAttribute( name, oss.str() ); -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - char buf[256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); - #else - sprintf( buf, "%f", val ); - #endif - SetAttribute( name, buf ); -} - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING _name( cname ); - TIXML_STRING _value( cvalue ); - #else - const char* _name = cname; - const char* _value = cvalue; - #endif - - TiXmlAttribute* node = attributeSet.Find( _name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) -{ - TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - // See STL_STRING_BUG below. - //StringToBuffer buf( value ); - - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - // See STL_STRING_BUG below. -// StringToBuffer buf( value ); -// -// if ( buf.buffer && SaveFile( buf.buffer ) ) -// return true; -// -// return false; - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - // There was a really terrifying little bug here. The code: - // value = filename - // in the STL case, cause the assignment method of the std::string to - // be called. What is strange, is that the std::string had the same - // address as it's c_str() method, and so bad things happen. Looks - // like a bug in the Microsoft STL implementation. - // Add an extra string to avoid the crash. - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // If we have a file, assume it is all one big XML file, and read it in. - // The document parser may decide the document ends sooner than the entire file, however. - TIXML_STRING data; - data.reserve( length ); - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - const char* lastPos = buf; - const char* p = buf; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - if ( *p == 0xa ) { - // Newline character. No special rules for this. Append all the characters - // since the last string, and include the newline. - data.append( lastPos, (p-lastPos+1) ); // append, include the newline - ++p; // move past the newline - lastPos = p; // and point to the new buffer (may be 0) - assert( p <= (buf+length) ); - } - else if ( *p == 0xd ) { - // Carriage return. Append what we have so far, then - // handle moving forward in the buffer. - if ( (p-lastPos) > 0 ) { - data.append( lastPos, p-lastPos ); // do not add the CR - } - data += (char)0xa; // a proper newline - - if ( *(p+1) == 0xa ) { - // Carriage return - new line sequence - p += 2; - lastPos = p; - assert( p <= (buf+length) ); - } - else { - // it was followed by something else...that is presumably characters again. - ++p; - lastPos = p; - assert( p <= (buf+length) ); - } - } - else { - ++p; - } - } - // Handle any left over characters. - if ( p-lastPos ) { - data.append( lastPos, p-lastPos ); - } - delete [] buf; - buf = 0; - - Parse( data.c_str(), 0, encoding ); - - if ( Error() ) - return false; - else - return true; -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} -int TiXmlAttribute::QueryBoolValue( bool* ival ) const -{ - if(value.compare("true") == 0) *ival = true; - else if(value.compare("false") == 0) *ival = false; - else return TIXML_WRONG_TYPE; - return TIXML_SUCCESS; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); - #else - sprintf (buf, "%lf", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} -*/ -#endif - - -const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} -*/ - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Sam Hendley, 7. November 2007. + * + * - added Boolean querying functions + * - added USE_STL preprocessor macro + */ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( replaceThis->parent != this ) + return 0; + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return &node->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const char* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s ); + } + else { + *i = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const std::string* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s->c_str() ); + } + else { + *i = 0; + } + } + return s; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const char* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s ); + } + else { + *d = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const std::string* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s->c_str() ); + } + else { + *d = 0; + } + } + return s; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} + +int TiXmlElement::QueryBoolAttribute( const char* name, bool* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryBoolValue( ival ); +} + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryBoolAttribute( const std::string& name, bool* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryBoolValue( ival ); +} +#endif + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + char buf[64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); + #else + sprintf( buf, "%d", val ); + #endif + SetAttribute( name, buf ); +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + std::ostringstream oss; + oss << val; + SetAttribute( name, oss.str() ); +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + char buf[256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); + #else + sprintf( buf, "%f", val ); + #endif + SetAttribute( name, buf ); +} + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING _name( cname ); + TIXML_STRING _value( cvalue ); + #else + const char* _name = cname; + const char* _value = cvalue; + #endif + + TiXmlAttribute* node = attributeSet.Find( _name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + // See STL_STRING_BUG below. + //StringToBuffer buf( value ); + + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + // See STL_STRING_BUG below. +// StringToBuffer buf( value ); +// +// if ( buf.buffer && SaveFile( buf.buffer ) ) +// return true; +// +// return false; + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // Add an extra string to avoid the crash. + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve( length ); + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + const char* lastPos = buf; + const char* p = buf; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + if ( *p == 0xa ) { + // Newline character. No special rules for this. Append all the characters + // since the last string, and include the newline. + data.append( lastPos, (p-lastPos+1) ); // append, include the newline + ++p; // move past the newline + lastPos = p; // and point to the new buffer (may be 0) + assert( p <= (buf+length) ); + } + else if ( *p == 0xd ) { + // Carriage return. Append what we have so far, then + // handle moving forward in the buffer. + if ( (p-lastPos) > 0 ) { + data.append( lastPos, p-lastPos ); // do not add the CR + } + data += (char)0xa; // a proper newline + + if ( *(p+1) == 0xa ) { + // Carriage return - new line sequence + p += 2; + lastPos = p; + assert( p <= (buf+length) ); + } + else { + // it was followed by something else...that is presumably characters again. + ++p; + lastPos = p; + assert( p <= (buf+length) ); + } + } + else { + ++p; + } + } + // Handle any left over characters. + if ( p-lastPos ) { + data.append( lastPos, p-lastPos ); + } + delete [] buf; + buf = 0; + + Parse( data.c_str(), 0, encoding ); + + if ( Error() ) + return false; + else + return true; +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} +int TiXmlAttribute::QueryBoolValue( bool* ival ) const +{ + if(value.compare("true") == 0) *ival = true; + else if(value.compare("false") == 0) *ival = false; + else return TIXML_WRONG_TYPE; + return TIXML_SUCCESS; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); + #else + sprintf (buf, "%lf", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} +*/ +#endif + + +const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} +*/ + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/tinyxml/tinyxml.h b/tinyxml/tinyxml.h index ef3086f5..ddbff8dd 100755 --- a/tinyxml/tinyxml.h +++ b/tinyxml/tinyxml.h @@ -1,1814 +1,1814 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* - * THIS FILE WAS ALTERED BY Sam Hendley, 7. November 2007. - * - * - added Boolean querying functions - * - added USE_STL preprocessor macro - */ - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#define TIXML_USE_STL - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SNSCANF _snscanf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SNSCANF _snscanf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SNSCANF snscanf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 5; -const int TIXML_PATCH_VERSION = 3; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simple called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_OUT_OF_MEMORY, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - DOCUMENT, - ELEMENT, - COMMENT, - UNKNOWN, - TEXT, - DECLARATION, - TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - int QueryBoolValue( bool* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - const TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* Find( const char* _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - #ifdef TIXML_USE_STL - const TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* Find( const std::string& _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - - #endif - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - - int QueryBoolAttribute( const char* name, bool* ival ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - /* - This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" - but template specialization is hard to get working cross-compiler. Leaving the bug for now. - - // The above will fail for std::string because the space character is used as a seperator. - // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string - template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - */ - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryBoolAttribute( const std::string& name, bool* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && LoadFile( f.buffer, encoding )); - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && SaveFile( f.buffer )); - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SNSCANF _snscanf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SNSCANF _snscanf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SNSCANF snscanf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 5; +const int TIXML_PATCH_VERSION = 3; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simple called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + int QueryBoolValue( bool* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + const TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* Find( const char* _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #ifdef TIXML_USE_STL + const TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* Find( const std::string& _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + + #endif + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + + int QueryBoolAttribute( const char* name, bool* ival ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + /* + This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" + but template specialization is hard to get working cross-compiler. Leaving the bug for now. + + // The above will fail for std::string because the space character is used as a seperator. + // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string + template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + */ + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryBoolAttribute( const std::string& name, bool* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && LoadFile( f.buffer, encoding )); + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && SaveFile( f.buffer )); + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/rake_build_system/plugins/rake.boost.rb b/tools/rake_build_system/plugins/rake.boost.rb index 41f7a384..128a35aa 100755 --- a/tools/rake_build_system/plugins/rake.boost.rb +++ b/tools/rake_build_system/plugins/rake.boost.rb @@ -1,47 +1,47 @@ - -class Boost - -#names of the various boost libraries -BOOST_SYSTEM_NAME = "boost_system" -BOOST_THREAD_NAME = "boost_thread" -BOOST_DATE_TIME_NAME = "boost_date_time" -BOOST_PROGRAM_OPTIONS_NAME = "boost_program_options" -BOOST_UNIT_TEST_NAME = "boost_unit_test_framework" - -BOOST_LIB_NAMES = [BOOST_SYSTEM_NAME, BOOST_THREAD_NAME, BOOST_DATE_TIME_NAME, BOOST_PROGRAM_OPTIONS_NAME, BOOST_UNIT_TEST_NAME] - -#figure out where the tools directory is -def self.get_tools_home - if ENV['TOOLS_HOME'] - fix_path(ENV['TOOLS_HOME'].gsub(/\\/,'/')) - else - abort 'The TOOLS_HOME environment variable is not set. On windows, set this in Control Panel -> System -> Advanced -> Environment variables. On linux add the following to the end of your ~/.bashrc export TOOLS_HOME=~/tools' - end -end - -def self.get_boost_version - if ENV['BOOST_VERSION'] - ENV['BOOST_VERSION'] - else - abort 'Environment variable BOOST_VERSION must be set in your main rakefile or OS environment. Format is booost_1_xx' - end -end - -def self.get_includes_dir - #puts get_tools_home - "#{get_tools_home}/boostlib/#{get_boost_version}/include".gsub(/\\/,'/') -end - -def self.get_libs_dir - __FILE__.pathmap("#{get_tools_home}/boostlib/#{get_boost_version}/#{$hw_os}") -end - -def self.get_shared_libs - ["-L#{get_libs_dir}"] + BOOST_LIB_NAMES.collect { |lib| "-l#{lib}" } -end - -def self.get_static_libs - BOOST_LIB_NAMES.collect { |lib| "#{get_libs_dir}/lib#{lib}.a" } -end - + +class Boost + +#names of the various boost libraries +BOOST_SYSTEM_NAME = "boost_system" +BOOST_THREAD_NAME = "boost_thread" +BOOST_DATE_TIME_NAME = "boost_date_time" +BOOST_PROGRAM_OPTIONS_NAME = "boost_program_options" +BOOST_UNIT_TEST_NAME = "boost_unit_test_framework" + +BOOST_LIB_NAMES = [BOOST_SYSTEM_NAME, BOOST_THREAD_NAME, BOOST_DATE_TIME_NAME, BOOST_PROGRAM_OPTIONS_NAME, BOOST_UNIT_TEST_NAME] + +#figure out where the tools directory is +def self.get_tools_home + if ENV['TOOLS_HOME'] + fix_path(ENV['TOOLS_HOME'].gsub(/\\/,'/')) + else + abort 'The TOOLS_HOME environment variable is not set. On windows, set this in Control Panel -> System -> Advanced -> Environment variables. On linux add the following to the end of your ~/.bashrc export TOOLS_HOME=~/tools' + end +end + +def self.get_boost_version + if ENV['BOOST_VERSION'] + ENV['BOOST_VERSION'] + else + abort 'Environment variable BOOST_VERSION must be set in your main rakefile or OS environment. Format is booost_1_xx' + end +end + +def self.get_includes_dir + #puts get_tools_home + "#{get_tools_home}/boostlib/#{get_boost_version}/include".gsub(/\\/,'/') +end + +def self.get_libs_dir + __FILE__.pathmap("#{get_tools_home}/boostlib/#{get_boost_version}/#{$hw_os}") +end + +def self.get_shared_libs + ["-L#{get_libs_dir}"] + BOOST_LIB_NAMES.collect { |lib| "-l#{lib}" } +end + +def self.get_static_libs + BOOST_LIB_NAMES.collect { |lib| "#{get_libs_dir}/lib#{lib}.a" } +end + end \ No newline at end of file diff --git a/tools/rake_build_system/plugins/rake.cpp.enviroment.rb b/tools/rake_build_system/plugins/rake.cpp.enviroment.rb index 74088886..35a5d765 100755 --- a/tools/rake_build_system/plugins/rake.cpp.enviroment.rb +++ b/tools/rake_build_system/plugins/rake.cpp.enviroment.rb @@ -1,88 +1,88 @@ - -# when buidling for ARM we have to modify PATH to point first to the cross compiler -if ENV['arm'] - ENV['PATH'] = case $hw_os - when 'pc_cygwin' - '/opt/crosstool/gcc-3.3.4-glibc-2.3.2/arm-unknown-linux-gnu/arm-unknown-linux-gnu/bin/:/opt/crosstool/gcc-3.3.4-glibc-2.3.2/arm-unknown-linux-gnu/bin/:' + ENV['PATH'] - when 'Linux_i686' - '/usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/bin:/usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/arm-linux/bin:' + ENV['PATH'] - else - puts "Don't know what cross-compiler to use for #{$hw_os}" - Process.exit(1) - end - $hw_os = 'pc_linux_arm' -end - -# defaults for compiler, arhiver, and indexer -$CC = ENV['ccache'] ? 'ccache g++' : 'g++' - -$AR = 'ar cruv' -$RANLIB = 'ranlib' -$LD = 'ld' - -COMPILER_VERSION = case $hw_os - when 'pc_cygwin' - '-gcc34' - when 'Linux_i686' - '-gcc41' - when 'pc_linux_arm' - '-gcc33' -end - -preprocessor = case $hw_os - when 'pc_cygwin' - ['APL_CYGWIN'] - when 'pc_linux_arm' - ['ARM'] - else [] -end - -if ENV['PREPROCESSOR'] - preprocessor << ENV['PREPROCESSOR'] -end - -$CC_PREPROCESSOR = preprocessor.collect { |d| "-D #{d}"}.join(' ') - -$WINSOCK_LIBS = case $hw_os - when 'pc_cygwin' - ['/lib/w32api/libwsock32.a','/lib/w32api/libws2_32.a'] - else - [] -end - -#By default, the build is set to debug -$WARN_FLAGS = ['-Wall'] -$RELEASE_TYPE = ENV['release'] ? 'release' : (ENV['coverage'] ? 'coverage' : 'debug') -$CC_FLAGS = case $RELEASE_TYPE - when 'release' - $hw_os == 'pc_linux_arm' ? ['-O3'] : ['-O3 -fPIC'] - when 'debug' - $hw_os == 'pc_linux_arm' ? [] : ['-g -fPIC'] # no gdb on arm, so no debug needed - when 'coverage' - $hw_os == 'pc_linux_arm' ? [] : ['-g -fPIC -O0 -fprofile-arcs -ftest-coverage -DNDEBUG -DPSI_LOGALL'] - else - puts "Unknown $RELEASE_TYPE = #{$RELEASE_TYPE}" - Process.exit 1 -end - -$OBJ_DIR = "#{$hw_os}/#{$RELEASE_TYPE}" - -$PLATFORM_LIBS = case $hw_os - when 'pc_cygwin' - ['-lpthread'] - when 'Linux_i686' - ['-lpthread'] - when 'pc_linux_arm' - ['-lpthread'] - else - [] -end - -RUBY_INC = case $hw_os - when 'pc_cygwin' - '/lib/ruby/1.8/i386-cygwin' - when 'Linux_i686' - '/usr/lib/ruby/1.8/i486-linux/' -end - -$PLATFORM_LIBS << '-lgcov' if $RELEASE_TYPE == 'coverage' + +# when buidling for ARM we have to modify PATH to point first to the cross compiler +if ENV['arm'] + ENV['PATH'] = case $hw_os + when 'pc_cygwin' + '/opt/crosstool/gcc-3.3.4-glibc-2.3.2/arm-unknown-linux-gnu/arm-unknown-linux-gnu/bin/:/opt/crosstool/gcc-3.3.4-glibc-2.3.2/arm-unknown-linux-gnu/bin/:' + ENV['PATH'] + when 'Linux_i686' + '/usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/bin:/usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/arm-linux/bin:' + ENV['PATH'] + else + puts "Don't know what cross-compiler to use for #{$hw_os}" + Process.exit(1) + end + $hw_os = 'pc_linux_arm' +end + +# defaults for compiler, arhiver, and indexer +$CC = ENV['ccache'] ? 'ccache g++' : 'g++' + +$AR = 'ar cruv' +$RANLIB = 'ranlib' +$LD = 'ld' + +COMPILER_VERSION = case $hw_os + when 'pc_cygwin' + '-gcc34' + when 'Linux_i686' + '-gcc41' + when 'pc_linux_arm' + '-gcc33' +end + +preprocessor = case $hw_os + when 'pc_cygwin' + ['APL_CYGWIN'] + when 'pc_linux_arm' + ['ARM'] + else [] +end + +if ENV['PREPROCESSOR'] + preprocessor << ENV['PREPROCESSOR'] +end + +$CC_PREPROCESSOR = preprocessor.collect { |d| "-D #{d}"}.join(' ') + +$WINSOCK_LIBS = case $hw_os + when 'pc_cygwin' + ['/lib/w32api/libwsock32.a','/lib/w32api/libws2_32.a'] + else + [] +end + +#By default, the build is set to debug +$WARN_FLAGS = ['-Wall'] +$RELEASE_TYPE = ENV['release'] ? 'release' : (ENV['coverage'] ? 'coverage' : 'debug') +$CC_FLAGS = case $RELEASE_TYPE + when 'release' + $hw_os == 'pc_linux_arm' ? ['-O3'] : ['-O3 -fPIC'] + when 'debug' + $hw_os == 'pc_linux_arm' ? [] : ['-g -fPIC'] # no gdb on arm, so no debug needed + when 'coverage' + $hw_os == 'pc_linux_arm' ? [] : ['-g -fPIC -O0 -fprofile-arcs -ftest-coverage -DNDEBUG -DPSI_LOGALL'] + else + puts "Unknown $RELEASE_TYPE = #{$RELEASE_TYPE}" + Process.exit 1 +end + +$OBJ_DIR = "#{$hw_os}/#{$RELEASE_TYPE}" + +$PLATFORM_LIBS = case $hw_os + when 'pc_cygwin' + ['-lpthread'] + when 'Linux_i686' + ['-lpthread'] + when 'pc_linux_arm' + ['-lpthread'] + else + [] +end + +RUBY_INC = case $hw_os + when 'pc_cygwin' + '/lib/ruby/1.8/i386-cygwin' + when 'Linux_i686' + '/usr/lib/ruby/1.8/i486-linux/' +end + +$PLATFORM_LIBS << '-lgcov' if $RELEASE_TYPE == 'coverage' diff --git a/tools/rake_build_system/plugins/rake.crosstest.rb b/tools/rake_build_system/plugins/rake.crosstest.rb index 85d8fccb..4b33f037 100755 --- a/tools/rake_build_system/plugins/rake.crosstest.rb +++ b/tools/rake_build_system/plugins/rake.crosstest.rb @@ -1,35 +1,35 @@ -require 'net/ftp' -require 'net/ssh' - -module CrossTest - - def self.put(host, user, passwd, file) - ftp = Net::FTP.new(host, user, passwd) - STDOUT.sync = true - ftp.putbinaryfile(file) { |block| print '*' } - ftp.close - end - - def self.get(host, user, passwd, remote_file, local_file) - ftp = Net::FTP.new(host, user, passwd) - STDOUT.sync = true - ftp.getbinaryfile(remote_file, local_file) { |block| print '*' } - ftp.close - end - - def self.run_tests(host, user, passwd, file) - Net::SSH.start(host, user, :password => passwd) do |ssh| - ssh.exec! "rm report.xml" - ssh.exec! "chmod +x #{file}" - ssh.exec! "./#{file} --output_format=XML --log_level=all --report_level=no > report.xml" - ssh.exec! "rm #{file}" - end - end - - def self.do_test_sequence(host, user, passwd, file, testfile) - self.put(host, user, passwd, file) - self.run_tests(host, user, passwd, File.basename(file)) - self.get(host, user, passwd, 'report.xml', testfile) - end - +require 'net/ftp' +require 'net/ssh' + +module CrossTest + + def self.put(host, user, passwd, file) + ftp = Net::FTP.new(host, user, passwd) + STDOUT.sync = true + ftp.putbinaryfile(file) { |block| print '*' } + ftp.close + end + + def self.get(host, user, passwd, remote_file, local_file) + ftp = Net::FTP.new(host, user, passwd) + STDOUT.sync = true + ftp.getbinaryfile(remote_file, local_file) { |block| print '*' } + ftp.close + end + + def self.run_tests(host, user, passwd, file) + Net::SSH.start(host, user, :password => passwd) do |ssh| + ssh.exec! "rm report.xml" + ssh.exec! "chmod +x #{file}" + ssh.exec! "./#{file} --output_format=XML --log_level=all --report_level=no > report.xml" + ssh.exec! "rm #{file}" + end + end + + def self.do_test_sequence(host, user, passwd, file, testfile) + self.put(host, user, passwd, file) + self.run_tests(host, user, passwd, File.basename(file)) + self.get(host, user, passwd, 'report.xml', testfile) + end + end \ No newline at end of file diff --git a/tools/rake_build_system/plugins/rake.swigjava.rb b/tools/rake_build_system/plugins/rake.swigjava.rb index 0688af34..ebae59aa 100755 --- a/tools/rake_build_system/plugins/rake.swigjava.rb +++ b/tools/rake_build_system/plugins/rake.swigjava.rb @@ -1,85 +1,85 @@ - - -jdk_home = if ENV['JDK_HOME'] - ENV['JDK_HOME'] -elsif ENV['JAVA_HOME'] - ENV['JAVA_HOME'] -else - puts 'To use the swig-java plugin, the JDK_HOME or JAVA_HOME environment variables must be set to your JDK directory' - nil -end - -if jdk_home - if File.directory? jdk_home - jdk_home = File.expand_path jdk_home #this will normailze to linux slashes in case we're using an ENV var from windows - else - puts "Invalid jdk path #{jdk_home}" - exit -1 - end - - puts "Using jdk directory #{jdk_home}" - - platform = case $hw_os #need this to get the correct directory for some of the jni includes - when 'pc_cygwin' - 'win32' - else - 'linux' - end - - jdk_includes = ["#{jdk_home}/include","#{jdk_home}/include/#{platform}"] - - def add_swig_java_dependencies(name, options) - - includes = options[:includes].flatten # these already are paths - includes << options[:dir] #the project directory should always be explicitly on the include path - - package = if options[:java_package] - "-package #{options[:java_package]}" - else - '' - end - - outdir = if options[:java_outdir] - dir = "#{options[:dir]}/#{options[:java_outdir]}" - directory dir #create the directory - dir - else - nil - end - - get_generated_swig_java_cpp(options[:dir]).each do |cppfile| - ifile = cppfile.ext('.i') - file cppfile => outdir if outdir - outdirective = '' - outdirective = "-outdir #{outdir}" if outdir - file cppfile => ifile do |t| - # we need to add this define that gcc normally adds if we are on 64bit - declares_necessary = [] - declares_necessary << '__x86_64__' if `uname -m`.strip == 'x86_64' - declares = declares_necessary.collect{|d|"-D#{d}"}.join(' ') - puts "creating swig cpp/java binding from #{ifile} (#{declares})" - sh "swig -c++ -java #{package} #{include_string(includes)} #{outdirective} #{declares} -o #{cppfile} #{ifile}" - end - end - - end - - def get_generated_swig_java_cpp(dir) - FileList["#{dir}/*.i"].ext('.cpp') - end - - $pre_build_lambdas << lambda do |name, options| - if options[:plugins] and (options[:plugins].include? 'swigjava') - options[:includes] ||= [] - options[:includes] += jdk_includes # add the jdk includes so that they are seen by both swig and C++ - options[:dynamic_src] ||= [] - options[:dynamic_src] += get_generated_swig_java_cpp options[:dir] - end - end - - $build_lambdas << lambda do |name, options| - if options[:plugins] and (options[:plugins].include? 'swigjava') - add_swig_java_dependencies(name, options) - end - end -end + + +jdk_home = if ENV['JDK_HOME'] + ENV['JDK_HOME'] +elsif ENV['JAVA_HOME'] + ENV['JAVA_HOME'] +else + puts 'To use the swig-java plugin, the JDK_HOME or JAVA_HOME environment variables must be set to your JDK directory' + nil +end + +if jdk_home + if File.directory? jdk_home + jdk_home = File.expand_path jdk_home #this will normailze to linux slashes in case we're using an ENV var from windows + else + puts "Invalid jdk path #{jdk_home}" + exit -1 + end + + puts "Using jdk directory #{jdk_home}" + + platform = case $hw_os #need this to get the correct directory for some of the jni includes + when 'pc_cygwin' + 'win32' + else + 'linux' + end + + jdk_includes = ["#{jdk_home}/include","#{jdk_home}/include/#{platform}"] + + def add_swig_java_dependencies(name, options) + + includes = options[:includes].flatten # these already are paths + includes << options[:dir] #the project directory should always be explicitly on the include path + + package = if options[:java_package] + "-package #{options[:java_package]}" + else + '' + end + + outdir = if options[:java_outdir] + dir = "#{options[:dir]}/#{options[:java_outdir]}" + directory dir #create the directory + dir + else + nil + end + + get_generated_swig_java_cpp(options[:dir]).each do |cppfile| + ifile = cppfile.ext('.i') + file cppfile => outdir if outdir + outdirective = '' + outdirective = "-outdir #{outdir}" if outdir + file cppfile => ifile do |t| + # we need to add this define that gcc normally adds if we are on 64bit + declares_necessary = [] + declares_necessary << '__x86_64__' if `uname -m`.strip == 'x86_64' + declares = declares_necessary.collect{|d|"-D#{d}"}.join(' ') + puts "creating swig cpp/java binding from #{ifile} (#{declares})" + sh "swig -c++ -java #{package} #{include_string(includes)} #{outdirective} #{declares} -o #{cppfile} #{ifile}" + end + end + + end + + def get_generated_swig_java_cpp(dir) + FileList["#{dir}/*.i"].ext('.cpp') + end + + $pre_build_lambdas << lambda do |name, options| + if options[:plugins] and (options[:plugins].include? 'swigjava') + options[:includes] ||= [] + options[:includes] += jdk_includes # add the jdk includes so that they are seen by both swig and C++ + options[:dynamic_src] ||= [] + options[:dynamic_src] += get_generated_swig_java_cpp options[:dir] + end + end + + $build_lambdas << lambda do |name, options| + if options[:plugins] and (options[:plugins].include? 'swigjava') + add_swig_java_dependencies(name, options) + end + end +end