Merge "There are Two modifications. 1. Restucturing Notification Manager Class ...
authorUze Choi <uzchoi@samsung.com>
Mon, 15 Dec 2014 05:01:33 +0000 (21:01 -0800)
committerGerrit Code Review <gerrit@oicreview.vlan14.01.org>
Mon, 15 Dec 2014 05:01:33 +0000 (21:01 -0800)
279 files changed:
.gitignore
Readme.scons.txt [new file with mode: 0644]
SConstruct [new file with mode: 0644]
arduino.scons [new file with mode: 0644]
auto_build.sh [moved from resource/auto_build.sh with 51% similarity]
build_common/SConscript [new file with mode: 0644]
build_common/android/SConscript [moved from resource/build_common/android/SConscript with 76% similarity]
build_common/android/jni/Android.mk [moved from resource/build_common/android/jni/Android.mk with 93% similarity]
build_common/arduino/SConscript [new file with mode: 0755]
build_common/darwin/SConscript [new file with mode: 0644]
build_common/ios/SConscript [new file with mode: 0644]
build_common/linux/SConscript [new file with mode: 0644]
build_common/windows/SConscript [new file with mode: 0644]
extra_options.scons [new file with mode: 0644]
resource/Readme.scons.txt [deleted file]
resource/SConscript [new file with mode: 0644]
resource/SConstruct [deleted file]
resource/arduino.scons [deleted file]
resource/buildScript.mk
resource/build_common/SConscript [deleted file]
resource/build_common/arduino/SConscript [deleted file]
resource/build_common/darwin/SConscript [deleted file]
resource/build_common/ios/SConscript [deleted file]
resource/build_common/linux/SConscript [deleted file]
resource/build_common/windows/SConscript [deleted file]
resource/csdk/SConscript
resource/csdk/libcoap-4.1.1/SConscript
resource/csdk/libcoap-4.1.1/block.h
resource/csdk/libcoap-4.1.1/makefile
resource/csdk/libcoap-4.1.1/net.c
resource/csdk/libcoap-4.1.1/net.h
resource/csdk/libcoap-4.1.1/pdu.h
resource/csdk/libcoap-4.1.1/sec/netdtls.c
resource/csdk/makefile
resource/csdk/occoap/include/occoap.h
resource/csdk/occoap/include/occoaphelper.h
resource/csdk/occoap/src/occoap.c
resource/csdk/occoap/src/occoaphelper.c
resource/csdk/ocmalloc/include/ocmalloc.h
resource/csdk/ocmalloc/src/ocmalloc.c
resource/csdk/ocmalloc/test/linux/makefile
resource/csdk/ocmalloc/test/linux/unittest.cpp
resource/csdk/ocsocket/include/ocsocket.h
resource/csdk/ocsocket/src/ocsocket.c
resource/csdk/ocsocket/test/sendrecv.cpp
resource/csdk/stack/include/internal/occlientcb.h
resource/csdk/stack/include/internal/occollection.h
resource/csdk/stack/include/internal/ocobserve.h
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocresourcehandler.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocserverrequest.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocsecurity.h [new file with mode: 0644]
resource/csdk/stack/include/ocsecurityconfig.h [new file with mode: 0644]
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/common.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/makefile
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h
resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.h
resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/common.cpp
resource/csdk/stack/samples/linux/secure/common.h [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/makefile
resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp
resource/csdk/stack/samples/linux/secure/occlientbasicops.h
resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/secure/ocserverbasicops.h
resource/csdk/stack/src/occlientcb.c
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocobserve.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocsecurity.c [new file with mode: 0644]
resource/csdk/stack/src/ocserverrequest.c [new file with mode: 0644]
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/arduino/makefile
resource/csdk/stack/test/makefile
resource/csdk/stack/test/stacktests.cpp
resource/examples/SConscript
resource/examples/fridgeclient.cpp
resource/examples/fridgeserver.cpp
resource/examples/garageclient.cpp
resource/examples/garageserver.cpp
resource/examples/ocicuc/Makefile
resource/examples/ocicuc/SConscript
resource/examples/ocicuc/client.cpp
resource/examples/ocicuc/demo_client.hpp
resource/examples/ocicuc/light_resource.cpp
resource/examples/ocicuc/light_resource.hpp
resource/examples/ocicuc/server.cpp
resource/examples/ocicuc/utility.hpp
resource/examples/presenceclient.cpp
resource/examples/presenceserver.cpp
resource/examples/roomclient.cpp
resource/examples/roomserver.cpp
resource/examples/simpleclient.cpp
resource/examples/simpleclientHQ.cpp
resource/examples/simpleclientserver.cpp
resource/examples/simpleserver.cpp
resource/examples/simpleserverHQ.cpp
resource/examples/threadingsample.cpp
resource/include/AttributeValue.h [new file with mode: 0644]
resource/include/IClientWrapper.h
resource/include/IServerWrapper.h
resource/include/InProcClientWrapper.h
resource/include/InProcServerWrapper.h
resource/include/OCApi.h
resource/include/OCPlatform.h
resource/include/OCPlatform_impl.h
resource/include/OCRepresentation.h
resource/include/OCResource.h
resource/include/OCResourceRequest.h
resource/include/OCResourceResponse.h
resource/include/OCSerialization.h [new file with mode: 0644]
resource/include/OicJsonSerializer.hpp [new file with mode: 0644]
resource/include/OutOfProcClientWrapper.h
resource/include/OutOfProcServerWrapper.h
resource/include/ResourceInitException.h
resource/include/StringConstants.h
resource/include/WrapperFactory.h
resource/makefile
resource/oc_logger/SConscript
resource/oc_logger/examples/SConscript [new file with mode: 0644]
resource/oc_logger/examples/test_logging.cpp
resource/patches/cereal_gcc46.patch [new file with mode: 0644]
resource/releaseNotes/Dec6th2014.txt [new file with mode: 0644]
resource/src/InProcClientWrapper.cpp
resource/src/InProcServerWrapper.cpp
resource/src/OCException.cpp
resource/src/OCPlatform.cpp
resource/src/OCPlatform_impl.cpp
resource/src/OCRepresentation.cpp [new file with mode: 0644]
resource/src/OCResource.cpp
resource/src/OCUtilities.cpp
resource/src/SConscript
resource/third_party_libs.scons
resource/unittests/makefile
resource/unittests/tests.cpp
scons_script_how_to.txt [new file with mode: 0644]
service/SConscript [new file with mode: 0644]
service/notification-manager/SConscript [new file with mode: 0644]
service/notification-manager/SampleApp/SConscript [new file with mode: 0644]
service/notification-manager/SampleApp/arduino/SConscript [new file with mode: 0644]
service/notification-manager/SampleApp/linux/SConscript [new file with mode: 0644]
service/protocol-plugin/SConscript [new file with mode: 0644]
service/protocol-plugin/build/linux/Makefile
service/protocol-plugin/lib/cpluff/SConscript [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp [new file with mode: 0644]
service/protocol-plugin/plugin-manager/SConscript [new file with mode: 0644]
service/protocol-plugin/plugin-manager/build/linux/Makefile
service/protocol-plugin/plugin-manager/src/Config.cpp [new file with mode: 0644]
service/protocol-plugin/plugin-manager/src/Config.h [new file with mode: 0644]
service/protocol-plugin/plugin-manager/src/CpluffAdapter.cpp
service/protocol-plugin/plugin-manager/src/CpluffAdapter.h
service/protocol-plugin/plugin-manager/src/FelixAdapter.cpp
service/protocol-plugin/plugin-manager/src/FelixAdapter.h
service/protocol-plugin/plugin-manager/src/Plugin.cpp
service/protocol-plugin/plugin-manager/src/Plugin.h
service/protocol-plugin/plugin-manager/src/PluginManager.cpp
service/protocol-plugin/plugin-manager/src/PluginManager.h
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.cpp
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.h
service/protocol-plugin/plugins/SConscript [new file with mode: 0644]
service/protocol-plugin/plugins/mqtt-fan/build/linux/Makefile
service/protocol-plugin/plugins/mqtt-fan/lib/Makefile
service/protocol-plugin/plugins/mqtt-fan/lib/SConscript [new file with mode: 0644]
service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript [new file with mode: 0644]
service/protocol-plugin/plugins/mqtt-fan/lib/python/Makefile
service/protocol-plugin/plugins/mqtt-fan/src/fanserver.cpp
service/protocol-plugin/plugins/mqtt-light/build/linux/Makefile
service/protocol-plugin/plugins/mqtt-light/lib/Makefile
service/protocol-plugin/plugins/mqtt-light/lib/python/Makefile
service/protocol-plugin/plugins/mqtt-light/src/lightserver.cpp
service/protocol-plugin/readme
service/protocol-plugin/sample-app/SConscript [new file with mode: 0644]
service/protocol-plugin/sample-app/linux/SConscript [new file with mode: 0644]
service/protocol-plugin/sample-app/linux/fan-control/Makefile [deleted file]
service/protocol-plugin/sample-app/linux/mqtt/Makefile [new file with mode: 0644]
service/protocol-plugin/sample-app/linux/mqtt/mqttclient.cpp [moved from service/protocol-plugin/sample-app/linux/fan-control/fanclient.cpp with 83% similarity]
service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml [new file with mode: 0644]
service/soft-sensor-manager/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SDK/build/linux/Makefile
service/soft-sensor-manager/SDK/include/ISSMClientListener.h
service/soft-sensor-manager/SDK/include/SSMClient.h
service/soft-sensor-manager/SDK/src/InprocSSMCore.cpp [new file with mode: 0644]
service/soft-sensor-manager/SDK/src/SSMClient.cpp
service/soft-sensor-manager/SSMCore/build/linux/Makefile
service/soft-sensor-manager/SSMCore/include/SSMInterface.h [new file with mode: 0644]
service/soft-sensor-manager/SSMCore/src/Common/InternalInterface.h
service/soft-sensor-manager/SSMCore/src/Common/PlatformLayer.h
service/soft-sensor-manager/SSMCore/src/Common/ThreadManager.cpp
service/soft-sensor-manager/SSMCore/src/Common/sqlite3.h
service/soft-sensor-manager/SSMCore/src/QueryProcessor/PropagationEngine.cpp
service/soft-sensor-manager/SSMCore/src/QueryProcessor/PropagationEngine.h
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore.h
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMResourceServer.cpp
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMResourceServer.h [moved from service/soft-sensor-manager/SSMCore/include/SSMResourceServer.h with 85% similarity]
service/soft-sensor-manager/SSMCore/src/SSMInterface/SoftSensorManager.cpp
service/soft-sensor-manager/SSMCore/src/SSMInterface/SoftSensorManager.h
service/soft-sensor-manager/SSMCore/src/SSMResourceServerLauncher.cpp [deleted file]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextExecutor.cpp
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextExecutor.h
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextRepository.cpp
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextRepository.h
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.cpp [deleted file]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.h [deleted file]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceFinder.cpp
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceFinder.h
service/soft-sensor-manager/SSMCore/src/SensorProcessor/SensingEngine.cpp [moved from service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResponseReactor.cpp with 81% similarity]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/SensingEngine.h [moved from service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResponseReactor.h with 84% similarity]
service/soft-sensor-manager/SampleApp/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build/Makefile
service/soft-sensor-manager/SampleApp/arduino/THSensorApp/src/thserver.cpp
service/soft-sensor-manager/SampleApp/linux/Makefile
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/build/Makefile [moved from service/soft-sensor-manager/SampleApp/linux/ClientApp/build/Makefile with 62% similarity]
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/include/SSMTestApp.h [moved from service/soft-sensor-manager/SampleApp/linux/ClientApp/include/SSMTestApp.h with 84% similarity]
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/src/SSMTestApp.cpp [moved from service/soft-sensor-manager/SampleApp/linux/ClientApp/src/SSMTestApp.cpp with 60% similarity]
service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/linux/THSensorApp/build/Makefile
service/soft-sensor-manager/SampleApp/linux/THSensorApp/include/ThingResourceServer.h
service/soft-sensor-manager/SampleApp/linux/THSensorApp/src/ThingResourceServer.cpp
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/build/Makefile
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/include/ThingResourceServer1.h
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/src/ThingResourceServer1.cpp
service/soft-sensor-manager/SampleApp/tizen/ClientApp/CMakeLists.txt [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/build.sh [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.rule [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.xml [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/ISSMClientListener.h [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.cpp [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.h [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.service [deleted file]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/README [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/README with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/RELEASE.txt [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/RELEASE.txt with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/makefile_org [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/makefile_org with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/CMakeLists.txt [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/CMakeLists.txt with 88% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-log.h [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-log.h with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-test.cpp [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-test.cpp with 76% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-test.h [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-test.h with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-utils.c [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-utils.c with 96% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-utils.h [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-utils.h with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/packaging/ssm.manifest [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.manifest with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/packaging/ssm.spec [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.spec with 65% similarity]
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/SoftSensorDescription.xml [new file with mode: 0644]
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/HighContextDictionary.xml [deleted file]
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/Makefile
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/src/DiscomfortIndexSensor.cpp
service/soft-sensor-manager/build/arduino/Makefile
service/soft-sensor-manager/build/arduino/environment.mk
service/soft-sensor-manager/build/arduino/local.properties
service/soft-sensor-manager/build/linux/Makefile
service/soft-sensor-manager/build/linux/environment.mk
service/things-manager/SConscript [new file with mode: 0644]
service/things-manager/sampleapp/SConscript [new file with mode: 0644]
service/things-manager/sampleapp/linux/tgmclient/SConscript [new file with mode: 0644]
service/third_party_libs.scons [new file with mode: 0644]

index 7583ff5..a5463f0 100644 (file)
@@ -1,16 +1,30 @@
 # Ignore output dirs
 /release
-/csdk/release
-/csdk/libcoap-4.1.1/release/
-/examples/release
+resource/release
+resource/csdk/release
+resource/csdk/libcoap-4.1.1/release/
+resource/examples/release
+resource/examples/debug
 
 /debug
-csdk/debug/
-csdk/libcoap-4.1.1/debug/
-/examples/debug
-csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/debug
+resource/csdk/debug/
+resource/csdk/libcoap-4.1.1/debug/
+resource/csdk/libcoap-4.1.1/linux/
+resource/csdk/linux
+resource/csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/csdk/stack/samples/linux/SimpleClientServer/release/
 
+resource/csdk/connectivity/build/out/
 
+resource/oc_logger/bin/
+resource/oc_logger/lib/
+resource/oc_logger/samples/linux/release/
+resource/oc_logger/samples/linux/debug
+
+service/things-manager/build/linux/release
+service/things-manager/build/linux/debug
+service/things-manager/sdk/build/linux/
 # Ignore any object files
 *.o
 *.obj
@@ -20,3 +34,13 @@ csdk/stack/samples/linux/SimpleClientServer/debug/
 *.settings/
 *.cproject
 *.project
+
+# Ignore dependencies folder, which should be generated
+dependencies/
+
+#ignore Klocwork stuff
+.kwlp/
+.kwps/
+
+#ignore various swap files
+*.swp
diff --git a/Readme.scons.txt b/Readme.scons.txt
new file mode 100644 (file)
index 0000000..8956c2d
--- /dev/null
@@ -0,0 +1,187 @@
+== How to build Iotivity projects ==
+
+Iotivity includes a series of projects. You can find all these projects here:
+    https://oic-review.01.org/gerrit/#/admin/projects/
+
+You can build Iotivity project on Linux / Windows / MAC OSX for various OS(
+Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...).
+The output of the build is in:
+  <top directory of the project>/out/<target_os>/<target_arch>/<build version>/
+e.g.
+       oic-resource/out/android/armeabi-v7a/release/.
+
+This document takes oic-resource project as example, the way to build other
+projects is almost the same.
+
+=== Iotivity project build tool scons ===
+
+Scons is a cross-platform build tool, its usage is quite similar to GNU make.
+To build a project, you just require to run following command at the directory
+where a SConstruct file exists(SConstruct is the entrance of scons build, it's
+equivalent to Makefile of 'make') :
+      $ scons [options] [target]
+
+In additional, usually the scons build script of a project provides useful help
+information(include build options). To see the help information:
+      $ scons [options] -h
+
+Note: If no value is specified for an option, the default value will be used.
+The change of options value may impact the output.
+
+
+=== Prerequites ===
+
+* 1. Scons
+
+Please refer to the following page to install scons:
+   http://www.scons.org/doc/production/HTML/scons-user.html#chap-build-install
+(Note: on Windows, install Python 2.x before installing scons)
+
+* 2. IDE/SDK Prerequites
+To build for some OS (Android / Arduino / IOS ...), an IDE/SDK may be required,
+please go to the relative page to download and install the required IDE/SDK.
+
+Android:
+To build for Android, Andorid NDK and SDK are required.
+  Android NDK: http://developer.android.com/tools/sdk/ndk/index.html
+  Android SDK: http://developer.android.com/sdk/index.html
+(Note: as in some Iotivity projects, C++11 features are used, recommend Android
+ NDK >= r10, according to our test result r10c is the best one currently)
+
+Arduino:
+To build for Arduino, Arduino IDE is required.
+  Arduino IDE: http://arduino.cc/en/Main/Software
+  (Note: recommend install Arduino IDE >=1.5.7)
+
+Arduino builds are dependent on latest Time library. Download it from here:
+    http://www.pjrc.com/teensy/td_libs_Time.html
+and extract to <arduino_ide_root>/libraries/
+
+(Note: If you are using Arduino IDE 1.5.8 BETA on Windows, it may pop up some
+dll isn't found. please copy relative dll from the IDE directory to
+C:\Windows\SysWOW64. IDE 1.5.7 doesn't have this issue. Other version IDE isn't
+tested.)
+
+Apple:
+To build for Mac OSX or IOS, Xcode is required.
+  Xcode: https://developer.apple.com/xcode/downloads/
+
+Java:
+To build the Java code, JDK is required.
+  JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html
+(If the project doesn't include Java code or you wouldn't like build the
+Java codes, this isn't required)
+
+(Note: for convenience, suggest add the IDE/SDK path in environment variable,
+so you don't need to add it in command line each time. The build script will
+guide you to do that.)
+
+* 3. External libraries
+For Android and IOS build, most of the external libraries are provided as
+binary in oic-utilities project (https://oic-review.01.org/gerrit/oic-utilities).
+Please download it in the same directory as other Iotivity projects. If it's
+in different directory, an additional option (OIC_UITLS) will be required. The
+build command should be:
+      $ scons OIC_UITLS=<path to oic-utilities> [other options] [target]
+
+(Note: for convenience, you can also add it in environment variable. So you
+don't need to add this option in command line each time.)
+  e.g.:
+      $ export OIC_UITLS=<path to oic-utilities project>
+
+
+=== Build Iotivity project on Linux(Ubuntu) ===
+
+1. Build Iotivity project for Linux
+      $ cd <top directory of the project>
+      $ sudo apt-get install libboost-dev libboost-program-options-dev
+      $ scons
+
+2. Build Iotivity project for Android
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard. To see all of its
+allowed value, please execute command 'scons TARGET_OS=android -Q -h'.
+
+Note: Currently as x86_64/arm64_v8a external library binaries aren't provided,
+you may meet link problem if build executable binary which depends on external
+library for x86_64/arm64_v8a.
+
+3. Build Iotivity project for Arduino
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy
+(xxx can be avr, arm; yyy is the name of the board, to get its allowed value
+run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in
+the output of above command line, that's due to some boards have different
+processor, to specify the processor, add 'CPU=zzz' in the command line. If no
+'CPU' option exists, that means the board only support one kind of processor,
+it's unnecessary to specify it)
+
+
+=== Build Iotivity project on Windows ===
+
+1. Build Iotivity project for Android(It's the same as on Ubuntu)
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard ...)
+
+2. Build Iotivity project for Arduino(It's the same as on Ubuntu)
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy
+(xxx can be avr, arm; yyy is the name of the board, to get its allowed value
+run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in
+the output of above command line, that's due to some boards have different
+processor, to specify the processor, add 'CPU=zzz' in the command line. If no
+'CPU' option exists, that means the board only support one kind of processor,
+it's unnecessary to specify it)
+
+
+Note: Currently most Iotivity project doesn't support Windows, so you can't set
+TARGET_OS to 'windows' except the project support Windows.
+
+That's to say if the project doesn't support Windows, run:
+      $ scons TARGET_OS=windows ....
+or run on Windows
+      $ scons
+may always fail.
+
+
+=== Build Iotivity project on Mac OSX ===
+
+1. Build Iotivity project for Mac OSX
+      $ cd <top directory of the project>
+      $ scons SYS_VERSION=yyy
+(yyy is the OSX version, e.g. 10.9)
+
+2. Build Iotivity project for Android(It's the same as on Ubuntu)
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard)
+
+3. Build Iotivity project for IOS
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=ios TARGET_ARCH=xxx SYS_VERSION=yyy
+(xxx can be i386, x86_64, armv7, armv7s, arm64, yyy is IOS version, e.g. 7.0)
+
+Note:
+1) for convenience, a script (auto_build.sh) is provided to run possible build
+at once. Following is the usage:
+
+To build:
+     $ auto_build.sh <path-to-android-ndk> <path-to-arduino-home>
+To clean:
+     $ auto_build.sh -c
+
+2) Last sync and test with commit e9403ce6d4d7a1a0ac8d12c5acc876af7f7a8f76
+If you meet build error with newest code, it may due to the scripts are not up
+to date. Please try commit 5f16c38a5380e4b5c0d82e2cfea4af5fdc30c9ac or send mail
+to <OIC-OSD@list.01.org>.
+
+3) The build scripts for services have been provided. As the services code is
+out of date, it must the sync with newest resource code, otherwise, it can't
+pass the build, currently, the build scripts for services aren't enabled. Please
+remove the '#' at line 31 in 'SConstruct' file to enable it after the code is
+updated.
+
+4) For Arduino build, the Time library should >=1.3. The old can only be built
+with Arduino IDE 1.0.x
diff --git a/SConstruct b/SConstruct
new file mode 100644 (file)
index 0000000..fd1b034
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# The main build script
+#
+##
+
+# Load common build config
+SConscript('build_common/SConscript')
+
+# Load extra options
+SConscript('extra_options.scons')
+Import('env')
+
+target_os = env.get('TARGET_OS')
+if target_os == 'arduino':
+       SConscript('arduino.scons')
+# By default, src_dir is current dir, the build_dir is:
+#     ./out/<target_os>/<target_arch>/<release or debug>/
+#
+# The build_dir is a variant directory of the source directory(You can
+# consider build_dir as a soft link to src_dir, for detail please refer to:
+#     http://www.scons.org/doc/production/HTML/scons-user.html#f-VariantDir
+#
+# Any way, to make the output is in build_dir, when load scripts, the path should
+# be relevant to build_dir.
+build_dir = env.get('BUILD_DIR')
+
+# Build 'resource' sub-project
+SConscript(build_dir + 'resource/SConscript')
+
+# Build 'service' sub-project
+#SConscript(build_dir + 'service/SConscript')
+
+# Append targets information to the help information, to see help info, execute command line:
+#     $ scon [options] -h
+env.PrintTargets()
+
+# Print bin upload command line (arduino only)
+if target_os == 'arduino':
+       env.UploadHelp()
diff --git a/arduino.scons b/arduino.scons
new file mode 100644 (file)
index 0000000..4ab2aff
--- /dev/null
@@ -0,0 +1,11 @@
+##
+# This script includes arduino specific config for oic-resource
+##
+Import('env')
+
+env.ImportLib('Time')
+if env.get('NET') == 'Ethernet':
+       env.ImportLib('Ethernet')
+else:
+       env.ImportLib('WiFi')
+env.ImportLib('SPI')
\ No newline at end of file
similarity index 51%
rename from resource/auto_build.sh
rename to auto_build.sh
index 14aca7f..9f947eb 100755 (executable)
@@ -4,58 +4,58 @@ function clean()
 {
        echo "*********** Clean build *************"
        scons -c
-       rm out -rf
+       rm -rf out
 }
 
 function build()
 {
-       echo "*********** Build for linux *************"
-       scons
+       if [ $(uname -s) = "Linux" ]
+        then
+               echo "*********** Build for linux *************"
+               scons RELEASE=$3
+       fi
 
        # Note: for android, as oic-resource uses C++11 feature stoi and to_string,
        # it requires gcc-4.9, currently only android-ndk-r10(for linux)
        # and windows android-ndk-r10(64bit target version) support these features.
 
        echo "*********** Build for android x86 *************"
-       scons BUILD_TARGET=Android CPU_ARCH=x86 ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=x86 ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for android armeabi *************"
-       scons BUILD_TARGET=Android CPU_ARCH=armeabi ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=armeabi ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for android armeabi-v7a *************"
-       scons BUILD_TARGET=Android CPU_ARCH=armeabi-v7a ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=armeabi-v7a ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for android armeabi-v7a-hard *************"
-       scons BUILD_TARGET=Android CPU_ARCH=armeabi-v7a-hard ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=armeabi-v7a-hard ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for arduino avr *************"
-       scons BUILD_TARGET=Arduino CPU_ARCH=avr ARDUINO_HOME=$3
+       scons TARGET_OS=arduino TARGET_ARCH=avr ARDUINO_HOME=$2 RELEASE=$3
 
        echo "*********** Build for arduino arm *************"
-       scons BUILD_TARGET=Arduino CPU_ARCH=arm ARDUINO_HOME=$3
+       scons TARGET_OS=arduino TARGET_ARCH=arm ARDUINO_HOME=$2 RELEASE=$3
 
        if [ $(uname -s) = "Darwin" ]
        then
-               echo "*********** Build for OSX i386 *************"
-               scons BUILD_TARGET=Darwin CPU_ARCH=i386 SYS_VERSION=10.9
-
-               echo "*********** Build for OSX x86_64 *************"
-               scons BUILD_TARGET=Darwin CPU_ARCH=x86_64 SYS_VERSION=10.9
+               echo "*********** Build for OSX *************"
+               scons TARGET_OS=darwin SYS_VERSION=10.9 RELEASE=$3
 
                echo "*********** Build for IOS i386 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=i386 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=i386 SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS x86_64 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=x86_64 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=x86_64 SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS armv7 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=armv7 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=armv7 SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS armv7s *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=armv7s SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=armv7s SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS arm64 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=arm64 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=arm64 SYS_VERSION=7.0 RELEASE=$3
        fi
 }
 
@@ -63,7 +63,7 @@ function  help()
 {
        echo "Usage:"
         echo "  build:"
-        echo "     `basename $0` <path-to-android-sdk> <path-to-android-ndk> <path-to-arduino-home>"
+        echo "     `basename $0` <path-to-android-ndk> <path-to-arduino-home>"
         echo "  clean:"
         echo "     `basename $0` -c"
 }
@@ -78,12 +78,14 @@ then
                help
                exit -1
        fi
-elif [ $# -ne 3 ]
+elif [ $# -ne 2 ]
 then
        help
        exit -1
 fi
 
-
-build $1 $2 $3
+# Suppress "Reading ..." message and enable parallel build
+export SCONSFLAGS="-Q -j 8"
+build $1 $2 true
+build $1 $2 false
 echo "===================== done ====================="
diff --git a/build_common/SConscript b/build_common/SConscript
new file mode 100644 (file)
index 0000000..c6708e4
--- /dev/null
@@ -0,0 +1,182 @@
+##
+# This script includes generic build options:
+#    release/debug, target os, target arch, cross toolchain, build environment etc
+##
+import os
+import platform
+
+# Map of host os and allowed target os (host: allowed target os)
+host_target_map = {
+               'linux': ['linux', 'android', 'arduino'],
+               'windows': ['windows', 'winrt', 'android', 'arduino'],
+               'darwin': ['darwin', 'ios', 'android', 'arduino'],
+               }
+
+# Map of os and allowed archs (os: allowed archs)
+os_arch_map = {
+               'linux': ['x86', 'x86_64', 'arm', 'arm64'],
+               'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'],
+               'windows': ['x86', 'amd64', 'arm'],
+               'winrt': ['arm'],
+               'darwin': ['i386', 'x86_64'],
+               'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'],
+               'arduino': ['avr', 'arm'],
+               }
+
+host = platform.system().lower()
+
+if not host_target_map.has_key(host):
+       print "\nError: Current system (%s) isn't supported\n" % host
+       Exit(1)
+
+######################################################################
+# Get build options (the optins from command line)
+######################################################################
+target_os = ARGUMENTS.get('TARGET_OS', host).lower() # target os
+
+if target_os not in host_target_map[host]:
+       print "\nError: Unknown target os: %s (Allow values: %s)\n" % (target_os, host_target_map[host])
+       Exit(1)
+
+default_arch = platform.machine()
+if default_arch not in os_arch_map[target_os]:
+       default_arch = os_arch_map[target_os][0].lower()
+
+target_arch = ARGUMENTS.get('TARGET_ARCH', default_arch) # target arch
+
+######################################################################
+# Common build options (release, target os, target arch)
+######################################################################
+help_vars = Variables()
+help_vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
+help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map[host]))
+help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
+
+######################################################################
+# Platform(build target) specific options: SDK/NDK & toolchain
+######################################################################
+targets_support_cc = ['linux', 'arduino']
+
+if target_os in targets_support_cc:
+       # Set cross compile toolchain
+       help_vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX'))
+       help_vars.Add(PathVariable('TC_PATH',
+                       'Toolchain path (Generally only be required for cross-compiling)',
+                       os.environ.get('TC_PATH')))
+
+if target_os in ['android', 'arduino']: # Android/Arduino always uses GNU compiler regardless of the host
+       env = Environment(variables = help_vars,
+                       tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
+                       )
+else:
+       env = Environment(variables = help_vars, TARGET_ARCH = target_arch, TARGET_OS = target_os)
+
+Help(help_vars.GenerateHelpText(env))
+
+tc_set_msg = '''
+************************************ Warning **********************************
+*   Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default *
+* toolchain, if it isn't what you expect you should unset it, otherwise it may*
+* cause inexplicable errors.                                                  *
+*******************************************************************************
+'''
+
+if target_os in targets_support_cc:
+       prefix = env.get('TC_PREFIX')
+       tc_path = env.get('TC_PATH')
+       if prefix:
+               env.Replace(CC = prefix + 'gcc')
+               env.Replace(CXX = prefix + 'g++')
+               env.Replace(AR = prefix + 'ar')
+               env.Replace(AS = prefix + 'as')
+               env.Replace(LINK = prefix + 'ld')
+               env.Replace(RANLIB = prefix + 'ranlib')
+
+       if tc_path:
+               env.PrependENVPath('PATH', tc_path)
+               sys_root = os.path.abspath(tc_path + '/../')
+               env.AppendUnique(CCFLAGS = ['--sysroot=' + sys_root])
+               env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
+
+       if prefix or tc_path:
+               print tc_set_msg
+
+# Ensure scons be able to change its working directory
+env.SConscriptChdir(1)
+
+# Set the source directory and build directory
+#   Source directory: 'dir'
+#   Build directory: 'dir'/out/<target_os>/<target_arch>/<release or debug>/
+#
+# You can get the directory as following:
+#   env.get('SRC_DIR')
+#   env.get('BUILD_DIR')
+
+def __set_dir(env, dir):
+       if not os.path.exists(dir + '/SConstruct'):
+               print '''
+*************************************** Error *********************************
+* The directory(%s) seems isn't a source code directory, no SConstruct file is
+* found. *
+*******************************************************************************
+''' % dir
+               Exit(1)
+
+       if env.get('RELEASE'):
+               build_dir = dir + '/out/' + target_os + '/' + target_arch + '/release/'
+       else:
+               build_dir = dir + '/out/' + target_os + '/' + target_arch + '/debug/'
+       env.VariantDir(build_dir, dir, duplicate=0)
+
+       env.Replace(BUILD_DIR = build_dir)
+       env.Replace(SRC_DIR = dir)
+
+def __src_to_obj(env, src, home = ''):
+       obj = env.get('BUILD_DIR') + src.replace(home, '')
+       if env.get('OBJSUFFIX'):
+               obj += env.get('OBJSUFFIX')
+       return env.Object(obj, src)
+
+def __install(ienv, targets, name):
+       i_n = ienv.Install(env.get('BUILD_DIR'), targets)
+       Alias(name, i_n)
+       env.AppendUnique(TS = [name])
+
+def __append_target(ienv, target):
+       env.AppendUnique(TS = [target])
+
+def __print_targets(env):
+       Help('''
+===============================================================================
+Targets:\n    ''')
+       for t in env.get('TS'):
+               Help(t + ' ')
+       Help('''
+\nDefault all targets will be built. You can specify the target to build:
+
+    $ scons [options] [target]
+===============================================================================
+''')
+
+env.AddMethod(__set_dir, 'SetDir')
+env.AddMethod(__print_targets, 'PrintTargets')
+env.AddMethod(__src_to_obj, 'SrcToObj')
+env.AddMethod(__append_target, 'AppendTarget')
+env.AddMethod(__install, 'InstallTarget')
+env.SetDir(env.GetLaunchDir())
+
+Export('env')
+
+# Load config of target os
+env.SConscript(target_os + '/SConscript')
+
+# Delete the temp files of configuration
+if env.GetOption('clean'):
+       dir = env.get('SRC_DIR')
+
+       if os.path.exists(dir + '/config.log'):
+               Execute(Delete(dir + '/config.log'))
+               Execute(Delete(dir + '/.sconsign.dblite'))
+               Execute(Delete(dir + '/.sconf_temp'))
+
+Return('env')
similarity index 76%
rename from resource/build_common/android/SConscript
rename to build_common/android/SConscript
index 7704e70..6e81213 100644 (file)
@@ -5,13 +5,19 @@ import os
 import platform
 import subprocess
 
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ANDROID_NDK')
+Import('env')
 
-if not ANDROID_NDK:
+help_vars = Variables()
+help_vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+android_ndk = env.get('ANDROID_NDK')
+if not android_ndk:
        print '''
 *************************************** Error *********************************
-*   Android NDK path (ANDROID_NDK) isn't set, you can set enviornment variable*
-* ANDROID_NDK or add it in command line as:                                   *
+*    Android NDK path isn't set, you can set enviornment variable ANDROID_NDK *
+* or add it in command line as:                                               *
 *      # scons ANDROID_NDK=<path to android NDK> ...                          *
 *******************************************************************************
 '''
@@ -46,7 +52,7 @@ env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections', '-Wl,-z,nocopyreloc'])
 ######################################################################
 # Probe Android NDK default flags
 ######################################################################
-ndk_build_cmd = ANDROID_NDK + '/ndk-build'
+ndk_build_cmd = android_ndk + '/ndk-build'
 if env['HOST_OS'] == 'win32':
        if os.path.isfile(ndk_build_cmd + '.cmd'):
                ndk_build_cmd += '.cmd'
@@ -57,7 +63,7 @@ if not os.path.isfile(ndk_build_cmd):
 *   It seems android ndk path is not set properly, please check if "%s"
 * is the root directory of android ndk.                                       *
 *******************************************************************************
-''' % ANDROID_NDK
+''' % android_ndk
        Exit(1)
 
 ANDROID_HOME = os.environ.get('ANDROID_HOME')
@@ -72,24 +78,26 @@ if ANDROID_HOME is None or not os.path.exists(ANDROID_HOME):
 *******************************************************************************
 '''
 
+target_arch = env.get('TARGET_ARCH')
+
 # Android ndk early version doesn't support C++11. Detect the toolchain
 # and platform version to make sure the newest version is used.
 
 # Detect toolchain version
 for tc_ver in ['4.9', '4.8', '4.7', '']:
-       if os.path.exists(ANDROID_NDK + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
+       if os.path.exists(android_ndk + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
                break
 
 # Detect platform version.
 platform_ver = ''
 for pf_ver in range(0, 100): # 100 should be big enough :)
-       if os.path.exists(ANDROID_NDK + '/platforms/android-%d' % pf_ver):
+       if os.path.exists(android_ndk + '/platforms/android-%d' % pf_ver):
                platform_ver = "%d" % pf_ver
 
 cmd = [ndk_build_cmd]
-cmd.append('APP_ABI=' + TARGET_CPU_ARCH)
+cmd.append('APP_ABI=' + target_arch)
 cmd.append('APP_STL=gnustl_static')
-if RELEASE_BUILD:
+if env.get('RELEASE'):
        cmd.append('APP_OPTIM=release')
 else:
        cmd.append('APP_OPTIM=debug')
@@ -127,25 +135,30 @@ for flags in p.stdout.readlines():
                env.AppendUnique(CPPPATH = Split(flags[8:]))
 
        elif cmp(flags[0:8], 'SYSROOT=') == 0:
-               env.AppendUnique(LINKFLAGS = ['--sysroot=' + flags[8:].strip()])
-               env.AppendUnique(LIBPATH = [flags[8:].strip() + '/usr/lib'])
+               sysroot = flags[8:].strip()
+               env.AppendUnique(LINKFLAGS = ['--sysroot=' + sysroot])
+               env.AppendUnique(LIBPATH = [sysroot + '/usr/lib'])
+               # To fix android NDK issue
+               # Some functions, e.g. rand, srand. strtof ... are static in static inline
+               # prior to android-L. so libc.so before android-L doesn't have them. If build
+               # build on android-L and the function(s) is used, should link libc.a
+               if platform_ver == '' or int(platform_ver) > 20:
+                       env.AppendUnique(LIBS = File(sysroot + '/usr/lib/libc.a'))
 
        elif cmp(flags[0:8], 'LDFLAGS=') == 0:
                env.AppendUnique(LINKFLAGS = Split(flags[8:]))
 
        elif cmp(flags[0:7], 'TC_VER=') == 0:  # set gnustl library path
                ver = flags[7:].strip()
-               env.AppendUnique(LIBPATH = [ANDROID_NDK + '/sources/cxx-stl/gnu-libstdc++/'
-                               + ver + '/libs/' + TARGET_CPU_ARCH])
+               env.AppendUnique(LIBPATH = [android_ndk + '/sources/cxx-stl/gnu-libstdc++/'
+                               + ver + '/libs/' + target_arch])
 
 ######################################################################
 # Set release/debug flags
 ######################################################################
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
        env.AppendUnique(CPPDEFINES = ['NDEBUG'])
        env.AppendUnique(LINKFLAGS = ['-s'])
 else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
+       env.AppendUnique(CCFLAGS = ['-g'])
similarity index 93%
rename from resource/build_common/android/jni/Android.mk
rename to build_common/android/jni/Android.mk
index a7f2267..9bc6284 100644 (file)
@@ -1,6 +1,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := flags_probe
-include $(BUILD_SHARE_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
 
 $(info TC_PREFIX=$(TOOLCHAIN_PREFIX))
 $(info CFLAGS=$(TARGET_CFLAGS))
diff --git a/build_common/arduino/SConscript b/build_common/arduino/SConscript
new file mode 100755 (executable)
index 0000000..4c3a01f
--- /dev/null
@@ -0,0 +1,400 @@
+##
+# This script includes arduino specific config
+##
+import os
+import platform
+
+Import('env')
+
+def __parse_config(f):
+       dict = {}
+
+       if not os.path.isfile(f):
+               return dict
+
+       file = open(f, 'r')
+       strs = file.readlines()
+       for str in strs:
+               str = str.strip()
+               if len(str) > 0 and str[0] == '#':
+                       continue
+
+               idx = str.find('=')
+               if idx > 0:
+                       dict.setdefault(str[0:idx], str[idx + 1:])
+
+       return dict
+
+def __get_boards(dict):
+       boards = []
+       keys = dict.keys()
+       for key in keys:
+               idx = key.find('.name')
+               if idx > 0:
+                       if key.endswith('.name'):
+                               boards.append(key[0:idx])
+       return boards
+
+def __get_cpu(dict, board):
+       cpus = []
+       keys = dict.keys()
+       for key in keys:
+               idx = key.find(board + '.menu.cpu.')
+               start = len(board + '.menu.cpu.')
+               if idx >= 0:
+                       end = key.find('.', start)
+                       if end > 0:
+                               cpu = key[start:end]
+                               exist = False
+                               for c in cpus:
+                                       if c == cpu:
+                                               exist = True
+                                               break
+
+                               if not exist:
+                                       cpus.append(cpu)
+       return cpus
+
+def __get_board_info(board, key):
+       if cpu:
+               v = boards_info.get(board + '.menu.cpu.' + cpu + key)
+               if not v:
+                       v = boards_info.get(board + key)
+       else:
+               v = boards_info.get(board + key)
+       return v
+
+def __search_files(path, pattern, ondisk=True, source=True, strings=False, recursive=True):
+       if not recursive:
+               return Glob(pattern, ondisk, source, strings)
+
+       matches = []
+       for root, dirnames, filenames in os.walk(path):
+               matches.extend(Glob(root + '/' + pattern, ondisk, source, strings))
+
+       return matches
+
+# To make sure the src is built in 'BUILD_DIR' (by default it will be built at
+# the same directory as the .c .cpp .S)
+def __src_to_obj(env, srcs):
+       objs = []
+       prefix = env.get('BOARD') + '_'
+       if env.get('CPU'):
+               prefix += env.get('CPU') + '_'
+
+       build_dir = env.get('BUILD_DIR') + '/arduino/'
+       for src in srcs:
+               obj = src.path.replace(arduino_home, build_dir)
+               i = obj.rfind('.')
+               obj = obj[0:i]
+               if env.get('OBJSUFFIX'):
+                       obj += env.get('OBJSUFFIX')
+               objs.extend(env.Object(obj, src, OBJPREFIX=prefix))
+       return objs
+
+def __import_lib(env, lib):
+       lib_path = arduino_home + '/libraries/' + lib
+       if not os.path.exists(lib_path):
+               if target_arch == 'avr':
+                       lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib
+               else:
+                       lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib
+
+       if os.path.exists(lib_path + '/src'):
+               lib_path = lib_path + '/src'
+
+       env.AppendUnique(CPPPATH = [lib_path])
+
+       if os.path.exists(lib_path + '/utility'):
+               env.AppendUnique(CPPPATH = [lib_path + '/utility'])
+
+       lib_src = []
+       lib_src.extend(__search_files(lib_path, '*.S'))
+       lib_src.extend(__search_files(lib_path, '*.c'))
+       lib_src.extend(__search_files(lib_path, '*.cpp'))
+
+       build_dir = env.get('BUILD_DIR')
+       if build_dir:
+               lib_a = env.StaticLibrary(build_dir + lib, __src_to_obj(env, lib_src))
+       else:
+               lib_a = env.StaticLibrary(lib, __src_to_obj(env, lib_src))
+       env.AppendUnique(LIBS = [File(lib_a[0])])
+
+def __build_core(env):
+       core_src = __search_files(core_folder, '*.S')
+       core_src.extend(__search_files(core_folder, '*.c'))
+       core_src.extend(__search_files(core_folder, '*.cpp'))
+
+       core_src.extend(__search_files(variant_folder, '*.S'))
+       core_src.extend(__search_files(variant_folder, '*.c'))
+       core_src.extend(__search_files(variant_folder, '*.cpp'))
+
+       core_obj = __src_to_obj(env, core_src)
+       build_dir = env.get('BUILD_DIR')
+       if build_dir:
+               s_core = env.StaticLibrary(build_dir + 'core', core_obj)
+       else:
+               s_core = env.StaticLibrary('core', core_obj)
+       env.AppendUnique(LIBS = [File(s_core[0])])
+
+       # To avoid compiler issue. Otherewise there may be warnings:
+       #       undefined reference to '_exit' '_close', '_getpid' ...
+       # Above functions are used in libc.a and implemented in syscalls_sam3.c
+       if env.get('TARGET_ARCH') == 'arm':
+               for obj in core_obj:
+                       if obj.name.endswith('syscalls_sam3.o'):
+                               env.AppendUnique(LIBS = [File(obj)])
+
+def __create_bin(env, source):
+       name = source
+       if env.get('TARGET_ARCH') == 'avr':
+               eep = env.Command(name + '.eep', source, 'avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $SOURCE $TARGET')
+               hex = env.Command(name + '.hex', source, 'avr-objcopy -O ihex -R .eeprom $SOURCE $TARGET')
+       else:
+               hex = env.Command(name + '.hex', source, 'arm-none-eabi-objcopy -O binary $SOURCE $TARGET')
+
+# Print the command line that to upload binary to the board
+def __upload_help(env):
+       if target_arch == 'avr':
+               protocol = __get_board_info(board, '.upload.protocol')
+               speed = __get_board_info(board, '.upload.speed')
+
+               upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \
+       + mcu + ' -c' + protocol + ' -P<serial_port>' + ' -b' + speed + ' -D -Uflash:w:<hex_file>:i'
+       else:
+               uu = __get_board_info(board, '.upload.native_usb')
+               upload_cmd = arduino_home + '/hardware/tools/bossac -i -d --port=<serial_port> -U ' + uu + ' -e -w -v -b <bin file> -R'
+
+       Help('''
+===============================================================================
+You can upload the bin file with following command line:
+''')
+       Help('\n   $ ' + upload_cmd)
+       Help('''
+\nPlease replace <xxx> according to the actual situation.
+===============================================================================
+''')
+
+# ARDUINO_HOME build option
+help_vars = Variables()
+help_vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+target_arch = env.get('TARGET_ARCH')
+arduino_home = env.get('ARDUINO_HOME')
+if not arduino_home:
+       print '''
+************************************* Error ***********************************
+*   Arduino root directory isn't set, you can set enviornment variable        *
+* ARDUINO_HOME or add it in command line as:                                  *
+*      # scons ARDUINO_HOME=<path to arduino root directory> ...              *
+*******************************************************************************
+'''
+       Exit(1)
+
+# Overwrite suffixes and prefixes
+if env['HOST_OS'] == 'win32':
+       env['OBJSUFFIX'] = '.o'
+       env['SHOBJSUFFIX'] = '.os'
+       env['LIBPREFIX'] = 'lib'
+       env['LIBSUFFIX'] = '.a'
+       env['SHLIBPREFIX'] = 'lib'
+       env['SHLIBSUFFIX'] = '.so'
+       env['LIBPREFIXES'] = ['lib']
+       env['LIBSUFFIXES'] = ['.a', '.so']
+       env['PROGSUFFIX'] = ''
+elif platform.system().lower() == 'darwin':
+       env['SHLIBSUFFIX'] = '.so'
+       env['LIBSUFFIXES'] = ['.a', '.so']
+       env['PROGSUFFIX'] = ''
+
+# Debug/release relative flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+# BOARD / CPU option
+
+# Get IDE version
+if os.path.exists(arduino_home + '/lib/version.txt'):
+       vf = open(arduino_home + '/lib/version.txt', 'r')
+       version = vf.readline().replace('.', '')
+else:
+       print '''
+************************************* Error ***********************************
+* Can't find version file (lib/version.txt), please check if (%s)
+* is arduino root directory.                                                  *
+*******************************************************************************
+''' % arduino_home
+       Exit(1)
+
+if version[0:2] == '10':
+       is_1_0_x = True
+       boards_info = __parse_config(arduino_home + '/hardware/arduino/boards.txt')
+       env.PrependENVPath('PATH', arduino_home + '/hardware/tools/avr/bin/')
+       env.Replace(CC = 'avr-gcc')
+       env.Replace(CXX = 'avr-g++')
+       env.Replace(AR = 'avr-ar')
+       env.Replace(AS = 'avr-as')
+       env.Replace(LINK = 'avr-gcc')
+       env.Replace(RANLIB = 'avr-ranlib')
+       if target_arch != 'avr':
+               print '''
+************************************* Error ***********************************
+* Arduino 1.0.x IDE only support 'avr', to support other arch at least 1.5.x  *
+* is required.
+*******************************************************************************
+'''
+               Exit(1)
+else:
+       is_1_0_x = False
+       if target_arch == 'avr':
+               boards_info = __parse_config(arduino_home + '/hardware/arduino/avr/boards.txt')
+               platform_info = __parse_config(arduino_home + '/hardware/arduino/avr/platform.txt')
+       elif target_arch == 'arm':
+               boards_info = __parse_config(arduino_home + '/hardware/arduino/sam/boards.txt')
+               platform_info = __parse_config(arduino_home + '/hardware/arduino/sam/platform.txt')
+       else:
+               print '''
+************************************* Error ***********************************
+* CPU arch %s isn't supported currently.
+*******************************************************************************
+''' % target_arch
+
+#Board option, let user to select the board
+boards = __get_boards(boards_info)
+help_vars = Variables()
+help_vars.Add(EnumVariable('BOARD', 'arduino board', boards[0], boards))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+#CPU option
+board = env.get('BOARD')
+cpus = __get_cpu(boards_info, board)
+if len(cpus) > 0:
+       help_vars = Variables()
+       help_vars.Add(EnumVariable('CPU', 'arduino board cpu', cpus[0], cpus))
+       help_vars.Update(env)
+       Help(help_vars.GenerateHelpText(env))
+
+# Arduino commom flags
+cpu = env.get('CPU')
+board = env.get('BOARD')
+mcu = __get_board_info(board, '.build.mcu')
+f_cpu = __get_board_info(board, '.build.f_cpu')
+usb_vid = __get_board_info(board, '.build.vid')
+usb_pid = __get_board_info(board, '.build.pid')
+variant = __get_board_info(board, '.build.variant')
+
+if not usb_vid:
+       usb_vid = __get_board_info(board, '.vid.0')
+if not usb_pid:
+       usb_pid = __get_board_info(board, '.pid.0')
+
+if is_1_0_x:
+       core_base = arduino_home + '/hardware/arduino/'
+else:
+       if target_arch == 'avr':
+               core_base = arduino_home + '/hardware/arduino/avr/'
+       else:
+               core_base = arduino_home + '/hardware/arduino/sam/'
+
+variant_folder = core_base + 'variants/' + variant
+env.AppendUnique(CPPPATH = [variant_folder])
+
+core = __get_board_info(board, '.build.core')
+core_folder = core_base + 'cores/' + core + '/'
+env.AppendUnique(CPPPATH = [core_folder])
+
+if is_1_0_x:
+       comm_flags = []
+       if mcu:
+               comm_flags.extend(['-mmcu=' + mcu])
+       if f_cpu:
+               comm_flags.extend(['-DF_CPU=' + f_cpu])
+       comm_flags.extend(['-DARDUINO=' + version])
+       if usb_vid:
+               comm_flags.extend(['-DUSB_VID=' + usb_vid])
+       if usb_pid:
+               comm_flags.extend(['-DUSB_PID=' + usb_pid])
+
+       env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+       env.AppendUnique(ASFLAGS = comm_flags)
+
+       env.AppendUnique(CFLAGS = ['-Os', '-ffunction-sections', '-fdata-sections', '-MMD'])
+       env.AppendUnique(CFLAGS = comm_flags)
+
+       env.AppendUnique(CXXFLAGS = ['-Os', '-fno-exceptions', '-ffunction-sections', '-fdata-sections','-MMD'])
+       env.AppendUnique(CXXFLAGS = comm_flags)
+
+       env.AppendUnique(LINKFLAGS = ['-Os'])
+       if mcu == 'atmega2560':
+               env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections,--relax'])
+       else:
+               env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections'])
+       env.AppendUnique(LINKFLAGS = ['-mmcu=' + mcu])
+else:
+       if target_arch == 'avr':
+               cpu_flag = '-mmcu=' + mcu
+       else:
+               cpu_flag = '-mcpu=' + mcu
+
+       comm_flag = [cpu_flag, '-DF_CPU=' + f_cpu, '-DARDUINO=' + version, '-DARDUINO_' + __get_board_info(board, '.build.board')]
+       if target_arch == 'arm':
+               comm_flag.extend(['-DARDUINO_ARCH_SAM'])
+       else:
+               comm_flag.extend(['-DARDUINO_ARCH_AVR'])
+
+       compiler_path = platform_info.get('compiler.path')
+       compiler_path = compiler_path.replace('{runtime.ide.path}', arduino_home)
+       env.PrependENVPath('PATH', compiler_path)
+       env.Replace(CC = platform_info.get('compiler.c.cmd'))
+       env.Replace(CXX = platform_info.get('compiler.cpp.cmd'))
+       env.Replace(AR = platform_info.get('compiler.ar.cmd'))
+       if target_arch == 'arm':
+               env.AppendUnique(CPPPATH = [arduino_home + '/hardware/arduino/sam/system/libsam',
+                                                       arduino_home + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include/',
+                                                       arduino_home + '/hardware/arduino/sam/system//CMSIS/Device/ATMEL'])
+       env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+       env.AppendUnique(ASFLAGS = comm_flag)
+       env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags')))
+       env.AppendUnique(CXXFLAGS = Split(platform_info.get('compiler.cpp.flags')))
+       env.AppendUnique(ARFLAGS = Split(platform_info.get('compiler.ar.flags')))
+       env.AppendUnique(CCFLAGS = comm_flag)
+
+       extra_flags = __get_board_info(board, '.build.extra_flags')
+       if extra_flags:
+               extra_flags = extra_flags.replace('{build.usb_flags}', '')
+               env.AppendUnique(CCFLAGS = Split(extra_flags))
+               usb_flags = ['-DUSB_VID=' + usb_vid, '-DUSB_PID=' + usb_pid, '-DUSBCON', '-DUSB_MANUFACTURER="Unknown"']
+               env.AppendUnique(CCFLAGS = usb_flags)
+
+       if target_arch == 'arm':
+               env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag,
+                                       '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript'),
+                                       '-Wl,-Map,' + env.get('BUILD_DIR') + 'arduino_prj.map'])
+               env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group'))
+
+               variant_system_lib = __get_board_info(board, '.build.variant_system_lib')
+               if variant_system_lib:
+                       if variant_folder.find(' ') >= 0:
+                               variant_folder = '"' + variant_folder + '"'
+                       env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS '
+                                       + variant_folder + '/' + variant_system_lib + ' -Wl,--end-group')
+               else:
+                       env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group')
+       else:
+               env.AppendUnique(LINKFLAGS = Split(platform_info.get('compiler.c.elf.flags')))
+               env.AppendUnique(LINKFLAGS = [cpu_flag])
+               env.AppendUnique(LIBS = 'm')
+       env.Replace(ARCOM = '$AR ' + platform_info.get('compiler.ar.flags') + ' $TARGET $SOURCES')
+
+__build_core(env)
+
+env.AddMethod(__import_lib, "ImportLib") #import arduino library
+#env.AddMethod(__build_core, "BuildCore") #build arduino core
+env.AddMethod(__create_bin, "CreateBin") #create binary files(.eep and .hex)
+env.AddMethod(__upload_help, "UploadHelp") #print the command line that to upload binary to the boardf
diff --git a/build_common/darwin/SConscript b/build_common/darwin/SConscript
new file mode 100644 (file)
index 0000000..7d57774
--- /dev/null
@@ -0,0 +1,54 @@
+##
+# This script set darwin specific flags (GNU GCC)
+#
+##
+import os
+import platform
+
+Import('env')
+
+# SYS_VERSION build option
+help_vars = Variables()
+help_vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION'))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+sys_version = env.get('SYS_VERSION')
+
+if sys_version is None:
+       print '''
+*********************************** Error *************************************
+*   MAC OSX/IOS version isn't set, please set it in command line as :         *
+*      # scons SYS_VERSION=<version> ...                                      *
+*   To get the version, please see:                                                              *
+* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/   *
+* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ *
+*******************************************************************************
+'''
+       Exit(1)
+
+target_arch = env.get('TARGET_ARCH')
+target_os = env.get('TARGET_OS')
+# Set release/debug flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+if target_os == 'darwin':
+       sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + sys_version + '.sdk/'
+else:
+       if target_arch in ['i386', 'x86_64']:
+               sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + sys_version + '.sdk/'
+       else:
+               sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + sys_version + '.sdk/'
+
+# Set arch flags
+env.AppendUnique(CCFLAGS = ['-arch', target_arch, '-isysroot', sys_root])
+env.AppendUnique(LINKFLAGS = ['-arch', target_arch, '-isysroot', sys_root])
+
+if target_os == 'darwin':
+       flag = '-mmacosx-version-min=' + sys_version
+       env.AppendUnique(CCFLAGS = [flag])
+       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/build_common/ios/SConscript b/build_common/ios/SConscript
new file mode 100644 (file)
index 0000000..fcf62aa
--- /dev/null
@@ -0,0 +1,18 @@
+##
+# This script set ios specific flags (GNU GCC)
+#
+##
+Import('env')
+
+# setting of IOS is almost the same as Darwin(MAC OSX)
+env.SConscript('../darwin/SConscript')
+
+sys_version = env.get('SYS_VERSION')
+if env.get('TARGET_ARCH') in ['i386', 'x86_64']: #Simulator
+       flag = '-mios-simulator-version-min=' + sys_version
+       env.AppendUnique(CCFLAGS = [flag])
+       env.AppendUnique(LINKFLAGS = [flag])
+else:
+       flag = '-miphoneos-version-min=' + sys_version
+       env.AppendUnique(CCFLAGS = [flag])
+       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/build_common/linux/SConscript b/build_common/linux/SConscript
new file mode 100644 (file)
index 0000000..bb939be
--- /dev/null
@@ -0,0 +1,33 @@
+##
+# This script set linux specific flags (GNU GCC)
+#
+##
+Import('env')
+
+# Set release/debug flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+       env.AppendUnique(LINKFLAGS = ['-s'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+# Set arch flags
+target_arch = env.get('TARGET_ARCH')
+if target_arch in ['x86']:
+       env.AppendUnique(CCFLAGS = ['-m32'])
+       env.AppendUnique(LINKFLAGS = ['-m32'])
+elif target_arch in ['x86_64']:
+       env.AppendUnique(CCFLAGS = ['-m64'])
+       env.AppendUnique(LINKFLAGS = ['-m64'])
+elif target_arch.find('v7a-hard') > 0:
+       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
+       env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard'])
+       env.AppendUnique(CCFLAGS = ['-mfloat-abi=hard'])
+       env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard'])
+elif target_arch.find('v7a') > 0:
+       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
+elif target_arch.find('arm64') > 0:
+       env.AppendUnique(CPPFLAGS = ['-march=armv8-a'])
+else:
+       env.AppendUnique(CPPFLAGS = ['-march=armv5te'])
diff --git a/build_common/windows/SConscript b/build_common/windows/SConscript
new file mode 100644 (file)
index 0000000..4c35d35
--- /dev/null
@@ -0,0 +1,17 @@
+##
+# This script includes windows specific config (MSVS/MSVC)
+##
+Import('env')
+
+# Set common flags
+env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996'])
+env.AppendUnique(CCFLAGS=['/EHsc'])
+
+# Set release/debug flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['/MD', '/O2', '/GF'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
+       env.AppendUnique(CPPDEFINES = ['_DEBUG'])
+       env.AppendUnique(LINKFLAGS = ['/debug'])
diff --git a/extra_options.scons b/extra_options.scons
new file mode 100644 (file)
index 0000000..e1280da
--- /dev/null
@@ -0,0 +1,65 @@
+######################################################################
+# This script manages extra build options
+#
+######################################################################
+import os
+import platform
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
+
+# Add 'OIC_UTILS' build option for user to set oic-utilities project path
+if target_os not in ['linux', 'darwin', 'arduino']:
+       default_dir = os.environ.get('OIC_UTILS')
+       if not default_dir:
+               default_dir = os.path.abspath(src_dir + '/../oic-utilities')
+       else:
+               default_dir = os.path.abspath(default_dir)
+
+       if not os.path.exists(default_dir):
+               default_dir = None
+
+       help_vars = Variables()
+       help_vars.Add(PathVariable('OIC_UTILS', 'oic-utilities project path', default_dir))
+       help_vars.Update(env)
+       Help(help_vars.GenerateHelpText(env))
+
+       utils_path = env.get('OIC_UTILS', default_dir)
+       if utils_path:
+               utils_path = os.path.abspath(utils_path)
+
+       if not utils_path or not os.path.exists(utils_path):
+               print '''
+*********************************** Error: ************************************
+*   oic-utilities project directory isn't set properly, please set enviornment*
+* variable OIC_UTILS or set it in command line:                               *
+*     # scons  OIC_UTILS=<path to oic-utilities> ...                          *
+*******************************************************************************
+'''
+               Exit(1)
+
+if target_os == 'arduino':
+       # Add 'NET' build option, let user select board network connection type
+       vars = Variables()
+       vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi']))
+       vars.Update(env)
+       Help(vars.GenerateHelpText(env))
+
+# check 'cereal' library, temporarily put it here
+if not os.path.exists(src_dir + '/extlibs/cereal'):
+       print '''
+*********************************** Error: **************************************
+*  'Cereal' library doesn't exist. please download cereal to extlibs directory  *
+* add apply the patch as following:                                             *
+*     $ git clone https://github.com/USCiLab/cereal.git <src_dir>/extlibs/cereal*
+*     $ cd <src_dir>/extlibs/cereal                                             *
+*     $ git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245               *
+*     $ git apply ../../resource/patches/cereal_gcc46.patch                     *
+*********************************************************************************
+'''
+       Exit(1)
+else:
+       env.AppendUnique(CPPPATH = [src_dir + '/extlibs/cereal/include'])
diff --git a/resource/Readme.scons.txt b/resource/Readme.scons.txt
deleted file mode 100644 (file)
index f8b9c45..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-1) Build with default option
-  To build with default option:
-  # scons
-
-  To see help information with default option(the output may be different with different options):
-  # scons -Q -h
-
-  To clean the project:
-  # scons -c
-
-2) Build with options
-  To build with options:
-  # scons OPTION1=xxx OPTION2=xxx OPTION3=....
-
-  To see help information:
-  # scons OPTION1=xxx OPTION2=xxx OPTION3=.... -Q -h
-
-  To clean the project:
-  # scons OPTION1=xxx OPTION2=xxx OPTION3=.... -c
-
-3) Examples
-  To build default
-  # scons
-  To see default help
-  # scons -Q -h
-  To clean
-  # scons -c
-
-  To build android armeabi-v7a
-  # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a
-  To see help
-  # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a -Q -h
-  To clean
-  # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a -c
-
-Note:
-  1. To build android binary, android NDK should be newer than r8e(recommend r10).
-  2. You may be asked to set some options. Besides set it in command line, you
-can also set it by create a environment variable. Command line has higher priority.
-If both are set, the command line value will be used.
diff --git a/resource/SConscript b/resource/SConscript
new file mode 100644 (file)
index 0000000..fc82826
--- /dev/null
@@ -0,0 +1,26 @@
+##
+# 'resource' sub-project main build script
+#
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+# Build libcoap
+SConscript('csdk/libcoap/SConscript')
+
+# Build liboctbstack
+SConscript('csdk/SConscript')
+
+if target_os != 'arduino':
+       # Build liboc_logger
+       SConscript('oc_logger/SConscript')
+
+       # Build liboc
+       SConscript('src/SConscript')
+
+       # Build examples
+       SConscript('examples/SConscript')
+else:
+       SConscript('csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript')
\ No newline at end of file
diff --git a/resource/SConstruct b/resource/SConstruct
deleted file mode 100644 (file)
index f2a9b50..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-##
-# The main build script
-#
-##
-import os
-
-SRC_TOP_DIR = os.path.abspath('.') + '/' #oic-resource project top directory
-
-# Common build options
-SConscript('build_common/SConscript')
-Import('RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH')
-
-# Set build directory
-if RELEASE_BUILD:
-       BUILD_DIR = SRC_TOP_DIR + '/out/' + BUILD_TARGET + '/' + TARGET_CPU_ARCH + '/release/'
-else:
-       BUILD_DIR = SRC_TOP_DIR + '/out/' + BUILD_TARGET + '/' + TARGET_CPU_ARCH + '/debug/'
-VariantDir(BUILD_DIR, SRC_TOP_DIR, duplicate=0)
-Export('SRC_TOP_DIR', 'BUILD_DIR')
-
-if BUILD_TARGET == 'arduino':
-       SConscript('arduino.scons')
-
-# Build libcoap
-SConscript(BUILD_DIR + 'csdk/libcoap/SConscript')
-
-# Build liboctbstack
-SConscript(BUILD_DIR + 'csdk/SConscript')
-
-if BUILD_TARGET != 'arduino':
-       # Build liboc_logger
-       SConscript(BUILD_DIR + 'oc_logger/SConscript')
-
-       # Build liboc
-       SConscript(BUILD_DIR + 'src/SConscript')
-
-       # Build examples
-       SConscript(BUILD_DIR + 'examples/SConscript')
-
-# Print targets
-Import('env')
-
-Help('''
-===============================================================================
-Targets:\n    ''')
-for t in env.get('TS'):
-       Help(t + ' ')
-Help('''
-\nDefault all targets will be built. You can specify the target to build:
-
-    #scons [options] [target]
-===============================================================================
-''')
\ No newline at end of file
diff --git a/resource/arduino.scons b/resource/arduino.scons
deleted file mode 100644 (file)
index 287482c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-##
-# This script includes arduino specific config for oic-resource
-##
-Import('env', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
-
-# 'NET' build option
-if env.get('NET') is None:
-       vars = Variables()
-       vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi']))
-       vars.Update(env)
-       Help(vars.GenerateHelpText(env))
-
-env.AppendUnique(CPPPATH = [
-               ARDUINO_HOME + '/libraries/Ethernet/src',
-               ARDUINO_HOME + '/libraries/Ethernet/src/utility',
-               ARDUINO_HOME + '/libraries/WiFi/src',
-               ARDUINO_HOME + '/libraries/WiFi/src/utility',
-               ARDUINO_HOME + '/libraries/Time/',
-               ])
-
-if TARGET_CPU_ARCH == 'arm':
-       # Include path
-       env.AppendUnique(CPPPATH = [
-                       ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino',
-                       ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/USB',
-                       ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/avr',
-                       ARDUINO_HOME + '/hardware/arduino/sam/system/libsam',
-                       ARDUINO_HOME + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include',
-                       ARDUINO_HOME + '/hardware/arduino/sam/system/CMSIS/Device/ATMEL',
-                       ARDUINO_HOME + '/hardware/arduino/sam/variants/arduino_due_x',
-                       ARDUINO_HOME + '/hardware/arduino/sam/libraries/SPI',
-                       ])
-
-       # Compiler/Linker flags
-       env.AppendUnique(CXXFLAGS = ['-ffunction-sections', '-fdata-sections', '-nostdlib',
-                                               '--param', 'max-inline-insns-single=500', '-fno-rtti', '-fno-exceptions',
-                                               '-mcpu=cortex-m3', '-mthumb'
-                                       ])
-       env.AppendUnique(CPPDEFINES = ['printf=iprintf', 'F_CPU=84000000L', 'ARDUINO=157',
-                                               'ARDUINO_SAM_DUE', 'ARDUINO_ARCH_SAM', '__SAM3X8E__', 'USB_VID=0x2341',
-                                               'USB_PID=0x003e', 'USBCON', 'DUSB_MANUFACTURER="Unknown"', 'WITH_ARDUINO',
-                                       ])
-
-       # Source
-       ARDUINO_SRC = []
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/*.c'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/avr/*.c'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/USB/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/variants/arduino_due_x/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/libraries/SPI/*.cpp'))
-else:
-       # Include path
-       env.AppendUnique(CPPPATH = [
-                       ARDUINO_HOME + '/hardware/arduino/avr/cores/arduino',
-                       ARDUINO_HOME + '/hardware/arduino/avr/libraries/SPI',
-                       ARDUINO_HOME + '/hardware/arduino/avr/variants/mega',
-                       ])
-
-       # Compiler/Linker flags
-       env.AppendUnique(CXXFLAGS = ['-mmcu=atmega2560', '-MMD', '-std=c++0x',
-                                               '-Wno-write-strings', '-ffunction-sections', '-fdata-sections',
-                                               '-fno-exceptions', '-felide-constructors'
-                                       ])
-       env.AppendUnique(CPPDEFINES = ['F_CPU=16000000L', 'ARDUINO=156', 'ARDUINO_AVR_MEGA2560',
-                                               'ARDUINO_ARCH_AVR', 'WITH_ARDUINO', 'ATMEGA2560'
-                                       ])
-
-       # Source
-       ARDUINO_SRC = [
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WInterrupts.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/wiring.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/wiring_digital.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/main.cpp',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/Stream.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WMath.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WString.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/HardwareSerial.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/Print.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/IPAddress.c',
-               ARDUINO_HOME + '/hardware/arduino/avr/libraries/SPI/SPI.cpp',
-               ]
-
-if env.get('NET') == 'Ethernet':
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/Ethernet/src/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/Ethernet/src/utility/*.cpp'))
-else:
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/WiFi/src/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/WiFi/src/utility/*.cpp'))
-
-Export('ARDUINO_SRC')
\ No newline at end of file
index bb53325..64afad1 100644 (file)
@@ -167,10 +167,12 @@ linux_tb_examples_all: linux_tb_stack_release linux_tb_examples_debug
 linux_tb_examples_release: linux_tb_stack_release
        @echo "=====BUILD TB SAMPLE APPS FOR LINUX - RELEASE - <oic-resource>/csdk/stack/samples/linux/SimpleClientServer/release/====="
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=release"
+       $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=release"
 
 linux_tb_examples_debug: linux_tb_stack_debug
        @echo "=====BUILD TB SAMPLE APPS FOR LINUX - DEBUG - <oic-resource>/csdk/stack/samples/linux/SimpleClientServer/debug/====="
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=debug"
+       $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=debug"
 
 ###############################################################################
 ####      UB Stack (& TB Stack as prerequisite) - Linux Only               ####
@@ -483,6 +485,7 @@ linux_clean:
        -rm -rf -C csdk/linux
        $(MAKE) -C csdk/stack/test/linux "clean"
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean"
+       $(MAKE) -C csdk/stack/samples/linux/secure "clean"
        $(MAKE) -C . "clean"
 
 ###############################################################################
@@ -513,6 +516,7 @@ clean:
        $(MAKE) -C csdk "clean" "deepclean"
        $(MAKE) -C csdk/stack/test/linux "clean"
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean"
+       $(MAKE) -C csdk/stack/samples/linux/secure "clean"
        $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "clean"
        $(MAKE) -C . "clean"
        $(MAKE) -C unittests/ "clean"
diff --git a/resource/build_common/SConscript b/resource/build_common/SConscript
deleted file mode 100644 (file)
index b3dd335..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-##
-# This script includes generic build options:
-#    release/debug, build target, CPU ARCH, toolchain, build environment etc
-##
-import os
-import platform
-
-host = platform.system()
-default_arch = platform.machine()
-
-if host not in ['Linux', 'Windows', 'Darwin']:
-       host = 'Linux'
-
-# Map of host and allowed targets
-allow_target_map = {
-               'Linux': ['Linux', 'Android', 'Arduino'],
-               'Windows': ['Windows', 'WinRT', 'Android', 'Arduino'],
-               'Darwin': ['Darwin', 'IOS', 'Android', 'Arduino'],
-               }
-
-# Map of platform(target) and allowed archs
-allow_arch_map = {
-               'linux': ['x86', 'x86_64', 'arm', 'arm64'],
-               'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'],
-               'windows': ['x86', 'amd64', 'arm'],
-               'winrt': ['arm'],
-               'darwin': ['i386', 'x86_64'],
-               'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'],
-               'arduino': ['avr', 'arm'],
-               }
-
-######################################################################
-# Get build options (the optins from command line)
-######################################################################
-BUILD_TARGET = ARGUMENTS.get('BUILD_TARGET', host).lower() # target platform
-
-if not allow_arch_map.has_key(BUILD_TARGET):
-       print "\nError: Unknown target platform: %s (Allow values: %s)\n" % (BUILD_TARGET, allow_target_map[host])
-       Exit(1)
-
-if default_arch not in allow_arch_map[BUILD_TARGET]:
-       default_arch = allow_arch_map[BUILD_TARGET][0]
-       default_arch = default_arch.lower()
-
-TARGET_CPU_ARCH = ARGUMENTS.get('CPU_ARCH', default_arch) # target CPU ARCH
-ANDROID_NDK = ARGUMENTS.get('ANDROID_NDK', os.environ.get('ANDROID_NDK')) # ANDROID NDK base directory
-SYS_VERSION = ARGUMENTS.get('SYS_VERSION', os.environ.get('SYS_VERSION'))  # OSX/IOS version
-ARDUINO_HOME = ARGUMENTS.get('ARDUINO_HOME', os.environ.get('ARDUINO_HOME')) # ARDUINO root directory
-
-######################################################################
-# Common build options (release, build target, CPU)
-######################################################################
-vars = Variables()
-vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
-vars.Add(EnumVariable('BUILD_TARGET', 'Target platform', host, allow_target_map[host]))
-vars.Add(EnumVariable('CPU_ARCH', 'Target CPU ARCH', default_arch, allow_arch_map[BUILD_TARGET]))
-
-######################################################################
-# Platform(build target) specific options: SDK/NDK & toolchain
-######################################################################
-targets_support_cc = ['linux', 'arduino']
-
-if BUILD_TARGET == 'android':
-       vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK')))
-
-elif BUILD_TARGET in ['darwin', 'ios']:
-       vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION'))
-
-elif BUILD_TARGET == 'arduino':
-       vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
-
-if BUILD_TARGET in targets_support_cc:
-       # Set cross compile toolchain
-       vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX'))
-       vars.Add(PathVariable('TC_PATH',
-                       'Toolchain path (Generally only be required for cross-compiling)',
-                       os.environ.get('TC_PATH')))
-
-if BUILD_TARGET == 'android': # Android always uses GNU compiler regardless of the host
-       env = Environment(variables = vars,
-                       tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
-                       )
-else:
-       env = Environment(variables = vars, TARGET_ARCH = TARGET_CPU_ARCH, TARGET_OS = BUILD_TARGET)
-
-Help(vars.GenerateHelpText(env))
-
-RELEASE_BUILD = env.get('RELEASE') # Whethere is release build, True: release, False: debug
-
-tc_set_msg = '''
-************************************ Warning **********************************
-*   Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default *
-* toolchain, if it isn't what you expect you should unset it, otherwise it may*
-* cause inexplicable errors.                                                  *
-*******************************************************************************
-'''
-
-if BUILD_TARGET in targets_support_cc:
-       prefix = ARGUMENTS.get('TC_PREFIX', os.environ.get('TC_PREFIX'))
-       tc_path = ARGUMENTS.get('TC_PATH', os.environ.get('TC_PATH'))
-       if prefix:
-               env.Replace(CC = prefix + 'gcc')
-               env.Replace(CXX = prefix + 'g++')
-               env.Replace(AR = prefix + 'ar')
-               env.Replace(AS = prefix + 'as')
-               env.Replace(LINK = prefix + 'ld')
-               env.Replace(RANLIB = prefix + 'ranlib')
-
-       if tc_path:
-               env.PrependENVPath('PATH', tc_path)
-               sys_root = os.path.abspath(tc_path + '/../')
-               env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
-               env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
-               env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
-
-       if prefix or tc_path:
-               print tc_set_msg
-
-# Ensure scons be able to change its working directory
-env.SConscriptChdir(1)
-
-Export('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH',
-               'ANDROID_NDK', 'SYS_VERSION', 'ARDUINO_HOME')
-
-# Load config of specific platform(build target)
-env.SConscript(BUILD_TARGET + '/SConscript')
-
-Return('env')
\ No newline at end of file
diff --git a/resource/build_common/arduino/SConscript b/resource/build_common/arduino/SConscript
deleted file mode 100644 (file)
index d33cc55..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-##
-# This script includes arduino specific config
-##
-import os
-import platform
-
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
-
-if not ARDUINO_HOME:
-       print '''
-************************************* Error ***********************************
-*   Arduino root directory (ARDUINO_HOME) isn't set, you can set enviornment  *
-* variable ARDUINO_HOME or add it in command line as:                         *
-*      # scons ARDUINO_HOME=<path to arduino root directory> ...              *
-*******************************************************************************
-'''
-       Exit(1)
-
-# Overwrite suffixes and prefixes
-if env['HOST_OS'] == 'win32':
-       env['OBJSUFFIX'] = '.o'
-       env['SHOBJSUFFIX'] = '.os'
-       env['LIBPREFIX'] = 'lib'
-       env['LIBSUFFIX'] = '.a'
-       env['SHLIBPREFIX'] = 'lib'
-       env['SHLIBSUFFIX'] = '.so'
-       env['LIBPREFIXES'] = ['lib']
-       env['LIBSUFFIXES'] = ['.a', '.so']
-       env['PROGSUFFIX'] = ''
-elif platform.system().lower() == 'darwin':
-       env['SHLIBSUFFIX'] = '.so'
-       env['LIBSUFFIXES'] = ['.a', '.so']
-       env['PROGSUFFIX'] = ''
-
-# Set toolchain
-def find_toolchain(dir, tc):
-       for root, dirs, files in os.walk(dir, True, None, False):
-               for f in files:
-                       lf = f.lower()
-                       if lf == tc:
-                               return root
-       return None
-
-if TARGET_CPU_ARCH == 'arm':
-       prefix = 'arm-none-eabi-'
-else:
-       prefix = 'avr-'
-
-tc_path = find_toolchain(ARDUINO_HOME + '/hardware/tools/', prefix + 'g++')
-if not tc_path:
-       print '''
-************************************* Error ***********************************
-*   Arduino toolchain isn't detected. Please specify the toolchain prefix and *
-* path, you can do it by setting enviornment variable TC_PREFIX and TC_PATH or*
-* add it in command line as:                                                  *
-*     # scons TC_PREFIX=<prefix> TC_PATH=<path to toolchain> ...              *
-* e.g. scons TC_PREFIX=avr- TC_PATH=/opt/arduino-1.5.7/hardware/tools/avr/bin *                                                                         *
-* Note: TC_PREFIX shouldn't include path                                      *
-*******************************************************************************
-'''
-       Exit(1)
-
-env.PrependENVPath('PATH', tc_path)
-env.Replace(CC = prefix + 'gcc')
-env.Replace(CXX = prefix + 'g++')
-env.Replace(AR = prefix + 'ar')
-env.Replace(AS = prefix + 'as')
-env.Replace(LINK = prefix + 'ld')
-env.Replace(RANLIB = prefix + 'ranlib')
-
-sys_root = os.path.abspath(os.path.join(tc_path, '..'))
-env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
-
-# Debug/release relative flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-       env.AppendUnique(LINKFLAGS = ['-s'])
-else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
diff --git a/resource/build_common/darwin/SConscript b/resource/build_common/darwin/SConscript
deleted file mode 100644 (file)
index fb98616..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-##
-# This script set darwin specific flags (GNU GCC)
-#
-##
-import platform
-
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'SYS_VERSION')
-
-if SYS_VERSION is None:
-       print '''
-*********************************** Error *************************************
-*   MAC OSX/IOS version isn't set, please set it in command line as :         *
-*      # scons SYS_VERSION=<version> ...                                      *
-*   To get the version, please see:                                                              *
-* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/   *
-* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ *
-*******************************************************************************
-'''
-       Exit(1)
-
-# Set release/debug flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
-
-if BUILD_TARGET == 'darwin':
-       SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + SYS_VERSION + '.sdk/'
-else:
-       if TARGET_CPU_ARCH in ['i386', 'x86_64']:
-               SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + SYS_VERSION + '.sdk/'
-       else:
-               SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + SYS_VERSION + '.sdk/'
-
-# Set arch flags
-env.AppendUnique(CXXFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-env.AppendUnique(CCFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-env.AppendUnique(LINKFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-
-if BUILD_TARGET == 'darwin':
-       flag = '-mmacosx-version-min=' + SYS_VERSION
-       env.AppendUnique(CXXFLAGS = [flag])
-       env.AppendUnique(CCFLAGS = [flag])
-       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/resource/build_common/ios/SConscript b/resource/build_common/ios/SConscript
deleted file mode 100644 (file)
index 78630b1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-##
-# This script set ios specific flags (GNU GCC)
-#
-##
-Import('env', 'TARGET_CPU_ARCH', 'SYS_VERSION')
-
-# setting of IOS is almost the same as Darwin(MAC OSX)
-env.SConscript('../darwin/SConscript')
-
-if TARGET_CPU_ARCH in ['i386', 'x86_64']: #Simulator
-       flag = '-mios-simulator-version-min=' + SYS_VERSION
-       env.AppendUnique(CXXFLAGS = [flag])
-       env.AppendUnique(CCFLAGS = [flag])
-       env.AppendUnique(LINKFLAGS = [flag])
-else:
-       flag = '-miphoneos-version-min=' + SYS_VERSION
-       env.AppendUnique(CXXFLAGS = [flag])
-       env.AppendUnique(CCFLAGS = [flag])
-       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/resource/build_common/linux/SConscript b/resource/build_common/linux/SConscript
deleted file mode 100644 (file)
index d0d999e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-##
-# This script set linux specific flags (GNU GCC)
-#
-##
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH')
-
-# Set release/debug flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-       env.AppendUnique(LINKFLAGS = ['-s'])
-else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
-
-# Set arch flags
-if TARGET_CPU_ARCH in ['x86']:
-       env.AppendUnique(CFLAGS = ['-m32'])
-       env.AppendUnique(CXXFLAGS = ['-m32'])
-       env.AppendUnique(LINKFLAGS = ['-m32'])
-elif TARGET_CPU_ARCH in ['x86_64']:
-       env.AppendUnique(CXXFLAGS = ['-m64'])
-       env.AppendUnique(CFLAGS = ['-m64'])
-       env.AppendUnique(LINKFLAGS = ['-m64'])
-elif TARGET_CPU_ARCH.find('v7a-hard') > 0:
-       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
-       env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard'])
-       env.AppendUnique(CFLAGS = ['-mfloat-abi=hard'])
-       env.AppendUnique(CXXFLAGS = ['-mfloat-abi=hard'])
-       env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard'])
-elif TARGET_CPU_ARCH.find('v7a') > 0:
-       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
-elif TARGET_CPU_ARCH.find('arm64') > 0:
-       env.AppendUnique(CPPFLAGS = ['-march=armv8-a'])
-else:
-       env.AppendUnique(CPPFLAGS = ['-march=armv5te'])
\ No newline at end of file
diff --git a/resource/build_common/windows/SConscript b/resource/build_common/windows/SConscript
deleted file mode 100644 (file)
index 49fd8a0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-##
-# This script includes windows specific config (MSVS/MSVC)
-##
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH')
-
-# Set common flags
-env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996'])
-env.AppendUnique(CFLAGS=['/EHsc'])
-env.AppendUnique(CXXFLAGS=['/EHsc'])
-
-# Set release/debug flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['/MD', '/O2', '/GF'])
-       env.AppendUnique(CXXFLAGS = ['/MD', '/O2', '/GF'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-else:
-       env.AppendUnique(CFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
-       env.AppendUnique(CXXFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
-       env.AppendUnique(CPPDEFINES = ['_DEBUG'])
-       env.AppendUnique(LINKFLAGS = ['/debug'])
\ No newline at end of file
index f8cc634..5df1507 100644 (file)
@@ -1,18 +1,18 @@
 ##
-# liboctbstack (static library) build script
+# liboctbstack (share library) build script
 ##
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'RELEASE_BUILD', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 
-liboctbstack_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
-# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-Import('OIC_UTILS')
+liboctbstack_env = lib_env.Clone()
 
+target_os = env.get('TARGET_OS')
 # As in the source code, it includes arduino Time library (C++)
 # It requires compile the .c with g++
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
        liboctbstack_env.Replace(CC = env.get('CXX'))
        liboctbstack_env.Replace(CFLAGS = env.get('CXXFLAGS'))
 
@@ -20,7 +20,7 @@ if BUILD_TARGET == 'arduino':
 # Build flags
 ######################################################################
 liboctbstack_env.PrependUnique(CPPPATH = [
-               OIC_UTILS + '/tb/cJSON/',
+               '../../extlibs/cjson/',
                'ocsocket/include',
                'logger/include',
                'ocrandom/include',
@@ -32,14 +32,28 @@ liboctbstack_env.PrependUnique(CPPPATH = [
                '../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
+if target_os not in ['arduino', 'windows', 'winrt']:
        liboctbstack_env.AppendUnique(CPPDEFINES  = ['WITH_POSIX'])
        liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99'])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
+if target_os not in ['windows', 'winrt']:
        liboctbstack_env.AppendUnique(CFLAGS = ['-Wall'])
 
-if not RELEASE_BUILD:
+if target_os == 'android':
+       liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       liboctbstack_env.AppendUnique(LIBS = ['coap', 'm'])
+
+if target_os == 'arduino':
+       liboctbstack_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+else:
+       liboctbstack_env.AppendUnique(CFLAGS = ['-fPIC'])
+
+if target_os in ['darwin', 'ios']:
+       liboctbstack_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+       liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       liboctbstack_env.AppendUnique(LIBS = ['coap'])
+
+if not env.get('RELEASE'):
        liboctbstack_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
 ######################################################################
@@ -47,23 +61,20 @@ if not RELEASE_BUILD:
 ######################################################################
 OCTBSTACK_SRC = 'stack/src/'
 liboctbstack_src = [
+       '../../extlibs/cjson/cJSON.c',
        'occoap/src/occoap.c',
        'occoap/src/occoaphelper.c',
        OCTBSTACK_SRC + 'ocstack.c',
        OCTBSTACK_SRC + 'occlientcb.c',
        OCTBSTACK_SRC + 'ocresource.c',
        OCTBSTACK_SRC + 'ocobserve.c',
+        OCTBSTACK_SRC + 'ocserverrequest.c',
        OCTBSTACK_SRC + 'occollection.c',
+       OCTBSTACK_SRC + 'ocsecurity.c'
        ]
-
-if RELEASE_BUILD:
-       prefix = TARGET_CPU_ARCH + '-'
+if target_os == 'arduino':
+       liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
 else:
-       prefix = TARGET_CPU_ARCH + 'd-'
-cjson_obj = liboctbstack_env.Object(OIC_UTILS + '/tb/cJSON/cJSON.c', OBJPREFIX=prefix)
-liboctbstack_src.append(cjson_obj)
+       liboctbstack = liboctbstack_env.SharedLibrary('octbstack', liboctbstack_src)
 
-liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
-i_lctbs = liboctbstack_env.Install(BUILD_DIR, liboctbstack)
-Alias('liboctbstack', i_lctbs)
-env.AppendUnique(TS = ['liboctbstack'])
+liboctbstack_env.InstallTarget(liboctbstack, 'liboctbstack')
index 3f3efe3..7e1bdf1 100644 (file)
@@ -1,14 +1,15 @@
 ##
-# libcoap (static library) build script
+# libcoap (share library) build script
 ##
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'RELEASE_BUILD', 'BUILD_DIR', 'ARDUINO_HOME')
+Import('env')
 
 libcoap_env = env.Clone()
 
-# As in the source code, it includes arduino Time library (C++)
+target_os = env.get('TARGET_OS')
+# As in the source code(C) includes arduino Time library head file(C++)
 # It requires compile the .c with g++
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
        libcoap_env.Replace(CC = env.get('CXX'))
        libcoap_env.Replace(CFLAGS = env.get('CXXFLAGS'))
 
@@ -24,15 +25,24 @@ libcoap_env.PrependUnique(CPPPATH = [
                '../../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
+if target_os not in ['arduino', 'windows', 'winrt']:
        libcoap_env.AppendUnique(CPPDEFINES = ['WITH_POSIX'])
-       libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99'])
+       libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99', '-fPIC'])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
+if target_os not in ['windows', 'winrt']:
        libcoap_env.AppendUnique(CFLAGS = ['-Wall', '-ffunction-sections',
                        '-fdata-sections', '-fno-exceptions'])
 
-if not RELEASE_BUILD:
+if target_os == 'android':
+       libcoap_env.AppendUnique(LIBS = ['log'])
+
+if target_os == 'arduino':
+       libcoap_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+
+if target_os in ['darwin', 'ios']:
+       libcoap_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+if not env.get('RELEASE'):
        libcoap_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
 ######################################################################
@@ -45,7 +55,7 @@ libcoap_src = [
        'encode.c',
        'uri.c',
        'coap_list.c',
-       'resource.c',
+#      'resource.c',
        'hashkey.c',
     'str.c',
        'option.c',
@@ -59,22 +69,17 @@ libcoap_src = [
        '../../oc_logger/c/oc_console_logger.c'
        ]
 
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
        if env.get('NET') == 'Wifi':
                libcoap_src.append(['../ocsocket/src/ocsocket_arduino_wifi.cpp'])
        else:
                libcoap_src.append(['../ocsocket/src/ocsocket_arduino.cpp'])
-
-       if RELEASE_BUILD:
-               prefix = TARGET_CPU_ARCH + '-'
-       else:
-               prefix = TARGET_CPU_ARCH + 'd-'
-       time_obj = libcoap_env.Object(ARDUINO_HOME + '/libraries/Time/Time.cpp', OBJPREFIX=prefix)
-       libcoap_src.append(time_obj)
 else:
        libcoap_src.append(['../ocsocket/src/ocsocket.c'])
 
-libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap')
-i_lc = libcoap_env.Install(BUILD_DIR, libcoap)
-Alias('libcoap', i_lc)
-env.AppendUnique(TS = ['libcoap'])
\ No newline at end of file
+if target_os == 'arduino':
+       libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
+else:
+       libcoap = libcoap_env.SharedLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
+
+libcoap_env.InstallTarget(libcoap, 'libcoap')
index 283ba69..ee2d5a9 100644 (file)
@@ -3,12 +3,16 @@
  * Copyright (C) 2010--2012,2014 Olaf Bergmann <bergmann@tzi.org>
  *
  * This file is part of the CoAP library libcoap. Please see
- * README for terms of use. 
+ * README for terms of use.
  */
 
 #ifndef _COAP_BLOCK_H_
 #define _COAP_BLOCK_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "option.h"
 #include "encode.h"
 #include "pdu.h"
 #endif
 
 /**
- * Structure of Block options. 
+ * Structure of Block options.
  */
 typedef struct {
-  unsigned int num:20;         /**< block number */
-  unsigned int m:1;            /**< 1 if more blocks follow, 0 otherwise */
-  unsigned int szx:3;          /**< block size */
+  unsigned int num:20;  /**< block number */
+  unsigned int m:1;     /**< 1 if more blocks follow, 0 otherwise */
+  unsigned int szx:3;   /**< block size */
 } coap_block_t;
 
 /**
- * Returns the value of the least significant byte of a Block option @p opt. 
+ * Returns the value of the least significant byte of a Block option @p opt.
  * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST
  * returns @c NULL.
  */
@@ -87,7 +91,7 @@ coap_opt_block_set_m(coap_opt_t *block_opt, int m) {
  * value @c 1. Otherwise, @c 0 is returned.
  *
  * @param pdu   The pdu to search for option @p type.
- * @param type  The option to search for (must be COAP_OPTION_BLOCK1 or 
+ * @param type  The option to search for (must be COAP_OPTION_BLOCK1 or
  *              COAP_OPTION_BLOCK2)
  * @param block The block structure to initilize.
  * @return @c 1 on success, @c 0 otherwise.
@@ -101,9 +105,9 @@ int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block);
  * space is required. The actual length of the resource is specified
  * in @p data_length.
  *
- * This function may change *block to reflect the values written to 
+ * This function may change *block to reflect the values written to
  * @p pdu. As the function takes into consideration the remaining space
- * @p pdu, no more options should be added after coap_write_block_opt() 
+ * @p pdu, no more options should be added after coap_write_block_opt()
  * has returned.
  *
  * @param block      The block structure to use. On return, this object
@@ -117,9 +121,9 @@ int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block);
  * @return @c 1 on success, or a negative value on error.
  */
 int coap_write_block_opt(coap_block_t *block, unsigned short type,
-                        coap_pdu_t *pdu, size_t data_length);
+                         coap_pdu_t *pdu, size_t data_length);
 
-/** 
+/**
  * Adds the @p block_num block of size 1 << (@p block_szx + 4) from
  * source @p data to @p pdu.
  *
@@ -131,7 +135,11 @@ int coap_write_block_opt(coap_block_t *block, unsigned short type,
  * @return @c 1 on success, @c 0 otherwise.
  */
 int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data,
-                  unsigned int block_num, unsigned char block_szx);
+                   unsigned int block_num, unsigned char block_szx);
 /**@}*/
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _COAP_BLOCK_H_ */
index 9e84a71..ddf4fec 100644 (file)
@@ -43,8 +43,10 @@ LOGGER_DIR    = $(ROOT_DIR)/logger
 RANDOM_DIR    = $(ROOT_DIR)/ocrandom
 STACK_DIR     = $(ROOT_DIR)/stack
 OCMALLOC_DIR  = $(ROOT_DIR)/ocmalloc
+EXTLIBS_DIR   = $(ROOT_DIR)/../../extlibs
+TINYDTLS_DIR  = $(EXTLIBS_DIR)/tinydtls
 INC_DIRS      = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include \
-                -I$(OCMALLOC_DIR)/include -I$(OC_LOG_DIR)/include 
+                -I$(OCMALLOC_DIR)/include -I$(OC_LOG_DIR)/include -I$(STACK_DIR)/include
 
 # Note for Arduino: The CC flag is set to the C++ compiler since Arduino build 
 # includes Time.h header file which has C++ style definitions.
@@ -105,11 +107,10 @@ VPATH += $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src:$(RANDOM_DIR)/src:$(OCMALLOC_DIR)/s
          :$(OC_LOG_DIR)/c
 
 ifeq ($(PLATFORM),linux)
-ifneq ($(wildcard $(ROOT_DIR)/tinydtls/libtinydtls.a),)
+ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),)
     $(info "Building libcoap with DTLS support")
        SOURCES += netdtls.c
        VPATH += sec
-       TINYDTLS_DIR  = $(ROOT_DIR)/tinydtls
        NETDTLS_DIR   = sec
        INC_DIRS += -I$(TINYDTLS_DIR) -I$(NETDTLS_DIR) -I.
        CC_FLAGS.debug += -DWITH_DTLS
index eb1f1eb..4fce8f9 100644 (file)
@@ -716,7 +716,7 @@ coap_tid_t coap_send(coap_context_t *context,
     else
     {
         node->timeout = MAX_MULTICAST_DELAY_SEC * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8);
-        node->delayedResponse = 1;
+        node->delayedResNeeded = 1;
     }
 
     if (flag & SEND_SECURE_PORT) {
@@ -857,7 +857,7 @@ int coap_read(coap_context_t *ctx, int sockfd) {
 
   coap_address_t src, dst;
   coap_queue_t *node;
-  unsigned char delayRes = 0;
+  unsigned char delayedResNeeded = 0;
 
 #ifdef WITH_CONTIKI
     pbuf = uip_appdata;
@@ -876,7 +876,7 @@ int coap_read(coap_context_t *ctx, int sockfd) {
 
   // Set the delayed response flag for responding to multicast requests
   if (sockfd == ctx->sockfd_wellknown && bytes_read > 0) {
-      delayRes = 1;
+      delayedResNeeded = 1;
   }
 #if defined(WITH_DTLS)
   // Perform the DTLS decryption if packet is coming on secure port
@@ -949,7 +949,7 @@ int coap_read(coap_context_t *ctx, int sockfd) {
     }
 
     //set the delayed response flag
-    node->delayedResponse = delayRes;
+    node->delayedResNeeded = delayedResNeeded;
 
     //set the secure flag on the received packet
 #if defined(WITH_DTLS)
@@ -1612,7 +1612,6 @@ handle_locally(coap_context_t *context __attribute__ ((unused)),
 
         if (ctx->timer_configured)
         {
-            printf("clearing\n");
             sys_untimeout(coap_retransmittimer_execute, (void*)ctx);
             ctx->timer_configured = 0;
         }
@@ -1636,8 +1635,6 @@ handle_locally(coap_context_t *context __attribute__ ((unused)),
                  * */
                 delay = 0;
             }
-
-            printf("scheduling for %d ticks\n", delay);
             sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx);
             ctx->timer_configured = 1;
         }
index 81f8031..cec3f0a 100644 (file)
@@ -51,12 +51,16 @@ extern "C" {
 #include "coap_time.h"
 
 typedef enum {
-    SEND_NOW            = (1 << 0), /*Flag used when sending non-confirmable, ACK and RESET coap pdus*/
-    SEND_NOW_CON        = (1 << 1), /*Flag used when sending confirmable coap pdu*/
-    SEND_DELAYED        = (1 << 2), /*Flag used to delay the transmission of coap pdu*/
-    SEND_RETX           = (1 << 3), /*Flag used to retransmit a confirmable pdu*/
-    SEND_SECURE_PORT    = (1 << 4)  /*Flag used to indicate that PDU needs to
-                                      be transmitted on secure port */
+    SEND_NOW            = (1 << 0), // Flag used when sending non-confirmable,
+                                    // ACK and RESET coap pdus, Automatically set in SendCoAPPdu
+                                    // Do not use in upper stack APIs
+    SEND_NOW_CON        = (1 << 1), // Flag used when sending confirmable coap pdu,
+                                    // Automatically set in SendCoAPPdu,
+                                    // Do not use in upper stack APIs
+    SEND_DELAYED        = (1 << 2), // Flag used to delay the transmission of coap pdu
+    SEND_RETX           = (1 << 3), // Flag used to retransmit a confirmable pdu
+    SEND_SECURE_PORT    = (1 << 4)  // Flag used to indicate that PDU needs to
+                                    // be transmitted on secure port
 } coap_send_flags_t;
 
 struct coap_queue_t;
@@ -74,7 +78,7 @@ typedef struct coap_queue_t {
 
   coap_pdu_t *pdu;      /**< the CoAP PDU to send */
 
-  unsigned char delayedResponse;  /**< delayed response flag */
+  unsigned char delayedResNeeded;  /**< delayed response flag */
   unsigned char secure;      /**< rx/tx will use secure channel (DTLS) */
 } coap_queue_t;
 
index 7428e63..8b76776 100644 (file)
@@ -80,6 +80,7 @@ extern "C" {
 #define COAP_OPTION_LOCATION_QUERY 20 /* E, String,   0-255 B, (none) */
 #define COAP_OPTION_PROXY_URI    35 /* C, String, 1-1034 B, (none) */
 #define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
+#define COAP_OPTION_SIZE2        28 /* E, uint, 0-4 B, (none) */
 #define COAP_OPTION_SIZE1        60 /* E, uint, 0-4 B, (none) */
 
 /* option types from draft-ietf-coap-observe-09 */
@@ -343,7 +344,7 @@ int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data);
  * This function returns the number of bytes written or @c 0 on error.
  */
 size_t coap_add_option(coap_pdu_t *pdu, unsigned short type,
-                      unsigned int len, const unsigned char *data);
+                       unsigned int len, const unsigned char *data);
 
 /**
  * Adds option of given type to pdu that is passed as first
@@ -353,7 +354,7 @@ size_t coap_add_option(coap_pdu_t *pdu, unsigned short type,
  * written before the PDU can be sent, or @c NULL on error.
  */
 unsigned char *coap_add_option_later(coap_pdu_t *pdu, unsigned short type,
-                     unsigned int len);
+                                     unsigned int len);
 
 /**
  * Adds given data to the pdu that is passed as first parameter. Note
index b15ed99..1535670 100644 (file)
 #include "debug.h"
 #include "logger.h"
 #include "mem.h"
+#include "ocsecurityconfig.h"
 
 #define MOD_NAME ("netdtls.c")
 
 #define get_dtls_ctx(coap_ctx) (coap_ctx->coap_dtls_ctx->dtls_ctx)
 
+extern void OCGetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo);
 
 /**
  * An internal method to invoke tinyDTLS library 'dtls_write' method.
@@ -123,7 +125,7 @@ static int coap_cache_pdu(coap_context_t *ctx,
 
     if (existing_node) {
         node->timeout = existing_node->timeout;
-        node->delayedResponse = existing_node->delayedResponse;
+        node->delayedResNeeded = existing_node->delayedResNeeded;
     }
 
     // Add the node in cachedqueue list
@@ -163,7 +165,7 @@ static void save_cached_con_pdu(coap_context_t *ctx,
         node->t = (now - ctx->sendqueue_basetime) + node->timeout;
     }
 
-    node->delayedResponse = 0;
+    node->delayedResNeeded = 0;
     node->next = NULL;
     coap_insert_node(&ctx->sendqueue, node);
 }
@@ -212,7 +214,7 @@ static void coap_send_cached_pdu( coap_context_t *ctx,
     if (!ctx)
         return ;
 
-    for (;node=get_cached_pdu(ctx, dst);) {
+    for (;(node=get_cached_pdu(ctx, dst));) {
         OC_LOG(DEBUG, MOD_NAME, PCF("Sending cached PDU"));
         OC_LOG_BUFFER(DEBUG, MOD_NAME, (uint8_t*)node->pdu->hdr, node->pdu->length);
         // Send this PDU to DTLS library for encryption
@@ -315,47 +317,38 @@ static int handle_secure_event(dtls_context_t *dtls_ctx,
 static int get_psk_credentials(dtls_context_t *ctx,
               const session_t *session,
               dtls_credentials_type_t type,
-              const unsigned char *desc, size_t descLen,
-              unsigned char *result, size_t resultLen)
+              const unsigned char *desc, size_t desc_len,
+              unsigned char *result, size_t result_len)
 {
+    int ret = -1;
+    OCDtlsPskCredsBlob *creds_blob = NULL;
 
-#define RS_IDENTITY     ("1111111111111111")
-#define CLIENT_IDENTITY ("2222222222222222")
-#define RS_CLIENT_PSK   ("AAAAAAAAAAAAAAAA")
+    //Retrieve the credentials blob from security module
+    OCGetDtlsPskCredentials(&creds_blob);
 
-    if (type == DTLS_PSK_HINT)
-    {
-        if (sizeof(RS_IDENTITY) < resultLen)
-        {
-            memcpy(result, RS_IDENTITY, sizeof(RS_IDENTITY));
-            return sizeof(RS_IDENTITY);
-        }
-    }
-    else if (type == DTLS_PSK_IDENTITY)
-    {
-        if (sizeof(CLIENT_IDENTITY) < resultLen)
-        {
-            memcpy(result, CLIENT_IDENTITY, sizeof(CLIENT_IDENTITY));
-            return sizeof(CLIENT_IDENTITY);
+    if (!creds_blob)
+        return ret;
+
+    if ((type == DTLS_PSK_HINT) || (type == DTLS_PSK_IDENTITY)) {
+        if (DTLS_PSK_ID_LEN <= result_len){
+            memcpy(result, creds_blob->identity, DTLS_PSK_ID_LEN);
+            ret = DTLS_PSK_ID_LEN;
         }
     }
-    else if (type == DTLS_PSK_KEY && (desc))
-    {
-        if (descLen == sizeof(RS_IDENTITY) &&
-            !memcmp(desc, RS_IDENTITY, descLen))
-        {
-            memcpy(result, RS_CLIENT_PSK, sizeof(RS_CLIENT_PSK));
-            return sizeof(RS_CLIENT_PSK);
-        }
-        if (descLen == sizeof(CLIENT_IDENTITY) &&
-            !memcmp(desc, CLIENT_IDENTITY, descLen))
-        {
-            memcpy(result, RS_CLIENT_PSK, sizeof(RS_CLIENT_PSK));
-            return sizeof(RS_CLIENT_PSK);
+
+    if ((type == DTLS_PSK_KEY) && (desc) && (desc_len == DTLS_PSK_PSK_LEN)) {
+        //Check if we have the credentials for the device with which we
+        //are trying to perform a handshake
+        for (int i =0; i < creds_blob->num; i++) {
+            if (memcmp(desc, creds_blob->creds[i].id, DTLS_PSK_ID_LEN) == 0)
+            {
+                memcpy(result, creds_blob->creds[i].psk, DTLS_PSK_PSK_LEN);
+                ret = DTLS_PSK_PSK_LEN;
+            }
         }
     }
 
-    return -1;
+    return ret;
 }
 
 
index 8fed5e0..238a65d 100644 (file)
@@ -90,7 +90,7 @@ OCTBSTACK_DIR = stack
 OCMALLOC_DIR   = ocmalloc
 EXTLIBS_DIR    = ../../extlibs
 CJSON_DIR      = $(EXTLIBS_DIR)/cjson
-TINYDTLS_DIR   = tinydtls
+TINYDTLS_DIR   = $(EXTLIBS_DIR)/tinydtls
 
 OCCOAP_SRC     = $(OCCOAP_DIR)/src
 OCTBSTACK_SRC  = $(OCTBSTACK_DIR)/src
@@ -133,7 +133,9 @@ OCTBSTACK_SOURCES   := $(OCTBSTACK_SRC)/ocstack.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occlientcb.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocresource.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocobserve.c
+OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocserverrequest.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occollection.c
+OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocsecurity.c
 
 SOURCES                        := $(CJSON_SOURCES)
 SOURCES                        += $(OCCOAP_SOURCES)
@@ -143,10 +145,10 @@ all:      make_lcoap objdirs obj_build liboctbstack.a
 
 buildScript_all: objdirs obj_build liboctbstack.a
 
-make_lcoap: 
+make_lcoap:
        $(MAKE) -C $(LCOAP_DIR) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)" "ARDUINOWIFI=$(ARDUINOWIFI)"
 
-objdirs: 
+objdirs:
        mkdir -p $(PLATFORM)
        mkdir -p $(PLATFORM)/$(ARDUINO_SHIELD_TYPE)
        mkdir -p $(OUT_DIR)
@@ -158,18 +160,18 @@ obj_build:
        $(foreach source,$(SOURCES), $(CC) $(CFLAGS) $(source) -o $(patsubst %.c, %.o, $(patsubst %, $(OBJ_DIR)/%, $(notdir $(source))));)
 
 liboctbstack.a: obj_build
-       @echo "Building $@" 
+       @echo "Building $@"
        # Unpackage libcoap.a to $(OBJ_DIR)/$(BUILD). The output objects from OCStack and OCCoap are already at this location
        @cd $(OBJ_DIR) && $(AR) -x $(PLATFORM_SPECIFIC_BACKOUT)$(LCOAP_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/libcoap.a
        # Repackage all the objects at this location into a single archive. This is OCStack, OCCoap, and LibCoap (LibCoap contains OCRandom, OCLogger, and OCSocket.).
        $(AR) -r $(OUT_DIR)/$@ $(OBJ_DIR)/*.o
-    
+
     ifeq ($(PLATFORM),linux)
      ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),)
                        $(info "Building liboctbstack with DTLS support")
-                       mkdir -p $(OBJ_DIR)/$(TINYDTLS_DIR)
-                       @cd $(OBJ_DIR)/$(TINYDTLS_DIR) && $(AR) -x ../$(PLATFORM_SPECIFIC_BACKOUT)$(TINYDTLS_DIR)/libtinydtls.a
-                       $(AR) -q $(OUT_DIR)/$@ $(OBJ_DIR)/$(TINYDTLS_DIR)/*.o
+                       mkdir -p $(OBJ_DIR)/tinydtls
+                       @cd $(OBJ_DIR)/tinydtls && $(AR) -x ../$(PLATFORM_SPECIFIC_BACKOUT)$(TINYDTLS_DIR)/libtinydtls.a
+                       $(AR) -q $(OUT_DIR)/$@ $(OBJ_DIR)/tinydtls/*.o
      endif
     endif
 
index 512ef74..31ab9f0 100644 (file)
@@ -70,6 +70,16 @@ OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode);
 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
         const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions);
 
+/**
+ * Send a response to a request.
+ *
+ * @param response - pointer to OCServerProtocolResponse that contains all request and
+ *                   response info necessary to send the response to the client
+ * @return
+ *     OC_STACK_OK               - No errors; Success
+ *     OC_STACK_ERROR            - Error sending response
+ */
+OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response);
 
 /**
  * Stop the CoAP client or server processing
@@ -94,15 +104,6 @@ OCStackResult OCProcessCoAP();
 void OCGenerateCoAPToken(OCCoAPToken * token);
 
 /**
- * Initiate sending of CoAP messages. Example: server uses it to send observe messages
- *
- * @return 0 - success, else - TBD error
- */
-OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
-        OCQualityOfService qos, OCCoAPToken * token,
-        unsigned char *payload, OCResource *resPtr, uint32_t maxAge);
-
-/**
  * Retrieve the end-point info where resource is being hosted.
  * Currently, this method only provides the IP port with which the socket
  * is bound. This internal method may be extended in future to retrieve
index b0999de..7be3e30 100644 (file)
@@ -68,31 +68,19 @@ coap_list_t *
 CreateNewOptionNode(unsigned short key, unsigned int length,
         unsigned char *data);
 
-// Internal function to create OCRequest struct at the server from a received coap pdu
-OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
-        unsigned char * uriBuf, OCObserveReq * observeReq,
-        OCEntityHandlerRequest * entityHandlerRequest,
-        uint8_t secure);
-
-// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
-        OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
-        unsigned char * queryBuf, unsigned char *newResUriBuf);
-
 // Internal function to retrieve Uri and Query from received coap pdu
 OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
-        unsigned char * queryBuf, uint8_t * * observeOptionLoc,
-        uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
-        OCHeaderOption * rcvVendorSpecificHeaderOptions,
-        uint8_t * numRcvVendorSpecificHeaderOptions);
+        unsigned char * queryBuf, uint32_t * observeOption,
+        uint32_t * maxAgeOption,
+        uint8_t * numVendorSpecificHeaderOptions,
+        OCHeaderOption * vendorSpecificHeaderOptions,
+        coap_block_t * block1, coap_block_t * block2,
+        uint16_t * size1, uint16_t * size2,
+        unsigned char * payload);
 
 // Internal function to retrieve a Token from received coap pdu
 void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken);
 
-// Internal function to create OCObserveReq at the server
-OCStackResult FormOCObserveReq(OCObserveReq ** observeReqLoc, uint32_t obsOption,
-            OCDevAddr * remote, OCCoAPToken * rcvdToken);
-
 // Internal function to create OCResponse struct at the client from a received coap pdu
 OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
         uint8_t TTL, OCClientResponse * clientResponse);
@@ -107,7 +95,7 @@ void HandleSendQueue(coap_context_t * gCoAPCtx);
 
 // Internal function to form the standard response option list
 OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
-        uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
+        uint32_t * addMaxAge, uint32_t * observeOptionPtr,
         uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
         uint8_t queryLength, unsigned char * query, OCHeaderOption * vendorSpecificHeaderOptions,
         uint8_t numVendorSpecificHeaderOptions);
index ee8cb3a..cc9c95a 100644 (file)
 #include <limits.h>
 #include <ctype.h>
 
-//-----------------------------------------------------------------------------
+//=============================================================================
 // Macros
-//-----------------------------------------------------------------------------
+//=============================================================================
 #define TAG    PCF("OCCoAP")
 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} }
 
 //=============================================================================
+// Defines
+//=============================================================================
+#define COAP_BLOCK_FILL_VALUE   (0xFF)
+
+//=============================================================================
 // Private Variables
 //=============================================================================
 
@@ -71,25 +76,27 @@ static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
 
     // silence warnings
     (void) ctx;
-
-    OCStackResult result = OC_STACK_OK;
-    OCCoAPToken sentToken;
-    uint8_t * observeOption = NULL;
     coap_pdu_t * sentPdu = sentQueue->pdu;
+    OCStackResult result = OC_STACK_ERROR;
+    uint32_t observationOption = OC_OBSERVE_NO_OPTION;
+    // {{0}} to eliminate warning for known compiler bug 53119
+    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
+    OCCoAPToken sentToken = {{0}};
 
-    // fill the buffers of Uri and Query
-    result = ParseCoAPPdu(sentPdu, NULL, NULL, &observeOption, NULL, NULL, NULL, NULL);
+    result = ParseCoAPPdu(sentPdu, NULL, NULL, &observationOption, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL, NULL);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // fill OCCoAPToken structure
     RetrieveOCCoAPToken(sentPdu, &sentToken);
 
-    if(msgType == COAP_MESSAGE_RST){
-        // now the observer should be deleted
+    if(msgType == COAP_MESSAGE_RST)
+    {
         if(myStackMode != OC_CLIENT)
         {
-            result = OCObserverStatus(&sentToken, OC_OBSERVER_NOT_INTERESTED);
-            if(result == OC_STACK_OK){
+            result = OCStackFeedBack(&sentToken, OC_OBSERVER_NOT_INTERESTED);
+            if(result == OC_STACK_OK)
+            {
                 OC_LOG_V(DEBUG, TAG,
                         "Received RST, removing all queues associated with Token %d bytes",
                         sentToken.tokenLength);
@@ -98,18 +105,19 @@ static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
                         sentToken.tokenLength);
             }
         }
-    }else if(observeOption && msgType == COAP_MESSAGE_ACK){
+    }
+    else if(observationOption != OC_OBSERVE_NO_OPTION && msgType == COAP_MESSAGE_ACK)
+    {
         OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength);
         OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
         // now the observer is still interested
         if(myStackMode != OC_CLIENT)
         {
-            OCObserverStatus(&sentToken, OC_OBSERVER_STILL_INTERESTED);
+            OCStackFeedBack(&sentToken, OC_OBSERVER_STILL_INTERESTED);
         }
     }
-
-    exit:
-        OCFree(observeOption);
+exit:
+    return;
 }
 
 //This function is called back by libcoap when a request is received
@@ -118,6 +126,17 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
 {
     // silence warnings
     (void) ctx;
+    OCServerProtocolRequest protocolRequest = {(OCMethod)0};
+    coap_block_t rcvdBlock1;
+    coap_block_t rcvdBlock2;
+    memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
+    memset(&rcvdBlock2, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
+    uint16_t rcvdSize1 = 0;
+    coap_pdu_t * rcvdPdu = rcvdRequest->pdu;
+    coap_pdu_t * sendPdu = NULL;
+    coap_send_flags_t sendFlag;
+    OCStackResult result = OC_STACK_ERROR;
+    OCStackResult requestResult = OC_STACK_ERROR;
 
     if(myStackMode == OC_CLIENT)
     {
@@ -125,181 +144,139 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
         return;
     }
 
-    OCStackResult result = OC_STACK_ERROR;
-    OCStackResult responseResult = OC_STACK_ERROR;
-    OCRequest * request = NULL;
-    OCEntityHandlerRequest entityHandlerRequest;
-    OCCoAPToken rcvdToken;
-    OCObserveReq * rcvdObsReq = NULL;
-    coap_pdu_t * sendPdu = NULL;
-    coap_list_t *optList = NULL;
-    uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
-    uint32_t maxAge = 0x2ffff;
-    OCMethod ocMethod;
-
-    unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
-    unsigned char rcvdQuery[MAX_QUERY_LENGTH] = { 0 };
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 };
-    unsigned char newResourceUri[MAX_RESPONSE_LENGTH] = { 0 };
-    uint8_t * rcvObserveOption = NULL;
-    unsigned char * bufReqPayload = NULL;
-    uint32_t observeOption = OC_RESOURCE_NO_OBSERVE;
-    coap_send_flags_t sendFlag;
-    memset(&entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
-
-    coap_pdu_t * recvPdu = rcvdRequest->pdu;
-
-    // fill the buffers of Uri and Query
-    result = ParseCoAPPdu(recvPdu, rcvdUri, rcvdQuery, &rcvObserveOption, NULL, &bufReqPayload,
-            entityHandlerRequest.rcvdVendorSpecificHeaderOptions,
-            &(entityHandlerRequest.numRcvdVendorSpecificHeaderOptions));
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-    if(rcvObserveOption){
-        observeOption = (uint32_t)(*rcvObserveOption);
-    }
+    protocolRequest.observationOption = OC_OBSERVE_NO_OPTION;
+    protocolRequest.qos = (rcvdPdu->hdr->type == COAP_MESSAGE_CON) ?
+            OC_HIGH_QOS : OC_LOW_QOS;
+    protocolRequest.coapID = rcvdPdu->hdr->id;
+    protocolRequest.delayedResNeeded = rcvdRequest->delayedResNeeded;
+    protocolRequest.secured = rcvdRequest->secure;
 
     // fill OCCoAPToken structure
-    RetrieveOCCoAPToken(recvPdu, &rcvdToken);
+    RetrieveOCCoAPToken(rcvdPdu, &protocolRequest.requestToken);
+    OC_LOG_V(INFO, TAG, " Token received %d bytes",
+            protocolRequest.requestToken.tokenLength);
+    OC_LOG_BUFFER(INFO, TAG, protocolRequest.requestToken.token,
+            protocolRequest.requestToken.tokenLength);
+
+    // fill OCDevAddr
+    memcpy(&protocolRequest.requesterAddr, (OCDevAddr *) &rcvdRequest->remote,
+            sizeof(OCDevAddr));
+
+    // Retrieve Uri and Query from received coap pdu
+    result =  ParseCoAPPdu(rcvdPdu, protocolRequest.resourceUrl,
+            protocolRequest.query,
+            &(protocolRequest.observationOption), NULL,
+            &(protocolRequest.numRcvdVendorSpecificHeaderOptions),
+            protocolRequest.rcvdVendorSpecificHeaderOptions,
+            &rcvdBlock1, &rcvdBlock2, &rcvdSize1, NULL,
+            protocolRequest.reqJSONPayload);
+    VERIFY_SUCCESS(result, OC_STACK_OK);
 
-    switch (recvPdu->hdr->code)
+    switch (rcvdPdu->hdr->code)
     {
         case COAP_REQUEST_GET:
-            {
-                ocMethod = OC_REST_GET;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_GET;
+            break;
+        }
         case COAP_REQUEST_POST:
-            {
-                ocMethod = OC_REST_POST;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_POST;
+            break;
+        }
         case COAP_REQUEST_DELETE:
-            {
-                ocMethod = OC_REST_DELETE;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_DELETE;
+            break;
+        }
         case COAP_REQUEST_PUT:
-            {
-                ocMethod = OC_REST_PUT;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_PUT;
+            break;
+        }
         default:
-            {
-                OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
-                         recvPdu->hdr->code);
-                goto exit;
-            }
+        {
+            OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
+                    rcvdPdu->hdr->code);
+            goto exit;
+        }
     }
 
-    // fill OCEntityHandlerRequest structure
-    result = FormOCEntityHandlerRequest(&entityHandlerRequest, ocMethod,
-                                        bufRes, bufReqPayload, rcvdQuery, newResourceUri);
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-   // fill OCObserveReq
-   result = FormOCObserveReq(&rcvdObsReq, observeOption,
-           (OCDevAddr *)&(rcvdRequest->remote), &rcvdToken);
-   VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    // fill OCRequest structure
-    result = FormOCRequest(&request, (recvPdu->hdr->type == COAP_MESSAGE_CON) ?
-            OC_HIGH_QOS : OC_LOW_QOS, rcvdUri, rcvdObsReq, &entityHandlerRequest,
-            rcvdRequest->secure);
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    OC_LOG_V(INFO, TAG, " Receveid uri:     %s", request->resourceUrl);
-    OC_LOG_V(INFO, TAG, " Receveid query:   %s", entityHandlerRequest.query);
-    OC_LOG_V(INFO, TAG, " Receveid payload: %s",
-            request->entityHandlerRequest->reqJSONPayload);
-    OC_LOG_V(INFO, TAG, " Token received %d bytes",
-            rcvdToken.tokenLength);
-    OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
-
-    // process the request
-    responseResult = HandleStackRequests(request);
-    #ifdef WITH_PRESENCE
-    if(responseResult == OC_STACK_PRESENCE_DO_NOT_HANDLE)
+    if(rcvdBlock1.szx != 7)
     {
-        goto exit;
+        protocolRequest.reqPacketSize = 1 << (rcvdBlock1.szx + 4);
+        protocolRequest.reqMorePacket = rcvdBlock1.m;
+        protocolRequest.reqPacketNum  = rcvdBlock1.num;
+    }
+    else
+    {
+        // No block1 received
+        rcvdSize1 = strlen((const char *)protocolRequest.reqJSONPayload)+1;
+        protocolRequest.reqTotalSize = rcvdSize1;
     }
-    #endif
 
-    // do not process further if received an error
-    // ex : when receive a non-secure request to a secure resource
-    if(responseResult == OC_STACK_ERROR)
+    if(rcvdBlock2.szx != 7)
     {
-        goto exit;
+        protocolRequest.resPacketSize = 1 << (rcvdBlock2.szx + 4);
+        protocolRequest.resPacketNum  = rcvdBlock2.num;
     }
 
-    OC_LOG_V(INFO, TAG, "Response from ocstack: %s",
-            request->entityHandlerRequest->resJSONPayload);
+    requestResult = HandleStackRequests(&protocolRequest);
 
-    if(rcvdObsReq)
+    if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE ||
+            requestResult == OC_STACK_OK ||
+            requestResult == OC_STACK_RESOURCE_CREATED ||
+            requestResult == OC_STACK_RESOURCE_DELETED)
     {
-        switch(rcvdObsReq->result)
-        {
-        case OC_STACK_OK:
-            observeOption = rcvdObsReq->option;
-            result = FormOptionList(&optList, &mediaType, &maxAge,
-                    sizeof(observeOption), &observeOption,
-                    NULL, 0, NULL, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
-            break;
-        case OC_STACK_OBSERVER_NOT_ADDED:
-        case OC_STACK_OBSERVER_NOT_REMOVED:
-        case OC_STACK_INVALID_OBSERVE_PARAM:
-        default:
-            result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                    0, NULL, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
-            break;
+        goto exit;
+    }
+    else if(requestResult == OC_STACK_NO_MEMORY ||
+            requestResult == OC_STACK_ERROR ||
+            requestResult == OC_STACK_NOTIMPL ||
+            requestResult == OC_STACK_NO_RESOURCE ||
+            requestResult == OC_STACK_RESOURCE_ERROR)
+    {
+        // TODO: should we send an error also when we receive a non-secured request to a secure resource?
+        // TODO: should we consider some sort of error response
+        OC_LOG(DEBUG, TAG, PCF("We should send some sort of error message"));
+        // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+        sendPdu = GenerateCoAPPdu((rcvdPdu->hdr->type == COAP_MESSAGE_CON)? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+                OCToCoAPResponseCode(requestResult), rcvdPdu->hdr->id,
+                &protocolRequest.requestToken, NULL, NULL);
+        VERIFY_NON_NULL(sendPdu);
+        coap_show_pdu(sendPdu);
+        sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
+        if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
+                sendFlag)
+                != OC_STACK_OK){
+            OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
         }
+        goto exit;
     }
-    else
+    else if(requestResult == OC_STACK_SLOW_RESOURCE)
     {
-        if (responseResult == OC_STACK_RESOURCE_CREATED)
+        if(rcvdPdu->hdr->type == COAP_MESSAGE_CON)
         {
-            result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                    strlen((char *)newResourceUri), newResourceUri, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
+            // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+            sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, rcvdPdu->hdr->id,
+                    NULL, NULL, NULL);
+            VERIFY_NON_NULL(sendPdu);
+            coap_show_pdu(sendPdu);
+
+            sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
+            if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
+                    sendFlag)
+                    != OC_STACK_OK){
+                OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
+            }
         }
         else
         {
-            result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                    0, NULL, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
+            goto exit;
         }
     }
-
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
-    sendPdu = GenerateCoAPPdu(
-            (rcvdRequest->pdu->hdr->type == COAP_MESSAGE_CON) ?
-                    COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
-                    OCToCoAPResponseCode(responseResult), rcvdRequest->pdu->hdr->id,
-                    &rcvdToken,
-                    request->entityHandlerRequest->resJSONPayload, optList);
-    VERIFY_NON_NULL(sendPdu);
-    coap_show_pdu(sendPdu);
-
-    sendFlag = (coap_send_flags_t)(rcvdRequest->delayedResponse ? SEND_DELAYED : 0);
-    sendFlag = (coap_send_flags_t)( sendFlag | (rcvdRequest->secure ? SEND_SECURE_PORT : 0));
-
-    if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
-         sendFlag)
-            != OC_STACK_OK){
-        OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
-    }
-
 exit:
-    OCFree(rcvObserveOption);
-    OCFree(rcvdObsReq);
-    OCFree(request);
+    return;
 }
 
 uint32_t GetTime(float afterSeconds)
@@ -314,47 +291,41 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         const coap_queue_t * rcvdResponse) {
     OCResponse * response = NULL;
     OCCoAPToken rcvdToken;
-    OCClientResponse clientResponse;
+    OCClientResponse clientResponse = {0};
     ClientCB * cbNode = NULL;
-    unsigned char * bufRes = NULL;
-    uint8_t * rcvObserveOption = NULL;
-    uint8_t * rcvMaxAgeOption = NULL;
-    uint32_t sequenceNumber = OC_RESOURCE_NO_OBSERVE;
+    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+    uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
     uint32_t maxAge = 0;
-    char * resourceTypeName = NULL;
     OCStackResult result = OC_STACK_ERROR;
-    coap_pdu_t *sendPdu = NULL;
+    coap_pdu_t * sendPdu = NULL;
     coap_pdu_t * recvPdu = NULL;
-    uint8_t remoteIpAddr[4];
-    uint16_t remotePortNu;
-    unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
     unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
     uint8_t isObserveNotification = 0;
     #ifdef WITH_PRESENCE
+    char * resourceTypeName = NULL;
+    uint8_t remoteIpAddr[4];
+    uint16_t remotePortNu;
+    unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
     uint8_t isPresenceNotification = 0;
     uint8_t isMulticastPresence = 0;
     uint32_t lowerBound;
     uint32_t higherBound;
     char * tok = NULL;
     #endif
-    memset(&clientResponse, 0, sizeof(OCClientResponse));
+    coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
+    coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
+    uint16_t rcvdSize2 = 0;
 
     VERIFY_NON_NULL(ctx);
     VERIFY_NON_NULL(rcvdResponse);
     recvPdu = rcvdResponse->pdu;
 
-    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &rcvObserveOption, &rcvMaxAgeOption, &bufRes,
+    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
+            &clientResponse.numRcvdVendorSpecificHeaderOptions,
             clientResponse.rcvdVendorSpecificHeaderOptions,
-            &(clientResponse.numRcvdVendorSpecificHeaderOptions));
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    if(rcvObserveOption){
-        sequenceNumber = *((uint32_t *) rcvObserveOption);
-    }
+            &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);
 
-    if(rcvMaxAgeOption){
-        maxAge = *((uint32_t *) rcvMaxAgeOption);
-    }
+    VERIFY_SUCCESS(result, OC_STACK_OK);
 
     OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber);
     OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge);
@@ -370,25 +341,30 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
         isPresenceNotification = 1;
         OC_LOG(INFO, TAG, PCF("Received a presence notification"));
-        tok = strtok((char *)bufRes, ":");
-        sequenceNumber = (uint32_t )atoi(tok);
+        tok = strtok((char *)bufRes, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
+        VERIFY_NON_NULL(tok);
+        sequenceNumber = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
-        tok = strtok(NULL, ":");
-        maxAge = (uint32_t )atoi(tok);
+        tok = strtok(NULL, "[:]}");
+        VERIFY_NON_NULL(tok);
+        maxAge = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
-        tok = strtok(NULL, ":");
-        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
         if(tok) {
+            bufRes[strlen((char *)bufRes)] = ':';
             resourceTypeName = (char *)OCMalloc(strlen(tok));
             if(!resourceTypeName)
             {
                 goto exit;
             }
             strcpy(resourceTypeName, tok);
-            bufRes[strlen((char *)bufRes)] = ':';
             OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
                     resourceTypeName);
         }
+        bufRes[strlen((char *)bufRes)] = ']';
     }
     #endif
 
@@ -405,7 +381,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     cbNode = GetClientCB(&rcvdToken, NULL, NULL);
 
     #ifdef WITH_PRESENCE
-    // Check if the application subcribed for presence
+    // Check if the application subscribed for presence
     if(!cbNode)
     {
         // get the address of the remote
@@ -424,6 +400,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
         cbNode = GetClientCB(NULL, NULL, fullUri);
         isMulticastPresence = 1;
+        isPresenceNotification = 0;
     }
     #endif
 
@@ -433,6 +410,26 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
 
     if(cbNode)
     {
+        if(!isObserveNotification)
+        {
+            #ifdef WITH_PRESENCE
+            if(!isPresenceNotification)
+            {
+            #endif
+                OC_LOG(INFO, TAG, PCF("Received a regular response"));
+                if(recvPdu->hdr->type == COAP_MESSAGE_CON)
+                {
+                    sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
+                            recvPdu->hdr->id, NULL, NULL, NULL);
+                    VERIFY_NON_NULL(sendPdu);
+                    result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
+                            sendPdu,
+                            (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
+                }
+            #ifdef WITH_PRESENCE
+            }
+            #endif
+        }
         if(isObserveNotification)
         {
             OC_LOG(INFO, TAG, PCF("Received an observe notification"));
@@ -449,7 +446,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
             if(cbNode->method == OC_REST_OBSERVE &&
                     (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
                             (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
-                                    clientResponse.sequenceNumber == MAX_SEQUENCE_NUMBER)))
+                                    clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER))))
             {
                 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
                         Ignoring Incoming:%d  Against Current:%d.",
@@ -482,6 +479,12 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                 {
                     OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
                     response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+                    if(cbNode->presence)
+                    {
+                        OCFree(cbNode->presence->timeOut);
+                        OCFree(cbNode->presence);
+                        cbNode->presence = NULL;
+                    }
                 }
                 else
                 {
@@ -509,12 +512,11 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     cbNode->sequenceNumber = clientResponse.sequenceNumber;;
                 }
 
+                // Ensure that a filter is actually applied.
                 if(resourceTypeName && response->cbNode->filterResourceType)
                 {
-                    if(strcmp(resourceTypeName,
-                            (const char *)response->cbNode->filterResourceType)!=0)
+                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
                     {
-                        //Ignore presence callback if resource type does not match filter.
                         goto exit;
                     }
                 }
@@ -529,7 +531,18 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     remotePortNu);
                 mcNode = GetMCPresenceNode(senderUri);
 
-                if(mcNode != NULL)
+                if(maxAge == 0)
+                {
+                    OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+                    response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+                    if(cbNode->presence)
+                    {
+                        OCFree(cbNode->presence->timeOut);
+                        OCFree(cbNode->presence);
+                        cbNode->presence = NULL;
+                    }
+                }
+                else if(mcNode != NULL)
                 {
                     if(mcNode->nonce == clientResponse.sequenceNumber)
                     {
@@ -562,20 +575,17 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     }
                 }
 
+                // Ensure that a filter is actually applied.
                 if(resourceTypeName && response->cbNode->filterResourceType)
                 {
-                    if(strcmp(resourceTypeName,
-                            (const char *)response->cbNode->filterResourceType)!=0)
+                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
                     {
-                        //Ignore presence callback if resource type does not match filter.
                         goto exit;
                     }
                 }
-
             }
             #endif
         }
-
         HandleStackResponses(response);
     }
     else if(!cbNode && isObserveNotification)
@@ -608,8 +618,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         VERIFY_SUCCESS(result, OC_STACK_OK);
     }
     exit:
-        OCFree(rcvObserveOption);
-        OCFree(rcvMaxAgeOption);
+        OCFree(resourceTypeName);
         OCFree(response);
 }
 
@@ -727,7 +736,7 @@ OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPTo
             goto exit;
         }
 
-        VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, 0, NULL,
+        VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, NULL,
                 (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
                 uri.query.s, options, numOptions), OC_STACK_OK);
 
@@ -764,7 +773,7 @@ OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPTo
         case OC_REST_CANCEL_OBSERVE:
             coapMethod = COAP_REQUEST_GET;
             observeOption = (method == OC_REST_CANCEL_OBSERVE)?
-                    OC_RESOURCE_OBSERVE_DEREGISTER:OC_RESOURCE_OBSERVE_REGISTER;
+                    OC_OBSERVE_DEREGISTER:OC_OBSERVE_REGISTER;
             coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
                         sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions);
             break;
@@ -790,60 +799,92 @@ exit:
     return ret;
 }
 
-OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
-                       OCQualityOfService qos, OCCoAPToken * token,
-                       unsigned char *payload, OCResource *resPtr, uint32_t maxAge)
+OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response)
 {
     OCStackResult result = OC_STACK_ERROR;
+    coap_pdu_t * sendPdu = NULL;
     coap_list_t *optList = NULL;
-    uint8_t coapMsgType = COAP_MESSAGE_NON;
+    uint8_t msgType = COAP_MESSAGE_NON;
     uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
-    coap_pdu_t *sendPdu;
+    uint32_t maxAge = 0x2ffff;
+    coap_send_flags_t sendFlag = (coap_send_flags_t)0;
 
-    OC_LOG(INFO, TAG, PCF("Entering OCSendCoAPNotification"));
+    //uint32_t observeOption = OC_OBSERVE_NO_OPTION;
+    //OCStackResult responseResult;
 
-    coapMsgType = OCToCoAPQoS(qos);
+    OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResponse"));
 
-    #ifdef WITH_PRESENCE
-    if(!strcmp((const char *)uri, OC_PRESENCE_URI))
+    if(response->notificationFlag && response->qos == OC_HIGH_QOS)
     {
-        result = FormOptionList(&optList, &mediaType, NULL, 0, NULL,
-                NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
+        msgType = COAP_MESSAGE_CON;
     }
-    else
+    else if(response->notificationFlag && response->qos != OC_HIGH_QOS)
     {
-    #endif
-        result = FormOptionList(&optList, &mediaType, &maxAge, sizeof(resPtr->sequenceNum),
-                &resPtr->sequenceNum, NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
-    #ifdef WITH_PRESENCE
+        msgType = COAP_MESSAGE_NON;
+    }
+    else if(!response->notificationFlag && !response->slowFlag && response->qos == OC_HIGH_QOS)
+    {
+        msgType = COAP_MESSAGE_ACK;
+    }
+    else if(!response->notificationFlag && response->slowFlag && response->qos == OC_HIGH_QOS)
+    {
+        msgType = COAP_MESSAGE_CON;
+    }
+    else if(!response->notificationFlag)
+    {
+        msgType = COAP_MESSAGE_NON;
+    }
+
+    if(response->coapID == 0)
+    {
+        response->coapID = coap_new_message_id(gCoAPCtx);
     }
-    #endif
-    VERIFY_SUCCESS(result, OC_STACK_OK);
 
-    if(resPtr->resourceProperties == 0)
+    if (response->observationOption != OC_OBSERVE_NO_OPTION)
     {
-        result = OC_STACK_RESOURCE_DELETED;
+        result = FormOptionList(&optList, &mediaType, &maxAge,
+                &response->observationOption, NULL,
+                strlen((char *)response->resourceUri), response->resourceUri,
+                0, NULL,
+                response->sendVendorSpecificHeaderOptions,
+                response->numSendVendorSpecificHeaderOptions);
     }
+    else
+    {
+        result = FormOptionList(&optList, &mediaType, &maxAge,
+                NULL, NULL,
+                strlen((char *)response->resourceUri), response->resourceUri,
+                0, NULL,
+                response->sendVendorSpecificHeaderOptions,
+                response->numSendVendorSpecificHeaderOptions);
+    }
+    VERIFY_SUCCESS(result, OC_STACK_OK);
+
+    sendPdu = GenerateCoAPPdu(msgType, OCToCoAPResponseCode(response->result),
+            response->coapID, response->requestToken, (unsigned char *)response->payload,
+            optList);
 
-    sendPdu = GenerateCoAPPdu(
-            coapMsgType == COAP_MESSAGE_CON ? COAP_MESSAGE_CON : COAP_MESSAGE_NON,
-                    OCToCoAPResponseCode(result), coap_new_message_id(gCoAPCtx),
-                    token, payload, optList);
     VERIFY_NON_NULL(sendPdu);
     coap_show_pdu(sendPdu);
 
-    // TODO : resourceProperties will determine if the packet will be send using secure port
-    if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) dstAddr, sendPdu ,
-            (coap_send_flags_t)((resPtr->resourceProperties & OC_SECURE) ? SEND_SECURE_PORT : 0) )
+    sendFlag = (coap_send_flags_t)(response->delayedResNeeded ? SEND_DELAYED : 0);
+    sendFlag = (coap_send_flags_t)( sendFlag | (response->secured ? SEND_SECURE_PORT : 0));
+
+    if (SendCoAPPdu(gCoAPCtx, (coap_address_t *) (response->requesterAddr), sendPdu, sendFlag)
             != OC_STACK_OK)
     {
-        OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
+        OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu"));
+        return OC_STACK_ERROR;
     }
+
     return OC_STACK_OK;
+
 exit:
+    OC_LOG(ERROR, TAG, PCF("Error formatting server response"));
     return OC_STACK_ERROR;
 }
 
+
 /**
  * Stop the CoAP client or server processing
  *
index ceed9dd..f1e9382 100644 (file)
@@ -24,7 +24,6 @@
 #include "occoaphelper.h"
 #include "ocstackconfig.h"
 #include "logger.h"
-#include "ocobserve.h"
 #include "coap_time.h"
 #include "ocmalloc.h"
 
@@ -81,6 +80,10 @@ uint8_t OCToCoAPResponseCode(OCStackResult result)
             ret = COAP_RESPONSE_405;
             break;
 
+        case OC_STACK_NOTIMPL :
+            ret = COAP_RESPONSE_501;
+            break;
+
         default:
             ret = COAP_RESPONSE_500;
     }
@@ -137,6 +140,10 @@ OCStackResult CoAPToOCResponseCode(uint8_t coapCode)
             ret = OC_STACK_INVALID_METHOD;
             break;
 
+        case COAP_RESPONSE_501 :
+            ret = OC_STACK_NOTIMPL;
+            break;
+
         default:
             decimal = ((coapCode >> 5) * 100) + (coapCode & 31);
             if (decimal >= 200 && decimal <= 231)
@@ -153,261 +160,171 @@ OCStackResult CoAPToOCResponseCode(uint8_t coapCode)
 
 // Retrieve Uri and Query from received coap pdu
 OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
-        unsigned char * queryBuf, uint8_t * * observeOptionLoc,
-        uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
-        OCHeaderOption * rcvVendorSpecificHeaderOptions,
-        uint8_t * numRcvVendorSpecificHeaderOptions)
+        unsigned char * queryBuf, uint32_t * observeOption,
+        uint32_t * maxAgeOption,
+        uint8_t * numVendorSpecificHeaderOptions,
+        OCHeaderOption * vendorSpecificHeaderOptions,
+        coap_block_t * block1, coap_block_t * block2,
+        uint16_t * size1, uint16_t * size2,
+        unsigned char * payload)
 {
     coap_opt_filter_t filter;
     coap_opt_iterator_t opt_iter;
     coap_opt_t *option = NULL;
-    size_t bufLen = 0;
     size_t optLen = 0;
-    uint8_t * observeOption = NULL;
-    uint8_t * maxAgeOption = NULL;
-    uint8_t optionFound = 0;
+    unsigned char * optVal = NULL;
+    size_t uriBufLen = 0;
+    size_t queryBufLen = 0;
+    unsigned char * payloadLoc = NULL;
+    size_t payloadLength = 0;
 
+    coap_option_filter_clear(filter);
     if(uriBuf)
     {
-        // parse the Uri
-        coap_option_filter_clear(filter);
         coap_option_setb(filter, COAP_OPTION_URI_PATH);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
+    }
+    if(queryBuf)
+    {
+        coap_option_setb(filter, COAP_OPTION_URI_QUERY);
+    }
+    if(observeOption)
+    {
+        coap_option_setb(filter, COAP_OPTION_OBSERVE);
+    }
+    if(maxAgeOption)
+    {
+        coap_option_setb(filter, COAP_OPTION_MAXAGE);
+    }
+    if(block1)
+    {
+        coap_option_setb(filter, COAP_OPTION_BLOCK1);
+    }
+    if(block2)
+    {
+        coap_option_setb(filter, COAP_OPTION_BLOCK2);
+    }
+    if(size1)
+    {
+        coap_option_setb(filter, COAP_OPTION_SIZE1);
+    }
+    if(size2)
+    {
+        coap_option_setb(filter, COAP_OPTION_SIZE2);
+    }
+    if(vendorSpecificHeaderOptions)
+    {
+        coap_option_setbVendor(filter);
+    }
+    if(payload)
+    {
+        coap_get_data(pdu, &payloadLength, &payloadLoc);
+        memcpy(payload, payloadLoc, payloadLength);
+    }
+    coap_option_iterator_init(pdu, &opt_iter, filter);
+
+    while ((option = coap_option_next(&opt_iter)))
+    {
+        optLen = COAP_OPT_LENGTH(option);
+        optVal = COAP_OPT_VALUE(option);
+        switch(opt_iter.type)
         {
-            optLen = COAP_OPT_LENGTH(option);
-            if (bufLen + 1 + optLen < MAX_URI_LENGTH)
+        case COAP_OPTION_URI_PATH:
+            if (uriBufLen + 1 + optLen < MAX_URI_LENGTH)
             {
                 //we still have room in the buffer
-                uriBuf[bufLen++] = '/';
-                memcpy(uriBuf + bufLen, COAP_OPT_VALUE(option), optLen);
-                bufLen += optLen;
+                uriBuf[uriBufLen++] = '/';
+                memcpy(uriBuf + uriBufLen, optVal, optLen);
+                uriBufLen += optLen;
             }
             else
             {
-                // TODO: we should check that resources do not have long uri at the resource creation
                 return OC_STACK_NO_MEMORY;
             }
-        }
-        uriBuf[bufLen] = '\0';
-    }
-
-    if(queryBuf)
-    {
-        // parse the Query
-        bufLen = 0;
-        coap_option_filter_clear(filter);
-        coap_option_setb(filter, COAP_OPTION_URI_QUERY);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
-        {
-            optLen = COAP_OPT_LENGTH(option);
-            if (bufLen + 1 + optLen < MAX_QUERY_LENGTH)
+            break;
+        case COAP_OPTION_URI_QUERY:
+            if (queryBufLen + 1 + optLen < MAX_QUERY_LENGTH)
             {
                 //we still have room in the buffer
-                memcpy(queryBuf + bufLen, COAP_OPT_VALUE(option), optLen);
-                bufLen += optLen;
-                queryBuf[bufLen++] = '&';
+                memcpy(queryBuf + queryBufLen, optVal, optLen);
+                queryBufLen += optLen;
+                queryBuf[queryBufLen++] = '&';
             }
             else
             {
-                // TODO: should it be OC_STACK_NO_MEMORY
+                // TODO: we should check that resources do not have long uri
+                // at the resource creation
                 return OC_STACK_NO_MEMORY;
             }
-        }
-        // delete last '&'
-        queryBuf[bufLen ? (bufLen - 1) : (bufLen)] = '\0';
-    }
-
-    if(observeOptionLoc)
-    {
-        optionFound = 0;
-        // parse the observe option
-        coap_option_filter_clear(filter);
-        coap_option_setb(filter, COAP_OPTION_OBSERVE);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
-        {
-            observeOption = (uint8_t *) OCMalloc(COAP_OPT_LENGTH(option));
-            if(!observeOption)
+            break;
+        case COAP_OPTION_OBSERVE:
+            memcpy(observeOption, optVal, optLen);
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the observe option %u",
+                    *observeOption);
+            break;
+        case COAP_OPTION_MAXAGE:
+            memcpy(maxAgeOption, optVal, optLen);
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the max age option %u",
+                    *maxAgeOption);
+            break;
+        case COAP_OPTION_BLOCK1:
+            block1->szx = COAP_OPT_BLOCK_SZX(option);
+            block1->num = coap_opt_block_num(option);
+            block1->m = 0;
+            if(COAP_OPT_BLOCK_MORE(option))
             {
-                return OC_STACK_NO_MEMORY;
+                block1->m = 1;
             }
-            memcpy(observeOption, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
-            optionFound = 1;
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block1 %u:%u:%u",
+                    block1->num, block1->m, block1->szx);
             break;
-        }
-        if(optionFound)
-        {
-            *observeOptionLoc = observeOption;
-        }
-        else
-        {
-            OCFree(observeOption);
-            *observeOptionLoc = NULL;
-        }
-    }
-
-
-    if(maxAgeOptionLoc)
-    {
-        optionFound = 0;
-        // parse the observe option
-        coap_option_filter_clear(filter);
-        coap_option_setb(filter, COAP_OPTION_MAXAGE);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
-        {
-            maxAgeOption = (uint8_t *) OCMalloc(COAP_OPT_LENGTH(option));
-            if(!maxAgeOption)
+        case COAP_OPTION_BLOCK2:
+            block2->szx = COAP_OPT_BLOCK_SZX(option);
+            block2->num = coap_opt_block_num(option);
+            block2->m = 0;
+            if(COAP_OPT_BLOCK_MORE(option))
             {
-                return OC_STACK_NO_MEMORY;
+                block2->m = 1;
             }
-            memcpy(maxAgeOption, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
-            optionFound = 1;
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block2 %u:%u:%u",
+                    block1->num, block1->m, block1->szx);
             break;
-        }
-        if(optionFound)
-        {
-            *maxAgeOptionLoc = maxAgeOption;
-        }
-        else
-        {
-            OCFree(maxAgeOption);
-            *maxAgeOptionLoc = NULL;
-        }
-    }
-
-    if(rcvVendorSpecificHeaderOptions)
-    {
-        coap_option_filter_clear(filter);
-        coap_option_setbVendor(filter);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        uint8_t i = 0;
-        while((option = coap_option_next(&opt_iter)))
-        {
-            if(i >= MAX_HEADER_OPTIONS ||
-                    COAP_OPT_LENGTH(option) > MAX_HEADER_OPTION_DATA_LENGTH)
+        case COAP_OPTION_SIZE1:
+            break;
+        case COAP_OPTION_SIZE2:
+            break;
+        default:
+            if(*numVendorSpecificHeaderOptions >= MAX_HEADER_OPTIONS ||
+                    optLen > MAX_HEADER_OPTION_DATA_LENGTH)
             {
                 return OC_STACK_NO_MEMORY;
             }
-            rcvVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
-            rcvVendorSpecificHeaderOptions[i].optionID = opt_iter.type;
-            rcvVendorSpecificHeaderOptions[i].optionLength = COAP_OPT_LENGTH(option);
-            memcpy(rcvVendorSpecificHeaderOptions[i].optionData, COAP_OPT_VALUE(option),
-                    rcvVendorSpecificHeaderOptions[i].optionLength);
-            OC_LOG_V(INFO, TAG, " Parsing option %d with", rcvVendorSpecificHeaderOptions[i].optionID);
-            OC_LOG_BUFFER(INFO, TAG, rcvVendorSpecificHeaderOptions[i].optionData,
-                    rcvVendorSpecificHeaderOptions[i].optionLength);
-            i++;
+            vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].protocolID = OC_COAP_ID;
+            vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID = opt_iter.type;
+            vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength = optLen;
+            memcpy(vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData, optVal, optLen);
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing vendor specific option %u",
+                    vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID);
+            OC_LOG_BUFFER(DEBUG, TAG, vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData,
+                    vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength);
+            (*numVendorSpecificHeaderOptions)++;
         }
-
-        *numRcvVendorSpecificHeaderOptions = i;
-    }
-
-    // get the payload
-    if(payloadLoc)
-    {
-        coap_get_data(pdu, &bufLen, payloadLoc);
-    }
-
-    return OC_STACK_OK;
-}
-
-// Form the OCRequest struct
-OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
-        unsigned char * uriBuf, OCObserveReq * observeReq,
-        OCEntityHandlerRequest * entityHandlerRequest,
-        uint8_t secure)
-{
-    OCRequest * request = NULL;
-
-    // allocate it
-    request = (OCRequest *) OCMalloc(sizeof(OCRequest));
-    if (!request)
-    {
-        return OC_STACK_NO_MEMORY;
     }
 
-    // fill in qos
-    request->qos = qos;
-
-    // fill in uri
-    request->resourceUrl = uriBuf;
-
-    request->secure = secure;
-
-    // fill in observe
-    request->observe = observeReq;
-
-    // add entityHandlerRequest
-    request->entityHandlerRequest = entityHandlerRequest;
-
-    //TODO: this needs to be filled in the future
-    request->sequenceNum = 0;
-
-    *requestLoc = request;
-    return OC_STACK_OK;
-}
-
-// Form the OCObserveReq struct
-OCStackResult FormOCObserveReq(OCObserveReq ** observeReqLoc, uint32_t observeOption,
-            OCDevAddr * remote, OCCoAPToken * rcvdToken)
-{
-    OCObserveReq * observeReq;
-
-    if(observeOption == OC_RESOURCE_NO_OBSERVE)
+    if(uriBuf)
     {
-        return OC_STACK_OK;
+        uriBuf[uriBufLen] = '\0';
     }
-
-    observeReq = (OCObserveReq *)OCMalloc(sizeof(OCObserveReq));
-    if(!observeReq)
+    // delete last '&' in the query
+    if(queryBuf)
     {
-        *observeReqLoc = NULL;
-        return OC_STACK_NO_MEMORY;
+        queryBuf[queryBufLen?queryBufLen-1:queryBufLen] = '\0';
     }
 
-    observeReq->option = observeOption;
-    observeReq->subAddr = remote;
-    observeReq->token = rcvdToken;
-    observeReq->result = OC_STACK_OK;
-
-    *observeReqLoc = observeReq;
+    OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed uri is %s", uriBuf);
+    OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed query is %s", queryBuf);
     return OC_STACK_OK;
 }
 
-// Form the OCEntityHandlerRequest struct
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
-        OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
-        unsigned char * queryBuf, unsigned char *newResUriBuf)
-{
-    if (entityHandlerRequestLoc)
-    {
-        //set it to NULL for now, it will be modified in ocstack
-        entityHandlerRequestLoc->resource = NULL;
-
-        entityHandlerRequestLoc->method = method;
-
-        // fill in query
-        entityHandlerRequestLoc->query = queryBuf;
-
-        // fill payload
-        entityHandlerRequestLoc->reqJSONPayload = bufReqPayload;
-
-        entityHandlerRequestLoc->resJSONPayload = resBuf;
-        entityHandlerRequestLoc->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
-
-        entityHandlerRequestLoc->obsInfo = NULL;
-        entityHandlerRequestLoc->newResourceUri = newResUriBuf;
-
-        entityHandlerRequestLoc->numSendVendorSpecificHeaderOptions = 0;
-        return OC_STACK_OK;
-    }
-
-    return OC_STACK_INVALID_PARAM;
-}
-
 // Retrieve the token from the PDU
 void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken)
 {
@@ -448,7 +365,7 @@ OCStackResult FormOCClientResponse(OCClientResponse * clientResponse,
 }
 
 OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
-        uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
+        uint32_t * addMaxAge, uint32_t * observeOptionPtr,
         uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
         uint8_t queryLength, unsigned char * query,
         OCHeaderOption * vendorSpecificHeaderOptions,
@@ -476,10 +393,10 @@ OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
         coap_insert(optListLoc, optNode, OrderOptions);
     }
 
-    if(observeOptionLength && observeOptionPtr)
+    if(observeOptionPtr)
     {
         optNode = CreateNewOptionNode(COAP_OPTION_OBSERVE,
-                observeOptionLength, (uint8_t *)observeOptionPtr);
+                sizeof(*observeOptionPtr), (uint8_t *)observeOptionPtr);
 
         VERIFY_NON_NULL(optNode);
         coap_insert(optListLoc, optNode, OrderOptions);
@@ -715,9 +632,9 @@ OCStackResult ReTXCoAPQueue(coap_context_t * ctx, coap_queue_t * queue)
 
 OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * queue)
 {
+    //TODO: this function should change to only use OCStackFeedBack
     OCResponse * response = NULL;
     ClientCB * cbNode = NULL;
-    ResourceObserver * observer = NULL;
     OCClientResponse clientResponse;
     OCCoAPToken token;
     OCStackResult result = OC_STACK_OK;
@@ -743,21 +660,12 @@ OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * que
     HandleStackResponses(response);
 
 observation:
-    observer = GetObserverUsingToken (&token);
-    if(!observer)
-    {
-        goto exit;
-    }
-
-    result = OCObserverStatus(&token, OC_OBSERVER_FAILED_COMM);
+    result = OCStackFeedBack(&token, OC_OBSERVER_FAILED_COMM);
     if(result == OC_STACK_OK)
     {
         coap_cancel_all_messages(ctx, &queue->remote, token.token, token.tokenLength);
     }
-
-    exit:
-
-        OCFree(response);
+    OCFree(response);
     return result;
 }
 
@@ -772,7 +680,7 @@ void HandleSendQueue(coap_context_t * ctx)
     while (nextQueue && nextQueue->t <= now - ctx->sendqueue_basetime)
     {
         nextQueue = coap_pop_next( ctx );
-        if((uint8_t)nextQueue->delayedResponse)
+        if((uint8_t)nextQueue->delayedResNeeded)
         {
             OC_LOG_V(DEBUG, TAG, "Sending Delayed response TID %d",
                     nextQueue->id);
index 66291d0..7019982 100644 (file)
@@ -58,9 +58,6 @@ extern "C" {
  * Allocates a block of size bytes, returning a pointer to the beginning of
  * the allocated block.
  *
- * NOTE: This function is intended to be used internally by the TB Stack.
- *       It is not intended to be used by applications.
- *
  * @param size - Size of the memory block in bytes, where size > 0
  *
  * @return
@@ -70,10 +67,20 @@ extern "C" {
 void *OCMalloc(size_t size);
 
 /**
- * Deallocate a block of memory previously allocated by a call to OCMalloc
+ * Allocates a block of memory for an array of num elements, each of them
+ * size bytes long and initializes all its bits to zero.
+ *
+ * @param num - The number of elements
+ * @param size - Size of the element type in bytes, where size > 0
  *
- * NOTE: This function is intended to be used internally by the TB Stack.
- *       It is not intended to be used by applications.
+ * @return
+ *     on success, a pointer to the allocated memory block
+ *     on failure, a null pointer is returned
+ */
+void *OCCalloc(size_t num, size_t size);
+
+/**
+ * Deallocate a block of memory previously allocated by a call to OCMalloc
  *
  * @param ptr - Pointer to block of memory previously allocated by OCMalloc.
  *              If ptr is a null pointer, the function does nothing.
index e9e109a..fe62c15 100644 (file)
 
 void *OCMalloc(size_t size)
 {
-#ifdef ENABLE_MALLOC_DEBUG
-    void *ptr = 0;
-
     if (0 == size)
     {
         return NULL;
     }
 
+#ifdef ENABLE_MALLOC_DEBUG
+    void *ptr = 0;
+
     ptr = malloc(size);
     OC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u", ptr, size);
     return ptr;
 #else
-    if (0 == size)
+    return malloc(size);
+#endif
+}
+
+void *OCCalloc(size_t num, size_t size)
+{
+    if(0 == size || 0 == num)
     {
         return NULL;
     }
-    return malloc(size);
+
+#ifdef ENABLE_MALLOC_DEBUG
+    void *ptr = 0;
+
+    ptr = calloc(num, size);
+    OC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size);
+    return ptr;
+#else
+    return calloc(num, size);
 #endif
 }
 
index 7a39d6c..31dd9a0 100644 (file)
@@ -71,12 +71,13 @@ INC_DIRS    += -I$(OCTBSTACK_INC)/internal
 INC_DIRS  += -I$(GTEST_DIR)/include
 
 CC_FLAGS.debug      := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
-                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
 CC_FLAGS.release    := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
-                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) 
-                                       
-LDLIBS         += -loctbstack -lgtest -lgtest_main -lpthread
-CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
+                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD)
+
+LDLIBS         += -loctbstack -lpthread
+CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS) $(GTEST_DIR)/lib/.libs/libgtest.a \
+                          $(GTEST_DIR)/lib/.libs/libgtest_main.a
 
 SOURCES := unittest.cpp
 
@@ -84,7 +85,7 @@ OBJECTS:= $(patsubst %.c, $(OBJ_DIR)/%.o, $(SOURCES))
 
 PROGRAMS := unittest
 
-all:   prep_dirs $(OBJECTS) $(PROGRAMS) 
+all:   prep_dirs $(OBJECTS) $(PROGRAMS)
 
 prep_dirs:
        -mkdir -p $(OUT_DIR)
@@ -93,7 +94,7 @@ prep_dirs:
 $(OBJ_DIR)/%.o: %.cpp
        $(CC) -c $(CPPFLAGS) $< -o $@
 
-unittest: $(OBJ_DIR)/unittest.o 
+unittest: $(OBJ_DIR)/unittest.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
 .PHONY: clean
index c485b26..acd9573 100644 (file)
@@ -82,3 +82,59 @@ TEST(OCMalloc, MallocFail2)
     EXPECT_TRUE(NULL == pBuffer);
     OCFree(pBuffer);
 }
+
+TEST(OCCalloc, CallocPass1)
+{
+    // Try to allocate a small buffer
+    pBuffer = (uint8_t *)OCCalloc(1, 1);
+    EXPECT_TRUE(pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass2)
+{
+    // Try to allocate a small buffer
+    pBuffer = (uint8_t *)OCCalloc(1, 128);
+    EXPECT_TRUE(pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass3)
+{
+    // Try to allocate a buffer for an array
+    pBuffer = (uint8_t *)OCCalloc(5, 128);
+    EXPECT_TRUE(pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail1)
+{
+    // Try to allocate a buffer of size 0
+    pBuffer = (uint8_t *)OCCalloc(1, 0);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail2)
+{
+    // Try to allocate a buffer with num of 0
+    pBuffer = (uint8_t *)OCCalloc(0, 5);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail3)
+{
+    // Try to allocate a buffer with size and num 0
+    pBuffer = (uint8_t *)OCCalloc(0, 0);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail4)
+{
+    // Try to allocate a ridiculous amount of RAM
+    pBuffer = (uint8_t *)OCCalloc(1, (size_t)0x7FFFFFFFFFFFFFFF);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
index ec6c0b7..9bad9ed 100644 (file)
@@ -242,6 +242,25 @@ int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addr
              uint8_t *addrv4,  uint32_t addrLen);
 
 
+//-- OCDevAddrToString ----------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to convert the OCDevAddr to string format
+ *
+ * @param[in]   addr
+ *               OCDevAddr address.
+ * @param[out]  stringAddress the target string where the address
+ *               is to be stored. Memory for this parameter is
+ *               allocated by the caller.
+ *
+ * Note: The length of stringAddress may not exceed DEV_ADDR_SIZE_MAX
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCDevAddrToString(OCDevAddr *addr, char *stringAddress);
+
+
 //-- OCDevAddrToIPv4Addr -------------------------------------------------
 /** @ingroup ocsocket
  *
index 205eba1..a857546 100644 (file)
@@ -245,11 +245,10 @@ int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd)
     }
 
     // bind to multicast port
-    struct sockaddr_in sa;
+    struct sockaddr_in sa = {0};
     struct sockaddr_in *sin;
 
     sin = (struct sockaddr_in *)(ipmcastaddr->addr);
-    memset(&sa, 0, sizeof(sa));
     sa.sin_family = AF_INET;
     sa.sin_addr.s_addr = sin->sin_addr.s_addr;
     sa.sin_port = sin->sin_port;
@@ -260,8 +259,7 @@ int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd)
     }
 
     // add membership to receiving socket
-    struct ip_mreq mreq;
-    memset(&mreq, 0, sizeof(struct ip_mreq));
+    struct ip_mreq mreq = {0};
     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
     mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
     if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
@@ -354,6 +352,30 @@ int32_t OCClose(int32_t sockfd)
     return (close(sockfd));
 }
 
+//convert OCDevAddr to String
+int32_t OCDevAddrToString(OCDevAddr* addr, char* stringAddress)
+{
+    uint8_t a;
+    uint8_t b;
+    uint8_t c;
+    uint8_t d;
+
+    if(OCDevAddrToIPv4Addr(addr, &a, &b, &c, &d) == 0)
+    {
+        if (!stringAddress)
+        {
+            return ERR_INVALID_INPUT;
+        }
+
+        sprintf(stringAddress, "%u.%u.%u.%u",
+                a, b, c, d);
+        return ERR_SUCCESS;
+    }
+    else
+    {
+        return ERR_INVALID_INPUT;
+    }
+}
 
 /// Retrieve the IPv4 address embedded inside OCDev address data structure
 int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
index 52ea37e..e657d6b 100644 (file)
@@ -70,7 +70,7 @@ int multicast_test(int argc, char* argv[])
     int32_t sfd;
     char loopch=0;
     int set_option_on = 1;
-    struct sockaddr_in mcastsock, peer;
+    struct sockaddr_in mcastsock = {0}, peer;
     uint8_t recvbuf[MAX_BUF];
     uint32_t len, bufLen, fromlen;
 
@@ -90,7 +90,6 @@ int multicast_test(int argc, char* argv[])
     }
 
     //Initialize the group sockaddr structure with a
-    memset((char *) &mcastsock, 0, sizeof(mcastsock));
     mcastsock.sin_family = AF_INET;
     mcastsock.sin_addr.s_addr = inet_addr(argv[2]);
     mcastsock.sin_port = htons(atoi(argv[3]));
@@ -118,8 +117,7 @@ int multicast_test(int argc, char* argv[])
         return -1;
     }
 
-    struct ip_mreq mreq;
-    memset(&mreq, 0, sizeof(struct ip_mreq));
+    struct ip_mreq mreq = {0};
     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
     mreq.imr_multiaddr.s_addr = mcastsock.sin_addr.s_addr;
     if ((setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
index 0f3a49f..67c58a9 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <ocstack.h>
 #include <occoaptoken.h>
+#include <ocresource.h>
 
 typedef struct OCPresence {
     // This is the TTL associated with presence
@@ -61,7 +62,7 @@ typedef struct ClientCB {
     // Struct to hold TTL info for presence
     #ifdef WITH_PRESENCE
     OCPresence * presence;
-    unsigned char * filterResourceType;
+    OCResourceType * filterResourceType;
     #endif
     // next node in this list
     struct ClientCB    *next;
@@ -85,7 +86,7 @@ extern struct ClientCB *cbList;
  * @param[in] requestUri
  *              the resource uri of the request.
  * @param[in] resourceType
- *              the resourceType associated with this request.
+ *              the resourceType associated with a presence request.
  *
  * @brief If the handle you're looking for does not exist, the stack will reply with a RST message.
  *
@@ -93,7 +94,7 @@ extern struct ClientCB *cbList;
  */
 //------------------------------------------------------------------------
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
-        OCCoAPToken * token, OCDoHandle handle, OCMethod method,
+        OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
         unsigned char * requestUri, unsigned char * resourceType);
 
 //-- DeleteClientCB -----------------------------------------------------------
@@ -127,6 +128,20 @@ void DeleteClientCB(ClientCB *cbNode);
 //------------------------------------------------------------------------
 ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
 
+
+/**
+ * Inserts a new resource type filter into this clientCB node.
+ *
+ * @param cbNode - the node to add the new resourceType filter to
+ * @param resourceTypeName - the value to create the new resourceType filter from
+ *
+ * @return
+ *      OC_STACK_OK on success
+ *      OC_STACK_ERROR with invalid parameters
+ *      OC_STACK_NO_MEMORY when out of memory
+ */
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+
 //-- DeleteClientCBList --------------------------------------------------
 /** @ingroup ocstack
  *
index 955b344..e421d06 100644 (file)
@@ -22,7 +22,9 @@
 #define OC_COLLECTION_H
 
 #include "ocstack.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
+
+uint8_t GetNumOfResourcesInCollection (OCResource *resource);
 
 OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                                               OCEntityHandlerRequest *entityHandlerRequest);
index a84bb98..ba87306 100644 (file)
 
 /* In CoAP sequence number is a 24 bit field */
 #define MAX_SEQUENCE_NUMBER              (0xFFFFFF)
-#define OC_RESOURCE_OBSERVE_REGISTER     (0)
-#define OC_RESOURCE_OBSERVE_DEREGISTER   (1)
-#define OC_RESOURCE_NO_OBSERVE           (2)
 
 #define MAX_OBSERVER_FAILED_COMM         (2)
 #define MAX_OBSERVER_NON_COUNT           (3)
 
-#define OC_OBSERVER_NOT_INTERESTED       (0)
-#define OC_OBSERVER_STILL_INTERESTED     (1)
-#define OC_OBSERVER_FAILED_COMM          (2)
-
 /* This information is stored for each registerd observer */
 typedef struct ResourceObserver {
     // Observation Identifier for request
@@ -60,12 +53,17 @@ typedef struct ResourceObserver {
     struct ResourceObserver *next;
 } ResourceObserver;
 
-OCStackResult OCObserverStatus(OCCoAPToken * token, uint8_t status);
-
-OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request);
-
-OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
-                                        OCResourceType *resourceType, OCQualityOfService qos);
+#ifdef WITH_PRESENCE
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCResourceType *resourceType, OCQualityOfService qos);
+#else
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCQualityOfService qos);
+#endif
+OCStackResult SendListObserverNotification (OCResource * resource,
+        OCObservationId  *obsIdList, uint8_t numberOfIds,
+        unsigned char *notificationJSONPayload, uint32_t maxAge,
+        OCQualityOfService qos);
 
 void DeleteObserverList();
 
index 10f7a91..542cfb6 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#ifndef OC_RESOURCE_H
-#define OC_RESOURCE_H
-
-#include "ocstack.h"
-#include "ocstackinternal.h"
-
-#define OC_RSRVD_OC                     "oc"
-#define OC_RSRVD_PAYLOAD                "payload"
-#define OC_RSRVD_HREF                   "href"
-#define OC_RSRVD_RESOURCE_TYPE          "rt"
-#define OC_RSRVD_INTERFACE              "if"
-#define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
-#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
-#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
-#define OC_RSRVD_OBSERVABLE             "obs"
-#define OC_RSRVD_SECURE                 "sec"
-#define OC_RSRVD_HOSTING_PORT           "port"
-
-#define OC_JSON_PREFIX                     "{\"oc\":["
-#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
-#define OC_JSON_SUFFIX                     "]}"
-#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
-#define OC_JSON_SEPARATOR                  ','
-
-#define OC_RESOURCE_OBSERVABLE   1
-#define OC_RESOURCE_SECURE       1
+#ifndef OCRESOURCE_H_
+#define OCRESOURCE_H_
 
-typedef enum {
-    STACK_RES_DISCOVERY_NOFILTER = 0,
-    STACK_RES_DISCOVERY_IF_FILTER,
-    STACK_RES_DISCOVERY_RT_FILTER
-} StackQueryTypes;
+#define OC_OBSERVER_NOT_INTERESTED       (0)
+#define OC_OBSERVER_STILL_INTERESTED     (1)
+#define OC_OBSERVER_FAILED_COMM          (2)
+
+//-----------------------------------------------------------------------------
+// Virtual Resource Presence Attributes
+//-----------------------------------------------------------------------------
+#ifdef WITH_PRESENCE
+typedef struct PRESENCERESOURCE{
+    OCResourceHandle handle;
+    uint32_t presenceTTL;
+} PresenceResource;
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct rsrc_t;
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
 
+// IF here stands for Interface
 typedef enum {
-    OC_RESOURCE_VIRTUAL = 0,
-    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
-    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
-    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
-    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
-    OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
-    OC_RESOURCE_NOT_SPECIFIED
-} ResourceHandling;
+    STACK_IF_DEFAULT = 0,
+    STACK_IF_LL,
+    STACK_IF_BATCH,
+    STACK_IF_INVALID
+} OCStackIfTypes;
+
+typedef struct resourcetype_t {
+    struct resourcetype_t *next; // linked list; for multiple types on resource
+
+    // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
+    // namespace and the final segment is the type; type and sub-types can be separate with
+    // ‘-‘ (dash) usually only two segments would be defined. Either way this string is meant to be
+    // human friendly and is used opaquely and not parsed by code. This name is used in the “rt=”
+    // parameter of a resource description when resources are introspected and is also use in the
+    // <base URI>/types list of available types.
+    char *resourcetypename;
+} OCResourceType;
+
+typedef struct attr_t {
+    struct attr_t *next; // Points to next resource in list
 
-OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * request);
+    // The name of the attribute; used to look up the attribute in list;
+    // for a given attribute SHOULD not be changed once assigned
+    const char *attrName;
+    char *attrValue; // value of the attribute as string
+} OCAttribute;
 
-const char * GetVirtualResourceUri( OCVirtualResources resource);
-OCResource *FindResourceByUri(const char* resourceUri);
-uint8_t IsVirtualResource(const char* resourceUri);
+typedef struct resourceinterface_t {
+    struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
 
-OCStackResult DetermineResourceHandling (OCRequest *request,
-                                         ResourceHandling *handling,
-                                         OCResource **resource);
+    // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is a
+    // namespace and the final segment is the interface; usually only two segments would be
+    // defined. Either way this string is opaque and not parsed by segment
+    char *name ;
 
-OCStackResult
-BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request);
+    // Supported content types to serialize request and response on this interface
+    // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
+#if 0
+    char *inputContentType ;
+    char *outputContentType ;
+#endif
+    /*** Future placeholder for access control and policy ***/
+} OCResourceInterface;
 
-OCEntityHandlerResult
-BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest);
+typedef struct rsrc_t {
+    struct rsrc_t *next; // Points to next resource in list
+    // Relative path on the device; will be combined with base url to create fully qualified path
+    char *host;
+    char *uri;
+    OCResourceType *rsrcType; // Resource type(s); linked list
+    OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
+    OCAttribute *rsrcAttributes; // Resource interface(s); linked list
+    // Array of pointers to resources; can be used to represent a container of resources
+    // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
+    struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
+    //struct rsrc_t *rsrcResources;
+    // Pointer to function that handles the entity bound to the resource.
+    // This handler has to be explicitly defined by the programmer
+    OCEntityHandler entityHandler;
+    // Properties on the resource – defines meta information on the resource
+    OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
+    // Pointer to an opaque object where app/user specific data can be placed with the resource;
+    // this could be information for the entity handler between invocations
+    void *context;
+    // NOTE: Methods supported by this resource should be based on the interface targeted
+    // i.e. look into the interface structure based on the query request Can be removed here;
+    // place holder for the note above
+    /* method_t methods; */
+    // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
+    uint32_t sequenceNum;
+} OCResource;
 
-OCStackResult
-BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
-                        char *filterValue, char * out, uint16_t *remaining);
 
-OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
 
-#endif //OC_RESOURCE_H
+#endif /* OCRESOURCE_H_ */
diff --git a/resource/csdk/stack/include/internal/ocresourcehandler.h b/resource/csdk/stack/include/internal/ocresourcehandler.h
new file mode 100644 (file)
index 0000000..e5a24bc
--- /dev/null
@@ -0,0 +1,86 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OC_RESOURCEHANDLER_H
+#define OC_RESOURCEHANDLER_H
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+
+#define OC_RSRVD_OC                     "oc"
+#define OC_RSRVD_PAYLOAD                "payload"
+#define OC_RSRVD_HREF                   "href"
+#define OC_RSRVD_RESOURCE_TYPE          "rt"
+#define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence"
+#define OC_RSRVD_INTERFACE              "if"
+#define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
+#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
+#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
+#define OC_RSRVD_OBSERVABLE             "obs"
+#define OC_RSRVD_SECURE                 "sec"
+#define OC_RSRVD_HOSTING_PORT           "port"
+
+#define OC_JSON_PREFIX                     "{\"oc\":["
+#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
+#define OC_JSON_SUFFIX                     "]}"
+#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
+#define OC_JSON_SEPARATOR                  ','
+
+#define OC_RESOURCE_OBSERVABLE   1
+#define OC_RESOURCE_SECURE       1
+
+typedef enum {
+    STACK_RES_DISCOVERY_NOFILTER = 0,
+    STACK_RES_DISCOVERY_IF_FILTER,
+    STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+typedef enum {
+    OC_RESOURCE_VIRTUAL = 0,
+    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
+    OC_RESOURCE_NOT_SPECIFIED
+} ResourceHandling;
+
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest * request);
+
+const char * GetVirtualResourceUri( OCVirtualResources resource);
+OCResource *FindResourceByUri(const char* resourceUri);
+uint8_t IsVirtualResource(const char* resourceUri);
+
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
+                                         ResourceHandling *handling,
+                                         OCResource **resource);
+
+OCStackResult
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+
+OCStackResult
+BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
+                        char *filterValue, char * out, uint16_t *remaining);
+
+OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
+
+#endif //OC_RESOURCEHANDLER_H
diff --git a/resource/csdk/stack/include/internal/ocserverrequest.h b/resource/csdk/stack/include/internal/ocserverrequest.h
new file mode 100644 (file)
index 0000000..e96ed51
--- /dev/null
@@ -0,0 +1,110 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OC_SERVER_REQUEST_H
+#define OC_SERVER_REQUEST_H
+
+#include "occoap.h"
+
+/**
+ * The signature of the internal call back functions to handle responses from entity handler
+ */
+typedef OCStackResult (* OCEHResponseHandler)(OCEntityHandlerResponse * ehResponse);
+OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse);
+OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse);
+
+// following structure will be created in occoap and passed up the stack on the server side
+typedef struct OCServerRequest {
+    // the REST method retrieved from received request PDU
+    OCMethod method;
+    // resourceUrl will be filled in occoap using the path options in received request PDU
+    unsigned char resourceUrl[MAX_URI_LENGTH];
+    // resource query send by client
+    unsigned char query[MAX_QUERY_LENGTH];
+
+    // qos is indicating if the request is CON or NON
+    OCQualityOfService qos;
+    // Observe option field
+    uint32_t observationOption;
+    OCStackResult observeResult;
+    uint8_t numResponses;
+    OCEHResponseHandler ehResponseHandler;
+    //////////////////////////////////////////////////////////
+    // IP address & port of client registered for observe   //These
+    OCDevAddr requesterAddr;                                //Members
+    // CoAP token for the observe request                   //Might
+    OCCoAPToken requestToken;                               //Be
+    // The ID of CoAP pdu                                   //Kept in
+    uint16_t coapID;                                        //CoAP
+    uint8_t delayedResNeeded;
+    uint8_t secured;
+    //////////////////////////////////////////////////////////
+    // An array of the received vendor specific header options
+    uint8_t numRcvdVendorSpecificHeaderOptions;
+    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+    uint8_t requestComplete;
+    struct OCServerRequest * next;
+    // Flag indicating slow response
+    uint8_t slowFlag;
+    uint8_t notificationFlag;
+    // reqJSON is retrieved from the payload of the received request PDU
+    unsigned char reqJSONPayload[1];
+} OCServerRequest;
+
+// following structure will be created in ocstack to aggregate responses (in future: for block transfer)
+typedef struct OCServerResponse {
+    struct OCServerResponse * next;
+    // this is the pointer to server payload data to be transferred
+    unsigned char *payload;
+    uint16_t remainingPayloadSize;
+    OCRequestHandle requestHandle;
+} OCServerResponse;
+
+OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token);
+
+OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle);
+
+OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle);
+
+OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
+        uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
+        uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
+        OCQualityOfService qos, unsigned char * query,
+        OCHeaderOption * rcvdVendorSpecificHeaderOptions,
+        unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
+        OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize);
+
+OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle);
+
+// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
+        OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
+        uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+        OCObservationId observeID);
+
+void FindAndDeleteServerRequest(OCServerRequest * serverRequest);
+
+void DeleteServerRequest(OCServerRequest * serverRequest);
+
+void FindAndDeleteServerResponse(OCServerResponse * serverResponse);
+
+void DeleteServerResponse(OCServerResponse * serverResponse);
+
+#endif //OC_SERVER_REQUEST_H
index 31844fa..2a4d8f6 100644 (file)
@@ -51,97 +51,6 @@ extern OCDeviceEntityHandler defaultDeviceHandler;
 #define OC_COAP_SCHEME "coap://"
 #define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5
 
-//-----------------------------------------------------------------------------
-// Virtual Resource Presence Attributes
-//-----------------------------------------------------------------------------
-#ifdef WITH_PRESENCE
-typedef struct PRESENCERESOURCE{
-    OCResourceHandle handle;
-    uint32_t presenceTTL;
-} PresenceResource;
-#endif
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-struct rsrc_t;
-
-//-----------------------------------------------------------------------------
-// Typedefs
-//-----------------------------------------------------------------------------
-
-// IF here stands for Interface
-typedef enum {
-    STACK_IF_DEFAULT = 0,
-    STACK_IF_LL,
-    STACK_IF_BATCH
-} OCStackIfTypes;
-
-typedef struct resourcetype_t {
-    struct resourcetype_t *next; // linked list; for multiple types on resource
-
-    // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
-    // namespace and the final segment is the type; type and sub-types can be separate with ‘-‘ (dash)
-    // usually only two segments would be defined. Either way this string is meant to be human friendly
-    // and is used opaquely and not parsed by code
-    // This name is used in the “rt=” parameter of a resource description when resources are introspected
-    // and is also use in the <base URI>/types list of available types
-    char *resourcetypename;
-} OCResourceType;
-
-typedef struct attr_t {
-    struct attr_t *next; // Points to next resource in list
-
-    // The name of the attribute; used to look up the attribute in list;
-    // for a given attribute SHOULD not be changed once assigned
-    const char *attrName;
-    char *attrValue; // value of the attribute as string
-} OCAttribute;
-
-typedef struct resourceinterface_t {
-    struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-
-    // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is
-    // a namespace and the final segment is the interface; usually only two segments would be defined.
-    // Either way this string is opaque and not parsed by segment
-    char *name ;
-
-    // Supported content types to serialize request and response on this interface
-    // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
-#if 0
-    char *inputContentType ;
-    char *outputContentType ;
-#endif
-    /*** Future placeholder for access control and policy ***/
-} OCResourceInterface;
-
-typedef struct rsrc_t {
-    struct rsrc_t *next; // Points to next resource in list
-    // Relative path on the device; will be combined with base url to create fully qualified path
-    char *host;
-    char *uri;
-    OCResourceType *rsrcType; // Resource type(s); linked list
-    OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
-    OCAttribute *rsrcAttributes; // Resource interface(s); linked list
-    // Array of pointers to resources; can be used to represent a container of resources
-    // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
-    struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
-    //struct rsrc_t *rsrcResources;
-    // Pointer to function that handles the entity bound to the resource.
-    // This handler has to be explicitly defined by the programmer
-    OCEntityHandler entityHandler;
-    // Properties on the resource – defines meta information on the resource
-    OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
-    // Pointer to an opaque object where app/user specific data can be placed with the resource;
-    // this could be information for the entity handler between invocations
-    void *context;
-    // NOTE: Methods supported by this resource should be based on the interface targeted
-    // i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
-    /* method_t methods; */
-    // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
-    uint32_t sequenceNum;
-} OCResource;
-
 typedef struct {
     // Observe option field
     uint32_t option;
@@ -155,19 +64,69 @@ typedef struct {
 
 // following structure will be created in occoap and passed up the stack on the server side
 typedef struct {
+    // Observe option field
+    uint32_t observationOption;
+    // the REST method retrieved from received request PDU
+    OCMethod method;
     // resourceUrl will be filled in occoap using the path options in received request PDU
-    unsigned char * resourceUrl;
+    unsigned char resourceUrl[MAX_URI_LENGTH];
+    // resource query send by client
+    unsigned char query[MAX_QUERY_LENGTH];
+    // reqJSON is retrieved from the payload of the received request PDU
+    unsigned char reqJSONPayload[MAX_REQUEST_LENGTH];
+    // qos is indicating if the request is CON or NON
+    OCQualityOfService qos;
+    // An array of the received vendor specific header options
+    uint8_t numRcvdVendorSpecificHeaderOptions;
+    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+    //////////////////////////////////////////////////////////
+    // TODO: Consider moving these member to CoAP
+    // IP address & port of client registered for observe
+    OCDevAddr requesterAddr;
+    // CoAP token for the observe request
+    OCCoAPToken requestToken;
+    // The ID of CoAP pdu
+    uint16_t coapID;
+    uint8_t delayedResNeeded;
+    uint8_t secured;
+    //////////////////////////////////////////////////////////
+    uint8_t reqMorePacket;
+    uint32_t reqPacketNum;
+    uint16_t reqPacketSize;
+    uint32_t resPacketNum;
+    uint16_t resPacketSize;
+    uint32_t reqTotalSize;
+} OCServerProtocolRequest;
+
+typedef struct
+{
+    // Observe option field
+    uint32_t observationOption;
     // qos is indicating if the request is CON or NON
     OCQualityOfService qos;
-    // this structure points to the information for processing observe option
-    OCObserveReq *observe;
-    // If a subscription update, this is count of observe notifications from server perspective.
-    uint32_t sequenceNum;
-    // this structure will be passed to entity handler
-    OCEntityHandlerRequest * entityHandlerRequest;
-    // Indicate whether the request arrives on a secure port
-    uint8_t secure;
-} OCRequest;
+    // Allow the entity handler to pass a result with the response
+    OCStackResult result;
+    // IP address & port of client registered for observe
+    OCDevAddr *requesterAddr;
+    // CoAP token for the observe request
+    OCCoAPToken *requestToken;
+    // The ID of CoAP pdu
+    uint16_t coapID;
+    // Flag indicating that response is to be delayed before sending
+    uint8_t delayedResNeeded;
+    uint8_t secured;
+    uint8_t slowFlag;
+    uint8_t notificationFlag;
+    // this is the pointer to server payload data to be transferred
+    unsigned char *payload;
+    // size of server payload data.  Don't rely on null terminated data for size
+    uint16_t payloadSize;
+    // An array of the vendor specific header options the entity handler wishes to use in response
+    uint8_t numSendVendorSpecificHeaderOptions;
+    OCHeaderOption *sendVendorSpecificHeaderOptions;
+    // URI of new resource that entity handler might create
+    unsigned char * resourceUri;
+} OCServerProtocolResponse;
 
 // following structure will be created in occoap and passed up the stack on the client side
 typedef struct {
@@ -182,17 +141,20 @@ typedef struct {
 //-----------------------------------------------------------------------------
 // Internal function prototypes
 //-----------------------------------------------------------------------------
-
-OCStackResult HandleStackRequests(OCRequest * request);
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos);
+OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status);
+OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest);
 void HandleStackResponses(OCResponse * response);
 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
+#ifdef WITH_PRESENCE
+OCStackResult SendPresenceNotification(OCResourceType *resourceType);
+#endif
 
 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
                                             const char *resourceInterfaceName);
 
 OCStackResult BindResourceTypeToResource(OCResource* resource,
                                             const char *resourceTypeName);
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName);
 
 #ifdef WITH_PRESENCE
 //TODO: should the following function be public?
diff --git a/resource/csdk/stack/include/ocsecurity.h b/resource/csdk/stack/include/ocsecurity.h
new file mode 100644 (file)
index 0000000..0d71086
--- /dev/null
@@ -0,0 +1,49 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OC_SECURITY_H
+#define OC_SECURITY_H
+
+#include "ocstack.h"
+#include "ocsecurityconfig.h"
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Provides the DTLS PSK credetials blob to OC stack.
+ *
+ * @param credInfo
+ *     binary blob containing credentials
+ * @param len
+ *     length of binary blob
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo,
+                size_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //OC_SECURITY_H
diff --git a/resource/csdk/stack/include/ocsecurityconfig.h b/resource/csdk/stack/include/ocsecurityconfig.h
new file mode 100644 (file)
index 0000000..eaa06b4
--- /dev/null
@@ -0,0 +1,59 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OC_SECURITY_CONFIG_H
+#define OC_SECURITY_CONFIG_H
+
+#include <stdint.h>
+
+#define DTLS_PSK_ID_LEN 16
+#define DTLS_PSK_PSK_LEN 16
+
+#define DtlsPskCredsBlobVer_1 1 /**< Credentials stored in plaintext */
+#define DtlsPskCredsBlobVer_CurrentVersion DtlsPskCredsBlobVer_1
+
+/**
+ * Credentials for a device. Includes identity and the associated PSK.
+ */
+typedef struct
+{
+   unsigned char id[DTLS_PSK_ID_LEN];
+   unsigned char psk[DTLS_PSK_PSK_LEN];
+} OCDtlsPskCreds;
+
+
+/**
+ * Binary blob containing device identity and the credentials for all devices
+ * trusted by this device.
+ */
+typedef struct
+{
+   uint16_t blobVer;                        /**< version of the blob */
+   uint16_t reserved;                       /**< reserved for future use */
+   unsigned char identity[DTLS_PSK_ID_LEN]; /**< identity of self */
+   uint32_t num;                            /**< number of credentials in this blob */
+   OCDtlsPskCreds creds[1];                 /**< list of credentials. Size of this
+                                                 array is determined by 'num' variable. */
+} OCDtlsPskCredsBlob;
+
+
+#endif //OC_SECURITY_CONFIG_H
+
+
index 2cca35c..085f497 100644 (file)
@@ -141,6 +141,7 @@ typedef enum {
     OC_STACK_OK = 0,
     OC_STACK_RESOURCE_CREATED,
     OC_STACK_RESOURCE_DELETED,
+    OC_STACK_CONTINUE,
     /* Success status code - END HERE */
     /* Error status code - START HERE */
     OC_STACK_INVALID_URI,
@@ -159,15 +160,16 @@ typedef enum {
     OC_STACK_SLOW_RESOURCE,
     OC_STACK_NO_OBSERVERS,              /* resource has no registered observers */
     OC_STACK_OBSERVER_NOT_FOUND,
-    OC_STACK_OBSERVER_NOT_ADDED,
-    OC_STACK_OBSERVER_NOT_REMOVED,
     #ifdef WITH_PRESENCE
     OC_STACK_PRESENCE_STOPPED,
     OC_STACK_PRESENCE_TIMEOUT,
     OC_STACK_PRESENCE_DO_NOT_HANDLE,
     #endif
+    OC_STACK_VIRTUAL_DO_NOT_HANDLE,
     OC_STACK_INVALID_OPTION,
     OC_STACK_MALFORMED_RESPONSE,        /* the remote reply contained malformed data */
+    OC_STACK_PERSISTENT_BUFFER_REQUIRED,
+    OC_STACK_INVALID_REQUEST_HANDLE,
     OC_STACK_ERROR
     /* Error status code - END HERE */
 } OCStackResult;
@@ -182,6 +184,9 @@ typedef void * OCDoHandle;
  */
 typedef void * OCResourceHandle;
 
+typedef void * OCRequestHandle;
+typedef void * OCResponseHandle;
+
 /**
  * Unique identifier for each observation request. Used when observations are
  * registered or deregistering. Used by entity handler to signal specific
@@ -206,6 +211,18 @@ typedef struct {
     OCObservationId obsId;
 } OCObservationInfo;
 
+/**
+ * Possible returned values from entity handler
+ */
+typedef enum {
+    OC_EH_OK = 0,
+    OC_EH_ERROR,
+    OC_EH_RESOURCE_CREATED,
+    OC_EH_RESOURCE_DELETED,
+    OC_EH_SLOW,
+    OC_EH_FORBIDDEN
+} OCEntityHandlerResult;
+
 // following structure will be used to define the vendor specific header options to be included
 // in communication packets
 
@@ -227,38 +244,29 @@ typedef struct OCHeaderOption {
 typedef struct {
     // Associated resource
     OCResourceHandle resource;
-    // resource query send by client
-    unsigned char * query;
+    OCRequestHandle requestHandle;
     // the REST method retrieved from received request PDU
     OCMethod method;
-    // reqJSON is retrieved from the payload of the received request PDU
-    unsigned const char * reqJSONPayload;
-    // resJSON is allocated in the stack and will be used by entity handler to fill in its response
-    unsigned char * resJSONPayload;
-    // Length of maximum allowed response
-    uint16_t resJSONPayloadLen;
+    // resource query send by client
+    unsigned char * query;
     // Information associated with observation - valid only when OCEntityHandler
     // flag includes OC_OBSERVE_FLAG
-    OCObservationInfo *obsInfo;
+    OCObservationInfo obsInfo;
     // An array of the received vendor specific header options
     uint8_t numRcvdVendorSpecificHeaderOptions;
-    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
-    // An array of the vendor specific header options the entity handler wishes to use in response
-    uint8_t numSendVendorSpecificHeaderOptions;
-    OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
-    // URI of new resource that entity handler might create
-    unsigned char *newResourceUri;
-
+    OCHeaderOption * rcvdVendorSpecificHeaderOptions;
+    // reqJSON is retrieved from the payload of the received request PDU
+    unsigned char * reqJSONPayload;
 }OCEntityHandlerRequest;
 
 /**
  * Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
  */
 typedef struct {
-    // the is the result of our stack, OCStackResult should contain coap/other error codes;
-    OCStackResult result;
     // Address of remote server
     OCDevAddr * addr;
+    // the is the result of our stack, OCStackResult should contain coap/other error codes;
+    OCStackResult result;
     // If associated with observe, this will represent the sequence of notifications from server.
     uint32_t sequenceNumber;
     // resJSONPayload is retrieved from the payload of the received request PDU
@@ -268,6 +276,30 @@ typedef struct {
     OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
 }OCClientResponse;
 
+typedef struct
+{
+    // Request handle is passed to server via the entity handler for each incoming request.
+    // Stack assigns when request is received, server sets to indicate what request response is for
+    OCRequestHandle requestHandle;
+    // New handle for tracking block (or slow) response.  Stack assigns, server uses for subsequent calls
+    OCResponseHandle  *responseHandle;
+    // Resource handle
+    OCResourceHandle resourceHandle;
+    // Allow the entity handler to pass a result with the response
+    OCEntityHandlerResult  ehResult;
+    // this is the pointer to server payload data to be transferred
+    unsigned char *payload;
+    // size of server payload data.  I don't think we should rely on null terminated data for size
+    uint16_t payloadSize;
+    // An array of the vendor specific header options the entity handler wishes to use in response
+    uint8_t numSendVendorSpecificHeaderOptions;
+    OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+    // URI of new resource that entity handler might create
+    unsigned char resourceUri[MAX_URI_LENGTH];
+    // Server sets to true for persistent response buffer, false for non-persistent response buffer
+    uint8_t persistentBufferFlag;
+} OCEntityHandlerResponse;
+
 typedef enum {
     OC_INIT_FLAG    = (1 << 0),
     OC_REQUEST_FLAG = (1 << 1),
@@ -306,17 +338,6 @@ typedef struct {
 } OCCallbackData;
 
 /**
- * Possible returned values from entity handler
- */
-typedef enum {
-    OC_EH_OK = 0,
-    OC_EH_ERROR,
-    OC_EH_RESOURCE_CREATED,
-    OC_EH_RESOURCE_DELETED,
-    OC_EH_FORBIDDEN
-} OCEntityHandlerResult;
-
-/**
  * Application server implementations must implement this callback to consume requests OTA.
  * Entity handler callback needs to fill the resPayload of the entityHandlerRequest.
  */
@@ -374,9 +395,11 @@ OCStackResult OCStop();
 OCStackResult OCProcess();
 
 /**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource (specified by that Resource's respective
+ * URI).
  *
- * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of
+ *                             calling this API.
  * @param method             - @ref OCMethod to perform on the resource
  * @param requiredUri        - URI of the resource to interact with
  * @param referenceUri       - URI of the reference resource
@@ -388,6 +411,10 @@ OCStackResult OCProcess();
  *                             header options to be sent with the request
  * @param numOptions         - Number of header options to be included
  *
+ * Note: Presence subscription amendments (ie. adding additional resource type filters by calling
+ * this API again) require the use of the same base URI as the original request to successfully
+ * amend the presence filters.
+ *
  * @return
  *     OC_STACK_OK               - no errors
  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
@@ -739,6 +766,7 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
  * @param obsIdList - list of observation ids that need to be notified
  * @param numberOfIds - number of observation ids included in obsIdList
  * @param notificationJSONPayload - JSON encoded payload to send in notification
+ * @param qos - desired quality of service of the observation notifications
  * NOTE: The memory for obsIdList and notificationJSONPayload is managed by the
  * entity invoking the API. The maximum size of the notification is 1015 bytes
  * for non-Arduino platforms. For Arduino the maximum size is 247 bytes.
@@ -749,10 +777,36 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
  */
 OCStackResult
 OCNotifyListOfObservers (OCResourceHandle handle,
-                         OCObservationId  *obsIdList,
-                         uint8_t          numberOfIds,
-                         unsigned char    *notificationJSONPayload,
-                         OCQualityOfService qos);
+                            OCObservationId  *obsIdList,
+                            uint8_t          numberOfIds,
+                            unsigned char    *notificationJSONPayload,
+                            OCQualityOfService qos);
+
+
+/**
+ * Send a response to a request.
+ * The response can be a normal, slow, or block (i.e. a response that
+ * is too large to be sent in a single PDU and must span multiple transmissions)
+ *
+ * @param response - pointer to structure that contains response parameters
+ *
+ * @return
+ *     OC_STACK_OK    - no errors
+ */
+OCStackResult OCDoResponse(OCEntityHandlerResponse *response);
+
+/**
+ * Cancel a response.  Applies to a block response
+ *
+ * @param responseHandle - response handle set by stack in OCServerResponse after
+ *                         OCDoResponse is called
+ *
+ * @return
+ *     OC_STACK_OK               - No errors; Success
+ *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
+ */
+OCStackResult OCCancelResponse(OCResponseHandle responseHandle);
+
 
 #ifdef __cplusplus
 }
diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript
new file mode 100644 (file)
index 0000000..f5a4222
--- /dev/null
@@ -0,0 +1,23 @@
+Import('env')
+
+arduino_simplecs_env = env.Clone()
+######################################################################
+# Build flags
+######################################################################
+arduino_simplecs_env.PrependUnique(CPPPATH = [
+               '../../../../../ocsocket/include',
+               '../../../../../logger/include',
+               '../../../../../stack/include',
+               '../../../../../../oc_logger/include'
+               ])
+
+arduino_simplecs_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+arduino_simplecs_env.PrependUnique(LIBS = ['octbstack', 'coap'])
+
+arduino_simplecs = arduino_simplecs_env.Program('SimpleClientServer', 'ocserver.cpp')
+env.CreateBin('SimpleClientServer')
+
+i_arduino_simplecs = arduino_simplecs_env.Install(env.get('BUILD_DIR'), arduino_simplecs)
+
+Alias('arduino_simplecs', i_arduino_simplecs)
+env.AppendTarget('arduino_simplecs')
\ No newline at end of file
index bba1f90..e5cd93f 100644 (file)
@@ -45,18 +45,20 @@ const char *getResult(OCStackResult result);
 
 PROGMEM const char TAG[] = "ArduinoServer";
 
-int gLEDUnderObservation = 0;
-void createLEDResource();
-typedef struct LEDRESOURCE{
+int gLightUnderObservation = 0;
+void createLightResource();
+
+/* Structure to represent a Light resource */
+typedef struct LIGHTRESOURCE{
     OCResourceHandle handle;
     bool state;
     int power;
-} LEDResource;
+} LightResource;
 
-static LEDResource LED;
+static LightResource Light;
 
-static char responsePayloadGet[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
-static char responsePayloadPut[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"power\":0}}";
+static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"off\",\"power\":0}}";
 
 /// This is the port which Arduino Server will use for all unicast communication with it's peers
 static uint16_t OC_WELL_KNOWN_PORT = 5683;
@@ -134,7 +136,7 @@ int ConnectToNetwork()
 // http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
 void PrintArduinoMemoryStats()
 {
-#ifdef ARDUINO_AVR_MEGA2560
+    #ifdef ARDUINO_AVR_MEGA2560
     //This var is declared in avr-libc/stdlib/malloc.c
     //It keeps the largest address not allocated for heap
     extern char *__brkval;
@@ -142,8 +144,8 @@ void PrintArduinoMemoryStats()
     int tmp;
     OC_LOG_V(INFO, TAG, "Stack: %u         Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
     OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
-             ((unsigned int)&tmp - (unsigned int)__brkval));
-#endif
+            ((unsigned int)&tmp - (unsigned int)__brkval));
+    #endif
 }
 
 // This is the entity handler for the registered resource.
@@ -151,42 +153,69 @@ void PrintArduinoMemoryStats()
 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest )
 {
     OCEntityHandlerResult ehRet = OC_EH_OK;
+    OCEntityHandlerResponse response = {0};
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
     {
         OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+
         if(OC_REST_GET == entityHandlerRequest->method)
         {
-            if (strlen(responsePayloadGet) < entityHandlerRequest->resJSONPayloadLen)
+            size_t responsePayloadGetLength = strlen(responsePayloadGet);
+            if (responsePayloadGetLength < (sizeof(payload) - 1))
             {
-                strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadGet, entityHandlerRequest->resJSONPayloadLen);
+                strncpy(payload, responsePayloadGet, responsePayloadGetLength);
             }
             else
             {
                 ehRet = OC_EH_ERROR;
             }
         }
-        if(OC_REST_PUT == entityHandlerRequest->method)
+        else if(OC_REST_PUT == entityHandlerRequest->method)
         {
             //Do something with the 'put' payload
-            if (strlen(responsePayloadPut) < entityHandlerRequest->resJSONPayloadLen)
+            size_t responsePayloadPutLength = strlen(responsePayloadPut);
+            if (responsePayloadPutLength < (sizeof(payload) - 1))
             {
-                strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadPut, entityHandlerRequest->resJSONPayloadLen);
+                strncpy((char *)payload, responsePayloadPut, responsePayloadPutLength);
             }
             else
             {
                 ehRet = OC_EH_ERROR;
             }
-         }
+        }
+
+        if (ehRet == OC_EH_OK)
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = entityHandlerRequest->requestHandle;
+            response.resourceHandle = entityHandlerRequest->resource;
+            response.ehResult = ehRet;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            response.numSendVendorSpecificHeaderOptions = 0;
+            memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+            memset(response.resourceUri, 0, sizeof response.resourceUri);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
+            {
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ehRet = OC_EH_ERROR;
+            }
+        }
     }
     if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
     {
-        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
-            gLEDUnderObservation = 1;
+            gLightUnderObservation = 1;
         }
-        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
         {
             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
         }
@@ -195,40 +224,35 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
     return ehRet;
 }
 
-
 // This method is used to display 'Observe' functionality of OC Stack.
 static uint8_t modCounter = 0;
-void *ChangeLEDRepresentation (void *param)
+void *ChangeLightRepresentation (void *param)
 {
     (void)param;
     OCStackResult result = OC_STACK_ERROR;
     modCounter += 1;
     if(modCounter % 10 == 0)  // Matching the timing that the Linux Sample Server App uses for the same functionality.
     {
-        LED.power += 5;
-        if (gLEDUnderObservation)
+        Light.power += 5;
+        if (gLightUnderObservation)
         {
-            OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power);
-            result = OCNotifyAllObservers (LED.handle, OC_NA_QOS);
+            OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
+            result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
             if (OC_STACK_NO_OBSERVERS == result)
             {
-                gLEDUnderObservation = 0;
+                gLightUnderObservation = 0;
             }
         }
     }
     return NULL;
 }
 
-
-
 //The setup function is called once at startup of the sketch
 void setup()
 {
     // Add your initialization code here
-
     // Note : This will initialize Serial port on Arduino at 115200 bauds
     OC_LOG_INIT();
-
     OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
     uint16_t port = OC_WELL_KNOWN_PORT;
 
@@ -246,9 +270,8 @@ void setup()
         return;
     }
 
-    // Declare and create the example resource: LED
-    createLEDResource();
-
+    // Declare and create the example resource: Light
+    createLightResource();
 }
 
 // The loop function is called in an endless loop
@@ -267,19 +290,19 @@ void loop()
         OC_LOG(ERROR, TAG, PCF("OCStack process error"));
         return;
     }
-    ChangeLEDRepresentation(NULL);
+    ChangeLightRepresentation(NULL);
 }
 
-void createLEDResource()
+void createLightResource()
 {
-    LED.state = false;
-    OCStackResult res = OCCreateResource(&LED.handle,
-            "core.led",
+    Light.state = false;
+    OCStackResult res = OCCreateResource(&Light.handle,
+            "core.light",
             "oc.mi.def",
-            "/a/led",
+            "/a/light",
             OCEntityHandlerCb,
             OC_DISCOVERABLE|OC_OBSERVABLE);
-    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+    OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
 }
 
 const char *getResult(OCStackResult result) {
index 6ce48b4..3f2b586 100644 (file)
@@ -59,8 +59,8 @@ const char *getResult(OCStackResult result) {
     case OC_STACK_NO_OBSERVERS:
         return "OC_STACK_NO_OBSERVERS";
     #ifdef WITH_PRESENCE
-    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-        return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+    case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+        return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
     case OC_STACK_PRESENCE_STOPPED:
         return "OC_STACK_PRESENCE_STOPPED";
     case OC_STACK_PRESENCE_TIMEOUT:
index fd2aaf8..07164ad 100644 (file)
@@ -38,6 +38,7 @@ OCRANDOM_DIR  = $(ROOT_DIR)/ocrandom
 OCSOCKET_DIR   = $(ROOT_DIR)/ocsocket
 LCOAP_DIR      = $(ROOT_DIR)/libcoap-4.1.1
 OCCOAP_DIR     = $(ROOT_DIR)/occoap
+OCMALLOC_DIR   = $(ROOT_DIR)/ocmalloc
 OCTBSTACK_DIR  = $(ROOT_DIR)/stack
 EXTLIBS_DIR    = $(ROOT_DIR)/../../extlibs
 CJSON_DIR      = $(EXTLIBS_DIR)/cjson
@@ -50,6 +51,7 @@ OCRANDOM_INC  = $(OCRANDOM_DIR)/include
 OCSOCKET_INC   = $(OCSOCKET_DIR)/include
 LCOAP_INC      = $(LCOAP_DIR)
 OCCOAP_INC     = $(OCCOAP_DIR)/include
+OCMALLOC_INC   = $(OCMALLOC_DIR)/include
 OCTBSTACK_INC  = $(OCTBSTACK_DIR)/include
 CJSON_INC      = $(CJSON_DIR)
 
@@ -59,6 +61,7 @@ INC_DIRS      += -I$(OCRANDOM_INC)
 INC_DIRS       += -I$(OCSOCKET_INC)
 INC_DIRS       += -I$(LCOAP_INC)
 INC_DIRS       += -I$(OCCOAP_INC)
+INC_DIRS       += -I$(OCMALLOC_INC)
 INC_DIRS       += -I$(OCTBSTACK_INC)
 INC_DIRS       += -I$(CJSON_INC)
 
@@ -72,17 +75,19 @@ CPPFLAGS    += $(CC_FLAGS.$(BUILD)) $(LDLIBS)
 
 CJSON_SOURCES          := $(CJSON_SRC)/cJSON.c
 
-SOURCES                := $(CJSON_SOURCES)
-SOURCES     += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp
+SOURCES        := $(CJSON_SOURCES)
+SOURCES        += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp ocserverslow.cpp occlientslow.cpp
 
 OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES))
 
 PROGRAMS       += ocserver
 PROGRAMS       += occlient
 PROGRAMS       += ocserverbasicops
+PROGRAMS       += ocserverslow
 PROGRAMS       += ocservercoll
 PROGRAMS       += occlientcoll
 PROGRAMS       += occlientbasicops
+PROGRAMS       += occlientslow
 
 all:   c_sdk prep_dirs $(OBJECTS) $(PROGRAMS)
 
@@ -99,6 +104,9 @@ $(OBJ_DIR)/%.o: %.cpp
 ocserver: $(OBJ_DIR)/ocserver.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+ocserverslow: $(OBJ_DIR)/ocserverslow.o $(OBJ_DIR)/common.o
+       $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
 ocserverbasicops: $(OBJ_DIR)/ocserverbasicops.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
@@ -111,6 +119,9 @@ occlient: $(OBJ_DIR)/occlient.o $(OBJ_DIR)/common.o
 occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+occlientslow: $(OBJ_DIR)/occlientslow.o $(OBJ_DIR)/common.o
+       $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
 occlientcoll: $(OBJ_DIR)/occlientcoll.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
index 4be565a..9f70f52 100644 (file)
@@ -93,7 +93,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     OCDoHandle handle;
 
     cbData.cb = cb;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, method, query.str().c_str(), 0,
@@ -119,7 +119,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
 }
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
     }
@@ -134,7 +134,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
     }
@@ -149,7 +149,7 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
 
 OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully");
     }
@@ -162,18 +162,22 @@ OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientRespo
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+    if(clientResponse == NULL)
     {
-        OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
     }
-
-    if(clientResponse)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
-        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
+        OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
+
+    OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+    OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
+
     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
             clientResponse->numRcvdVendorSpecificHeaderOptions)
     {
@@ -195,7 +199,7 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 }
 
 OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully");
     }
@@ -207,10 +211,9 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse
         OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumObserveNotifies);
         OC_LOG_V(INFO, TAG, "JSON = %s =============> Obs Response", clientResponse->resJSONPayload);
         gNumObserveNotifies++;
-        if (gNumObserveNotifies == 50) //large number to test observing in DELETE case.
+        if (gNumObserveNotifies == 3)  //large number to test observing in DELETE case.
         {
             if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON){
-                printf ("RESET\n");
                 if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK){
                     OC_LOG(ERROR, TAG, "Observe cancel error");
                 }
@@ -235,7 +238,7 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 }
 #ifdef WITH_PRESENCE
 OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for Presence recvd successfully");
     }
@@ -265,7 +268,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     uint8_t remoteIpAddr[4];
     uint16_t remotePortNu;
 
-    if (ctx == (void*) CTX_VAL)
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
     }
@@ -508,7 +511,7 @@ int InitDiscovery()
         strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     }
     cbData.cb = discoveryReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
index 1bc1d57..cb59cb0 100644 (file)
@@ -28,7 +28,7 @@
 // Defines
 //-----------------------------------------------------------------------------
 #define TAG "occlient"
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 #ifndef MAX_LENGTH_IPv4_ADDR
 #define MAX_LENGTH_IPv4_ADDR 16
 #endif
index 5ac6a90..a526935 100644 (file)
@@ -67,7 +67,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     OCDoHandle handle;
 
     cbData.cb = cb;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, method, query.str().c_str(), 0,
@@ -84,7 +84,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
     }
@@ -99,7 +99,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
     }
@@ -115,18 +115,21 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
 
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(clientResponse == NULL)
     {
-        OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
     }
-
-    if(clientResponse)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
-        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
-                clientResponse->resJSONPayload);
+        OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
+
+    OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+    OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+            clientResponse->resJSONPayload);
+
     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
             clientResponse->numRcvdVendorSpecificHeaderOptions)
     {
@@ -154,7 +157,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     uint8_t remoteIpAddr[4];
     uint16_t remotePortNu;
 
-    if (ctx == (void*) CTX_VAL)
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
     }
@@ -262,7 +265,7 @@ int InitDiscovery()
         strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     }
     cbData.cb = discoveryReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
index debd8ed..6752bed 100644 (file)
@@ -27,7 +27,7 @@
 // Defines
 //-----------------------------------------------------------------------------
 #define TAG "occlientbasicops"
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 #ifndef MAX_LENGTH_IPv4_ADDR
 #define MAX_LENGTH_IPv4_ADDR 16
 #endif
index 2a93a6f..e8db15a 100644 (file)
@@ -33,7 +33,7 @@ std::string getPortTBServer(OCClientResponse * clientResponse);
 std::string getQueryStrForGetPut(unsigned  const char * responsePayload);
 
 #define TAG PCF("occlient")
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 #ifndef MAX_LENGTH_IPv4_ADDR
 #define MAX_LENGTH_IPv4_ADDR 16
 #endif
@@ -98,7 +98,7 @@ int InitDiscovery();
 
 void PrintUsage()
 {
-    OC_LOG(INFO, TAG, "Usage : occlient -t <Test Case>");
+    OC_LOG(INFO, TAG, "Usage : occlientcoll -t <Test Case>");
     OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources && Initiate GET Request on an"\
             "available resource using default interface.");
     OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources && Initiate GET Request on an"\
@@ -120,8 +120,12 @@ void PrintUsage()
 }
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(clientResponse) {}
-    if(ctx == (void*)CTX_VAL) {
+    if(clientResponse == NULL)
+    {
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
         OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
     }
@@ -132,14 +136,14 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
     OC_LOG_V(INFO, TAG, "StackResult: %s",
             getResult(clientResponse->result));
-    if(ctx == (void*)CTX_VAL) {
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
         if(clientResponse->sequenceNumber == 0) {
             OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
             OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
         }
         else {
-            OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumObserveNotifies);
+            OC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d", gNumObserveNotifies);
             OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
             gNumObserveNotifies++;
             if (gNumObserveNotifies == 3)
@@ -169,19 +173,18 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     OC_LOG_V(INFO, TAG, "StackResult: %s",
             getResult(clientResponse->result));
 
-    if (ctx == (void*) CTX_VAL) {
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
     }
 
     OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
             remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
     OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
-#if 0
+
     OC_LOG_V(INFO, TAG,
             "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
             clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
             remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
-#endif
 
     if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
             TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
@@ -204,7 +207,7 @@ int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse)
     std::ostringstream getQuery;
     getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource";
     cbData.cb = getReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS,
@@ -225,7 +228,7 @@ int InitObserveRequest(OCClientResponse * clientResponse)
     std::ostringstream obsReg;
     obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
     cbData.cb = getReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     OC_LOG_V(INFO, TAG, "OBSERVE payload from client = %s ", putPayload.c_str());
 
@@ -253,7 +256,7 @@ int InitPutRequest(OCClientResponse * clientResponse)
     getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) <<
     "/a/room" << queryInterface[TEST].text;
     cbData.cb = putReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
 
@@ -288,7 +291,7 @@ int InitGetRequest(OCClientResponse * clientResponse)
     std::cout << "Get Query: " << getQuery.str() << std::endl;
 
     cbData.cb = getReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS,
             &cbData, NULL, 0);
@@ -310,7 +313,7 @@ int InitDiscovery()
     strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
 
     cbData.cb = discoveryReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS,
             &cbData, NULL, 0);
@@ -322,24 +325,28 @@ int InitDiscovery()
 }
 
 int main(int argc, char* argv[]) {
-    if(argc >= 2 && strcmp(argv[1], "-t") == 0)
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = USE_RANDOM_PORT;
+    uint8_t ifname[] = "eth0";
+    int opt;
+
+    while ((opt = getopt(argc, argv, "t:")) != -1)
     {
-        TEST = atoi(argv[2]);
-        if(TEST >= MAX_TESTS || TEST < 1)
+        switch(opt)
         {
+        case 't':
+            TEST = atoi(optarg);
+            break;
+        default:
             PrintUsage();
-            return 0;
+            return -1;
         }
     }
-    else
-    {
+    if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){
         PrintUsage();
-        return 0;
+        return -1;
     }
-    uint8_t addr[20] = {0};
-    uint8_t* paddr = NULL;
-    uint16_t port = USE_RANDOM_PORT;
-    uint8_t ifname[] = "eth0";
 
     /*Get Ip address on defined interface and initialize coap on it with random port number
      * this port number will be used as a source port in all coap communications*/
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp
new file mode 100644 (file)
index 0000000..689b015
--- /dev/null
@@ -0,0 +1,310 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <iostream>
+#include <sstream>
+#include "ocstack.h"
+#include "logger.h"
+#include "occlientslow.h"
+
+static int UNICAST_DISCOVERY = 0;
+static int TEST_CASE = 0;
+static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core";
+static std::string putPayload = "{\"state\":\"off\",\"power\":10}";
+static std::string coapServerIP = "255.255.255.255";
+static std::string coapServerPort = "5683";
+static std::string coapServerResource = "/a/led";
+
+int gQuitFlag = 0;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+static void PrintUsage()
+{
+    OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>");
+    OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
+    OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
+    OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request");
+    OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get Request");
+}
+
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+        OCMethod method, OCQualityOfService qos,
+        OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+
+    cbData.cb = cb;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+
+    ret = OCDoResource(&handle, method, query.str().c_str(), 0,
+            NULL,
+            qos, &cbData, options, numOptions);
+
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
+    }
+
+    return ret;
+}
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+    if(clientResponse == NULL)
+    {
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+    {
+        OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+    }
+
+    OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+    OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+            clientResponse->resJSONPayload);
+
+    if(clientResponse->rcvdVendorSpecificHeaderOptions &&
+            clientResponse->numRcvdVendorSpecificHeaderOptions)
+    {
+        OC_LOG (INFO, TAG, "Received vendor specific options");
+        uint8_t i = 0;
+        OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
+        for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
+        {
+            if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
+            {
+                OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
+                        ((OCHeaderOption)rcvdOptions[i]).optionID );
+                OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
+                        ((OCHeaderOption)rcvdOptions[i]).optionLength);
+            }
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+        OCClientResponse * clientResponse)
+{
+    uint8_t remoteIpAddr[4];
+    uint16_t remotePortNu;
+
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
+    {
+        OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
+    }
+
+    if (clientResponse)
+    {
+        OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+
+        OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
+                remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+        OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
+
+        OC_LOG_V(INFO, TAG,
+                "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
+                clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
+                remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
+
+        parseClientResponse(clientResponse);
+
+        switch(TEST_CASE)
+        {
+            case TEST_NON_CON_OP:
+                InitGetRequest(OC_LOW_QOS);
+                break;
+            case TEST_CON_OP:
+                InitGetRequest(OC_HIGH_QOS);
+                break;
+            default:
+                PrintUsage();
+                break;
+        }
+    }
+
+    return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
+
+}
+
+int InitGetRequest(OCQualityOfService qos)
+{
+    OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+    std::ostringstream query;
+    query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+
+    return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
+            OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+}
+
+int InitDiscovery()
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+    /* Start a discovery query*/
+    char szQueryUri[64] = { 0 };
+    if (UNICAST_DISCOVERY)
+    {
+        strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY);
+    }
+    else
+    {
+        strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
+    }
+    cbData.cb = discoveryReqCB;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+    return ret;
+}
+
+int main(int argc, char* argv[])
+{
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = USE_RANDOM_PORT;
+    uint8_t ifname[] = "eth0";
+    int opt;
+
+    while ((opt = getopt(argc, argv, "u:t:")) != -1)
+    {
+        switch(opt)
+        {
+            case 'u':
+                UNICAST_DISCOVERY = atoi(optarg);
+                break;
+            case 't':
+                TEST_CASE = atoi(optarg);
+                break;
+            default:
+                PrintUsage();
+                return -1;
+        }
+    }
+
+    if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
+            (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) )
+    {
+        PrintUsage();
+        return -1;
+    }
+
+
+    /*Get Ip address on defined interface and initialize coap on it with random port number
+     * this port number will be used as a source port in all coap communications*/
+    if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+                sizeof(addr)) == ERR_SUCCESS)
+    {
+        OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr);
+        paddr = addr;
+    }
+
+    /* Initialize OCStack*/
+    if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    InitDiscovery();
+
+    // Break from loop with Ctrl+C
+    OC_LOG(INFO, TAG, "Entering occlient main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+
+        sleep(2);
+    }
+    OC_LOG(INFO, TAG, "Exiting occlient main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack stop error");
+    }
+
+    return 0;
+}
+
+std::string getIPAddrTBServer(OCClientResponse * clientResponse)
+{
+    if(!clientResponse) return "";
+    if(!clientResponse->addr) return "";
+    uint8_t a, b, c, d = 0;
+    if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return "";
+
+    char ipaddr[16] = {'\0'};
+    // ostringstream not working correctly here, hence snprintf
+    snprintf(ipaddr,  sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d);
+    return std::string (ipaddr);
+}
+
+
+std::string getPortTBServer(OCClientResponse * clientResponse)
+{
+    if(!clientResponse) return "";
+    if(!clientResponse->addr) return "";
+    uint16_t p = 0;
+    if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return "";
+    std::ostringstream ss;
+    ss << p;
+    return ss.str();
+}
+
+std::string getQueryStrForGetPut(OCClientResponse * clientResponse)
+{
+    return "/a/led";
+}
+
+void parseClientResponse(OCClientResponse * clientResponse)
+{
+    coapServerIP = getIPAddrTBServer(clientResponse);
+    coapServerPort = getPortTBServer(clientResponse);
+    coapServerResource = getQueryStrForGetPut(clientResponse);
+}
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h
new file mode 100644 (file)
index 0000000..60713d7
--- /dev/null
@@ -0,0 +1,95 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OCCLIENT_BASICOPS_H_
+#define OCCLIENT_BASICOPS_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "occlientslow"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#ifndef MAX_LENGTH_IPv4_ADDR
+#define MAX_LENGTH_IPv4_ADDR 16
+#endif
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/**
+ * List of methods that can be inititated from the client
+ */
+typedef enum {
+    TEST_DISCOVER_REQ = 1,
+    TEST_NON_CON_OP,
+    TEST_CON_OP,
+    MAX_TESTS
+} CLIENT_TEST;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+
+/* call getResult in common.cpp to get the result in string format. */
+const char *getResult(OCStackResult result);
+
+/* Get the IP address of the server */
+std::string getIPAddrTBServer(OCClientResponse * clientResponse);
+
+/* Get the port number the server is listening on */
+std::string getPortTBServer(OCClientResponse * clientResponse);
+
+/* Returns the query string for GET and PUT operations */
+std::string getQueryStrForGetPut(OCClientResponse * clientResponse);
+
+/* Following are initialization functions for GET, PUT
+ * POST & Discovery operations
+ */
+int InitGetRequest(OCQualityOfService qos);
+int InitDiscovery();
+
+/* Function to retrieve ip address, port no. of the server
+ *  and query for the operations to be performed.
+ */
+void parseClientResponse(OCClientResponse * clientResponse);
+
+/* This function calls OCDoResource() which in turn makes calls
+ * to the lower layers
+ */
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+        OCMethod method, OCQualityOfService qos,
+        OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Following are callback functions for the  GET and Discovery operations
+ */
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
+
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+        OCClientResponse * clientResponse);
+
+#endif
index a2ca7dc..1bed2bf 100644 (file)
@@ -30,6 +30,9 @@
 #include "cJSON.h"
 #include "ocserver.h"
 
+//string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
+// 9 + 9 + 1 = 19
+const int URI_MAXSIZE = 19;
 
 static int gObserveNotifyType = 3;
 
@@ -101,43 +104,51 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     return jsonResponse;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *getResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+    if (maxPayloadSize > strlen ((char *)getResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, getResp,
-                strlen((char *)getResp));
+        strncpy(payload, getResp, strlen((char *)getResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(getResp);
+
+    return ehResult;
 }
 
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *putResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+    if (maxPayloadSize > strlen ((char *)putResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, putResp,
-                strlen((char *)putResp));
+        strncpy(payload, putResp, strlen((char *)putResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(putResp);
+
+    return ehResult;
 }
 
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
 {
     OCEntityHandlerResult ehResult = OC_EH_OK;
     char *respPLPost_light = NULL;
@@ -160,8 +171,9 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
         {
             // Create new Light instance
-            char newLightUri[15] = "/a/light/";
-            sprintf (newLightUri + strlen(newLightUri), "%d", gCurrLightInstance);
+            char newLightUri[URI_MAXSIZE];
+            snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
+
             json = cJSON_CreateObject();
             cJSON_AddStringToObject(json,"href",gResourceUri);
             cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
@@ -174,7 +186,7 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
                 gLightInstance[gCurrLightInstance].power = 0;
                 gCurrLightInstance++;
                 respPLPost_light = cJSON_Print(json);
-                strncpy ((char *)ehRequest->newResourceUri, newLightUri, MAX_URI_LENGTH);
+                strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
                 ehResult = OC_EH_RESOURCE_CREATED;
             }
 
@@ -209,24 +221,28 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         }
     }
 
-    if (respPLPost_light != NULL && ehRequest->resJSONPayloadLen > \
-            strlen((char *)respPLPost_light))
+    if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
     {
-        strncpy((char *)ehRequest->resJSONPayload, respPLPost_light,
-                strlen((char *)respPLPost_light));
+        strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(respPLPost_light);
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    if(ehRequest == NULL)
+    {
+        OC_LOG(INFO, TAG, "The ehRequest is NULL");
+        return OC_EH_ERROR;
+    }
     OCEntityHandlerResult ehResult = OC_EH_OK;
 
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
@@ -236,7 +252,7 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
      * 1a. pass the delete request to the c stack
      * 1b. internally, the c stack figures out what needs to be done and does it accordingly
      *    (e.g. send observers notification, remove observers...)
-     * 1c. the c stack returns with the result whether the request is fullfilLight.
+     * 1c. the c stack returns with the result whether the request is fullfilled.
      * 2. optionally, app removes observers out of its array 'interestedObservers'
      */
 
@@ -286,20 +302,21 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
         ehResult = OC_EH_FORBIDDEN;
     }
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)deleteResponse))
+    if (maxPayloadSize > strlen ((char *)deleteResponse))
     {
-        strncpy((char *)ehRequest->resJSONPayload, deleteResponse, strlen((char *)deleteResponse));
+        strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                  ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
 
@@ -307,14 +324,14 @@ OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *
     response = responsePayloadResourceDoesNotExist;
 
     if ( (ehRequest != NULL) &&
-         (ehRequest->resJSONPayloadLen > strlen ((char *)response)) )
+         (maxPayloadSize > strlen ((char *)response)) )
     {
-        strncpy((char *)ehRequest->resJSONPayload, response, strlen((char *)response));
+        strncpy((char *)payload, response, strlen((char *)response));
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                  ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
     }
 
     return OC_EH_RESOURCE_DELETED;
@@ -323,12 +340,12 @@ OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *
 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
 {
     OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
-            ehRequest->obsInfo->obsId);
+            ehRequest->obsInfo.obsId);
     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
     {
         if (interestedObservers[i].valid == false)
         {
-            interestedObservers[i].observationId = ehRequest->obsInfo->obsId;
+            interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
             interestedObservers[i].valid = true;
             gLightUnderObservation = 1;
             break;
@@ -341,10 +358,10 @@ void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
     bool clientStillObserving = false;
 
     OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
-            ehRequest->obsInfo->obsId);
+            ehRequest->obsInfo.obsId);
     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
     {
-        if (interestedObservers[i].observationId == ehRequest->obsInfo->obsId)
+        if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
         {
             interestedObservers[i].valid = false;
         }
@@ -365,6 +382,20 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
     OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
 
     OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    // Initialize certain response fields
+    response.numSendVendorSpecificHeaderOptions = 0;
+    memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+    memset(response.resourceUri, 0, sizeof response.resourceUri);
 
     if (flag & OC_INIT_FLAG)
     {
@@ -373,47 +404,62 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
     if (flag & OC_REQUEST_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
-        if (entityHandlerRequest)
+        if (entityHandlerRequest->resource == NULL) {
+            OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
+            ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_GET == entityHandlerRequest->method)
         {
-            if (entityHandlerRequest->resource == NULL) {
-                OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
-                ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
-            }
-            else if (OC_REST_GET == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_PUT == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_DELETE == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
-                ehResult = ProcessDeleteRequest (entityHandlerRequest);
-            }
-            else
+            OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+            ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_PUT == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+            ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_DELETE == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
+            ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    entityHandlerRequest->method);
+            ehResult = OC_EH_ERROR;
+        }
+
+        // If the result isn't an error or forbidden, send response
+        if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = entityHandlerRequest->requestHandle;
+            response.resourceHandle = entityHandlerRequest->resource;
+            response.ehResult = ehResult;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
             {
-                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
-                        entityHandlerRequest->method);
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ehResult = OC_EH_ERROR;
             }
         }
     }
     if (flag & OC_OBSERVE_FLAG)
     {
         OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
-        if (entityHandlerRequest)
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
-            if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
-            }
-            else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
-            }
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
+        }
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
+        {
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
         }
     }
 
@@ -428,6 +474,20 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
 
     OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    // Initialize certain response fields
+    response.numSendVendorSpecificHeaderOptions = 0;
+    memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+    memset(response.resourceUri, 0, sizeof response.resourceUri);
 
     if (flag & OC_INIT_FLAG)
     {
@@ -436,80 +496,97 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
     if (flag & OC_REQUEST_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
-        if (entityHandlerRequest)
+        if (OC_REST_GET == entityHandlerRequest->method)
         {
-            if (OC_REST_GET == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_PUT == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_POST == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ehResult = ProcessPostRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_DELETE == entityHandlerRequest->method)
+            OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+            ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_PUT == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+            ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_POST == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+            ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_DELETE == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
+            ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    entityHandlerRequest->method);
+        }
+
+        // If the result isn't an error or forbidden, send response
+        if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = entityHandlerRequest->requestHandle;
+            response.resourceHandle = entityHandlerRequest->resource;
+            response.ehResult = ehResult;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Handle vendor specific options
+            if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
+                    entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
             {
-                OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
-                ehResult = ProcessDeleteRequest (entityHandlerRequest);
+                OC_LOG (INFO, TAG, "Received vendor specific options");
+                uint8_t i = 0;
+                OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
+                for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
+                {
+                    if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
+                    {
+                        OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
+                                ((OCHeaderOption)rcvdOptions[i]).optionID );
+                        OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
+                                ((OCHeaderOption)rcvdOptions[i]).optionLength);
+                    }
+                }
+                OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
+                uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
+                uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
+                sendOptions[0].protocolID = OC_COAP_ID;
+                sendOptions[0].optionID = 2248;
+                memcpy(sendOptions[0].optionData, option2, sizeof(option2));
+                sendOptions[0].optionLength = 10;
+                sendOptions[1].protocolID = OC_COAP_ID;
+                sendOptions[1].optionID = 2600;
+                memcpy(sendOptions[1].optionData, option3, sizeof(option3));
+                sendOptions[1].optionLength = 10;
+                response.numSendVendorSpecificHeaderOptions = 2;
             }
-            else
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
             {
-                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
-                        entityHandlerRequest->method);
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ehResult = OC_EH_ERROR;
             }
         }
     }
     if (flag & OC_OBSERVE_FLAG)
     {
         OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
-        if (entityHandlerRequest)
+
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
-            if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
-                ProcessObserveRegister (entityHandlerRequest);
-            }
-            else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
-                ProcessObserveDeregister (entityHandlerRequest);
-            }
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
+            ProcessObserveRegister (entityHandlerRequest);
         }
-    }
-    if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
-            entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
-    {
-        OC_LOG (INFO, TAG, "Received vendor specific options");
-        uint8_t i = 0;
-        OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
-        for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
         {
-            if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
-            {
-                OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
-                        ((OCHeaderOption)rcvdOptions[i]).optionID );
-                OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
-                        ((OCHeaderOption)rcvdOptions[i]).optionLength);
-            }
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
+            ProcessObserveDeregister (entityHandlerRequest);
         }
-        OCHeaderOption * sendOptions = entityHandlerRequest->sendVendorSpecificHeaderOptions;
-        uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
-        uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
-        sendOptions[0].protocolID = OC_COAP_ID;
-        sendOptions[0].optionID = 2248;
-        memcpy(sendOptions[0].optionData, option2, sizeof(option2));
-        sendOptions[0].optionLength = 10;
-        sendOptions[1].protocolID = OC_COAP_ID;
-        sendOptions[1].optionID = 2600;
-        memcpy(sendOptions[1].optionData, option3, sizeof(option3));
-        sendOptions[1].optionLength = 10;
-        entityHandlerRequest->numSendVendorSpecificHeaderOptions = 2;
     }
 
     return ehResult;
@@ -531,7 +608,7 @@ void *ChangeLightRepresentation (void *param)
     uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
     OCObservationId obsNotify[numNotifies];
 
-    while (1)
+    while (!gQuitFlag)
     {
         sleep(10);
         Light.power += 5;
index c34f130..f5e45e5 100644 (file)
@@ -70,11 +70,24 @@ void *ChangeLightRepresentation (void *param);
 
 /* Following methods process the PUT, GET, POST, Delete,
  * & Observe requests */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                          OCEntityHandlerResponse *response,
+                                          char *payload,
+                                          uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
+                                            char *payload,
+                                            uint16_t maxPayloadSize);
+
+OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest,
+                                                         char *payload,
+                                                         uint16_t maxPayloadSize);
+
 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest);
 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest);
 
index 971056d..bcd741c 100644 (file)
 #include "cJSON.h"
 #include "ocserverbasicops.h"
 
-int gQuitFlag = 0;
+//string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
+// 7 + 9 + 1 = 17
+const int URI_MAXSIZE = 17;
+
+volatile sig_atomic_t gQuitFlag = 0;
 
 static LEDResource LED;
 // This variable determines instance number of the LED resource.
@@ -81,47 +85,56 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     return jsonResponse;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *getResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+    if (maxPayloadSize > strlen ((char *)getResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, getResp,
-                strlen((char *)getResp));
+        strncpy(payload, getResp, strlen((char *)getResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(getResp);
+
+    return ehResult;
 }
 
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *putResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+    if (maxPayloadSize > strlen ((char *)putResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, putResp,
-                strlen((char *)putResp));
+        strncpy(payload, putResp, strlen((char *)putResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(putResp);
+
+    return ehResult;
 }
 
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
     char *respPLPost_led = NULL;
     cJSON *json;
     cJSON *format;
+    OCEntityHandlerResult ehResult;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -139,8 +152,8 @@ void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
         {
             // Create new LED instance
-            char newLedUri[15] = "/a/led/";
-            sprintf (newLedUri + strlen(newLedUri), "%d", gCurrLedInstance);
+            char newLedUri[URI_MAXSIZE ];
+            snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
 
             json = cJSON_CreateObject();
 
@@ -183,18 +196,21 @@ void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         }
     }
 
-    if (respPLPost_led != NULL && ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+    if ((respPLPost_led != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_led)))
     {
-        strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
-                strlen((char *)respPLPost_led));
+        strncpy(payload, respPLPost_led, strlen((char *)respPLPost_led));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(respPLPost_led);
+
+    return ehResult;
 }
 
 OCEntityHandlerResult
@@ -202,9 +218,15 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         OCEntityHandlerRequest *entityHandlerRequest)
 {
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
+
     if (flag & OC_INIT_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
+        ehResult = OC_EH_OK;
     }
     if (flag & OC_REQUEST_FLAG)
     {
@@ -214,26 +236,48 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             if (OC_REST_GET == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
+                ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
             }
             else if (OC_REST_PUT == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
+                ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
             }
             else if (OC_REST_POST == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ProcessPostRequest (entityHandlerRequest);
+                ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
             }
             else
             {
                 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
                         entityHandlerRequest->method);
             }
+
+            if (ehResult == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
         }
     }
-    return OC_EH_OK;
+    return ehResult;
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
@@ -251,8 +295,6 @@ int main(int argc, char* argv[])
     uint8_t* paddr = NULL;
     uint16_t port = OC_WELL_KNOWN_PORT;
     uint8_t ifname[] = "eth0";
-    int opt;
-
 
     OC_LOG(DEBUG, TAG, "OCServer is starting...");
     /*Get Ip address on defined interface and initialize coap on it with random port number
index af9f00c..74f862e 100644 (file)
@@ -54,9 +54,15 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
 /* Following methods process the PUT, GET, POST
  * requests
  */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                          char *payload,
+                                          uint16_t maxPayloadSize);
 
 /* call getResult in common.cpp to get the result in string format. */
 const char *getResult(OCStackResult result);
index 7a6d239..75124bb 100644 (file)
@@ -33,7 +33,7 @@ const char *getResult(OCStackResult result);
 
 #define TAG PCF("ocservercontainer")
 
-int gQuitFlag = 0;
+volatile sig_atomic_t gQuitFlag = 0;
 int gLightUnderObservation = 0;
 void createResources();
 typedef struct LIGHTRESOURCE{
@@ -69,18 +69,40 @@ const char rspPutFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"false
 const char rspPutFanCollection[] = "{\"href\":\"/a/fan\"}";
 const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}";
 
+typedef enum {
+    TEST_INVALID = 0,
+    TEST_DEFAULT_COLL_EH,
+    TEST_APP_COLL_EH,
+    MAX_TESTS
+} SERVER_TEST;
+
+void PrintUsage()
+{
+    OC_LOG(INFO, TAG, "Usage : ocservercoll -t <Test Case>");
+    OC_LOG(INFO, TAG, "Test Case 1 : Create room resource with default collection entity handler.");
+    OC_LOG(INFO, TAG, "Test Case 2 : Create room resource with application collection entity handler.");
+}
+
+unsigned static int TEST = TEST_INVALID;
+
 static OCEntityHandlerResult
-HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char* errStr)
+HandleCallback(OCEntityHandlerRequest * ehRequest,
+               const char* opStr,
+               const char* errStr,
+               char *payload,
+               uint16_t maxPayloadSize)
 {
     OCEntityHandlerResult ret = OC_EH_OK;
 
-    if (strlen(opStr) < ehRequest->resJSONPayloadLen)
+    // Append opStr or errStr, after making sure there is
+    // enough room in the payload
+    if (strlen(opStr) < (maxPayloadSize - strlen(payload)))
     {
-        strncat((char*)ehRequest->resJSONPayload, opStr, ehRequest->resJSONPayloadLen);
+        strncat((char*)payload, opStr, strlen(opStr));
     }
-    else if (strlen(errStr) < ehRequest->resJSONPayloadLen)
+    else if (strlen(errStr) < (maxPayloadSize - strlen(payload)))
     {
-        strncat((char*)ehRequest->resJSONPayload, errStr, ehRequest->resJSONPayloadLen);
+        strncat((char*)payload, errStr, strlen(errStr));
         ret = OC_EH_ERROR;
     }
     else
@@ -92,7 +114,7 @@ HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char
 }
 
 static void
-PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest )
+PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
 {
     const char* typeOfMessage;
 
@@ -115,10 +137,12 @@ PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehReques
              (ehRequest->method == OC_REST_GET) ? "OC_REST_GET" : "OC_REST_PUT" );
 }
 
-OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
-        OCEntityHandlerRequest * ehRequest )
+OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
+                                            OCEntityHandlerRequest * ehRequest)
 {
     OCEntityHandlerResult ret = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG_V(INFO, TAG, "Callback for Room");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -131,90 +155,136 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
         {
             if(query.find("oc.mi.def") != std::string::npos)
             {
-                ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom);
+                ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom, payload, sizeof(payload));
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
                 }
             }
             else if(query.find("oc.mi.ll") != std::string::npos)
             {
-                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom);
+                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
                 }
             }
             else if(query.find("oc.mi.b") != std::string::npos)
             {
-                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom);
+                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
+                }
+            }
+            if (ret == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = ehRequest->requestHandle;
+                response.resourceHandle = ehRequest->resource;
+                response.ehResult = ret;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof response.resourceUri);
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ret = OC_EH_ERROR;
                 }
             }
         }
-        if(OC_REST_PUT == ehRequest->method)
+        else if(OC_REST_PUT == ehRequest->method)
         {
             if(query.find("oc.mi.def") != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom);
+                    ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom, payload, sizeof(payload));
                 }
             }
             if(query.find("oc.mi.ll") != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom);
+                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan, payload, sizeof(payload));
                 }
             }
             if(query.find("oc.mi.b") != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom);
+                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
                 }
             }
+            if (ret == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = ehRequest->requestHandle;
+                response.resourceHandle = ehRequest->resource;
+                response.ehResult = ret;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof response.resourceUri);
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ret = OC_EH_ERROR;
+                }
+            }
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    ehRequest->method);
+            ret = OC_EH_ERROR;
         }
     }
     else if (ehRequest && flag == OC_OBSERVE_FLAG)
@@ -224,8 +294,11 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
     return ret;
 }
 
-OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
+{
     OCEntityHandlerResult ret = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG_V(INFO, TAG, "Callback for Light");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -234,11 +307,39 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityH
     {
         if(OC_REST_GET == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight);
+            ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
+        }
+        else if(OC_REST_PUT == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
         }
-        if(OC_REST_PUT == ehRequest->method)
+        else
         {
-            ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight);
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    ehRequest->method);
+            ret = OC_EH_ERROR;
+        }
+
+        if (ret == OC_EH_OK)
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = ehRequest->requestHandle;
+            response.resourceHandle = ehRequest->resource;
+            response.ehResult = ret;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            response.numSendVendorSpecificHeaderOptions = 0;
+            memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+            memset(response.resourceUri, 0, sizeof response.resourceUri);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
+            {
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ret = OC_EH_ERROR;
+            }
         }
     }
     else if (ehRequest && flag == OC_OBSERVE_FLAG)
@@ -249,8 +350,11 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityH
     return ret;
 }
 
-OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
+{
     OCEntityHandlerResult ret = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG_V(INFO, TAG, "Callback for Fan");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -259,12 +363,41 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHan
     {
         if(OC_REST_GET == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan);
+            ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
+        }
+        else if(OC_REST_PUT == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
         }
-        if(OC_REST_PUT == ehRequest->method)
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    ehRequest->method);
+            ret = OC_EH_ERROR;
+        }
+
+        if (ret == OC_EH_OK)
         {
-            ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan);
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = ehRequest->requestHandle;
+            response.resourceHandle = ehRequest->resource;
+            response.ehResult = ret;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            response.numSendVendorSpecificHeaderOptions = 0;
+            memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+            memset(response.resourceUri, 0, sizeof response.resourceUri);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
+            {
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ret = OC_EH_ERROR;
+            }
         }
+
     }
     else if (ehRequest && flag == OC_OBSERVE_FLAG)
     {
@@ -275,8 +408,10 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHan
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
-void handleSigInt(int signum) {
-    if (signum == SIGINT) {
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
         gQuitFlag = 1;
     }
 }
@@ -286,13 +421,14 @@ void *ChangeLightRepresentation (void *param)
     (void)param;
     OCStackResult result = OC_STACK_ERROR;
 
-    while (1)
+    while (!gQuitFlag)
     {
         sleep(10);
         light.power += 5;
         if (gLightUnderObservation)
         {
-     OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", light.power);
+            OC_LOG_V(INFO, TAG,
+                " =====> Notifying stack of new power level %d\n", light.power);
             result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
             if (OC_STACK_NO_OBSERVERS == result)
             {
@@ -303,18 +439,36 @@ void *ChangeLightRepresentation (void *param)
     return NULL;
 }
 
-int main() {
-    printf("hello world from main\n");
-    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+int main(int argc, char* argv[])
+{
     uint8_t addr[20] = {0};
     uint8_t* paddr = NULL;
     uint16_t port = 0;
     uint8_t ifname[] = "eth0";
     pthread_t threadId;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "t:")) != -1)
+    {
+        switch(opt)
+        {
+        case 't':
+            TEST = atoi(optarg);
+            break;
+        default:
+            PrintUsage();
+            return -1;
+        }
+    }
+    if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){
+        PrintUsage();
+        return -1;
+    }
 
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
     /*Get Ip address on defined interface and initialize coap on it with random port number
      * this port number will be used as a source port in all coap communications*/
-    if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+    if (OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
                                sizeof(addr)) == ERR_SUCCESS)
     {
         OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
@@ -339,8 +493,10 @@ int main() {
     // Break from loop with Ctrl-C
     OC_LOG(INFO, TAG, "Entering ocserver main loop...");
     signal(SIGINT, handleSigInt);
-    while (!gQuitFlag) {
-        if (OCProcess() != OC_STACK_OK) {
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
             OC_LOG(ERROR, TAG, "OCStack process error");
             return 0;
         }
@@ -355,13 +511,15 @@ int main() {
 
     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
 
-    if (OCStop() != OC_STACK_OK) {
+    if (OCStop() != OC_STACK_OK)
+    {
         OC_LOG(ERROR, TAG, "OCStack process error");
     }
 
     return 0;
 }
-void createResources() {
+void createResources()
+{
     light.state = false;
 
     OCResourceHandle fan;
@@ -383,12 +541,26 @@ void createResources() {
     OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
 
     OCResourceHandle room;
-    res = OCCreateResource(&room,
-            "core.room",
-            "oc.mi.b",
-            "/a/room",
-            OCEntityHandlerRoomCb,
-            OC_DISCOVERABLE);
+
+    if(TEST == TEST_APP_COLL_EH)
+    {
+        res = OCCreateResource(&room,
+                "core.room",
+                "oc.mi.b",
+                "/a/room",
+                OCEntityHandlerRoomCb,
+                OC_DISCOVERABLE);
+    }
+    else
+    {
+        res = OCCreateResource(&room,
+                "core.room",
+                "oc.mi.b",
+                "/a/room",
+                NULL,
+                OC_DISCOVERABLE);
+    }
+
     OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
     OCBindResourceInterfaceToResource(room, "oc.mi.ll");
     OCBindResourceInterfaceToResource(room, "oc.mi.def");
@@ -399,5 +571,3 @@ void createResources() {
     res = OCBindResource(room, fan);
     OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
 }
-
-
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp
new file mode 100644 (file)
index 0000000..e1184e1
--- /dev/null
@@ -0,0 +1,362 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <list>
+#include "ocstack.h"
+#include "ocmalloc.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "ocserverslow.h"
+
+volatile sig_atomic_t gQuitFlag = 0;
+
+static std::list<OCEntityHandlerRequest *> gRequestList;
+static constexpr unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static unsigned int gCurrLedInstance = 0;
+static constexpr unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+//char *gResourceUri= const_cast<char *>("/a/led");
+char *gResourceUri= (char *)"/a/led";
+
+static constexpr uint16_t OC_WELL_KNOWN_PORT = 5683;
+
+//This function takes the request as an input and returns the response
+//in JSON format.
+char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+{
+    cJSON *json = cJSON_CreateObject();
+    cJSON *format;
+    char *jsonResponse;
+    LEDResource *currLEDResource = &LED;
+
+    OC_LOG(INFO, TAG, "Entering constructJsonResponse");
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        OC_LOG(INFO, TAG, "handle 0");
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = const_cast<char *>("a/led/0");
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        OC_LOG(INFO, TAG, "handle 1");
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = const_cast<char *>("a/led/1");
+    }
+
+    if(OC_REST_PUT == ehRequest->method)
+    {
+        cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
+        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
+                "on") ? true:false);
+        currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
+        cJSON_Delete(putJson);
+    }
+
+    cJSON_AddStringToObject(json,"href",gResourceUri);
+    cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
+    cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off"));
+    cJSON_AddNumberToObject(format, "power", currLEDResource->power);
+
+    OC_LOG(INFO, TAG, "Before constructJsonResponse print");
+    jsonResponse = cJSON_Print(json);
+    OC_LOG(INFO, TAG, "Before constructJsonResponse delete");
+    cJSON_Delete(json);
+
+    OC_LOG(INFO, TAG, "Before constructJsonResponse return");
+    return jsonResponse;
+}
+
+void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+{
+    OC_LOG(INFO, TAG, "Entering ProcessGetRequest");
+    char *getResp = constructJsonResponse(ehRequest);
+    OC_LOG(INFO, TAG, "After constructJsonResponse");
+    OCEntityHandlerResponse response;
+
+    // Format the response.  Note this requires some info about the request
+    response.requestHandle = ehRequest->requestHandle;
+    response.resourceHandle = ehRequest->resource;
+    response.ehResult = OC_EH_OK;
+    response.payload = (unsigned char *)getResp;
+    response.payloadSize = strlen(getResp) + 1;
+    response.numSendVendorSpecificHeaderOptions = 0;
+    memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+    memset(response.resourceUri, 0, sizeof(response.resourceUri));
+    // Indicate that response is NOT in a persistent buffer
+    response.persistentBufferFlag = 0;
+
+    // Send the response
+    if (OCDoResponse(&response) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "Error sending response");
+    }
+
+    free(getResp);
+}
+
+OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
+{
+    OC_LOG(INFO, TAG, "Copying received request for slow response");
+    OCEntityHandlerRequest *request = (OCEntityHandlerRequest *)OCMalloc(sizeof(OCEntityHandlerRequest));
+    if (request)
+    {
+        // Do shallow copy
+        memcpy(request, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
+        // Do deep copy of query
+        request->query = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->query) + 1);
+        if (request->query)
+        {
+            strcpy((char *)request->query, (const char *)entityHandlerRequest->query);
+
+            // Copy the request payload
+            request->reqJSONPayload = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->reqJSONPayload) + 1);
+            if (request->reqJSONPayload)
+            {
+                strcpy((char *)request->reqJSONPayload, (const char *)entityHandlerRequest->reqJSONPayload);
+
+                // Ignore vendor specific header options for example
+                request->numRcvdVendorSpecificHeaderOptions = 0;
+                request->rcvdVendorSpecificHeaderOptions = NULL;
+            }
+            else
+            {
+                OCFree(request->query);
+                OCFree(request);
+                request = NULL;
+            }
+        }
+        else
+        {
+            OCFree(request);
+            request = NULL;
+        }
+    }
+
+    if (request)
+    {
+        OC_LOG(INFO, TAG, "Copied client request");
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Error copying client request");
+    }
+    return request;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest)
+{
+    OCEntityHandlerResult result = OC_EH_ERROR;
+    OCEntityHandlerRequest *request = NULL;
+
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+    if (flag & OC_INIT_FLAG)
+    {
+        OC_LOG(INFO, TAG, "Flag includes OC_INIT_FLAG");
+        result = OC_EH_OK;
+    }
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            OC_LOG_V (INFO, TAG, "request query %s from client",
+                                        entityHandlerRequest->query);
+            OC_LOG_V (INFO, TAG, "request payload %s from client",
+                                        entityHandlerRequest->reqJSONPayload);
+            // Make deep copy of received request and queue it for slow processing
+            request = CopyRequest(entityHandlerRequest);
+            if (request)
+            {
+
+                OC_LOG(INFO, TAG, "Scheduling slow response for received request");
+                gRequestList.push_back(request);
+                // Indicate to the stack that this is a slow response
+                result = OC_EH_SLOW;
+                // Start the slow response alarm
+                alarm(SLOW_RESPONSE_DELAY_SEC);
+            }
+            else
+            {
+                OC_LOG(ERROR, TAG, "Error queuing request for slow response");
+                // Indicate to the stack that this is a slow response
+                result = OC_EH_ERROR;
+            }
+        }
+        else
+        {
+            OC_LOG(ERROR, TAG, "Invalid request");
+            result = OC_EH_ERROR;
+        }
+    }
+    return result;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+// SIGINT alarm handler:  alarm set by entity handler.  Does
+// slow response when fired
+void AlarmHandler(int sig)
+{
+    if (sig == SIGALRM)
+    {
+        OC_LOG (INFO, TAG, "Server starting slow response");
+        if (gRequestList.empty())
+        {
+            OC_LOG (INFO, TAG, "No requests to service");
+            return;
+        }
+
+        // Get the request from the list
+        OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
+        gRequestList.pop_front();
+        if (entityHandlerRequest->method == OC_REST_GET)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+            ProcessGetRequest (entityHandlerRequest);
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    entityHandlerRequest->method);
+        }
+        // Free the request
+        OCFree(entityHandlerRequest->query);
+        OCFree(entityHandlerRequest->reqJSONPayload);
+        OCFree(entityHandlerRequest);
+
+        // If there are more requests in list, re-arm the alarm signal
+        if (gRequestList.empty())
+        {
+            alarm(SLOW_RESPONSE_DELAY_SEC);
+        }
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = OC_WELL_KNOWN_PORT;
+    uint8_t ifname[] = "eth0";
+
+
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+    /*Get Ip address on defined interface and initialize coap on it with random port number
+     * this port number will be used as a source port in all coap communications*/
+    if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+                sizeof(addr)) == ERR_SUCCESS)
+    {
+        OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+        paddr = addr;
+    }
+
+    if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * Declare and create the example resource: LED
+     */
+    createLEDResource(gResourceUri, &LED, false, 0);
+
+    // Initialize slow response alarm
+    signal(SIGALRM, AlarmHandler);
+
+    // Break from loop with Ctrl-C
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+
+        sleep(2);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    // Free requests
+    if (!gRequestList.empty())
+    {
+        for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
+        {
+            OCFree((*iter)->query);
+            OCFree((*iter)->reqJSONPayload);
+            OCFree(*iter);
+        }
+        gRequestList.clear();
+    }
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            "oc.mi.def",
+            uri,
+            OCEntityHandlerCb,
+            OC_DISCOVERABLE|OC_OBSERVABLE);
+    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h
new file mode 100644 (file)
index 0000000..bf37c34
--- /dev/null
@@ -0,0 +1,71 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OCSERVER_SLOW_H_
+#define OCSERVER_SLOW_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "ocserverslow"
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+//-----------------------------------------------------------------------------
+// Function prototypes
+//-----------------------------------------------------------------------------
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following method process the GET request
+ */
+void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
+
+/* call getResult in common.cpp to get the result in string format. */
+const char *getResult(OCStackResult result);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Entity Handler callback functions */
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest);
+
+#endif
index 8664f2e..55fb32a 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+#include <ocstack.h>
+#include <ocsecurity.h>
+#include <logger.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <ocstack.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define TAG "sample-common"
+
+OCStackResult SetCredentials(const char* filename) {
+
+    FILE *fp = NULL;
+    uint8_t *data = NULL;
+    struct stat st;
+    OCStackResult ret = OC_STACK_ERROR;
+
+    fp = fopen(filename, "rb");
+    if (fp)
+    {
+        if (stat(filename, &st) == 0)
+        {
+            data = (uint8_t*)malloc(st.st_size);
+            if (data)
+            {
+                if (fread(data, 1, st.st_size, fp) == (size_t)st.st_size)
+                {
+                    // Provide credentials to OC Stack
+                    ret = OCSetDtlsPskCredentials((OCDtlsPskCredsBlob *)data,
+                            st.st_size);
+                }
+                else
+                {
+                    OC_LOG_V(FATAL, TAG, "Error in reading file %s", filename);
+                }
+            }
+        }
+        fclose(fp);
+    }
+    else
+    {
+        OC_LOG_V(FATAL, TAG, "Unable to open %s file", filename);
+    }
+
+    free(data);
+
+    return ret;
+}
 
 const char *getResult(OCStackResult result) {
     switch (result) {
@@ -59,8 +104,8 @@ const char *getResult(OCStackResult result) {
     case OC_STACK_NO_OBSERVERS:
         return "OC_STACK_NO_OBSERVERS";
     #ifdef WITH_PRESENCE
-    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-        return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+    case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+        return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
     case OC_STACK_PRESENCE_STOPPED:
         return "OC_STACK_PRESENCE_STOPPED";
     #endif
diff --git a/resource/csdk/stack/samples/linux/secure/common.h b/resource/csdk/stack/samples/linux/secure/common.h
new file mode 100644 (file)
index 0000000..408ba59
--- /dev/null
@@ -0,0 +1,31 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 OCSAMPLE_COMMON_H_
+#define OCSAMPLE_COMMON_H_
+
+/* Get the result in string format. */
+const char *getResult(OCStackResult result);
+
+/* Read the credentials from persistent storage and provide to OC stack. */
+OCStackResult SetCredentials(const char* filename);
+
+#endif //OCSAMPLE_COMMON_H_
+
diff --git a/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp b/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp
new file mode 100644 (file)
index 0000000..2a259ac
--- /dev/null
@@ -0,0 +1,123 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 "ocsecurityconfig.h"
+#include "logger.h"
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG "gen_sec_bin"
+
+void printStruct(const char * device, OCDtlsPskCredsBlob* s)
+{
+    OC_LOG(INFO, TAG, device);
+    OC_LOG_V(INFO, TAG, "Version - %d", s->blobVer);
+    OC_LOG(INFO, TAG, "My Identity :");
+    OC_LOG_BUFFER(INFO, TAG, s->identity, DTLS_PSK_ID_LEN);
+
+    OC_LOG_V(INFO, TAG, "Number of trusted Peers  - %d", s->num);
+    OC_LOG(INFO, TAG, "Peer Identity :");
+    OC_LOG_BUFFER(INFO, TAG, s->creds[0].id, DTLS_PSK_ID_LEN);
+    OC_LOG(INFO, TAG, "Peer Psk :");
+    OC_LOG_BUFFER(INFO, TAG, s->creds[0].psk, DTLS_PSK_PSK_LEN);
+}
+
+
+int main()
+{
+    OCDtlsPskCredsBlob * s = NULL;
+    OCDtlsPskCredsBlob * c = NULL;
+    FILE* fps, *fpc;
+
+    int i;
+
+    srand(time(NULL));
+
+    s = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob));
+    c = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob));
+
+    memset(s, 0, sizeof(OCDtlsPskCredsBlob));
+    memset(c, 0, sizeof(OCDtlsPskCredsBlob));
+
+    s->blobVer = DtlsPskCredsBlobVer_CurrentVersion;
+    c->blobVer = DtlsPskCredsBlobVer_CurrentVersion;
+
+    s->num = c->num = 1;
+
+    for(i = 0; i < DTLS_PSK_ID_LEN; i++)
+    {
+        c->creds[0].id[i] = s->identity[i] = rand() % (2^8);
+
+        s->creds[0].id[i] = c->identity[i] = rand() % (2^8);
+
+        c->creds[0].psk[i] = s->creds[0].psk[i] = rand() % (2^8);
+    }
+
+    // Print Credentials
+    printStruct("Server", s);
+    printStruct("Client", c);
+
+    // Write to files
+    if ((fps = (FILE*) fopen("server_cred.bin", "wb")) != NULL)
+    {
+        fwrite(s, sizeof(OCDtlsPskCredsBlob), 1, fps);
+        fclose(fps);
+    }
+
+
+    if ((fpc = (FILE*) fopen("client_cred.bin", "wb")) != NULL)
+    {
+        fwrite(c, sizeof(OCDtlsPskCredsBlob), 1, fpc);
+        fclose(fpc);
+    }
+
+    memset(s, 0, sizeof(OCDtlsPskCredsBlob));
+    memset(c, 0, sizeof(OCDtlsPskCredsBlob));
+    // Read from files; print and verify manually
+    if ((fps = (FILE*) fopen("server_cred.bin", "rb")) != NULL)
+    {
+        if (sizeof(OCDtlsPskCredsBlob) != fread(s, 1, sizeof(OCDtlsPskCredsBlob), fps))
+        {
+            OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
+        }
+        fclose(fps);
+    }
+
+
+    if ((fpc = (FILE*) fopen("client_cred.bin", "rb")) != NULL)
+    {
+        if (sizeof(OCDtlsPskCredsBlob) != fread(c, 1, sizeof(OCDtlsPskCredsBlob), fpc))
+        {
+            OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
+        }
+        fclose(fpc);
+    }
+
+    printf("\n\n");
+    OC_LOG(INFO, TAG, PCF("Reading from file and printing again to verify manually"));
+    printStruct("Server", s);
+    printStruct("Client", c);
+
+    free(s);
+    free(c);
+}
+
index 9e5bcc1..c77d733 100644 (file)
@@ -73,12 +73,13 @@ CPPFLAGS    += $(CC_FLAGS.$(BUILD)) $(LDLIBS)
 CJSON_SOURCES          := $(CJSON_SRC)/cJSON.c
 
 SOURCES                := $(CJSON_SOURCES)
-SOURCES     += common.cpp ocserverbasicops.cpp occlientbasicops.cpp
+SOURCES     += common.cpp ocserverbasicops.cpp occlientbasicops.cpp gen_sec_bin.cpp
 
 OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES))
 
 PROGRAMS       += ocserverbasicops
 PROGRAMS       += occlientbasicops
+PROGRAMS       += gen_sec_bin
 
 all:   c_sdk prep_dirs $(OBJECTS) $(PROGRAMS)
 
@@ -98,6 +99,9 @@ ocserverbasicops: $(OBJ_DIR)/ocserverbasicops.o $(OBJ_DIR)/common.o
 occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+gen_sec_bin: $(OBJ_DIR)/gen_sec_bin.o
+       $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
 .PHONY: clean
 
 clean: legacy_clean
index 0e69b9a..e4125d2 100644 (file)
@@ -29,6 +29,7 @@
 #include "logger.h"
 #include "occlientbasicops.h"
 #include "cJSON.h"
+#include "common.h"
 
 #define TAG "occlientbasicops"
 static int UNICAST_DISCOVERY = 0;
@@ -40,6 +41,12 @@ static std::string coapServerPort;
 static std::string coapServerResource;
 static int coapSecureResource;
 
+//File containing Client's Identity and the PSK credentials
+//of other devices which the client trusts
+//This can be generated using 'gen_sec_bin' application
+static char CRED_FILE[] = "client_cred.bin";
+
+
 int gQuitFlag = 0;
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
@@ -296,6 +303,16 @@ int main(int argc, char* argv[])
         return 0;
     }
 
+    /*
+     * Read DTLS PSK credentials from persistent storage and
+     * set in the OC stack.
+     */
+    if (SetCredentials(CRED_FILE) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "SetCredentials failed");
+        return 0;
+    }
+
     InitDiscovery();
 
     timeout.tv_sec  = 0;
index 104e653..689d7e6 100644 (file)
@@ -41,9 +41,6 @@ typedef enum {
 // Function prototype
 //-----------------------------------------------------------------------------
 
-/* call getResult in common.cpp to get the result in string format. */
-const char *getResult(OCStackResult result);
-
 /* Get the IP address of the server */
 std::string getIPAddrTBServer(OCClientResponse * clientResponse);
 
index 7ed8d14..216268b 100644 (file)
@@ -28,6 +28,7 @@
 #include "logger.h"
 #include "cJSON.h"
 #include "ocserverbasicops.h"
+#include "common.h"
 
 int gQuitFlag = 0;
 
@@ -42,6 +43,11 @@ char *gResourceUri= (char *)"/a/led";
 
 static uint16_t OC_WELL_KNOWN_PORT = 5683;
 
+//File containing Server's Identity and the PSK credentials
+//of other devices which the server trusts
+//This can be generated using 'gen_sec_bin' application
+static char CRED_FILE[] = "server_cred.bin";
+
 //This function takes the request as an input and returns the response
 //in JSON format.
 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
@@ -81,47 +87,59 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     return jsonResponse;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                        char *payload, size_t maxPayloadSize)
 {
-    char *getResp = constructJsonResponse(ehRequest);
+    OCEntityHandlerResult ehResult;
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+    char *getResp = constructJsonResponse(ehRequest);
+    if (maxPayloadSize > strlen (getResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, getResp,
-                strlen((char *)getResp));
+        strcpy(payload, getResp);
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(getResp);
+
+    return ehResult;
 }
 
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                        char *payload, size_t maxPayloadSize)
 {
-    char *putResp = constructJsonResponse(ehRequest);
+    OCEntityHandlerResult ehResult;
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+    char *putResp = constructJsonResponse(ehRequest);
+    if (maxPayloadSize > strlen (putResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, putResp,
-                strlen((char *)putResp));
+        strcpy(payload, putResp);
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(putResp);
+
+    return ehResult;
 }
 
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                        char *payload, size_t maxPayloadSize)
 {
     char *respPLPost_led = NULL;
     cJSON *json;
     cJSON *format;
+    OCEntityHandlerResult ehResult;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -183,18 +201,21 @@ void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         }
     }
 
-    if (respPLPost_led != NULL && ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+    if ((respPLPost_led != NULL) && (maxPayloadSize > strlen (respPLPost_led)))
     {
-        strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
-                strlen((char *)respPLPost_led));
+        strcpy(payload, respPLPost_led);
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(respPLPost_led);
+
+    return ehResult;
 }
 
 OCEntityHandlerResult
@@ -202,9 +223,15 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         OCEntityHandlerRequest *entityHandlerRequest)
 {
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH];
+
     if (flag & OC_INIT_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
+        ehResult = OC_EH_OK;
     }
     if (flag & OC_REQUEST_FLAG)
     {
@@ -214,26 +241,48 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             if (OC_REST_GET == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
+                ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload));
             }
             else if (OC_REST_PUT == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
+                ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload));
             }
             else if (OC_REST_POST == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ProcessPostRequest (entityHandlerRequest);
+                ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload));
             }
             else
             {
                 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
                         entityHandlerRequest->method);
             }
+
+            if (ehResult == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
         }
     }
-    return OC_EH_OK;
+    return ehResult;
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
@@ -270,6 +319,15 @@ int main(int argc, char* argv[])
     }
 
     /*
+     * Read DTLS PSK credentials from persistent storage and
+     * set in the OC stack.
+     */
+    if (SetCredentials(CRED_FILE) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "SetCredentials failed");
+        return 0;
+    }
+    /*
      * Declare and create the example resource: LED
      */
     createLEDResource(gResourceUri, &LED, false, 0);
@@ -288,7 +346,6 @@ int main(int argc, char* argv[])
             return 0;
         }
         nanosleep(&timeout, NULL);
-        //sleep(2);
     }
 
     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
index af9f00c..4e1f7eb 100644 (file)
@@ -54,12 +54,15 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
 /* Following methods process the PUT, GET, POST
  * requests
  */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
-
-/* call getResult in common.cpp to get the result in string format. */
-const char *getResult(OCStackResult result);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         size_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         size_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                          char *payload,
+                                          size_t maxPayloadSize);
 
 //-----------------------------------------------------------------------------
 // Callback functions
index e5e98e3..9e0b232 100644 (file)
@@ -33,29 +33,65 @@ struct ClientCB *cbList = NULL;
 OCMulticastNode * mcPresenceNodes = NULL;
 
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
-        OCCoAPToken * token, OCDoHandle handle, OCMethod method,
-        unsigned char * requestUri, unsigned char * resourceType) {
-    ClientCB *cbNode;
-    cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
-    if (cbNode) {
-        cbNode->callBack = cbData->cb;
-        cbNode->context = cbData->context;
-        cbNode->deleteCallback = cbData->cd;
-        memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
-        cbNode->handle = handle;
-        cbNode->method = method;
-        cbNode->sequenceNumber = 0;
-        #ifdef WITH_PRESENCE
-        cbNode->presence = NULL;
-        cbNode->filterResourceType = resourceType;
-        #endif
-        cbNode->requestUri = requestUri;
-        LL_APPEND(cbList, cbNode);
+        OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
+        unsigned char * requestUri, unsigned char * resourceTypeName) {
+
+    ClientCB *cbNode = NULL;
+
+    #ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE)
+    {   // Retrieve the presence callback structure for this specific requestUri.
+        cbNode = GetClientCB(NULL, NULL, requestUri);
+    }
+    #endif // WITH_PRESENCE
+
+    if(!cbNode)// If it does not already exist, create new node.
+    {
+        cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
+        if(!cbNode)
+        {
+            *clientCB = NULL;
+            goto exit;
+        }
+        else
+        {
+            cbNode->callBack = cbData->cb;
+            cbNode->context = cbData->context;
+            cbNode->deleteCallback = cbData->cd;
+            memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
+            cbNode->handle = *handle;
+            cbNode->method = method;
+            cbNode->sequenceNumber = 0;
+            #ifdef WITH_PRESENCE
+            cbNode->presence = NULL;
+            cbNode->filterResourceType = NULL;
+            #endif // WITH_PRESENCE
+            cbNode->requestUri = requestUri;
+            LL_APPEND(cbList, cbNode);
+            *clientCB = cbNode;
+        }
+    }
+    else
+    {
+        // Ensure that the handle the SDK hands back up to the application layer for the
+        // OCDoResource call matches the found ClientCB Node.
         *clientCB = cbNode;
-        return OC_STACK_OK;
+        OCFree(requestUri);
+        OCFree(*handle);
+        *handle = cbNode->handle;
     }
-    *clientCB = NULL;
-    return OC_STACK_NO_MEMORY;
+
+    #ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE && resourceTypeName)
+    {   // Amend the found or created node by adding a new resourceType to it.
+        return InsertResourceTypeFilter(cbNode, (const char *)resourceTypeName);
+    }
+    #endif
+
+    return OC_STACK_OK;
+
+    exit:
+        return OC_STACK_NO_MEMORY;
 }
 
 void DeleteClientCB(ClientCB * cbNode) {
@@ -74,9 +110,20 @@ void DeleteClientCB(ClientCB * cbNode) {
         if(cbNode->presence) {
             OCFree(cbNode->presence->timeOut);
             OCFree(cbNode->presence);
-            OCFree(cbNode->filterResourceType);
         }
-        #endif
+        if(cbNode->method == OC_REST_PRESENCE)
+        {
+            OCResourceType * pointer = cbNode->filterResourceType;
+            OCResourceType * next = NULL;
+            while(pointer)
+            {
+                next = pointer->next;
+                OCFree(pointer->resourcetypename);
+                OCFree(pointer);
+                pointer = next;
+            }
+        }
+        #endif // WITH_PRESENCE
         OCFree(cbNode);
         cbNode = NULL;
     }
@@ -113,6 +160,26 @@ ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * re
     return NULL;
 }
 
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
+{
+    OCResourceType * newResourceType = NULL;
+    if(cbNode && resourceTypeName)
+    {
+        // Form a new resourceType member.
+        newResourceType = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+        if(!newResourceType)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        newResourceType->next = NULL;
+        newResourceType->resourcetypename = (char *) resourceTypeName;
+
+        LL_APPEND(cbNode->filterResourceType, newResourceType);
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
 
 void DeleteClientCBList() {
     ClientCB* out;
index 2e4b276..2efba22 100644 (file)
@@ -22,7 +22,7 @@
 #include <string.h>
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "logger.h"
 #include "debug.h"
 #include "cJSON.h"
@@ -92,10 +92,10 @@ ValidateQuery (const unsigned char *query, OCResourceHandle resource,
         char *endToken;
         char *innerToken = strtok_r (token, "=", &endToken);
         numParam = 0;
+
         // Internal loop parses the field to extract values (parameters) assigned to each field
         while (innerToken != NULL)
         {
-
             numParam++;
             if (strcmp (innerToken, OC_RSRVD_INTERFACE) == 0)
             {
@@ -123,45 +123,59 @@ ValidateQuery (const unsigned char *query, OCResourceHandle resource,
         return OC_STACK_INVALID_QUERY;
     }
 
-    if (!ifPtr)
-    {
-        // IF not specified in query, use default IF
-        *ifParam = STACK_IF_DEFAULT;
-    }
-    else
+    if (ifPtr)
     {
         if(CheckIFParamSupport((OCResource *)resource, ifPtr) != OC_STACK_OK)
+        {
             return OC_STACK_INVALID_QUERY;
-
+        }
         if (strcmp (ifPtr, OC_RSRVD_INTERFACE_DEFAULT) == 0)
+        {
             *ifParam = STACK_IF_DEFAULT;
+        }
         else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_LL) == 0)
+        {
             *ifParam = STACK_IF_LL;
+        }
         else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_BATCH) == 0)
+        {
             *ifParam = STACK_IF_BATCH;
+        }
         else
         {
             return OC_STACK_ERROR;
         }
     }
-
-    if (!rtPtr)
+    else
     {
-        // RT not specified in query. Use the first resource type for the resource as default.
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+        // IF not specified in query, use default IF
+        *ifParam = STACK_IF_DEFAULT;
     }
-    else
+
+    if (rtPtr)
     {
         if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK)
+        {
             *rtParam = rtPtr;
+        }
         else
+        {
             return OC_STACK_INVALID_QUERY;
+        }
+    }
+    else
+    {
+        // RT not specified in query. Use the first resource type for the resource as default.
+        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
     }
     OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam);
 
     return OC_STACK_OK;
 }
-static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandlerRequest *ehRequest)
+
+
+static OCStackResult BuildRootResourceJSON(OCResource *resource,
+        unsigned char * bufferPtr, uint16_t *remaining)
 {
     OCStackResult ret = OC_STACK_ERROR;
     cJSON *resObj;
@@ -170,25 +184,18 @@ static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandler
 
     OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON"));
     resObj = cJSON_CreateObject();
+
     if (resource)
     {
         cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri));
     }
     jsonStr = cJSON_PrintUnformatted (resObj);
     jsonLen = strlen(jsonStr);
-    if (jsonLen < ehRequest->resJSONPayloadLen)
+    if (jsonLen < *remaining)
     {
-        strcpy((char*)ehRequest->resJSONPayload, jsonStr);
-        ehRequest->resJSONPayloadLen -= jsonLen;
-        ehRequest->resJSONPayload += jsonLen;
-        ret = OC_STACK_OK;
-    }
-
-    if (ehRequest->resJSONPayloadLen >= (sizeof(OC_JSON_SEPARATOR) + 1))
-    {
-        *ehRequest->resJSONPayload = OC_JSON_SEPARATOR;
-        ehRequest->resJSONPayload++;
-        ehRequest->resJSONPayloadLen--;
+        strcpy((char*) bufferPtr, jsonStr);
+        *remaining -= jsonLen;
+        bufferPtr += jsonLen;
         ret = OC_STACK_OK;
     }
 
@@ -200,112 +207,168 @@ static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandler
 
 
 static OCStackResult
-BuildCollectionJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest,
+HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
                        uint8_t filterOn, char *filterValue)
 {
     OCStackResult ret = OC_STACK_ERROR;
-    ret = BuildRootResourceJSON(resource, ehRequest);
+    unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+    size_t jsonbufferLength = 0;
+    uint16_t remaining = 0;
+    unsigned char * ptr = NULL;
+    OCResource * collResource = (OCResource *) ehRequest->resource;
+
+    ptr = jsonbuffer;
+    remaining = MAX_RESPONSE_LENGTH;
+
+    ret = BuildRootResourceJSON(collResource, ptr, &remaining);
+    ptr += strlen((char*)ptr);
+
+    if (ret == OC_STACK_OK && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1))
+    {
+        *ptr = OC_JSON_SEPARATOR;
+        ptr++;
+        remaining--;
+    }
+    else
+    {
+        ret = OC_STACK_ERROR;
+    }
+    *(ptr + 1) = '\0';
 
-    unsigned char* buffer = ehRequest->resJSONPayload;
-    uint16_t remaining = ehRequest->resJSONPayloadLen;
     if (ret == OC_STACK_OK)
     {
         for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
         {
-            OCResource* temp = resource->rsrcResources[i];
+            OCResource* temp = collResource->rsrcResources[i];
             if (temp)
             {
-                ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)buffer, &remaining);
+                ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)ptr, &remaining);
                 if (ret != OC_STACK_OK)
                 {
                     break;
                 }
-
-                buffer += strlen((char*)buffer);
-                if (resource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
+                ptr += strlen((char*)ptr);
+                if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
                 {
-                    *buffer = OC_JSON_SEPARATOR;
-                    buffer++;
+                    *ptr = OC_JSON_SEPARATOR;
+                    ptr++;
                     remaining--;
                 }
+                *(ptr + 1) = '\0';
             }
             else
             {
                 break;
             }
         }
-        ehRequest->resJSONPayload = buffer;
-        ehRequest->resJSONPayloadLen = remaining;
     }
 
+    jsonbufferLength = strlen((const char *)jsonbuffer);
+    if(ret == OC_STACK_OK && jsonbufferLength)
+    {
+        OCEntityHandlerResponse response = {0};
+        response.ehResult = OC_EH_OK;
+        response.payload = jsonbuffer;
+        response.payloadSize = jsonbufferLength + 1;
+        response.persistentBufferFlag = 0;
+        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+        response.resourceHandle = (OCResourceHandle) collResource;
+        ret = OCDoResponse(&response);
+    }
     return ret;
 }
 
-
 static OCStackResult
-BuildCollectionBatchJSONResponse(OCEntityHandlerFlag flag,
-                OCResource *resource, OCEntityHandlerRequest *ehRequest)
+HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 {
     OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+    size_t jsonbufferLength = 0;
+    uint16_t remaining = 0;
+    unsigned char * ptr = NULL;
+    OCResource * collResource = (OCResource *) ehRequest->resource;
+
+    ptr = jsonbuffer;
+    remaining = MAX_RESPONSE_LENGTH;
+
+    stackRet = BuildRootResourceJSON(collResource, ptr, &remaining);
+    ptr += strlen((char*)ptr);
+    *(ptr + 1) = '\0';
+
+    jsonbufferLength = strlen((const char *)jsonbuffer);
+    if(jsonbufferLength)
+    {
+        OCEntityHandlerResponse response = {0};
+        response.ehResult = OC_EH_OK;
+        response.payload = jsonbuffer;
+        response.payloadSize = jsonbufferLength + 1;
+        response.persistentBufferFlag = 0;
+        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+        response.resourceHandle = (OCResourceHandle) collResource;
+        stackRet = OCDoResponse(&response);
+    }
 
-    stackRet = BuildRootResourceJSON(resource, ehRequest);
     if (stackRet == OC_STACK_OK)
     {
-        OCResourceHandle origResourceHandle = ehRequest->resource;
-
         for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
         {
-            OCResource* temp = resource->rsrcResources[i];
+            OCResource* temp = collResource->rsrcResources[i];
             if (temp)
             {
+                // Note that all entity handlers called through a collection
+                // will get the same pointer to ehRequest, the only difference
+                // is ehRequest->resource
                 ehRequest->resource = (OCResourceHandle) temp;
 
-                ehRet = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
-                stackRet = EntityHandlerCodeToOCStackCode(ehRet);
+                ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
 
-                if(ehRet == OC_EH_OK)
+                // The default collection handler is returning as OK
+                if(stackRet != OC_STACK_SLOW_RESOURCE)
                 {
-                    unsigned char* buffer = ehRequest->resJSONPayload;
-                    ehRequest->resJSONPayloadLen =
-                            ehRequest->resJSONPayloadLen - strlen((char*)buffer);
-
-                    buffer += strlen((char*)buffer);
-                    ehRequest->resJSONPayload = buffer;
-                    if ( resource->rsrcResources[i+1] &&
-                         ehRequest->resJSONPayloadLen > sizeof(OC_JSON_SEPARATOR) )
-                    {
-                        * buffer = OC_JSON_SEPARATOR;
-                        buffer++;
-                        ehRequest->resJSONPayload = buffer;
-                        ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen - 1;
-                    }
+                    stackRet = OC_STACK_OK;
                 }
-                else
+                // if a single resource is slow, then entire response will be treated
+                // as slow response
+                if(ehResult == OC_EH_SLOW)
                 {
-                    break;
+                    OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+                    ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
+                    stackRet = EntityHandlerCodeToOCStackCode(ehResult);
                 }
             }
             else
             {
-               break;
+                break;
             }
         }
-
-        ehRequest->resource = origResourceHandle;
+        ehRequest->resource = (OCResourceHandle) collResource;
     }
     return stackRet;
 }
 
+uint8_t GetNumOfResourcesInCollection (OCResource *resource)
+{
+    uint8_t num = 0;
+    for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+    {
+        if (resource->rsrcResources[i])
+        {
+            num++;
+        }
+    }
+    return num;
+}
+
 
 OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                                               OCEntityHandlerRequest *ehRequest)
 {
-    OCStackResult result;
-    OCStackIfTypes ifQueryParam;
-    char *rtQueryParam;
+    OCStackResult result = OC_STACK_ERROR;
+    OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
+    char *rtQueryParam = NULL;
 
-    OC_LOG(INFO, TAG, PCF("DefaultCollectionEntityHandler"));
+    OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
 
     if (flag != OC_REQUEST_FLAG)
         return OC_STACK_ERROR;
@@ -328,19 +391,19 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                 // Get attributes of collection resource and properties of contined resource
                 // M1 release does not support attributes for collection resource, so the GET
                 // operation is same as the GET on LL interface.
-
                 OC_LOG(INFO, TAG, PCF("STACK_IF_DEFAULT"));
-                return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
-                             ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+                return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
 
             case STACK_IF_LL:
                 OC_LOG(INFO, TAG, PCF("STACK_IF_LL"));
-                return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
-                             ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+                return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
 
             case STACK_IF_BATCH:
                 OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH"));
-                return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+                ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+                ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+                        GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+                return HandleBatchInterface(ehRequest);
 
             default:
                 return OC_STACK_ERROR;
@@ -357,7 +420,10 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                 return OC_STACK_ERROR;
 
             case STACK_IF_BATCH:
-                return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+                ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+                ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+                        GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+                return HandleBatchInterface(ehRequest);
 
             default:
                 return OC_STACK_ERROR;
index c59089f..e8e58d4 100644 (file)
 #include "ocstackconfig.h"
 #include "ocstackinternal.h"
 #include "ocobserve.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "occoap.h"
 #include "utlist.h"
 #include "debug.h"
 #include "ocrandom.h"
 #include "ocmalloc.h"
+#include "ocserverrequest.h"
 
 // Module Name
 #define MOD_NAME PCF("ocobserve")
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
 
 static struct ResourceObserver * serverObsList = NULL;
-extern uint32_t SERVER_DISCOVERABLE;
 
-OCStackResult OCObserverStatus(OCCoAPToken * token, uint8_t status)
+// send notifications based on the qos of the request
+// The qos passed as a parameter overrides what the client requested
+// If we want the client preference taking high priority make:
+// qos = resourceObserver->qos;
+OCQualityOfService DetermineObserverQoS(OCMethod method, ResourceObserver * resourceObserver,
+        OCQualityOfService appQoS)
 {
-    OCStackResult result = OC_STACK_ERROR;
-    ResourceObserver * observer = NULL;
-    OCEntityHandlerRequest ehRequest;
-    OCObservationInfo observationInfo;
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
-
-    switch(status)
+    OCQualityOfService decidedQoS = appQoS;
+    if(appQoS == OC_NA_QOS)
     {
-    case OC_OBSERVER_NOT_INTERESTED:
-        OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
-        observer = GetObserverUsingToken (token);
-        if(observer)
-        {
-            FormOCEntityHandlerRequest(&ehRequest, OC_REST_CANCEL_OBSERVE, bufRes, 
-                                        NULL, NULL, NULL);
-            ehRequest.obsInfo = &observationInfo;
-            ehRequest.obsInfo->action = OC_OBSERVE_DEREGISTER;
-            ehRequest.obsInfo->obsId = observer->observeId;
-            observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
-        }
-        //observer is dead, or it is not observing anymore
-        result = DeleteObserverUsingToken (token);
-        if(result != OC_STACK_OK)
-        {
-            result = OC_STACK_OBSERVER_NOT_REMOVED;
-        }
-        else
-        {
-            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
-        }
-        break;
-    case OC_OBSERVER_STILL_INTERESTED:
-        //observer is still interested
-        OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
-                notifications, reset the failedCount"));
-        observer = GetObserverUsingToken(token);
-        if(observer)
-        {
-            observer->forceHighQos = 0;
-            observer->failedCommCount = 0;
-            result = OC_STACK_OK;
-        }
-        else
-        {
-            result = OC_STACK_OBSERVER_NOT_FOUND;
-        }
-        break;
-    case OC_OBSERVER_FAILED_COMM:
-        //observer is not reachable
-        OC_LOG(DEBUG, TAG, PCF("observer is not reachable"));
-        observer = GetObserverUsingToken(token);
-        if(observer)
-        {
-            if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
-            {
-                FormOCEntityHandlerRequest(&ehRequest, OC_REST_CANCEL_OBSERVE, bufRes, 
-                                            NULL, NULL, NULL);
-                ehRequest.obsInfo = &observationInfo;
-                ehRequest.obsInfo->action = OC_OBSERVE_DEREGISTER;
-                ehRequest.obsInfo->obsId = observer->observeId;
-                observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
-
-                result = DeleteObserverUsingToken (token);
-                if(result != OC_STACK_OK)
-                {
-                    result = OC_STACK_OBSERVER_NOT_REMOVED;
-                }
-                else
-                {
-                    OC_LOG(DEBUG, TAG, PCF("removing an observer"));
-                }
-            }
-            else
-            {
-                observer->failedCommCount++;
-                result = OC_STACK_OBSERVER_NOT_REMOVED;
-            }
-            observer->forceHighQos = 1;
-            OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
-        }
-        break;
-    default:
-        break;
+        decidedQoS = resourceObserver->qos;
     }
 
-    return result;
-}
-
-OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
-{
-    OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
-    OCEntityHandlerRequest *ehReq = request->entityHandlerRequest;
-    OCObserveReq *obs = request->observe;
-    OCObservationInfo observationInfo;
-    OCObservationId obsId;
-    ResourceObserver *resObs = NULL;
-
-    OC_LOG(INFO, TAG, PCF("Entering ProcessObserveRequest"));
-
-    request->entityHandlerRequest->resource = (OCResourceHandle)resource;
-    request->entityHandlerRequest->obsInfo = &observationInfo;
-
-    if (obs->option == OC_RESOURCE_OBSERVE_REGISTER)
+    if(appQoS != OC_HIGH_QOS)
     {
-        // Request to register new observation
-        observationInfo.action = OC_OBSERVE_REGISTER;
-        // Generate observation Id for the request
-        while (1)
-        {
-            if (OC_STACK_OK != GenerateObserverId (&obsId))
-                return OC_STACK_ERROR;
-
-            // Check if observation Id already exists
-            resObs = GetObserverUsingId (obsId);
-            if (NULL == resObs)
-            {
-                OC_LOG_V(INFO, TAG, "Observation ID is %d", obsId);
-                break;
-            }
-        }
-
-        observationInfo.obsId = obsId;
-        // Register the observation request with entity handler
-        ehRet = resource->entityHandler ((OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG),
-                                         request->entityHandlerRequest);
-        if (ehRet == OC_EH_OK)
-        {
-            // Add subscriber to the server observation list
-            stackRet = AddObserver ((const char*)(request->resourceUrl),
-                                    (const char *)(ehReq->query),
-                                    obsId, obs->token, obs->subAddr,
-                                    resource, request->qos);
-            if(stackRet != OC_STACK_OK)
-            {
-                obs->result = OC_STACK_OBSERVER_NOT_ADDED;
-                stackRet = OC_STACK_OBSERVER_NOT_ADDED;
-                // If the observation was not added in the stack notify the entity handler
-                observationInfo.action = OC_OBSERVE_DEREGISTER;
-                // If the entity handler is unable to deregister, stack cannot do anything,
-                // hence the return value from entity handler is not being checked
-                resource->entityHandler (OC_OBSERVE_FLAG, request->entityHandlerRequest);
-            }
-            else
+        OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
+                resourceObserver->lowQosCount);
+        #ifdef WITH_PRESENCE
+        if((resourceObserver->forceHighQos \
+                || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
+                && method != OC_REST_PRESENCE)
+        #else
+        if(resourceObserver->forceHighQos \
+                || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT)
+        #endif
             {
-                OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+            resourceObserver->lowQosCount = 0;
+            // at some point we have to to send CON to check on the
+            // availability of observer
+            OC_LOG(INFO, TAG, PCF("This time we are sending the  notification as High qos"));
+            decidedQoS = OC_HIGH_QOS;
             }
-        }
-        else
-        {
-            stackRet = OC_STACK_OBSERVER_NOT_ADDED;
-        }
-    }
-    else if (obs->option == OC_RESOURCE_OBSERVE_DEREGISTER)
-    {
-        // Request to deregister observation
-        observationInfo.action = OC_OBSERVE_DEREGISTER;
-
-        // Get observation Id using token
-        resObs = GetObserverUsingToken (obs->token);
-        if (NULL == resObs)
-        {
-            // Stack does not contain this observation request
-            // Either token is incorrect or observation list is corrupted
-            return OC_STACK_ERROR;
-        }
-        observationInfo.action = OC_OBSERVE_DEREGISTER;
-        observationInfo.obsId = resObs->observeId;
-        // Deregister the observation with entity handler. Ignoring return value
-        // from entity handler and deleting the observation from stack
-        resource->entityHandler ((OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG),
-                                 request->entityHandlerRequest);
-        stackRet = DeleteObserverUsingToken (obs->token);
-        if(stackRet != OC_STACK_OK)
-        {
-            obs->result = OC_STACK_OBSERVER_NOT_REMOVED;
-            stackRet = OC_STACK_OBSERVER_NOT_REMOVED;
-        }
         else
         {
-            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+            (resourceObserver->lowQosCount)++;
         }
     }
-    else
-    {
-        // Invalid observe option
-        OC_LOG(ERROR, TAG, PCF("Invalid CoAP observe option"));
-        obs->result = OC_STACK_INVALID_OBSERVE_PARAM;
-    }
-    return stackRet;
+    return decidedQoS;
 }
 
-OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
-                OCResourceType *resourceType, OCQualityOfService qos)
+#ifdef WITH_PRESENCE
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCResourceType *resourceType, OCQualityOfService qos)
+#else
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCQualityOfService qos)
+#endif
 {
+    OC_LOG(INFO, TAG, PCF("Entering SendObserverNotification"));
+    OCStackResult result = OC_STACK_ERROR;
+    ResourceObserver * resourceObserver = serverObsList;
     uint8_t numObs = 0;
-    OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
-    ResourceObserver *resourceObserver = serverObsList;
-    OCEntityHandlerRequest entityHandlerReq;
-    unsigned char* jsonPayload = NULL;
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+    OCServerRequest * request = NULL;
+    OCEntityHandlerRequest ehRequest = {0};
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     // Find clients that are observing this resource
     while (resourceObserver)
@@ -255,103 +106,170 @@ OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uin
             if(method != OC_REST_PRESENCE)
             {
             #endif
-                // Invoke the entity handler for the client to process
-                // the query according to the new representation
-                FormOCEntityHandlerRequest(&entityHandlerReq, OC_REST_GET, bufRes,
-                        NULL, resourceObserver->query, NULL);
-                entityHandlerReq.resource = (OCResourceHandle)resPtr;
-
-                // Even if entity handler for a resource is not successful
-                // we continue calling entity handler for other resources
-                ehRet = BuildObsJSONResponse((OCResource *) resPtr, &entityHandlerReq);
-                jsonPayload = (unsigned char *)(entityHandlerReq.resJSONPayload);
+                qos = DetermineObserverQoS(method, resourceObserver, qos);
+                result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+                        0, resPtr->sequenceNum, qos, resourceObserver->query,
+                        NULL, NULL,
+                        &resourceObserver->token, resourceObserver->addr,
+                        resourceObserver->resUri, 0);
+                request->observeResult = OC_STACK_OK;
+                if(request && result == OC_STACK_OK)
+                {
+                    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+                                request->method, (OCResourceHandle) resPtr, request->query,
+                                request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+                                request->rcvdVendorSpecificHeaderOptions, OC_OBSERVE_NO_OPTION, 0);
+                    if(result == OC_STACK_OK)
+                    {
+                        ehResult = resPtr->entityHandler(OC_REQUEST_FLAG, &ehRequest);
+                        if(ehResult == OC_EH_ERROR)
+                        {
+                            FindAndDeleteServerRequest(request);
+                        }
+                    }
+                }
             #ifdef WITH_PRESENCE
             }
             else
             {
-                //we know it is the default entity handler
+                OCEntityHandlerResponse ehResponse = {0};
+                unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0};
+                //This is effectively the implementation for the presence entity handler.
                 OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
-
-                // we create the payload here
-                if(resourceType)
+                result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+                        0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS,
+                        NULL, NULL, NULL, &resourceObserver->token,
+                        resourceObserver->addr, resourceObserver->resUri, 0);
+                if(result == OC_STACK_OK)
                 {
-                    sprintf((char *)bufRes, "%u:%u:%s",
-                            resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
-                }
-                else
-                {
-                    sprintf((char *)bufRes, "%u:%u", resPtr->sequenceNum, maxAge);
+                    // we create the payload here
+                    if(resourceType && resourceType->resourcetypename)
+                    {
+                        sprintf((char *)presenceResBuf, "%u:%u:%s",
+                                resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
+                    }
+                    else
+                    {
+                        sprintf((char *)presenceResBuf, "%u:%u", resPtr->sequenceNum, maxAge);
+                    }
+                    ehResponse.ehResult = OC_EH_OK;
+                    ehResponse.payload = presenceResBuf;
+                    ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1;
+                    ehResponse.persistentBufferFlag = 0;
+                    ehResponse.requestHandle = (OCRequestHandle) request;
+                    ehResponse.resourceHandle = (OCResourceHandle) resPtr;
+                    strcpy((char *)ehResponse.resourceUri, (const char *)resourceObserver->resUri);
+                    result = OCDoResponse(&ehResponse);
                 }
-
-                jsonPayload = bufRes;
-                ehRet = OC_EH_OK;
             }
-
             #endif
-            if (OC_EH_OK == ehRet)
+        }
+        resourceObserver = resourceObserver->next;
+    }
+    if (numObs == 0)
+    {
+        OC_LOG(INFO, TAG, PCF("Resource has no observers"));
+        result = OC_STACK_NO_OBSERVERS;
+    }
+    return result;
+}
+
+OCStackResult SendListObserverNotification (OCResource * resource,
+        OCObservationId  *obsIdList, uint8_t numberOfIds,
+        unsigned char *notificationJSONPayload, uint32_t maxAge,
+        OCQualityOfService qos)
+{
+    uint8_t numIds = numberOfIds;
+    ResourceObserver *observation = NULL;
+    uint8_t numSentNotification = 0;
+    OCServerRequest * request = NULL;
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerResponse ehResponse = {0};
+
+    OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification"));
+    while(numIds)
+    {
+        OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
+        observation = NULL;
+        observation = GetObserverUsingId (*obsIdList);
+        if(observation)
+        {
+            // Found observation - verify if it matches the resource handle
+            if (observation->resource == resource)
             {
-                stackRet = OC_STACK_OK;
-                OC_LOG_V(INFO, TAG, "OCStack payload: %s",
-                        jsonPayload);
-
-                // send notifications based on the qos of the request
-                // The qos passed as a parameter overrides what the client requested
-                // If we want the client preference taking high priority add:
-                // qos = resourceObserver->qos;
-                if(qos == OC_NA_QOS){
-                    qos = resourceObserver->qos;
-                }
-                if(qos != OC_HIGH_QOS)
+                qos = DetermineObserverQoS(OC_REST_GET, observation, qos);
+
+                result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+                        0, resource->sequenceNum, qos, observation->query,
+                        NULL, NULL, &observation->token,
+                        observation->addr, observation->resUri, 0);
+                request->observeResult = OC_STACK_OK;
+                if(request && result == OC_STACK_OK)
                 {
-                    OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
-                            resourceObserver->lowQosCount);
-                    #ifdef WITH_PRESENCE
-                    if((resourceObserver->forceHighQos \
-                            || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
-                            && method != OC_REST_PRESENCE)
-                    #else
-                    if(resourceObserver->forceCON \
-                            || resourceObserver->NONCount >= MAX_OBSERVER_NON_COUNT)
-                    #endif
+                    memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+                    ehResponse.ehResult = OC_EH_OK;
+                    ehResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+                    if(!ehResponse.payload)
                     {
-                        resourceObserver->lowQosCount = 0;
-                        // at some point we have to to send CON to check on the
-                        // availability of observer
-                        OC_LOG(INFO, TAG, PCF("This time we are sending the \
-                                notification as High qos"));
-                        qos = OC_HIGH_QOS;
+                        FindAndDeleteServerRequest(request);
+                        continue;
                     }
-                    else
+                    strcpy((char *)ehResponse.payload, (const char *)notificationJSONPayload);
+                    ehResponse.payloadSize = strlen((const char *)ehResponse.payload) + 1;
+                    ehResponse.persistentBufferFlag = 0;
+                    ehResponse.requestHandle = (OCRequestHandle) request;
+                    ehResponse.resourceHandle = (OCResourceHandle) resource;
+                    result = OCDoResponse(&ehResponse);
+                    if(result == OC_STACK_OK)
                     {
-                        resourceObserver->lowQosCount++;
+                        OCFree(ehResponse.payload);
+                        FindAndDeleteServerRequest(request);
                     }
                 }
-                stackRet = OCSendCoAPNotification(resourceObserver->resUri, resourceObserver->addr,
-                        qos, &(resourceObserver->token), jsonPayload, resPtr, maxAge);
-            }
-            else
-            {
-                stackRet = OC_STACK_ERROR;
+                else
+                {
+                    FindAndDeleteServerRequest(request);
+                }
+
+                numSentNotification++;
             }
         }
-        resourceObserver = resourceObserver->next;
+        obsIdList++;
+        numIds--;
     }
-    if (numObs == 0)
+    if(numSentNotification == numberOfIds)
     {
-        OC_LOG(INFO, TAG, PCF("Resource has no observers"));
-        stackRet = OC_STACK_NO_OBSERVERS;
+        return OC_STACK_OK;
+    }
+    else if(numSentNotification == 0)
+    {
+        return OC_STACK_NO_OBSERVERS;
+    }
+    else
+    {
+        //TODO: we need to signal that not every one in the
+        // list got an update, should we also indicate who did not receive on?
+        return OC_STACK_OK;
     }
-    return stackRet;
 }
 
 OCStackResult GenerateObserverId (OCObservationId *observationId)
 {
-    OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
+    ResourceObserver *resObs = NULL;
 
+    OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
     VERIFY_NON_NULL (observationId);
-    *observationId = OCGetRandomByte();
-    return OC_STACK_OK;
 
+    do
+    {
+        *observationId = OCGetRandomByte();
+        // Check if observation Id already exists
+        resObs = GetObserverUsingId (*observationId);
+    } while (NULL != resObs);
+
+    OC_LOG_V(INFO, TAG, "Observation ID is %u", *observationId);
+
+    return OC_STACK_OK;
 exit:
     return OC_STACK_ERROR;
 }
@@ -366,10 +284,9 @@ OCStackResult AddObserver (const char         *resUri,
 {
     ResourceObserver *obsNode = NULL;
 
-    obsNode = (ResourceObserver *) OCMalloc(sizeof(ResourceObserver));
+    obsNode = (ResourceObserver *) OCCalloc(1, sizeof(ResourceObserver));
     if (obsNode)
     {
-        memset(obsNode, 0, sizeof(ResourceObserver));
         obsNode->observeId = obsId;
 
         obsNode->resUri = (unsigned char *)OCMalloc(strlen(resUri)+1);
@@ -385,7 +302,7 @@ OCStackResult AddObserver (const char         *resUri,
         }
 
         obsNode->token.tokenLength = token->tokenLength;
-        memcpy (&(obsNode->token.token), token->token, token->tokenLength);
+        memcpy (obsNode->token.token, token->token, token->tokenLength);
 
         obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr));
         VERIFY_NON_NULL (obsNode->addr);
index c9ed805..01abbc1 100644 (file)
@@ -22,7 +22,7 @@
 #include "ocstack.h"
 #include "ocstackconfig.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "ocobserve.h"
 #include "occollection.h"
 #include "occoap.h"
@@ -32,6 +32,9 @@
 
 /// Module Name
 #define TAG PCF("ocresource")
+#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+            {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
+
 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
              TAG, PCF(#arg " is NULL")); return (retVal); } }
 
@@ -182,6 +185,7 @@ OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filt
         }
     }
     jsonStr = cJSON_PrintUnformatted (resObj);
+
     jsonLen = strlen(jsonStr);
     if (jsonLen < *remaining)
     {
@@ -195,39 +199,10 @@ OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filt
     cJSON_Delete (resObj);
     free (jsonStr);
 
-
     OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
     return ret;
 }
 
-OCEntityHandlerResult
-BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest)
-{
-    OCEntityHandlerResult ret = OC_EH_ERROR;
-    unsigned char* saveJSONPayLoadPtr = ehRequest->resJSONPayload;
-
-    if (ehRequest->resJSONPayloadLen > OC_JSON_PREFIX_LEN)
-    {
-        strcpy((char*)ehRequest->resJSONPayload, OC_JSON_PREFIX);
-        ehRequest->resJSONPayloadLen -= OC_JSON_PREFIX_LEN;
-        ehRequest->resJSONPayload += OC_JSON_PREFIX_LEN;
-    }
-
-    ret = resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
-
-    ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
-            strlen((char*)ehRequest->resJSONPayload);
-    ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
-
-    if (ehRequest->resJSONPayloadLen > OC_JSON_SUFFIX_LEN)
-    {
-        strcpy((char*)ehRequest->resJSONPayload, OC_JSON_SUFFIX);
-    }
-    ehRequest->resJSONPayload = saveJSONPayLoadPtr;
-    return ret;
-}
-
-
 TODO ("Does it make sense to make this method as inline")
 const char * GetVirtualResourceUri( OCVirtualResources resource)
 {
@@ -277,7 +252,7 @@ OCResource *FindResourceByUri(const char* resourceUri)
 }
 
 
-OCStackResult DetermineResourceHandling (OCRequest *request,
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
                                          ResourceHandling *handling,
                                          OCResource **resource)
 {
@@ -312,11 +287,12 @@ OCStackResult DetermineResourceHandling (OCRequest *request,
 
             // Resource does not exist
             // and default device handler does not exist
+            *handling = OC_RESOURCE_NOT_SPECIFIED;
             return OC_STACK_NO_RESOURCE;
         }
 
         // secure resource will entertain only authorized requests
-        if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secure == 0))
+        if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0))
         {
             OC_LOG(INFO, TAG, PCF("Un-authorized request. Ignore it!"));
             return OC_STACK_RESOURCE_ERROR;
@@ -356,6 +332,9 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
         case OC_EH_OK:
             result = OC_STACK_OK;
             break;
+        case OC_EH_SLOW:
+            result = OC_STACK_SLOW_RESOURCE;
+            break;
         case OC_EH_ERROR:
             result = OC_STACK_ERROR;
             break;
@@ -366,7 +345,7 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
             result = OC_STACK_RESOURCE_CREATED;
             break;
         case OC_EH_RESOURCE_DELETED:
-            result = OC_STACK_NO_RESOURCE;
+            result = OC_STACK_RESOURCE_DELETED;
             break;
         default:
             result = OC_STACK_ERROR;
@@ -376,26 +355,29 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
 }
 
 static OCStackResult
-HandleVirtualResource (OCRequest *request, OCResource* resource)
+HandleVirtualResource (OCServerRequest *request, OCResource* resource)
 {
     OCStackResult result = OC_STACK_ERROR;
     char *filterValue = NULL;
     uint8_t filterOn = 0;
     uint16_t remaining = 0;
-    unsigned char *buffer = NULL;
+    unsigned char * ptr = NULL;
+    uint8_t firstLoopDone = 0;
+    unsigned char discoveryResBuf[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
 
     result = ValidateUrlQuery (request->resourceUrl,
-            request->entityHandlerRequest->query, &filterOn,
+            request->query, &filterOn,
             &filterValue);
 
     if (result == OC_STACK_OK)
     {
         if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
         {
-            remaining = request->entityHandlerRequest->resJSONPayloadLen;
-            buffer = request->entityHandlerRequest->resJSONPayload;
+            ptr = discoveryResBuf;
+            remaining = MAX_RESPONSE_LENGTH;
+
             while(resource)
             {
                 if((resource->resourceProperties & OC_ACTIVE)
@@ -403,205 +385,260 @@ HandleVirtualResource (OCRequest *request, OCResource* resource)
                 {
                     // if there is data on the buffer, we have already added a response,
                     // so we need to add a comma before we do anything
-                    if(buffer != request->entityHandlerRequest->resJSONPayload
-                        && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
+                    if(firstLoopDone
+                            && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
                     {
-                        *buffer = OC_JSON_SEPARATOR;
-                        buffer++;
+                        *ptr = OC_JSON_SEPARATOR;
+                        ptr++;
                         remaining--;
                     }
-
+                    firstLoopDone = 1;
                     result = BuildVirtualResourceResponse(resource, filterOn, filterValue,
-                            (char*)buffer, &remaining);
+                            (char*)ptr, &remaining);
+
                     if (result != OC_STACK_OK)
                     {
                         // if this failed, we need to remove the comma added above.
-                        if(buffer != request->entityHandlerRequest->resJSONPayload)
+                        if(!firstLoopDone)
                         {
-                            buffer--;
-                            *buffer = '\0';
+                            ptr--;
+                            *ptr = '\0';
                             remaining++;
                         }
-
                         break;
                     }
-                    buffer += strlen((char*)buffer);
+                    ptr += strlen((char *)ptr);
+                    *(ptr + 1) = '\0';
                 }
                 resource = resource->next;
             }
+
+            if(strlen((const char *)discoveryResBuf) > 0)
+            {
+                OCEntityHandlerResponse response = {0};
+
+                response.ehResult = OC_EH_OK;
+                response.payload = discoveryResBuf;
+                response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
+                response.persistentBufferFlag = 0;
+                response.requestHandle = (OCRequestHandle) request;
+                response.resourceHandle = (OCResourceHandle) resource;
+
+                result = OCDoResponse(&response);
+            }
         }
         #ifdef WITH_PRESENCE
         else
         {
             if(resource->resourceProperties & OC_ACTIVE){
-                SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+                SendPresenceNotification(NULL);
             }
-            result = OC_STACK_PRESENCE_DO_NOT_HANDLE;
         }
         #endif
     }
-
-    if (result == OC_STACK_OK)
-    {
-        request->entityHandlerRequest->resJSONPayloadLen = remaining;
-        request->entityHandlerRequest->resJSONPayload = buffer;
-    }
-
+    result = OC_STACK_VIRTUAL_DO_NOT_HANDLE;
     return result;
 }
 
 static OCStackResult
-HandleDefaultDeviceEntityHandler (OCRequest *request)
+HandleDefaultDeviceEntityHandler (OCServerRequest *request)
 {
     OCStackResult result = OC_STACK_OK;
-    OCEntityHandlerResult ehResult;
-    OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerRequest ehRequest = {0};
+
+    OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
+    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+            request->method, (OCResourceHandle) NULL, request->query,
+            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->rcvdVendorSpecificHeaderOptions, (OCObserveAction)request->observationOption, (OCObservationId)0);
+    VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // At this point we know for sure that defaultDeviceHandler exists
-    ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, ehRequest,
+    ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
                                   (char*) request->resourceUrl);
-
+    if(ehResult == OC_EH_SLOW)
+    {
+        OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+        request->slowFlag = 1;
+    }
+    else if(ehResult == OC_EH_ERROR)
+    {
+        FindAndDeleteServerRequest(request);
+    }
     result = EntityHandlerCodeToOCStackCode(ehResult);
-
-    ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
-                                    strlen((char*)ehRequest->resJSONPayload);
-    ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
-
+exit:
     return result;
 }
 
 static OCStackResult
-HandleResourceWithEntityHandler (OCRequest *request,
+HandleResourceWithEntityHandler (OCServerRequest *request,
                                  OCResource *resource,
                                  uint8_t collectionResource)
 {
-    OCStackResult result = OC_STACK_OK;
-    OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
+    ResourceObserver *resObs = NULL;
 
-    OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+    OCEntityHandlerRequest ehRequest = {0};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
-
-    ehRequest->resource = (OCResourceHandle)resource;
-
-    // status code from entity handler is ignored unless observe call
-    if (request->observe == NULL)
+    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+            request->method, (OCResourceHandle) resource, request->query,
+            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->rcvdVendorSpecificHeaderOptions,
+            (OCObserveAction)request->observationOption, 0);
+    VERIFY_SUCCESS(result, OC_STACK_OK);
+
+    if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
     {
-        ehResult = resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
-        result = EntityHandlerCodeToOCStackCode(ehResult);
+        OC_LOG(INFO, TAG, PCF("No observation requested"));
+        ehFlag = OC_REQUEST_FLAG;
     }
-    else
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
+            !collectionResource)
     {
-        // If an observation register/deregister is included handle separately
-        if (!collectionResource)
+        OC_LOG(INFO, TAG, PCF("Registering observation requested"));
+        result = GenerateObserverId(&ehRequest.obsInfo.obsId);
+        VERIFY_SUCCESS(result, OC_STACK_OK);
+
+        result = AddObserver ((const char*)(request->resourceUrl),
+                (const char *)(request->query),
+                ehRequest.obsInfo.obsId, &request->requestToken,
+                &request->requesterAddr, resource, request->qos);
+        if(result == OC_STACK_OK)
         {
-            result = ProcessObserveRequest (resource, request);
+            OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+            request->observeResult = OC_STACK_OK;
+            ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
         }
         else
         {
-            // Observation on collection resources not currently supported
-            result = OC_STACK_ERROR;
+            result = OC_STACK_OK;
+            request->observeResult = OC_STACK_ERROR;
+            OC_LOG(DEBUG, TAG, PCF("Observer Addition failed"));
+            ehFlag = OC_REQUEST_FLAG;
         }
+
     }
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
+            !collectionResource)
+    {
+        OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
+        resObs = GetObserverUsingToken (&request->requestToken);
+        if (NULL == resObs)
+        {
+            // Stack does not contain this observation request
+            // Either token is incorrect or observation list is corrupted
+            result = OC_STACK_ERROR;
+            goto exit;
+        }
+        ehRequest.obsInfo.obsId = resObs->observeId;
+        ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
 
-    if (result == OC_STACK_OK || OC_STACK_RESOURCE_CREATED)
+        result = DeleteObserverUsingToken (&request->requestToken);
+        if(result == OC_STACK_OK)
+        {
+            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+            request->observeResult = OC_STACK_OK;
+        }
+        else
+        {
+            result = OC_STACK_OK;
+            request->observeResult = OC_STACK_ERROR;
+            OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+        }
+    }
+    else
     {
-        ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
-            strlen((char*)ehRequest->resJSONPayload);
-        ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
+        result = OC_STACK_ERROR;
+        goto exit;
     }
 
+    ehResult = resource->entityHandler(ehFlag, &ehRequest);
+    if(ehResult == OC_EH_SLOW)
+    {
+        OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+        request->slowFlag = 1;
+    }
+    else if(ehResult == OC_EH_ERROR)
+    {
+        FindAndDeleteServerRequest(request);
+    }
+    result = EntityHandlerCodeToOCStackCode(ehResult);
+exit:
     return result;
 }
 
-
 static OCStackResult
-HandleCollectionResourceDefaultEntityHandler (OCRequest *request,
+HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
                                               OCResource *resource)
 {
-    request->entityHandlerRequest->resource = (OCResourceHandle)resource;
-    return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, request->entityHandlerRequest));
-}
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerRequest ehRequest = {0};
+
+    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+            request->method, (OCResourceHandle) resource, request->query,
+            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->rcvdVendorSpecificHeaderOptions,
+            (OCObserveAction)request->observationOption, (OCObservationId) 0);
+    if(result != OC_STACK_OK)
+    {
+        return result;
+    }
 
+    return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
+}
 
 OCStackResult
-BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request)
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
 {
     OCStackResult ret = OC_STACK_OK;
 
-    // save the response payload pointer, this pointer will be moved as
-    // different entity handlers will be called
-    unsigned char* saveJSONPayLoadPtr = request->entityHandlerRequest->resJSONPayload;
-    unsigned char* buffer = saveJSONPayLoadPtr;
-    uint16_t remaining = request->entityHandlerRequest->resJSONPayloadLen;
-
-    // add suffix in payload
-    if (remaining > OC_JSON_PREFIX_LEN)
-    {
-        strcpy((char*)buffer, OC_JSON_PREFIX);
-        remaining -= OC_JSON_PREFIX_LEN;
-        buffer += OC_JSON_PREFIX_LEN;
-    }
-
-    // move the entity handler payload pointer and update
-    // remaining valid bytes to fill data
-    request->entityHandlerRequest->resJSONPayload = buffer;
-    request->entityHandlerRequest->resJSONPayloadLen = remaining;
-
     switch (resHandling)
     {
         case OC_RESOURCE_VIRTUAL:
-            {
-                ret = HandleVirtualResource (request, resource);
-                break;
-            }
-
+        {
+            ret = HandleVirtualResource (request, resource);
+            break;
+        }
         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
-            {
-                ret = HandleDefaultDeviceEntityHandler(request);
-                break;
-            }
+        {
+            ret = HandleDefaultDeviceEntityHandler(request);
+            break;
+        }
         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
-            {
-                OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
-                return OC_STACK_ERROR;
-            }
-
+        {
+            OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
+            return OC_STACK_ERROR;
+        }
         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
-            {
-                ret = HandleResourceWithEntityHandler (request, resource, 0);
-                break;
-            }
+        {
+            ret = HandleResourceWithEntityHandler (request, resource, 0);
+            break;
+        }
         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
-            {
-                ret = HandleResourceWithEntityHandler (request, resource, 1);
-                break;
-            }
-
+        {
+            ret = HandleResourceWithEntityHandler (request, resource, 1);
+            break;
+        }
         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
-            {
-                ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
-                break;
-            }
-
+        {
+            ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
+            break;
+        }
+        case OC_RESOURCE_NOT_SPECIFIED:
+        {
+            ret = OC_STACK_NO_RESOURCE;
+            break;
+        }
         default:
-            {
-                OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
-                return OC_STACK_ERROR;
-            }
-    }
-
-    remaining = request->entityHandlerRequest->resJSONPayloadLen;
-
-    if (remaining > OC_JSON_SUFFIX_LEN)
-    {
-        strcpy((char*)request->entityHandlerRequest->resJSONPayload, OC_JSON_SUFFIX);
+        {
+            OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
+            return OC_STACK_ERROR;
+        }
     }
-
-    // update payload pointer with it's original location and original length
-    request->entityHandlerRequest->resJSONPayload = saveJSONPayLoadPtr;
-    request->entityHandlerRequest->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
-
     return ret;
 }
 
diff --git a/resource/csdk/stack/src/ocsecurity.c b/resource/csdk/stack/src/ocsecurity.c
new file mode 100644 (file)
index 0000000..0dd7aae
--- /dev/null
@@ -0,0 +1,86 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 "ocstack.h"
+#include "ocmalloc.h"
+#include "ocsecurity.h"
+#include "ocsecurityconfig.h"
+#include <string.h>
+
+static OCDtlsPskCredsBlob* pskCredsBlob;
+static int pskCredsBlobLen;
+
+// Internal API. Invoked by OC stack to cleanup memory
+void DeinitOCSecurityInfo()
+{
+    if (pskCredsBlob)
+    {
+        // Initialize sensitive data to zeroes before freeing.
+        memset(pskCredsBlob, 0, pskCredsBlobLen);
+
+        OCFree(pskCredsBlob);
+        pskCredsBlob = NULL;
+    }
+}
+
+// Internal API. Invoked by OC stack to retrieve credentials from this module
+void OCGetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo)
+{
+    *credInfo = pskCredsBlob;
+}
+
+/**
+ * Provides the DTLS PSK credetials blob to OC stack.
+ *
+ * @param credInfo
+ *     binary blob containing credentials
+ * @param len
+ *     length of binary blob
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo,
+                size_t len)
+{
+    if(credInfo && len > 0)
+    {
+        if (credInfo->blobVer != DtlsPskCredsBlobVer_CurrentVersion)
+        {
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        // Remove existing blob
+        DeinitOCSecurityInfo();
+        // Allocate storage for new blob
+        pskCredsBlob = (OCDtlsPskCredsBlob*)OCMalloc(len);
+        if (pskCredsBlob)
+        {
+            memcpy(pskCredsBlob, credInfo, len);
+            pskCredsBlobLen = len;
+            return OC_STACK_OK;
+        }
+
+        return OC_STACK_NO_MEMORY;
+    }
+
+    return OC_STACK_INVALID_PARAM;
+}
+
+
diff --git a/resource/csdk/stack/src/ocserverrequest.c b/resource/csdk/stack/src/ocserverrequest.c
new file mode 100644 (file)
index 0000000..99dbe1f
--- /dev/null
@@ -0,0 +1,379 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 "ocstack.h"
+#include "ocserverrequest.h"
+#include "ocresourcehandler.h"
+
+// Module Name
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
+
+#define TAG  PCF("ocserverrequest")
+
+static struct OCServerRequest * serverRequestList = NULL;
+static struct OCServerResponse * serverResponseList = NULL;
+
+OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token)
+{
+    OCServerRequest * out = NULL;
+    LL_FOREACH (serverRequestList, out)
+    {
+        OC_LOG(INFO, TAG,PCF("comparing tokens"));
+        OC_LOG_BUFFER(INFO, TAG, token.token, token.tokenLength);
+        OC_LOG_BUFFER(INFO, TAG, out->requestToken.token, out->requestToken.tokenLength);
+        if((out->requestToken.tokenLength == token.tokenLength) &&
+                (memcmp(out->requestToken.token, token.token, token.tokenLength) == 0))
+        {
+            return out;
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+    return NULL;
+}
+
+OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle)
+{
+    OCServerRequest * out = NULL;
+    LL_FOREACH (serverRequestList, out)
+    {
+        if(out == handle)
+        {
+            return out;
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+    return NULL;
+}
+
+OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
+{
+    OCServerResponse * out = NULL;
+    LL_FOREACH (serverResponseList, out)
+    {
+        if(out->requestHandle == handle)
+        {
+            return out;
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("Server Response not found!!"));
+    return NULL;
+}
+
+OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
+        uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
+        uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
+        OCQualityOfService qos, unsigned char * query,
+        OCHeaderOption * rcvdVendorSpecificHeaderOptions,
+        unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
+        OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize)
+{
+    OCServerRequest * serverRequest = NULL;
+
+    serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1);
+    VERIFY_NON_NULL(serverRequest);
+
+    serverRequest->coapID = coapID;
+    serverRequest->delayedResNeeded = delayedResNeeded;
+    serverRequest->secured = secured;
+    serverRequest->notificationFlag = notificationFlag;
+
+    serverRequest->method = method;
+    serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions;
+    serverRequest->observationOption = observationOption;
+    serverRequest->observeResult = OC_STACK_ERROR;
+    serverRequest->qos = qos;
+    serverRequest->ehResponseHandler = HandleSingleResponse;
+    serverRequest->numResponses = 1;
+    if(query)
+    {
+        memcpy(serverRequest->query, query, strlen((const char *)query) + 1);
+    }
+    if(rcvdVendorSpecificHeaderOptions)
+    {
+        memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
+            MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
+    }
+    if(reqJSONPayload)
+    {
+        memcpy((void *)serverRequest->reqJSONPayload, (void *)reqJSONPayload,
+            strlen((const char *)reqJSONPayload) + 1);
+    }
+    serverRequest->requestComplete = 0;
+    if(requestToken)
+    {
+        memcpy(&serverRequest->requestToken, requestToken, sizeof(OCCoAPToken));
+    }
+    if(requesterAddr)
+    {
+        memcpy(&serverRequest->requesterAddr, requesterAddr, sizeof(OCDevAddr));
+    }
+    if(resourceUrl)
+    {
+        memcpy(serverRequest->resourceUrl, resourceUrl, strlen((const char *)resourceUrl) + 1);
+    }
+    *request = serverRequest;
+    OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
+    LL_APPEND (serverRequestList, serverRequest);
+    return OC_STACK_OK;
+
+exit:
+    if (serverRequest)
+    {
+        OCFree(serverRequest);
+        serverRequest = NULL;
+    }
+    *request = NULL;
+    return OC_STACK_NO_MEMORY;
+}
+
+OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
+{
+    OCServerResponse * serverResponse = NULL;
+
+    serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
+    VERIFY_NON_NULL(serverResponse);
+
+    serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+    VERIFY_NON_NULL(serverResponse->payload);
+    memset(serverResponse->payload, 0, sizeof(MAX_RESPONSE_LENGTH));
+
+    serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
+    serverResponse->requestHandle = requestHandle;
+
+    *response = serverResponse;
+    OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
+    LL_APPEND (serverResponseList, serverResponse);
+    return OC_STACK_OK;
+
+exit:
+    if (serverResponse)
+    {
+        OCFree(serverResponse);
+        serverResponse = NULL;
+    }
+    *response = NULL;
+    return OC_STACK_NO_MEMORY;
+}
+
+// Form the OCEntityHandlerRequest struct
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
+        OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
+        uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+        OCObservationId observeID)
+{
+    if (entityHandlerRequest)
+    {
+        memset(entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
+        entityHandlerRequest->requestHandle = request;
+        entityHandlerRequest->method = method;
+        entityHandlerRequest->resource = (OCResourceHandle) resource;
+        entityHandlerRequest->query = queryBuf;
+        entityHandlerRequest->reqJSONPayload = bufReqPayload;
+        entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
+        entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
+
+        entityHandlerRequest->obsInfo.action = observeAction;
+        entityHandlerRequest->obsInfo.obsId = observeID;
+        return OC_STACK_OK;
+    }
+
+    return OC_STACK_INVALID_PARAM;
+}
+
+void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
+{
+    OCServerResponse* tmp;
+    if(serverResponse)
+    {
+        LL_FOREACH(serverResponseList, tmp)
+        {
+            if (serverResponse == tmp)
+            {
+                DeleteServerResponse(tmp);
+                return;
+            }
+        }
+    }
+}
+
+void DeleteServerResponse(OCServerResponse * serverResponse)
+{
+    if(serverResponse) {
+        LL_DELETE(serverResponseList, serverResponse);
+        OCFree(serverResponse->payload);
+        OCFree(serverResponse);
+        OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
+    }
+}
+
+void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
+{
+    OCServerRequest* tmp;
+    if(serverRequest)
+    {
+        LL_FOREACH(serverRequestList, tmp)
+        {
+            if (serverRequest == tmp)
+            {
+                DeleteServerRequest(tmp);
+                return;
+            }
+        }
+    }
+}
+
+void DeleteServerRequest(OCServerRequest * serverRequest)
+{
+    if(serverRequest) {
+        LL_DELETE(serverRequestList, serverRequest);
+        OCFree(serverRequest);
+        serverRequest = NULL;
+        OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+    }
+}
+
+OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCServerProtocolResponse protocolResponse = {0};
+
+    OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
+
+    OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
+    // Format protocol response structure with data needed for
+    // sending the response
+    protocolResponse.qos = serverRequest->qos;
+
+    if((OCResource *)ehResponse->resourceHandle &&
+            ((OCResource *)ehResponse->resourceHandle)->resourceProperties == (OCResourceProperty) 0)
+    {
+        ehResponse->ehResult = OC_EH_RESOURCE_DELETED;
+    }
+    protocolResponse.result = EntityHandlerCodeToOCStackCode(ehResponse->ehResult);
+    protocolResponse.requesterAddr = &serverRequest->requesterAddr;
+    protocolResponse.requestToken = &serverRequest->requestToken;
+    protocolResponse.numSendVendorSpecificHeaderOptions = ehResponse->numSendVendorSpecificHeaderOptions;
+    protocolResponse.sendVendorSpecificHeaderOptions = ehResponse->sendVendorSpecificHeaderOptions;
+    protocolResponse.resourceUri = ehResponse->resourceUri;
+    protocolResponse.delayedResNeeded = serverRequest->delayedResNeeded;
+    protocolResponse.secured = serverRequest->secured;
+    protocolResponse.slowFlag = serverRequest->slowFlag;
+    protocolResponse.notificationFlag = serverRequest->notificationFlag;
+
+    //should we put the prefix and suffix here?
+    protocolResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+    if(!protocolResponse.payload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+    strcpy((char *)protocolResponse.payload, (const char *)OC_JSON_PREFIX);
+    strcat((char *)protocolResponse.payload, (const char *)ehResponse->payload);
+    strcat((char *)protocolResponse.payload, (const char *)OC_JSON_SUFFIX);
+    protocolResponse.payloadSize = strlen((const char *)protocolResponse.payload) + 1;
+    protocolResponse.resourceUri = ehResponse->resourceUri;
+
+    //revise the following
+    protocolResponse.coapID = serverRequest->coapID;
+    if(serverRequest->observeResult == OC_STACK_OK)
+    {
+        protocolResponse.observationOption = serverRequest->observationOption;
+    }
+    else
+    {
+        protocolResponse.observationOption = OC_OBSERVE_NO_OPTION;
+    }
+    // Make call to OCCoAP layer
+    result = OCDoCoAPResponse(&protocolResponse);
+
+    OCFree(protocolResponse.payload);
+    //Delete the request
+    FindAndDeleteServerRequest(serverRequest);
+    return result;
+}
+
+OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
+{
+    OCStackResult stackRet = OC_STACK_ERROR;
+    OCServerRequest * serverRequest = NULL;
+    OCServerResponse * serverResponse = NULL;
+
+    OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload);
+
+    serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+    serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+
+    if(serverRequest)
+    {
+        if(!serverResponse)
+        {
+            OC_LOG(INFO, TAG, PCF("This is the first response fragment"));
+            stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
+            if (OC_STACK_OK != stackRet)
+            {
+                OC_LOG(ERROR, TAG, PCF("Error adding server response"));
+                return stackRet;
+            }
+            VERIFY_NON_NULL(serverResponse);
+            VERIFY_NON_NULL(serverResponse->payload);
+        }
+
+        if((serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 1 &&
+                serverRequest->numResponses == 1) ||
+                (serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 2 &&
+                        serverRequest->numResponses > 1))
+        {
+            OC_LOG(INFO, TAG, PCF("There is room in response buffer"));
+            // append
+            sprintf((char *)serverResponse->payload, "%s%s", (char *)serverResponse->payload, (char *)ehResponse->payload);
+            OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
+            serverResponse->remainingPayloadSize -= ehResponse->payloadSize;
+            (serverRequest->numResponses)--;
+            if(serverRequest->numResponses == 0)
+            {
+                OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
+                ehResponse->payload = serverResponse->payload;
+                ehResponse->payloadSize = strlen((char *) serverResponse->payload) + 1;
+                stackRet = HandleSingleResponse(ehResponse);
+                //Delete the request and response
+                FindAndDeleteServerRequest(serverRequest);
+                FindAndDeleteServerResponse(serverResponse);
+            }
+            else
+            {
+                OC_LOG(INFO, TAG, PCF("More response fragment to come"));
+                // TODO: we should consider using strcat rather than setting a char by char here!
+                sprintf((char *)serverResponse->payload, "%s%c", (char *)serverResponse->payload,OC_JSON_SEPARATOR);
+                OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
+                (serverResponse->remainingPayloadSize)--;
+                stackRet = OC_STACK_OK;
+            }
+        }
+        else
+        {
+            OC_LOG(INFO, TAG, PCF("No room in response buffer"));
+            //Delete the request and response
+            FindAndDeleteServerRequest(serverRequest);
+            FindAndDeleteServerResponse(serverResponse);
+            stackRet = OC_STACK_NO_MEMORY;
+        }
+    }
+exit:
+    return stackRet;
+}
index 8b08345..f09d19f 100644 (file)
 //-----------------------------------------------------------------------------
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "occlientcb.h"
 #include "ocobserve.h"
 #include "ocrandom.h"
 #include "debug.h"
 #include "occoap.h"
 #include "ocmalloc.h"
+#include "ocserverrequest.h"
 
 //-----------------------------------------------------------------------------
 // Typedefs
 //-----------------------------------------------------------------------------
 typedef enum {
-    OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
+    OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
 } OCStackState;
 
 #ifdef WITH_PRESENCE
@@ -68,12 +69,116 @@ OCDeviceEntityHandler defaultDeviceHandler;
 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
              TAG, PCF(#arg " is NULL")); return (retVal); } }
 
+//TODO: we should allow the server to define this
+#define MAX_OBSERVE_AGE (0x2FFFFUL)
+//-----------------------------------------------------------------------------
+// Externs
+//-----------------------------------------------------------------------------
+extern void DeinitOCSecurityInfo();
+
 //-----------------------------------------------------------------------------
 // Internal API function
 //-----------------------------------------------------------------------------
 
+// This internal function is called to update the stack with the status of
+// observers and communication failures
+OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    ResourceObserver * observer = NULL;
+    OCEntityHandlerRequest ehRequest = {0};
+
+    switch(status)
+    {
+    case OC_OBSERVER_NOT_INTERESTED:
+        OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
+        observer = GetObserverUsingToken (token);
+        if(observer)
+        {
+            result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
+                    OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+                    NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+            if(result != OC_STACK_OK)
+            {
+                return result;
+            }
+            observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
+        }
+        //observer is not observing anymore
+        result = DeleteObserverUsingToken (token);
+        if(result == OC_STACK_OK)
+        {
+            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+        }
+        else
+        {
+            result = OC_STACK_OK;
+            OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+        }
+        break;
+    case OC_OBSERVER_STILL_INTERESTED:
+        //observer is still interested
+        OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
+                notifications, reset the failedCount"));
+        observer = GetObserverUsingToken(token);
+        if(observer)
+        {
+            observer->forceHighQos = 0;
+            observer->failedCommCount = 0;
+            result = OC_STACK_OK;
+        }
+        else
+        {
+            result = OC_STACK_OBSERVER_NOT_FOUND;
+        }
+        break;
+    case OC_OBSERVER_FAILED_COMM:
+        //observer is not reachable
+        OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
+        observer = GetObserverUsingToken(token);
+        if(observer)
+        {
+            if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
+            {
+                result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
+                        OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+                        NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+                if(result != OC_STACK_OK)
+                {
+                    return OC_STACK_ERROR;
+                }
+                observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
+                //observer is unreachable
+                result = DeleteObserverUsingToken (token);
+                if(result == OC_STACK_OK)
+                {
+                    OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+                }
+                else
+                {
+                    result = OC_STACK_OK;
+                    OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+                }
+            }
+            else
+            {
+                observer->failedCommCount++;
+                result = OC_STACK_CONTINUE;
+            }
+            observer->forceHighQos = 1;
+            OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
+        }
+        break;
+    default:
+        OC_LOG(ERROR, TAG, PCF("Unknown status"));
+        result = OC_STACK_ERROR;
+        break;
+        }
+    return result;
+}
+
 //This function will be called back by occoap layer when a request is received
-OCStackResult HandleStackRequests(OCRequest * request)
+OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
 {
     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
 
@@ -81,16 +186,53 @@ OCStackResult HandleStackRequests(OCRequest * request)
     ResourceHandling resHandling;
     OCResource *resource;
 
-    VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
-    VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
-
-    result = DetermineResourceHandling (request, &resHandling, &resource);
+    OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
+    if(!request)
+    {
+        OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
+        result = AddServerRequest(&request, protocolRequest->coapID,
+                protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
+                protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
+                protocolRequest->observationOption, protocolRequest->qos,
+                protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
+                protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
+                &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
+                protocolRequest->reqTotalSize);
+        if (OC_STACK_OK != result)
+        {
+            OC_LOG(ERROR, TAG, PCF("Error adding server request"));
+            return result;
+        }
+        VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
 
-    if (result == OC_STACK_OK)
+        if(!protocolRequest->reqMorePacket)
+        {
+            request->requestComplete = 1;
+        }
+    }
+    else
     {
-        result = BuildJSONResponse(resHandling, resource, request);
+        OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
     }
 
+    if(request->requestComplete)
+    {
+        OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
+        result = DetermineResourceHandling (request, &resHandling, &resource);
+        if (result == OC_STACK_OK)
+        {
+            result = ProcessRequest(resHandling, resource, request);
+        }
+        else
+        {
+            result = OC_STACK_ERROR;
+        }
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
+        result = OC_STACK_CONTINUE;
+    }
     return result;
 }
 
@@ -206,9 +348,9 @@ static void deleteAllResources();
 static void incrementSequenceNumber(OCResource * resPtr);
 static OCStackResult verifyUriQueryLength(const char * inputUri,
         uint16_t uriLen);
+static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
 
-
 //-----------------------------------------------------------------------------
 // Public APIs
 //-----------------------------------------------------------------------------
@@ -291,12 +433,25 @@ OCStackResult OCStop()
 
     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
 
-    if (stackState != OC_STACK_INITIALIZED)
+    if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
+    {
+        OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
+        return OC_STACK_OK;
+    }
+    else if (stackState != OC_STACK_INITIALIZED)
     {
         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
         return OC_STACK_ERROR;
     }
 
+    stackState = OC_STACK_UNINIT_IN_PROGRESS;
+
+    #ifdef WITH_PRESENCE
+    // Ensure that the TTL associated with ANY and ALL presence notifications originating from
+    // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
+    presenceResource.presenceTTL = 0;
+    #endif // WITH_PRESENCE
+
     // Free memory dynamically allocated for resources
     deleteAllResources();
 
@@ -310,9 +465,13 @@ OCStackResult OCStop()
         stackState = OC_STACK_UNINITIALIZED;
         result = OC_STACK_OK;
     } else {
+        stackState = OC_STACK_INITIALIZED;
         result = OC_STACK_ERROR;
     }
 
+    // Deinit security blob
+    DeinitOCSecurityInfo();
+
     if (result != OC_STACK_OK) {
         OC_LOG(ERROR, TAG, PCF("Stack stop error"));
     }
@@ -386,7 +545,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     ClientCB *clientCB = NULL;
     unsigned char * requestUri = NULL;
     unsigned char * resourceType = NULL;
-    char * newURI = (char *)requiredUri;
+    char * newUri = (char *)requiredUri;
     (void) referenceUri;
 
     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
@@ -434,7 +593,14 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
 #ifdef WITH_PRESENCE
     if(method == OC_REST_PRESENCE)
     {
-        result = getResourceType(requiredUri, &resourceType, &newURI);
+        result = getResourceType(requiredUri, &resourceType, &newUri);
+        if(resourceType) {
+            OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+        }
+        else
+        {
+            OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+        }
         if(result != OC_STACK_OK)
         {
             goto exit;
@@ -445,7 +611,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
     if(requestUri)
     {
-        memcpy(requestUri, newURI, (uriLen + 1));
+        memcpy(requestUri, newUri, (uriLen + 1));
     }
     else
     {
@@ -464,7 +630,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     // with the request
     OCGenerateCoAPToken(&token);
 
-    if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri, resourceType))
+    if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
             != OC_STACK_OK)
     {
         result = OC_STACK_NO_MEMORY;
@@ -472,12 +638,12 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     }
 
     // Make call to OCCoAP layer
-    result = OCDoCoAPResource(method, qos, &token, newURI, request, options, numOptions);
+    result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
 
 exit:
-    if(newURI != requiredUri)
+    if(newUri != requiredUri)
     {
-        OCFree(newURI);
+        OCFree(newUri);
     }
     if (result != OC_STACK_OK)
     {
@@ -709,7 +875,7 @@ OCStackResult OCStartPresence(const uint32_t ttl)
     // a different random 32-bit integer number is used
     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
 
-    return SendPresenceNotification(NULL, OC_LOW_QOS);
+    return SendPresenceNotification(NULL);
 }
 
 /**
@@ -730,7 +896,7 @@ OCStackResult OCStopPresence()
     result = OCChangeResourceProperty(
             &(((OCResource *) presenceResource.handle)->resourceProperties),
             OC_ACTIVE, 0);
-    result = SendPresenceNotification(NULL, OC_LOW_QOS);
+    result = SendPresenceNotification(NULL);
 
     return result;
 }
@@ -808,11 +974,10 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
         }
     }
     // Create the pointer and insert it into the resource list
-    pointer = (OCResource *) OCMalloc(sizeof(OCResource));
+    pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResource));
     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
 
     insertResource(pointer);
@@ -862,7 +1027,7 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(pointer->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(pointer->rsrcType);
     }
     #endif
 exit:
@@ -975,7 +1140,7 @@ OCStackResult OCBindResource(
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
     }
     #endif
 
@@ -1033,7 +1198,7 @@ OCStackResult OCUnBindResource(
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
     }
     #endif
 
@@ -1059,11 +1224,10 @@ OCStackResult BindResourceTypeToResource(OCResource* resource,
     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
 
     // Create the resourcetype and insert it into the resource list
-    pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+    pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResourceType));
 
     // Set the resourceTypeName
     size = strlen(resourceTypeName) + 1;
@@ -1101,11 +1265,10 @@ OCStackResult BindResourceInterfaceToResource(OCResource* resource,
     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
 
     // Create the resourceinterface and insert it into the resource list
-    pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
+    pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResourceInterface));
 
     // Set the resourceinterface name
     size = strlen(resourceInterfaceName) + 1;
@@ -1159,7 +1322,7 @@ OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(resource->rsrcType);
     }
     #endif
 
@@ -1197,7 +1360,7 @@ OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(resource->rsrcType);
     }
     #endif
 
@@ -1495,7 +1658,7 @@ OCStackResult OCBindResourceHandler(OCResourceHandle handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(resource->rsrcType);
     }
     #endif
 
@@ -1538,6 +1701,7 @@ void incrementSequenceNumber(OCResource * resPtr)
     return;
 }
 
+#ifdef WITH_PRESENCE
 /**
  * Notify Presence subscribers that a resource has been modified
  *
@@ -1546,7 +1710,7 @@ void incrementSequenceNumber(OCResource * resPtr)
  * @param qos          - Quality Of Service
  *
  */
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos)
+OCStackResult SendPresenceNotification(OCResourceType *resourceType)
 {
     OCResource *resPtr = NULL;
     OCStackResult result;
@@ -1566,10 +1730,10 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOf
         maxAge = 0;
     }
 
-    result = SendObserverNotification(method, resPtr, maxAge, resourceType, qos);
-
+    result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
     return result;
 }
+#endif
 
 /**
  * Notify observers that an observed value has changed.
@@ -1582,13 +1746,21 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOf
  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
  */
 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
+
+    OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
+
     OCResource *resPtr = NULL;
     OCStackResult result;
     OCMethod method = OC_REST_NOMETHOD;
     uint32_t maxAge = 0;
 
     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
-
+    #ifdef WITH_PRESENCE
+    if(handle == presenceResource.handle)
+    {
+        return OC_STACK_OK;
+    }
+    #endif // WITH_PRESENCE
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
 
     // Verify that the resource exists
@@ -1602,8 +1774,12 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
         //only increment in the case of regular observing (not presence)
         incrementSequenceNumber(resPtr);
         method = OC_REST_OBSERVE;
-        maxAge = 0x2FFFF;
-        result = SendObserverNotification (method, resPtr, maxAge, NULL, qos);
+        maxAge = MAX_OBSERVE_AGE;
+        #ifdef WITH_PRESENCE
+        result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
+        #else
+        result = SendAllObserverNotification (method, resPtr, maxAge, qos);
+        #endif
         return result;
     }
 }
@@ -1617,27 +1793,14 @@ OCNotifyListOfObservers (OCResourceHandle handle,
 {
     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
 
+    OCResource *resPtr = NULL;
+    //TODO: we should allow the server to define this
+    uint32_t maxAge = MAX_OBSERVE_AGE;
+
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
 
-    uint8_t numIds = numberOfIds;
-    ResourceObserver *observation;
-    OCResource *resPtr = NULL;
-    uint32_t maxAge = 0;
-    unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
-    unsigned char *currPtr;
-    uint8_t numSentNotification = 0;
-
-    // Verify the notification payload length does not exceed the maximim
-    // the stack can handle
-    if ((strlen((char *)notificationJSONPayload) +
-         OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
-    {
-        OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
-        return OC_STACK_ERROR;
-    }
-
     // Verify that the resource exists
     resPtr = findResource ((OCResource *) handle);
     if (NULL == resPtr || myStackMode == OC_CLIENT)
@@ -1647,75 +1810,88 @@ OCNotifyListOfObservers (OCResourceHandle handle,
     else
     {
         incrementSequenceNumber(resPtr);
-        //TODO: we should allow the serve to define thisl
-        maxAge = 0x2FFFF;
     }
+    return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
+            notificationJSONPayload, maxAge, qos));
+}
 
-    while (numIds)
+/**
+ * Send a response to a request.
+ * The response can be a regular, slow, or block (i.e. a response that
+ * is too large to be sent in a single PDU and must span multiple transmissions)
+ *
+ * @param response - pointer to structure that contains response parameters
+ *
+ * @return
+ *     OC_STACK_OK                         - No errors; Success
+ *     OC_STACK_INVALID_PARAM              - Invalid pointer to OCServerResponse
+ *     OC_STACK_INVALID_REQUEST_HANDLE     - Request handle not found
+ *     OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
+ *                                           persistent response buffer is necessary
+ */
+OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCServerRequest *serverRequest = NULL;
+
+    OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
+
+    // Validate input parameters
+    VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
+
+    // TODO: Placeholder for creating a response entry when implementing
+    // block transfer feature
+
+    // If a response payload is present, check if block transfer is required
+    if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
+            (const char *)ehResponse->payload, ehResponse->payloadSize))
     {
-        OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
-        observation = NULL;
-        observation = GetObserverUsingId (*obsIdList);
-        if (observation)
+        OC_LOG(INFO, TAG, PCF("Block transfer required"));
+
+        // Persistent response buffer is needed for block transfer
+        if (!ehResponse->persistentBufferFlag)
         {
-            // Found observation - verify if it matches the resource handle
-            if (observation->resource == resPtr)
-            {
-                strcpy((char*)bufNotify, OC_JSON_PREFIX);
-                currPtr = bufNotify + OC_JSON_PREFIX_LEN;
-                memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
-                currPtr += strlen((char *)notificationJSONPayload);
-                strcpy((char*)currPtr, OC_JSON_SUFFIX);
-
-                // send notifications based on the qos of the request
-                // The qos passed as a parameter overrides what the client requested
-                // If we want the client preference taking high priority add:
-                // QoS = resourceObserver->qos;
-                if(qos == OC_NA_QOS){
-                    qos = observation->qos;
-                }
-                if(qos != OC_HIGH_QOS)
-                {
-                    OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
-                            observation->lowQosCount);
-                    if(observation->forceHighQos \
-                            || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
-                    {
-                        observation->lowQosCount = 0;
-                        // at some point we have to to send CON to check on the
-                        // availability of observer
-                        OC_LOG(INFO, TAG, PCF("This time we are sending the \
-                                notification as High qos"));
-                        qos = OC_HIGH_QOS;
-                    }
-                    else
-                    {
-                        observation->lowQosCount++;
-                    }
-                }
-                OCSendCoAPNotification (observation->resUri, observation->addr,
-                                        qos, &(observation->token),
-                                        bufNotify, resPtr, maxAge);
-                numSentNotification++;
-            }
+            OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
+            return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
         }
-        obsIdList++;
-        numIds--;
-    }
-    if(numSentNotification == numberOfIds)
-    {
-        return OC_STACK_OK;
-    }
-    else if(numSentNotification == 0)
-    {
-        return OC_STACK_NO_OBSERVERS;
+        // TODO: Placeholder for block transfer handling
+        // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
+            // when implementing the block transfer feature
     }
     else
     {
-        //TODO: we need to signal that not every one in the
-        // list got an update, should we also indicate who did not receive on?
-        return OC_STACK_OK;
+        // Normal response
+
+        // Get pointer to request info
+        serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+        if(serverRequest)
+        {
+            result = serverRequest->ehResponseHandler(ehResponse);
+        }
     }
+    return result;
+}
+
+/**
+ * Cancel a response.  Applies to a block response
+ *
+ * @param responseHandle - response handle set by stack in OCServerResponse after
+ *                         OCDoResponse is called
+ *
+ * @return
+ *     OC_STACK_OK               - No errors; Success
+ *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
+ */
+OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
+{
+    OCStackResult result = OC_STACK_NOTIMPL;
+
+    OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
+
+    // TODO: validate response handle
+
+    return result;
 }
 
 //-----------------------------------------------------------------------------
@@ -1728,7 +1904,7 @@ static OCDoHandle GenerateInvocationHandle()
 {
     OCDoHandle handle = NULL;
     // Generate token here, it will be deleted when the transaction is deleted
-    handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+    handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
     if (handle)
     {
         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
@@ -1769,7 +1945,7 @@ OCStackResult initResources() {
     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
     //presenceResource.token = OCGenerateCoAPToken();
     result = OCCreateResource(&presenceResource.handle,
-            "core.presence",
+            OC_RSRVD_RESOURCE_TYPE_PRESENCE,
             "core.r",
             OC_PRESENCE_URI,
             NULL,
@@ -1831,9 +2007,22 @@ void deleteAllResources()
     while (pointer)
     {
         temp = pointer->next;
-        deleteResource(pointer);
+        #ifdef WITH_PRESENCE
+        if(pointer != (OCResource *) presenceResource.handle)
+        {
+            #endif // WITH_PRESENCE
+            deleteResource(pointer);
+            #ifdef WITH_PRESENCE
+        }
+        #endif // WITH_PRESENCE
         pointer = temp;
     }
+
+    #ifdef WITH_PRESENCE
+    // Ensure that the last resource to be deleted is the presence resource. This allows for all
+    // presence notification attributed to their deletion to be processed.
+    deleteResource((OCResource *) presenceResource.handle);
+    #endif // WITH_PRESENCE
 }
 
 /**
@@ -1853,15 +2042,27 @@ int deleteResource(OCResource *resource) {
         if (temp == resource) {
             // Invalidate all Resource Properties.
             resource->resourceProperties = (OCResourceProperty) 0;
-            OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
-
             #ifdef WITH_PRESENCE
+            if(resource != (OCResource *) presenceResource.handle)
+            {
+            #endif // WITH_PRESENCE
+                OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
+            #ifdef WITH_PRESENCE
+            }
+
             if(presenceResource.handle)
             {
                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-                SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+                if(resource != (OCResource *) presenceResource.handle)
+                {
+                    SendPresenceNotification(resource->rsrcType);
+                }
+                else
+                {
+                    SendPresenceNotification(NULL);
+                }
             }
-            #endif
+        #endif
 
             if (temp == headResource) {
                 headResource = temp->next;
@@ -2000,6 +2201,35 @@ OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
 }
 
 /**
+ * Finds a resource type in an OCResourceType link-list.
+ *
+ * @param resourceTypeList - the link-list to be searched through
+ * @param resourceTypeName - the key to search for
+ *
+ * @return
+ *      resourceType that matches the key (ie. resourceTypeName)
+ *      NULL - either an invalid parameter or this function was unable to find the key.
+ */
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
+{
+    if(resourceTypeList && resourceTypeName)
+    {
+        OCResourceType * rtPointer = resourceTypeList;
+        while(resourceTypeName && rtPointer)
+        {
+            if(rtPointer->resourcetypename &&
+                    strcmp(resourceTypeName, (const char *)
+                    (rtPointer->resourcetypename)) == 0)
+            {
+                break;
+            }
+            rtPointer = rtPointer->next;
+        }
+        return rtPointer;
+    }
+    return NULL;
+}
+/**
  * Insert a resource interface into a resource's resource interface linked list.
  *
  * @param resource - resource where resource interface is to be inserted
@@ -2059,6 +2289,45 @@ OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
 }
 
 /**
+ * Determine if a request/response must be sent in a block transfer because it is too large to be
+ * sent in a single PDU.  This function can be used for either a request or a response
+ *
+ * @param request  - NULL or pointer to request
+ * @param response - NULL or pointer to response
+ * @param size     - 0 or size of the request/response.  If 0, strlen is used for determining
+ *                   the length of the request/response
+ *
+ * @return
+ *    0 - packet transfer NOT required (i.e. normal request/response)
+ *    1 - packet transfer required (i.e. block transfer needed)
+ */
+uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
+{
+    uint8_t result = 0;
+
+    // Determine if we are checking a request or a response
+    if (request)
+    {
+        // If size is greater than 0, use it for the request size value, otherwise
+        // assume request is null terminated and use strlen for size value
+        if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
+        {
+            result = 1;
+        }
+    }
+    else if (response)
+    {
+        // If size is greater than 0, use it for the response size value, otherwise
+        // assume response is null terminated and use strlen for size value
+        if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
+        {
+            result = 1;
+        }
+    }
+    return result;
+}
+
+/**
  * Retrieves a resource type based upon a uri string if the uri string contains only just one
  * resource attribute (and that has to be of type "rt").
  *
@@ -2085,14 +2354,12 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
     {
         return OC_STACK_INVALID_PARAM;
     }
-    char * ptr = NULL;
     char * leftToken = NULL;
-    char * tempURI = (char *) OCMalloc(strlen(uri));
+    char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
     if(!tempURI)
     {
         goto exit;
     }
-    ptr = tempURI;
     strcpy(tempURI, uri);
     leftToken = strtok((char *)tempURI, "?");
 
@@ -2111,12 +2378,10 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
         leftToken = strtok(NULL, "?");
     }
 
-    *newURI = ptr;
+    *newURI = tempURI;
 
     return OC_STACK_OK;
 
     exit:
         return OC_STACK_NO_MEMORY;
 }
-
-
index a69b10d..f753da8 100644 (file)
@@ -72,7 +72,7 @@ CORE_COBJ = WInterrupts.o wiring.o wiring_digital.o
 CORE_CPPOBJ = main.o Stream.o WMath.o WString.o HardwareSerial.o Print.o SPI.o IPAddress.o wiring_analog.o
 ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o
 ETH_UTIL_CPPOBJ = socket.o w5100.o
-OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocstack.o occoaphelper.o occoap.o occlientcb.o
+OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocserverrequest.o ocstack.o occoaphelper.o occoap.o occlientcb.o
 OCDEPENDENT_CPPOBJ = wiring_analog.o
 CJSON_COBJ = cJSON.o
 
index 4f9d70d..ac76a47 100644 (file)
@@ -44,33 +44,36 @@ OBJ_DIR       := $(OUT_DIR)/obj
 
 OUT_DIR          := $(PWD)
 
-OCLOGGER_DIR   = $(ROOT_DIR)/logger
+LOGGER_DIR     = $(ROOT_DIR)/logger
+OC_LOG_DIR      = $(ROOT_DIR)/../oc_logger
 OCRANDOM_DIR   = $(ROOT_DIR)/ocrandom
 OCSOCKET_DIR   = $(ROOT_DIR)/ocsocket
-LCOAP_DIR              = $(ROOT_DIR)/libcoap-4.1.1
-OCCOAP_DIR             = $(ROOT_DIR)/occoap
+LCOAP_DIR      = $(ROOT_DIR)/libcoap-4.1.1
+OCCOAP_DIR     = $(ROOT_DIR)/occoap
 OCTBSTACK_DIR  = $(ROOT_DIR)/stack
 
-OCLOGGER_INC   = $(OCLOGGER_DIR)/include
+LOGGER_INC     = $(LOGGER_DIR)/include
+OC_LOG_INC     = $(OC_LOG_DIR)/include
 OCRANDOM_INC   = $(OCRANDOM_DIR)/include
 OCSOCKET_INC   = $(OCSOCKET_DIR)/include
-LCOAP_INC              = $(LCOAP_DIR)
-OCCOAP_INC             = $(OCCOAP_DIR)/include
+LCOAP_INC      = $(LCOAP_DIR)
+OCCOAP_INC     = $(OCCOAP_DIR)/include
 OCTBSTACK_INC  = $(OCTBSTACK_DIR)/include
 
-INC_DIRS       := -I$(OCLOGGER_INC)
+INC_DIRS       := -I$(LOGGER_INC)
+INC_DIRS       += -I$(OC_LOG_INC)
 INC_DIRS       += -I$(OCRANDOM_INC)
 INC_DIRS       += -I$(OCSOCKET_INC)
 INC_DIRS       += -I$(LCOAP_INC)
 INC_DIRS       += -I$(OCCOAP_INC)
 INC_DIRS       += -I$(OCTBSTACK_INC)
 INC_DIRS       += -I$(OCTBSTACK_INC)/internal
-INC_DIRS  += -I$(GTEST_DIR)/include
+INC_DIRS       += -I$(GTEST_DIR)/include
 
 CC_FLAGS.debug      := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
-                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
 CC_FLAGS.release    := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
-                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) 
+                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) 
                                        
 LDLIBS         += -loctbstack -lpthread -lgtest -lgtest_main
 CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
index bf47613..31c8dff 100644 (file)
@@ -43,7 +43,7 @@ extern "C" {
 #include <stdint.h>
 using namespace std;
 
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 //-----------------------------------------------------------------------------
 // Private variables
 //-----------------------------------------------------------------------------
@@ -57,7 +57,7 @@ extern "C"  OCStackApplicationResult asyncDoResourcesCallback(void* ctx, OCDoHan
 
     EXPECT_EQ(OC_STACK_OK, clientResponse->result);
 
-    if(ctx == (void*)CTX_VAL) {
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
     }
     OC_LOG_V(INFO, TAG, "result = %d", clientResponse->result);
@@ -128,9 +128,10 @@ TEST(StackTest, DoResourceDeviceDiscovery) {
     char szQueryUri[64] = { 0 };
     strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     cbData.cb = asyncDoResourcesCallback;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
+
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
     //EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
@@ -158,9 +159,9 @@ TEST(StackTest, UpdateResourceNullURI) {
     char szQueryUri[64] = { 0 };
     strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     cbData.cb = asyncDoResourcesCallback;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
     //EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
index 3c7380f..12a7dcc 100644 (file)
@@ -1,10 +1,12 @@
 ##
 # Examples build script
 ##
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 # Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-examples_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
 
 ######################################################################
 # Build flags
@@ -19,34 +21,52 @@ examples_env.AppendUnique(CPPPATH = [
                '../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
-       examples_env.AppendUnique(CXXFLAGS = ['-std=c++11', '-Wall'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       examples_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+       # Note: 'pthread' is in libc for android. On other platform, if use
+       # new gcc(>4.9?) it isn't required, otherwise, it's required
+       if target_os != 'android':
+               examples_env.AppendUnique(LIBS = ['-lpthread'])
 
-examples_env.AppendUnique(LIBPATH = [BUILD_DIR])
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 examples_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger'])
 
-if BUILD_TARGET == 'android':
+if target_os == 'android':
        examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        examples_env.AppendUnique(LIBS = ['gnustl_static'])
-       examples_env.AppendUnique(LINKFLAGS = ['-static'])
        examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
 
-       if not RELEASE_BUILD:
+       if not env.get('RELEASE'):
                examples_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+       examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
 ######################################################################
 # Source files and Targets
 ######################################################################
 simpleserver = examples_env.Program('simpleserver', 'simpleserver.cpp')
+simpleserverHQ = examples_env.Program('simpleserverHQ', 'simpleserverHQ.cpp')
 simpleclient = examples_env.Program('simpleclient', 'simpleclient.cpp')
+simpleclientHQ = examples_env.Program('simpleclientHQ', 'simpleclientHQ.cpp')
+fridgeserver = examples_env.Program('fridgeserver', 'fridgeserver.cpp')
+fridgeclient = examples_env.Program('fridgeclient', 'fridgeclient.cpp')
 presenceserver = examples_env.Program('presenceserver', 'presenceserver.cpp')
 presenceclient = examples_env.Program('presenceclient', 'presenceclient.cpp')
 simpleclientserver = examples_env.Program('simpleclientserver', 'simpleclientserver.cpp')
 roomserver = examples_env.Program('roomserver', 'roomserver.cpp')
 roomclient = examples_env.Program('roomclient', 'roomclient.cpp')
+garageserver = examples_env.Program('garageserver', 'garageserver.cpp')
+garageclient = examples_env.Program('garageclient', 'garageclient.cpp')
 
-Alias("examples", [simpleserver, simpleclient, presenceserver, presenceclient,
-               simpleclientserver, roomserver, roomclient])
-env.AppendUnique(TS = ['examples'])
+Alias("examples", [simpleserver, simpleserverHQ, simpleclient, simpleclientHQ,
+               fridgeserver, fridgeclient, presenceserver, presenceclient,
+               simpleclientserver, roomserver, roomclient, garageserver,
+               garageclient])
+env.AppendTarget('examples')
 
-if BUILD_TARGET not in ['ios']:
-       SConscript(BUILD_DIR + 'examples/ocicuc/SConscript')
+#ios doesn't allow run application from terminal, so won't build these examples
+if target_os != 'ios':
+       SConscript('ocicuc/SConscript')
index 60d5757..a37c581 100644 (file)
@@ -82,14 +82,37 @@ class ClientFridge
         OCResource::Ptr light = constructResourceObject(resource->host(),
                                 "/light", false, lightTypes, ifaces);
 
+        if(!light)
+        {
+            std::cout << "Error: Light Resource Object construction returned null\n";
+            return;
+        }
+
         std::vector<std::string> doorTypes = {"intel.fridge.door"};
 
         OCResource::Ptr leftdoor = constructResourceObject(resource->host(),
                                 "/door/left", false, doorTypes, ifaces);
+        if(!leftdoor)
+        {
+            std::cout << "Error: Left Door Resource Object construction returned null\n";
+            return;
+        }
+
         OCResource::Ptr rightdoor = constructResourceObject(resource->host(),
                                 "/door/right", false, doorTypes, ifaces);
+        if(!rightdoor)
+        {
+            std::cout << "Error: Right Door Resource Object construction returned null\n";
+            return;
+        }
+
         OCResource::Ptr randomdoor = constructResourceObject(resource->host(),
                                 "/door/random", false, doorTypes, ifaces);
+        if(!randomdoor)
+        {
+            std::cout << "Error: Random Door Resource Object construction returned null\n";
+            return;
+        }
 
         // Set header options with API version and token
         HeaderOptions headerOptions;
@@ -164,7 +187,7 @@ class ClientFridge
                 }
             case 1:
                 {
-                    bool isOn;
+                    bool isOn = false;
                     rep.getValue("on",isOn);
                     std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"<<std::endl;
                 }
@@ -172,7 +195,7 @@ class ClientFridge
             case 2:
             case 3:
                 {
-                    bool isOpen;
+                    bool isOpen = false;
                     std::string side;
                     rep.getValue("open", isOpen);
                     rep.getValue("side", side);
index 3700e30..ae6eb32 100644 (file)
@@ -18,7 +18,7 @@
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/// The purpose of this server is to simulate a refridgerator that contains a device resource for
+/// The purpose of this server is to simulate a refrigerator that contains a device resource for
 /// its description, a light resource for the internal light, and 2 door resources for the purpose
 /// of representing the doors attached to this fridge.  This is used by the fridgeclient to
 /// demonstrate using std::bind to attach to instances of a class as well as using
@@ -50,8 +50,7 @@ class Resource
     protected:
     OCResourceHandle m_resourceHandle;
     OCRepresentation m_rep;
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)=0;
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)=0;
 };
 
 class DeviceResource : public Resource
@@ -63,10 +62,10 @@ class DeviceResource : public Resource
         std::string resourceURI = "/device";
         std::string resourceTypeName = "intel.fridge";
         std::string resourceInterface = DEFAULT_INTERFACE;
-        EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1);
 
-        EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler, this,
-                                                                         PH::_1, PH::_2);
+        EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler
+                                            ,this, PH::_1);
 
         std::cout << "Setting device default entity handler\n";
         OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
@@ -88,11 +87,11 @@ class DeviceResource : public Resource
     private:
     OCRepresentation get()
     {
-        m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refridgerator"));
+        m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator"));
         return m_rep;
     }
 
-    void deleteDeviceResource()
+    OCStackResult deleteDeviceResource()
     {
         OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
         if(OC_STACK_OK != result)
@@ -100,13 +99,14 @@ class DeviceResource : public Resource
             throw std::runtime_error(
                std::string("Device Resource failed to unregister/delete") + std::to_string(result));
         }
+        return result;
     }
 
     std::string m_modelName;
     protected:
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
         if(request)
         {
             // Get the header options from the request
@@ -152,30 +152,45 @@ class DeviceResource : public Resource
 
                 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
                 {
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
+                    pResponse->setHeaderOptions(serverHeaderOptions);
+
                     if(request->getRequestType() == "GET")
                     {
-                        if(response)
+                        std::cout<<"DeviceResource Get Request"<<std::endl;
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get(), "");
+                        if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            std::cout<<"DeviceResource Get Request"<<std::endl;
-                            response->setErrorCode(200);
-                            response->setHeaderOptions(serverHeaderOptions);
-                            response->setResourceRepresentation(get(), "");
+                            ehResult = OC_EH_OK;
                         }
                     }
-                    if(request->getRequestType() == "DELETE")
+                    else if(request->getRequestType() == "DELETE")
                     {
-                        if(response)
+                        std::cout<<"DeviceResource Delete Request"<<std::endl;
+                        if(deleteDeviceResource() == OC_STACK_OK)
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
+                            ehResult = OC_EH_OK;
+                        }
+                        else
                         {
-                            std::cout<<"DeviceResource Delete Request"<<std::endl;
-                            deleteDeviceResource();
-                            response->setErrorCode(200);
-                            response->setHeaderOptions(serverHeaderOptions);
+                            pResponse->setResponseResult(OC_EH_ERROR);
+                            ehResult = OC_EH_ERROR;
                         }
+                        OCPlatform::sendResponse(pResponse);
                     }
                     else
                     {
                         std::cout <<"DeviceResource unsupported request type "
                         << request->getRequestType() << std::endl;
+                        pResponse->setResponseResult(OC_EH_ERROR);
+                        OCPlatform::sendResponse(pResponse);
+                        ehResult = OC_EH_ERROR;
                     }
                 }
                 else
@@ -189,12 +204,12 @@ class DeviceResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 
-    virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
     {
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
         if(request)
         {
             std::cout << "In Default Entity Handler, uri received: "
@@ -202,19 +217,27 @@ class DeviceResource : public Resource
 
             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
             {
+                auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                pResponse->setRequestHandle(request->getRequestHandle());
+                pResponse->setResourceHandle(request->getResourceHandle());
+
                 if(request->getRequestType() == "GET")
                 {
-                    if(response)
+                    std::cout<<"Default Entity Handler: Get Request"<<std::endl;
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout<<"Default Entity Handler: Get Request"<<std::endl;
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
                     std::cout <<"Default Entity Handler: unsupported request type "
                     << request->getRequestType() << std::endl;
+                    pResponse->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(pResponse);
+                    ehResult = OC_EH_ERROR;
                 }
             }
             else
@@ -223,7 +246,7 @@ class DeviceResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
    }
 
 };
@@ -236,7 +259,7 @@ class LightResource : public Resource
         std::string resourceURI = "/light";
         std::string resourceTypeName = "intel.fridge.light";
         std::string resourceInterface = DEFAULT_INTERFACE;
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
         uint8_t resourceProperty = 0;
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
             resourceURI,
@@ -265,9 +288,9 @@ class LightResource : public Resource
 
     bool m_isOn;
     protected:
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
         if(request)
         {
             std::cout << "In entity handler for Light, URI is : "
@@ -275,30 +298,38 @@ class LightResource : public Resource
 
             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
             {
+                auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                pResponse->setRequestHandle(request->getRequestHandle());
+                pResponse->setResourceHandle(request->getResourceHandle());
+
                 if(request->getRequestType() == "GET")
                 {
-                    if(response)
+                    std::cout<<"Light Get Request"<<std::endl;
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout<<"Light Get Request"<<std::endl;
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if(request->getRequestType() == "PUT")
                 {
-                    if(response)
+                    std::cout <<"Light Put Request"<<std::endl;
+                    put(request->getResourceRepresentation());
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout <<"Light Put Request"<<std::endl;
-                        put(request->getResourceRepresentation());
-
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(),"");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
                     std::cout << "Light unsupported request type"
                     << request->getRequestType() << std::endl;
+                    pResponse->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(pResponse);
+                    ehResult = OC_EH_ERROR;
                 }
             }
             else
@@ -307,7 +338,7 @@ class LightResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 };
 
@@ -320,7 +351,7 @@ class DoorResource : public Resource
         std::string resourceURI = "/door/"+ side;
         std::string resourceTypeName = "intel.fridge.door";
         std::string resourceInterface = DEFAULT_INTERFACE;
-        EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1);
 
         uint8_t resourceProperty = 0;
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
@@ -353,10 +384,11 @@ class DoorResource : public Resource
     bool m_isOpen;
     std::string m_side;
     protected:
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
         std::cout << "EH of door invoked " << std::endl;
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
         if(request)
         {
             std::cout << "In entity handler for Door, URI is : "
@@ -364,31 +396,40 @@ class DoorResource : public Resource
 
             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
             {
+                auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                pResponse->setRequestHandle(request->getRequestHandle());
+                pResponse->setResourceHandle(request->getResourceHandle());
+
                 if(request->getRequestType() == "GET")
                 {
-                    if(response)
+                    // note that we know the side because std::bind gives us the
+                    // appropriate object
+                    std::cout<< m_side << " Door Get Request"<<std::endl;
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        // note that we know the side because std::bind gives us the
-                        // appropriate object
-                        std::cout<<m_side << " Door Get Request"<<std::endl;
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if(request->getRequestType() == "PUT")
                 {
-                    if(response)
+                    std::cout << m_side <<" Door Put Request"<<std::endl;
+                    put(request->getResourceRepresentation());
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(),"");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout <<m_side <<" Door Put Request"<<std::endl;
-                        put(request->getResourceRepresentation());
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(),"");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
                     std::cout <<m_side<<" Door unsupported request type "
                     << request->getRequestType() << std::endl;
+                    pResponse->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(pResponse);
+                    ehResult = OC_EH_ERROR;
                 }
             }
             else
@@ -397,7 +438,7 @@ class DoorResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 
 };
index e1b4e5c..ba8a09a 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <string>
 #include <cstdlib>
+#include <mutex>
+#include <condition_variable>
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -283,11 +285,15 @@ int main(int argc, char* argv[]) {
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.garage",
                     &foundResource);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
 
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException& e)
     {
index e033504..e2a57d8 100644 (file)
@@ -25,6 +25,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -33,8 +35,7 @@ using namespace OC;
 using namespace std;
 
 // Forward declaring the entityHandler
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
 /// This class represents a single resource named 'lightResource'. This resource has
 
@@ -104,7 +105,7 @@ public:
         // setting json string
         std::string json = "{\"num\":10,\"rno\":23.5,\"aoa\":[[1,2],[3]],\"str\":\"john\",\
 \"object\":{\"bl1\":false,\"ar\":[2,3]}, \"objects\":[{\"bl2\":true,\"nl\":null},{\"ar1\":[1,2]}]}";
-        m_garageRep.setValue("json", escapeString(json));
+        m_garageRep.setValue("json", json);
     }
 
     /* Note that this does not need to be a member function: for classes you do not have
@@ -173,10 +174,22 @@ public:
 // Create the instance of the resource class (in this case instance of class 'GarageResource').
 GarageResource myGarage;
 
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response)
+OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(myGarage.get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     if(request)
     {
@@ -198,34 +211,21 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(myGarage.get());
+                    ehResult = OC_EH_OK;
                 }
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
-
                 OCRepresentation rep = request->getResourceRepresentation();
-
                 // Do related operations related to PUT request
-
-                // Update the lightResource
                 myGarage.put(rep);
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(myGarage.get());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "POST")
             {
@@ -246,7 +246,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return ehResult;
 }
 
 int main(int argc, char* argv[1])
@@ -266,11 +266,14 @@ int main(int argc, char* argv[1])
         // Invoke createResource function of class light.
         myGarage.createResource();
 
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -279,4 +282,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the OCPlatform
     // When OCPlatform destructor is invoked, internally we do Platform cleanup
+
+    return 0;
 }
index 0acf542..17556f8 100644 (file)
@@ -41,7 +41,7 @@ CXX_INC=-I$(OCLIB)/include \
        -I../../csdk/stack/include \
        -I../../csdk/ocsocket/include \
        -I../../csdk/ocrandom/include \
-       -I../../csdk/logger/include
+       -I../../csdk/logger/include \
 
 BOOST_LIBS=-lboost_program_options
 #BOOST_LIBS=-L/usr/local/boost/lib/ -lboost_program_options    # for boost libraries at the specified path
index eae0706..0b52b29 100644 (file)
@@ -1,11 +1,12 @@
 ##
 # Examples build script
 ##
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 # Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-ocicuc_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
+ocicuc_env = lib_env.Clone()
 ######################################################################
 # Build flags
 ######################################################################
@@ -18,22 +19,22 @@ ocicuc_env.AppendUnique(CPPPATH = [
                '../../oc_logger/include'
                ])
 
-ocicuc_env.AppendUnique(LIBPATH = [BUILD_DIR])
+ocicuc_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 ocicuc_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger'])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
-       ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++11'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++0x'])
 
-if BUILD_TARGET == 'android':
+if target_os == 'android':
        ocicuc_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        ocicuc_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
        ocicuc_env.AppendUnique(LIBS = ['boost_program_options-gcc-mt-1_49', 'boost_thread-gcc-mt-1_49', 'gnustl_static'])
-       ocicuc_env.AppendUnique(LINKFLAGS = ['-static'])
 
-       if not RELEASE_BUILD:
+       if not env.get('RELEASE'):
                ocicuc_env.AppendUnique(LIBS = ['log'])
 
-if BUILD_TARGET == 'darwin':
+if target_os == 'darwin':
        ocicuc_env.AppendUnique(LIBS = ['boost_program_options'])
 
 ######################################################################
@@ -41,8 +42,8 @@ if BUILD_TARGET == 'darwin':
 ######################################################################
 client = ocicuc_env.Program('client', ['client.cpp', 'driver.cpp', 'utility.cpp'])
 server = ocicuc_env.Program('server', ['server.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
-monoprocess = ocicuc_env.Program('monoprocess',
-               ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
+monoprocess = ocicuc_env.Program('monoprocess', ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
+small_example = ocicuc_env.Program('small_example', ['small_example.cpp', 'driver.cpp', 'utility.cpp'])
 
-Alias("examples_ocicuc", [client, server, monoprocess])
-env.AppendUnique(TS = ['examples_ocicuc'])
+Alias("examples_ocicuc", [client, server, monoprocess, small_example])
+env.AppendTarget('examples_ocicuc')
\ No newline at end of file
index d2edcfc..c3771bb 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+// This contains the Boost MPL defines required for the boost_variant
+// serialization, so it must go before the boost/program_options
+#include "OCApi.h"
+
 #include <map>
 #include <string>
 #include <memory>
@@ -28,7 +32,6 @@
 
 #include <boost/program_options.hpp>
 
-#include "OCApi.h"
 #include "OCResource.h"
 #include "OCPlatform.h"
 
index 47830b0..d5ce578 100644 (file)
@@ -143,20 +143,23 @@ void resource_handle::onResourceGet(const OC::HeaderOptions& headerOptions,
         return;
   }
 
- std::cout << "input attributes:\n" << rep.getAttributeMap() << '\n';
+ std::cout << "input attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
 
  // Now, make a change to the light representation (replacing, rather than parsing):
- OC::AttributeMap attrs {
-                         { "state", { "true" } },
-                         { "power", { "10" } }
-                        };
+ bool state = true;
+ int power = 10;
 
- std::cout << "output attributes:\n" << attrs << '\n';
+ std::cout << "output attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< state<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< power<<"; \n";
 
  call_timer.mark("put_resource");
 
  OC::OCRepresentation out_rep;
- out_rep.setAttributeMap(attrs);
+ out_rep.setValue("state", state);
+ out_rep.setValue("power", power);
 
  resource->put(out_rep, OC::QueryParamsMap(),
                std::bind(&resource_handle::onResourcePut, this, std::placeholders::_1,
@@ -179,7 +182,9 @@ void resource_handle::onResourcePut(const OC::HeaderOptions& headerOptions,
         throw OC::OCException(os.str());
   }
 
- std::cout << "input attributes:\n" << rep.getAttributeMap() << '\n';
+ std::cout << "input attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
 
  call_timer.mark("observe_resource");
 
@@ -204,7 +209,8 @@ void resource_handle::onObserve(const OC::HeaderOptions& headerOptions,
 
  call_timer.report_and_reset("observe_resource");
 
- std::cout << rep.getAttributeMap() << '\n';
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
 
  const auto oc = observe_count();
 
index 6b3dd42..6586ac6 100644 (file)
@@ -50,7 +50,7 @@ void LightResource::createResource(const unsigned int resource_number)
  OCStackResult result = OC::OCPlatform::registerResource(
                                             m_resourceHandle, resourceURI, resourceTypeName,
                                             DEFAULT_INTERFACE,
-                                            std::bind(&LightResource::entityHandler, this, std::placeholders::_1, std::placeholders::_2),
+                                            std::bind(&LightResource::entityHandler, this, std::placeholders::_1),
                                             OC_DISCOVERABLE | OC_OBSERVABLE);
   if (OC_STACK_OK != result)
    std::cout << "Resource creation failed.\n";
@@ -99,7 +99,7 @@ void LightResource::unregisterResource()
 
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     if(!request)
      {
@@ -107,12 +107,6 @@ OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceReq
         return OC_EH_ERROR;
      }
 
-    if(!response)
-     {
-        cerr << "entityHandler(): Received invalid response object.\n";
-        return OC_EH_ERROR;
-     }
-
     switch(request->getRequestHandlerFlag())
     {
         default:
@@ -124,37 +118,37 @@ OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceReq
                 break;
 
         case RequestHandlerFlag::RequestFlag:
-                dispatch_request(request->getRequestType(), request, response);
+                dispatch_request(request->getRequestType(), request);
                 break;
 
         case RequestHandlerFlag::ObserverFlag:
-                handle_observe_event(request, response);
+                handle_observe_event(request);
                 break;
     }
 
     return OC_EH_OK;
 }
 
-void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request)
 {
  std::cout << "dispatch_request(): " << request_type << '\n';
 
  if("GET" == request_type)
-  return handle_get_request(request, response);
+  return handle_get_request(request);
 
  if("PUT" == request_type)
-  return handle_put_request(request, response);
+  return handle_put_request(request);
 
  if("POST" == request_type)
-  return handle_post_request(request, response);
+  return handle_post_request(request);
 
  if("DELETE" == request_type)
-  return handle_delete_request(request, response);
+  return handle_delete_request(request);
 
  cerr << "entityHandler(): Invalid request type \"" << request_type << "\".\n";
 }
 
-void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request)
 {
  cout << "handle_get_request():\n";
 
@@ -163,11 +157,16 @@ void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> reques
  // ...do any processing of the query here...
 
  // Get a representation of the resource and send it back as a response:
- response->setErrorCode(200);
- response->setResourceRepresentation(getRepresentation());
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(getRepresentation());
+ OCPlatform::sendResponse(pResponse);
 }
 
-void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request)
 {
  // Here's how you would get any query parameters:
  const auto query_params_map = request->getQueryParameters();
@@ -177,25 +176,27 @@ void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> reques
 
  setRepresentation(rep);
 
- if(!response)
-  return;
-
- response->setErrorCode(200);
- response->setResourceRepresentation(getRepresentation());
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(getRepresentation());
+ OCPlatform::sendResponse(pResponse);
 }
 
-void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request)
 {
  // ...demo-code...
 }
 
-void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request)
 {
  // ...demo-code...
 }
 
 // Set up observation in a separate thread:
-void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request)
 {
  if(observe_thread.joinable())
   return;
index c569302..494b366 100644 (file)
@@ -75,20 +75,19 @@ class LightResource
     void addInterface(const std::string& interface) const;
 
     private:
-    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                        std::shared_ptr<OCResourceResponse> response);
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
     private:
     void observe_function();
 
     // Request handlers:
     private:
-    void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+    void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request);
+    void handle_get_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_put_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_post_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_delete_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_observe_event(std::shared_ptr<OCResourceRequest> request);
 };
 
 }} // namespace Intel::OCDemo
index 47b909c..65fca0e 100644 (file)
@@ -18,9 +18,9 @@
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#include "exec.hpp"
 #include "utility.hpp"
 
+#include "exec.hpp"
 #include "light_resource.hpp"
 
 namespace Intel { namespace OCDemo {
index 6b92fd9..bc734d7 100644 (file)
 
 namespace Intel { namespace OCDemo {
 
-// Prettyprinter for AttributeMaps:
-inline std::ostream& operator<<(std::ostream& os, const OC::AttributeMap& attrs)
-{
- for(const auto& attr : attrs)
-  os << "Attribute \"" << attr.first << "\": " << attr.second << "; ";
-
- return os;
-}
-
 /* A static observation counter: */
 int observe_count();
 
 /* Helpers for measuring request times: */
-typedef std::pair< 
-                    std::chrono::time_point<std::chrono::high_resolution_clock>, 
-                    std::chrono::time_point<std::chrono::high_resolution_clock> 
+typedef std::pair<
+                    std::chrono::time_point<std::chrono::high_resolution_clock>,
+                    std::chrono::time_point<std::chrono::high_resolution_clock>
                  > clock_interval;
 
 struct call_times
@@ -64,7 +55,7 @@ struct call_times
  call_times(const bool& display_reports_)
   : display_reports(display_reports_)
  {}
+
  public:
  void reset(const std::string& entry);
  void mark(const std::string& name);
@@ -73,8 +64,8 @@ struct call_times
  void report_and_reset(const std::string& name);
 };
 
-extern call_times call_timer; 
+extern call_times call_timer;
+
 }} // namespace Intel::OCDemo
 
 #endif
index 6d5e70d..6bd79fe 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -55,8 +58,9 @@ void printUsage()
 }
 
 // Callback to presence
-void presenceHandler(OCStackResult result, const unsigned int nonce)
+void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)
 {
+    std::cout << "Received presence notification from : " << hostAddress << std::endl;
     std::cout << "In presenceHandler: ";
 
     switch(result)
@@ -70,8 +74,8 @@ void presenceHandler(OCStackResult result, const unsigned int nonce)
         case OC_STACK_PRESENCE_TIMEOUT:
             std::cout << "Presence Timeout\n";
             break;
-        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-            std::cout << "Presence do not handle\n";
+        case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+            std::cout << "Virtual do not handle\n";
             break;
         default:
             std::cout << "Error\n";
@@ -120,7 +124,7 @@ void foundResource(std::shared_ptr<OCResource> resource)
             if(resourceURI == "/a/light")
             {
                 curResource = resource;
-                OCPlatform::OCPresenceHandle presenceHandle;
+                OCPlatform::OCPresenceHandle presenceHandle = nullptr;
 
                 if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
                 {
@@ -186,7 +190,7 @@ int main(int argc, char* argv[]) {
     {
         std::cout << "Created Platform..."<<std::endl;
 
-        OCPlatform::OCPresenceHandle presenceHandle;
+        OCPlatform::OCPresenceHandle presenceHandle = nullptr;
 
         if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
         {
@@ -205,10 +209,15 @@ int main(int argc, char* argv[]) {
             OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
             std::cout<< "Finding Resource... " <<std::endl;
         }
-        while(true)
-        {
-            // some operations
-        }
+        //
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index 305537b..63d63da 100644 (file)
@@ -26,6 +26,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -34,8 +36,7 @@ using namespace OC;
 using namespace std;
 
 // Forward declaring the entityHandler
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
 /// This class represents a single resource named 'lightResource'. This resource has
 /// two simple properties named 'state' and 'power'
@@ -151,7 +152,7 @@ public:
 // Create the instance of the resource class (in this case instance of class 'LightResource').
 LightResource myLightResource;
 
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     cout << "\tIn Server CPP entity handler:\n";
     return OC_EH_OK;
@@ -197,11 +198,14 @@ int main()
 
         myLightResource.createResource3();
 
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -210,4 +214,6 @@ int main()
 
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 60f0a4d..7e73597 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -232,10 +235,15 @@ int main(int argc, char* argv[]) {
         // Find all resources
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index f9d3978..25c7ee9 100644 (file)
@@ -24,7 +24,8 @@
 
 #include <functional>
 
-#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -34,12 +35,12 @@ using namespace std;
 
 
 // Forward declaring the entityHandler (room)
-OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request,
-                                        std::shared_ptr<OCResourceResponse> response);
-OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request,
-                                         std::shared_ptr<OCResourceResponse> response);
-OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request,
-                                       std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request);
+OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request);
+OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request);
+
+/// Specifies whether default collection entity handler is used or not
+bool useDefaultCollectionEH = false;
 
 class RoomResource
 {
@@ -110,13 +111,26 @@ public:
     /// This function internally calls registerResource API.
     void createResources()
     {
+        // This function internally creates and registers the resource.
         using namespace OC::OCPlatform;
-        // This will internally create and register the resource.
-        OCStackResult result = registerResource(
+        OCStackResult result = OC_STACK_ERROR;
+
+        // Based on the case, we will use default collection EH (by passing NULL in entity handler
+        // parameter) or use application entity handler.
+        if(useDefaultCollectionEH)
+        {
+            result = registerResource(
+                                    m_roomHandle, m_roomUri, m_roomTypes[0],
+                                    m_roomInterfaces[0], NULL,
+                                    OC_DISCOVERABLE | OC_OBSERVABLE);
+        }
+        else
+        {
+            result = registerResource(
                                     m_roomHandle, m_roomUri, m_roomTypes[0],
                                     m_roomInterfaces[0], entityHandlerRoom,
-                                    OC_DISCOVERABLE | OC_OBSERVABLE
-                                  );
+                                    OC_DISCOVERABLE | OC_OBSERVABLE);
+        }
 
         if (OC_STACK_OK != result)
         {
@@ -135,22 +149,18 @@ public:
             cout << "Binding TypeName to Resource was unsuccessful\n";
         }
 
-        result = registerResource(
-                                    m_lightHandle, m_lightUri, m_lightTypes[0],
-                                    m_lightInterfaces[0], entityHandlerLight,
-                                    OC_DISCOVERABLE | OC_OBSERVABLE
-                                   );
+        result = registerResource(m_lightHandle, m_lightUri, m_lightTypes[0],
+                                  m_lightInterfaces[0], entityHandlerLight,
+                                  OC_DISCOVERABLE | OC_OBSERVABLE);
 
         if (OC_STACK_OK != result)
         {
             cout << "Resource creation (light) was unsuccessful\n";
         }
 
-        result = registerResource(
-                                    m_fanHandle, m_fanUri, m_fanTypes[0],
-                                    m_fanInterfaces[0], entityHandlerFan,
-                                    OC_DISCOVERABLE | OC_OBSERVABLE
-                                   );
+        result = registerResource(m_fanHandle, m_fanUri, m_fanTypes[0],
+                                  m_fanInterfaces[0], entityHandlerFan,
+                                  OC_DISCOVERABLE | OC_OBSERVABLE);
 
         if (OC_STACK_OK != result)
         {
@@ -221,16 +231,10 @@ public:
 
     OCRepresentation getRoomRepresentation(void)
     {
-        std::vector<OCRepresentation> children;
-
-        OCRepresentation light = getLightRepresentation();
-        children.push_back(light);
-
-        OCRepresentation fan = getFanRepresentation();
-        children.push_back(fan);
-
-        m_roomRep.setChildren(children);
+        m_roomRep.clearChildren();
 
+        m_roomRep.addChild(getLightRepresentation());
+        m_roomRep.addChild(getFanRepresentation());
         return m_roomRep;
     }
 
@@ -239,11 +243,46 @@ public:
 // Create the instance of the resource class (in this case instance of class 'RoomResource').
 RoomResource myRoomResource;
 
-OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request,
-                       std::shared_ptr<OCResourceResponse> response)
+OCStackResult sendRoomResponse(std::shared_ptr<OCResourceRequest> pRequest)
 {
-    cout << "\tIn Server CPP entity handler:\n";
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+
+    // Check for query params (if any)
+    QueryParamsMap queryParamsMap = pRequest->getQueryParameters();
+
+    cout << "\t\t\tquery params: \n";
+    for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
+    {
+        cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
+    }
 
+    OCRepresentation rep;
+    rep = myRoomResource.getRoomRepresentation();
+
+    auto findRes = queryParamsMap.find("if");
+
+    if(findRes != queryParamsMap.end())
+    {
+        pResponse->setResourceRepresentation(rep, findRes->second);
+    }
+    else
+    {
+        pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
+    }
+
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+// This function prepares a response for any incoming request to Light resource.
+bool prepareLightResponse(std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "\tIn Server CPP (Light) prepareLightResponse:\n";
+    bool result = false;
     if(request)
     {
         // Get the request type and request flag
@@ -264,64 +303,18 @@ OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> reque
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
-                cout << "\t\t\tquery params: \n";
-                for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
-                {
-                    cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
-                }
-
-                OCRepresentation rep;
-                rep = myRoomResource.getRoomRepresentation();
-
-                if(response)
-                {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    auto findRes = queryParamsMap.find("if");
-
-                    if(findRes != queryParamsMap.end())
-                    {
-                        response->setResourceRepresentation(rep, findRes->second);
-                    }
-                    else
-                    {
-                        response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
-                    }
-                }
-
+                // GET operations are directly handled while sending the response
+                // in the sendLightResponse function
+                result = true;
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
+                OCRepresentation rep = request->getResourceRepresentation();
 
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
-                entityHandlerLight(request, response);
-                entityHandlerFan(request, response);
-
-                OCRepresentation rep;
-                rep = myRoomResource.getRoomRepresentation();
-
-                if(response)
-                {
-                    response->setErrorCode(200);
-
-                    auto findRes = queryParamsMap.find("if");
-
-                    if(findRes != queryParamsMap.end())
-                    {
-                        response->setResourceRepresentation(rep, findRes->second);
-                    }
-                    else
-                    {
-                        response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
-                    }
-                }
+                // Do related operations related to PUT request
+                myRoomResource.setLightRepresentation(rep);
+                result= true;
             }
             else if(requestType == "POST")
             {
@@ -342,13 +335,14 @@ OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> reque
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return result;
 }
 
-OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request,
-                                         std::shared_ptr<OCResourceResponse> response)
+// This function prepares a response for any incoming request to Fan resource.
+bool prepareFanResponse(std::shared_ptr<OCResourceRequest> request)
 {
-    cout << "\tIn Server CPP (Light) entity handler:\n";
+    cout << "\tIn Server CPP (Fan) prepareFanResponse:\n";
+    bool result = false;
 
     if(request)
     {
@@ -370,14 +364,9 @@ OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> requ
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
-                {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-                    response->setResourceRepresentation(myRoomResource.getLightRepresentation());
-                }
-
+                // GET operations are directly handled while sending the response
+                // in the sendLightResponse function
+                result = true;
             }
             else if(requestType == "PUT")
             {
@@ -386,15 +375,8 @@ OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> requ
                 OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to PUT request
-                myRoomResource.setLightRepresentation(rep);
-
-                if(response)
-                {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-                    response->setResourceRepresentation(myRoomResource.getLightRepresentation());
-                }
-
+                myRoomResource.setFanRepresentation(rep);
+                result = true;
             }
             else if(requestType == "POST")
             {
@@ -415,13 +397,13 @@ OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> requ
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return result;
 }
 
-OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request,
-                                       std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request)
 {
-    cout << "\tIn Server CPP (Fan) entity handler:\n";
+    cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     if(request)
     {
@@ -443,30 +425,21 @@ OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> reques
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(OC_STACK_OK == sendRoomResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(myRoomResource.getFanRepresentation());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
-
-                OCRepresentation rep = request->getResourceRepresentation();
-
-                // Do related operations related to PUT request
-                myRoomResource.setFanRepresentation(rep);
-
-                if(response)
+                // Call these functions to prepare the response for child resources and
+                // then send the final response using sendRoomResponse function
+                prepareLightResponse(request);
+                prepareFanResponse(request);
+                if(OC_STACK_OK == sendRoomResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-                    response->setResourceRepresentation(myRoomResource.getFanRepresentation());
+                    ehResult = OC_EH_OK;
                 }
             }
             else if(requestType == "POST")
@@ -488,11 +461,112 @@ OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> reques
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return ehResult;
+}
+
+OCStackResult sendLightResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(myRoomResource.getLightRepresentation());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+
+
+OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "\tIn Server CPP (Light) entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    if(prepareLightResponse(request))
+    {
+        if(OC_STACK_OK == sendLightResponse(request))
+        {
+            ehResult = OC_EH_OK;
+        }
+        else
+        {
+            std::cout << "sendLightResponse failed." << std::endl;
+        }
+    }
+    else
+    {
+        std::cout << "PrepareLightResponse failed." << std::endl;
+    }
+    return ehResult;
+}
+
+OCStackResult sendFanResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(myRoomResource.getFanRepresentation());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
 }
 
-int main()
+
+OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request)
 {
+    cout << "\tIn Server CPP (Fan) entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    if(prepareFanResponse(request))
+    {
+        if(OC_STACK_OK == sendFanResponse(request))
+        {
+            ehResult = OC_EH_OK;
+        }
+        else
+        {
+            std::cout << "sendFanResponse failed." << std::endl;
+        }
+    }
+    else
+    {
+        std::cout << "PrepareFanResponse failed." << std::endl;
+    }
+
+    return ehResult;
+}
+
+void printUsage()
+{
+    std::cout << std::endl;
+    std::cout << "Usage : roomserver <value>\n";
+    std::cout << "1 : Create room resource with default collection entity handler.\n";
+    std::cout << "2 : Create room resource with application collection entity handler.\n";
+}
+
+int main(int argc, char* argv[])
+{
+    printUsage();
+
+    if(argc == 2)
+    {
+        int value = atoi(argv[1]);
+        switch (value)
+        {
+            case 1:
+                useDefaultCollectionEH = true;
+                break;
+            case 2:
+            default:
+                break;
+       }
+    }
+    else
+    {
+        return -1;
+    }
+
     // Create PlatformConfig object
     PlatformConfig cfg {
         OC::ServiceType::InProc,
@@ -508,11 +582,15 @@ int main()
 
         myRoomResource.createResources();
 
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
+
     }
     catch(OCException e)
     {
@@ -521,4 +599,6 @@ int main()
 
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 400591a..85c0dc1 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -118,7 +121,7 @@ void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, co
     }
     else
     {
-        std::cout << "onPost Response error: " << eCode << std::endl;
+        std::cout << "onPost2 Response error: " << eCode << std::endl;
         std::exit(-1);
     }
 }
@@ -365,13 +368,20 @@ int main(int argc, char* argv[]) {
     OCPlatform::Configure(cfg);
     try
     {
+        // makes it so that all boolean values are printed as 'true/false' in this stream
+        std::cout.setf(std::ios::boolalpha);
         // Find all resources
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index 204de3e..e3a6f2c 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -131,7 +134,7 @@ void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, co
     }
     else
     {
-        std::cout << "onPost Response error: " << eCode << std::endl;
+        std::cout << "onPost2 Response error: " << eCode << std::endl;
         std::exit(-1);
     }
 }
@@ -384,10 +387,15 @@ int main(int argc, char* argv[]) {
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource,
                 OC::QualityOfService::LowQos);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index 444c4dc..d3ee18b 100644 (file)
@@ -186,7 +186,7 @@ struct FooResource
         uint8_t resourceProperty = OC_DISCOVERABLE;
 
         EntityHandler eh(std::bind(&FooResource::entityHandler,
-                    this, std::placeholders::_1, std::placeholders::_2));
+                    this, std::placeholders::_1));
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
                 resourceURI, resourceTypeName,
                                     resourceInterface,
@@ -214,14 +214,27 @@ struct FooResource
         rep.getValue("barCount", m_barCount);
     }
 
-    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                        std::shared_ptr<OCResourceResponse> response)
+    OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+    {
+        auto pResponse = std::make_shared<OC::OCResourceResponse>();
+        pResponse->setRequestHandle(pRequest->getRequestHandle());
+        pResponse->setResourceHandle(pRequest->getResourceHandle());
+        pResponse->setResourceRepresentation(get(), "");
+        pResponse->setErrorCode(200);
+        pResponse->setResponseResult(OC_EH_OK);
+
+        return OCPlatform::sendResponse(pResponse);
+    }
+
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
         std::cout<<"\tConsumer Entity Handler:"<<std::endl;
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
         if(request)
         {
-            // Note: Most of the handlers are not here, since this is for demoing client/server co-process existence.
+            // Note: Most of the handlers are not here, since this is for
+            // demoing client/server co-process existence.
             // See simpleserver for a more complete example.
             if(request->getRequestHandlerFlag()  == RequestHandlerFlag::RequestFlag)
             {
@@ -230,11 +243,9 @@ struct FooResource
                 if(request->getRequestType() == "GET")
                 {
                     std::cout<<"\t\t\trequestType : GET"<<std::endl;
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if (request->getRequestType() == "PUT")
@@ -243,16 +254,15 @@ struct FooResource
 
                     OCRepresentation rep = request->getResourceRepresentation();
                     put(rep);
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
-                    std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<request->getRequestType()<<std::endl;
+                    std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<
+                            request->getRequestType()<<std::endl;
                 }
             }
             else
@@ -274,10 +284,11 @@ struct FooResource
             std::cout << "Request Invalid!"<<std::endl;
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 
 };
+
 int main()
 {
     PlatformConfig cfg {
@@ -306,4 +317,6 @@ int main()
     {
         std::cout<< "Exception in main: "<<e.what()<<std::endl;
     }
+
+    return 0;
 }
index 186ffd4..86b1546 100644 (file)
@@ -26,6 +26,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -36,6 +38,7 @@ namespace PH = std::placeholders;
 
 int gObservation = 0;
 void * ChangeLightRepresentation (void *param);
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 
 // Specifies where to notify all observers or list of observers
 // false: notifies all observers
@@ -47,6 +50,9 @@ bool isListOfObservers = false;
 // true: secure resource
 bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
+
 // Forward declaring the entityHandler
 
 /// This class represents a single resource named 'lightResource'. This resource has
@@ -83,8 +89,8 @@ public:
     /// This function internally calls registerResource API.
     void createResource()
     {
-        std::string resourceURI = m_lightUri; // URI of the resource
-        std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
+        std::string resourceURI = m_lightUri; //URI of the resource
+        std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light
         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
 
         // OCResourceProperty is defined ocstack.h
@@ -97,7 +103,7 @@ public:
         {
             resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
         }
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         // This will internally create and register the resource.
         OCStackResult result = OCPlatform::registerResource(
@@ -126,7 +132,7 @@ public:
         {
             resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
         }
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         OCResourceHandle resHandle;
 
@@ -239,13 +245,10 @@ public:
 private:
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
-    OCEntityHandlerResult result = OC_EH_OK;
-
     cout << "\tIn Server CPP entity handler:\n";
-
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
     if(request)
     {
         // Get the request type and request flag
@@ -261,39 +264,51 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         if(requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
+            auto pResponse = std::make_shared<OC::OCResourceResponse>();
+            pResponse->setRequestHandle(request->getRequestHandle());
+            pResponse->setResourceHandle(request->getResourceHandle());
 
             // If the request type is GET
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(isSlowResponse) // Slow response case
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    static int startedThread = 0;
+                    if(!startedThread)
+                    {
+                        std::thread t(handleSlowResponse, (void *)this, request);
+                        startedThread = 1;
+                        t.detach();
+                    }
+                    ehResult = OC_EH_SLOW;
+                }
+                else // normal response case.
+                {
+                    pResponse->setErrorCode(200);
+                    pResponse->setResponseResult(OC_EH_OK);
+                    pResponse->setResourceRepresentation(get());
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                    {
+                        ehResult = OC_EH_OK;
+                    }
                 }
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
-
                 OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to PUT request
-
                 // Update the lightResource
                 put(rep);
-
-                if(response)
+                pResponse->setErrorCode(200);
+                pResponse->setResponseResult(OC_EH_OK);
+                pResponse->setResourceRepresentation(get());
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "POST")
             {
@@ -302,26 +317,19 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to POST request
-
                 OCRepresentation rep_post = post(rep);
-
-                if(response)
+                pResponse->setResourceRepresentation(rep_post);
+                pResponse->setErrorCode(200);
+                if(rep_post.hasAttribute("createduri"))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(rep_post);
-
-                    if(rep_post.hasAttribute("createduri"))
-                    {
-                        result = OC_EH_RESOURCE_CREATED;
-
-                        response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                    }
-
+                    pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                    pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                 }
 
-                // POST request operations
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                {
+                    ehResult = OC_EH_OK;
+                }
             }
             else if(requestType == "DELETE")
             {
@@ -358,6 +366,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                 startedThread = 1;
             }
+            ehResult = OC_EH_OK;
         }
     }
     else
@@ -365,7 +374,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         std::cout << "Request invalid" << std::endl;
     }
 
-    return result;
+    return ehResult;
 }
 
 };
@@ -422,18 +431,40 @@ void * ChangeLightRepresentation (void *param)
     return NULL;
 }
 
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    LightResource* lightPtr = (LightResource*) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(lightPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
+
 void PrintUsage()
 {
     std::cout << std::endl;
-    std::cout << "Usage : simpleserver < secure resource and observer >\n";
+    std::cout << "Usage : simpleserver <value>\n";
     std::cout << "    Default - Non-secure resource and notify all observers\n";
     std::cout << "    1 - Non-secure resource and notify list of observers\n\n";
     std::cout << "    2 - Secure resource and notify all observers\n";
     std::cout << "    3 - Secure resource and notify list of observers\n\n";
+    std::cout << "    4 - Non-secure resource, GET slow response, notify all observers\n";
 }
 
 
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
 {
     PrintUsage();
 
@@ -459,6 +490,8 @@ int main(int argc, char* argv[1])
                 isListOfObservers = true;
                 isSecure = true;
                 break;
+            case 4:
+                isSlowResponse = true;
             default:
                 break;
        }
@@ -480,7 +513,8 @@ int main(int argc, char* argv[1])
     OCPlatform::Configure(cfg);
     try
     {
-        // Create the instance of the resource class (in this case instance of class 'LightResource').
+        // Create the instance of the resource class
+        // (in this case instance of class 'LightResource').
         LightResource myLight;
 
         // Invoke createResource function of class light.
@@ -488,11 +522,15 @@ int main(int argc, char* argv[1])
 
         myLight.addType(std::string("core.brightlight"));
         myLight.addInterface(std::string("oc.mi.ll"));
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -501,4 +539,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the platform.
     // When OCPlatform::destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 1b20294..cf0d09a 100644 (file)
@@ -26,6 +26,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -42,8 +44,6 @@ void * ChangeLightRepresentation (void *param);
 // 1 - notifies list of observers
 int isListOfObservers = 0;
 
-// Forward declaring the entityHandler
-
 /// This class represents a single resource named 'lightResource'. This resource has
 /// two simple properties named 'state' and 'power'
 
@@ -85,7 +85,7 @@ public:
         // OCResourceProperty is defined ocstack.h
         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         // This will internally create and register the resource.
         OCStackResult result = OCPlatform::registerResource(
@@ -107,7 +107,7 @@ public:
         // OCResourceProperty is defined ocstack.h
         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         OCResourceHandle resHandle;
 
@@ -180,7 +180,6 @@ public:
             if(OC_STACK_OK == createResource1())
             {
                 std::cout << "Created a new resource\n";
-
                 OCRepresentation rep1;
                 rep1.setValue("createduri", std::string("/a/light1"));
 
@@ -224,11 +223,41 @@ public:
     }
 
 private:
+
+OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+OCStackResult sendPostResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+
+    OCRepresentation rep = pRequest->getResourceRepresentation();
+    OCRepresentation rep_post = post(rep);
+
+    pResponse->setResourceRepresentation(rep_post);
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     if(request)
     {
@@ -239,7 +268,6 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         if(requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
-
             // entity handler to perform resource initialization operations
         }
         if(requestFlag & RequestHandlerFlag::RequestFlag)
@@ -250,13 +278,9 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    ehResult = OC_EH_OK;
                 }
             }
             else if(requestType == "PUT")
@@ -264,40 +288,21 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 cout << "\t\t\trequestType : PUT\n";
 
                 OCRepresentation rep = request->getResourceRepresentation();
-
                 // Do related operations related to PUT request
-
                 // Update the lightResource
                 put(rep);
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "POST")
             {
                 cout << "\t\t\trequestType : POST\n";
-
-                OCRepresentation rep = request->getResourceRepresentation();
-
-                // Do related operations related to POST request
-
-                OCRepresentation rep_post = post(rep);
-
-                if(response)
+                if(OC_STACK_OK == sendPostResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(rep_post);
+                    ehResult = OC_EH_OK;
                 }
-
-                // POST request operations
             }
             else if(requestType == "DELETE")
             {
@@ -334,6 +339,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                 startedThread = 1;
             }
+            ehResult = OC_EH_OK;
         }
     }
     else
@@ -341,7 +347,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return ehResult;
 }
 
 };
@@ -410,7 +416,7 @@ void PrintUsage()
 }
 
 
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
 {
     PrintUsage();
 
@@ -452,11 +458,15 @@ int main(int argc, char* argv[1])
 
         myLight.addType(std::string("core.brightlight"));
         myLight.addInterface(std::string("oc.mi.ll"));
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -465,4 +475,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index c2f9ec0..ff556e2 100644 (file)
@@ -59,7 +59,7 @@ struct FooResource
         uint8_t resourceProperty = OC_DISCOVERABLE;
 
         EntityHandler eh(std::bind(&FooResource::entityHandler, this,
-                                    std::placeholders::_1, std::placeholders::_2));
+                                    std::placeholders::_1));
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle, m_uri,
                                     m_resourceType, resourceInterface, eh, resourceProperty);
         if(OC_STACK_OK != result)
@@ -85,10 +85,22 @@ struct FooResource
         rep.getValue("barCount", m_barCount);
     }
 
-    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                        std::shared_ptr<OCResourceResponse> response)
+    OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+    {
+        auto pResponse = std::make_shared<OC::OCResourceResponse>();
+        pResponse->setRequestHandle(pRequest->getRequestHandle());
+        pResponse->setResourceHandle(pRequest->getResourceHandle());
+        pResponse->setResourceRepresentation(get(), "");
+        pResponse->setErrorCode(200);
+        pResponse->setResponseResult(OC_EH_OK);
+
+        return OCPlatform::sendResponse(pResponse);
+    }
+
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
         std::cout<<"\tConsumer Entity Handler:"<<std::endl;
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
         if(request)
         {
@@ -101,11 +113,9 @@ struct FooResource
                 if(request->getRequestType() == "GET")
                 {
                     std::cout<<"\t\t\trequestType : GET"<<std::endl;
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if (request->getRequestType() == "PUT")
@@ -114,11 +124,9 @@ struct FooResource
 
                     OCRepresentation rep = request->getResourceRepresentation();
                     put(rep);
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
@@ -146,16 +154,15 @@ struct FooResource
             std::cout << "Request Invalid!"<<std::endl;
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
-
 };
 
 void putResourceInfo(const HeaderOptions& headerOptions,
         const OCRepresentation rep, const OCRepresentation rep2, const int eCode)
 {
-   bool m_isFoo;
-   int m_barCount;
+   bool m_isFoo = false;
+   int m_barCount = 0;
    std::cout << "In PutResourceInfo" << std::endl;
 
    std::cout <<"Clientside Put response to get was: "<<std::endl;
@@ -185,8 +192,8 @@ void getResourceInfo(std::shared_ptr<OCResource> resource, const HeaderOptions&
             const OCRepresentation rep,
             const int eCode)
 {
-    bool m_isFoo;
-    int m_barCount;
+    bool m_isFoo = false;
+    int m_barCount = 0;
     std::cout << "In getResourceInfo" << std::endl;
 
     std::cout<<"Clientside response to get was: "<<std::endl;
@@ -277,10 +284,14 @@ void client1()
     std::cout<<"result1:" << OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo",
             foundResource1)<< std::endl;
 
-    while(1)
-    {
-        // client1 related operations
-    }
+    // A condition variable will free the mutex it is given, then do a non-
+    // intensive block until 'notify' is called on it.  In this case, since we
+    // don't ever call cv.notify, this should be a non-processor intensive version
+    // of while(true);
+    std::mutex blocker;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(blocker);
+    cv.wait(lock);
 }
 
 void client2()
@@ -291,10 +302,14 @@ void client2()
                 "coap://224.0.1.187/oc/core?rt=core.foo",
                 foundResource2)<< std::endl;
 
-    while(1)
-    {
-        // client2 related operations
-    }
+    // A condition variable will free the mutex it is given, then do a non-
+    // intensive block until 'notify' is called on it.  In this case, since we
+    // don't ever call cv.notify, this should be a non-processor intensive version
+    // of while(true);
+    std::mutex blocker;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(blocker);
+    cv.wait(lock);
 }
 
 void server()
@@ -306,10 +321,14 @@ void server()
         return;
     }
 
-    while(1)
-    {
-        // server related operations
-    }
+    // A condition variable will free the mutex it is given, then do a non-
+    // intensive block until 'notify' is called on it.  In this case, since we
+    // don't ever call cv.notify, this should be a non-processor intensive version
+    // of while(true);
+    std::mutex blocker;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(blocker);
+    cv.wait(lock);
 }
 
 int main()
@@ -347,10 +366,14 @@ int main()
         std::thread t2(client2);
         t2.detach();
 
-        while(1)
-        {
-            // server related operations
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException& e)
     {
diff --git a/resource/include/AttributeValue.h b/resource/include/AttributeValue.h
new file mode 100644 (file)
index 0000000..5d0d524
--- /dev/null
@@ -0,0 +1,82 @@
+
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file AttributeValue.h
+
+/// @brief  This file contains the definition of the internally used
+// type AttributeValue
+
+#ifndef __ATTRIBUTEVALUE_H
+#define __ATTRIBUTEVALUE_H
+
+// These defines are required to get the boost::variant to hold more than 20 items.
+// documentation requires that you use a power of 10
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_LIST_SIZE 30
+#define BOOST_MPL_LIMIT_VECTOR_SIZE 30
+#include <boost/variant.hpp>
+
+namespace OC
+{
+    class OCRepresentation;
+
+    struct NullType{};
+    // Since null needs to be encoded in a special fashion in JSON, the encoder
+    // needs to know the index of the NullType Sentinel  Any time the code does a special
+    // case for the NullType, we use the AttributeValueNullIndex.  This MUST be kept up to date
+    // with the variant's which() for NullType.
+    static const int AttributeValueNullIndex = 0;
+    typedef boost::variant<
+
+        // Base values:
+        NullType, // Note: this handles the null-type and must match the above static const
+        int,
+        double,
+        bool,
+        std::string,
+        OC::OCRepresentation,
+
+        // Sequences:
+        std::vector<int>,
+        std::vector<double>,
+        std::vector<bool>,
+        std::vector<std::string>,
+        std::vector<OC::OCRepresentation>,
+
+        // Nested sequences:
+        std::vector<std::vector<int>>,
+        std::vector<std::vector<std::vector<int>>>,
+
+        std::vector<std::vector<double>>,
+        std::vector<std::vector<std::vector<double>>>,
+
+        std::vector<std::vector<bool>>,
+        std::vector<std::vector<std::vector<bool>>>,
+
+        std::vector<std::vector<std::string>>,
+        std::vector<std::vector<std::vector<std::string>>>,
+
+        std::vector<std::vector<OC::OCRepresentation>>,
+        std::vector<std::vector<std::vector<OC::OCRepresentation>>>
+    > AttributeValue;
+
+}
+#endif // __ATTRIBUTEVALUE_H
index a03ae76..8ec23a5 100644 (file)
@@ -33,13 +33,11 @@ namespace OC
     class IClientWrapper : public std::enable_shared_from_this<IClientWrapper>
     {
     protected:
-        OCPlatform_impl& m_owner;
 
     public:
         typedef std::shared_ptr<IClientWrapper> Ptr;
 
-        IClientWrapper(OCPlatform_impl& owner)
-         : m_owner(owner)
+        IClientWrapper()
         {}
 
         virtual OCStackResult ListenForResource(const std::string& serviceUrl,
@@ -81,13 +79,6 @@ namespace OC
         virtual OCStackResult GetDefaultQos(QualityOfService& qos) = 0;
 
         virtual ~IClientWrapper(){}
-
-
-        // Note: this should never be called by anyone but the handler for the listen command.
-        // It is public becuase that needs to be a non-instance callback
-        virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
-                        OCDevAddr& addr, const boost::property_tree::ptree resourceNode)=0;
-    private:
     };
 }
 
index 1796b02..10e0515 100644 (file)
@@ -34,13 +34,11 @@ namespace OC
     class IServerWrapper
     {
     protected:
-        OCPlatform_impl& m_owner;
 
     public:
         typedef std::shared_ptr<IServerWrapper> Ptr;
 
-        IServerWrapper(OCPlatform_impl& owner)
-         : m_owner(owner)
+        IServerWrapper()
         {}
 
         virtual ~IServerWrapper(){};
@@ -77,6 +75,8 @@ namespace OC
         virtual OCStackResult stopPresence() = 0;
 
         virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) = 0;
+
+        virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse) = 0;
     };
 }
 
index 5fecf6d..9ca0779 100644 (file)
@@ -26,9 +26,6 @@
 #include <sstream>
 #include <iostream>
 
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
 #include <OCApi.h>
 #include <ocstack.h>
 #include <IClientWrapper.h>
 
 namespace OC
 {
-    class InProcClientWrapper : public IClientWrapper
+    namespace ClientCallbackContext
     {
+        struct GetContext
+        {
+            GetCallback callback;
+        };
 
-    public:
-        enum OCSecureType
+        struct SetContext
+        {
+            PutCallback callback;
+        };
+
+        struct ListenContext
+        {
+            FindCallback callback;
+            std::weak_ptr<IClientWrapper> clientWrapper;
+        };
+
+        struct SubscribePresenceContext
         {
-            IPV4Secure,
-            IPV4
+            SubscribeCallback callback;
         };
 
-        InProcClientWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+        struct DeleteContext
+        {
+            DeleteCallback callback;
+        };
+
+        struct ObserveContext
+        {
+            ObserveCallback callback;
+        };
+    }
+
+    class InProcClientWrapper : public IClientWrapper
+    {
+
+    public:
+
+        InProcClientWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
                             PlatformConfig cfg);
         virtual ~InProcClientWrapper();
 
@@ -84,15 +110,8 @@ namespace OC
             const std::string& resourceType, SubscribeCallback& presenceHandler);
 
         virtual OCStackResult UnsubscribePresence(OCDoHandle handle);
-        // Note: this should never be called by anyone but the handler for the listen command.
-        // It is public becuase that needs to be a non-instance callback
-        virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
-            OCDevAddr& addr, const boost::property_tree::ptree resourceNode);
-
         OCStackResult GetDefaultQos(QualityOfService& QoS);
     private:
-        std::string convertOCAddrToString(OCDevAddr& addr,
-        OCSecureType type, const std::string &portStr = std::string());
         void listeningFunc();
         std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams);
         std::string assembleSetResourcePayload(const OCRepresentation& attributes);
@@ -103,7 +122,6 @@ namespace OC
         std::weak_ptr<std::recursive_mutex> m_csdkLock;
 
     private:
-        OC::OCPlatform_impl& m_owner;
         PlatformConfig  m_cfg;
     };
 }
index c74f838..aab856b 100644 (file)
@@ -32,7 +32,8 @@ namespace OC
     class InProcServerWrapper : public IServerWrapper
     {
     public:
-        InProcServerWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+        InProcServerWrapper(
+            std::weak_ptr<std::recursive_mutex> csdkLock,
             PlatformConfig cfg);
         virtual ~InProcServerWrapper();
 
@@ -69,6 +70,8 @@ namespace OC
         virtual OCStackResult stopPresence();
 
         virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler);
+
+        virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
     private:
         void processFunc();
         std::thread m_processThread;
index ec49526..97076c5 100644 (file)
 #include <memory>
 #include <iterator>
 
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-#include <boost/variant.hpp>
-
 #include "ocstack.h"
 #include "OCHeaderOption.h"
 #include <OCException.h>
 #include "StringConstants.h"
 #include "oc_logger.hpp"
 
+#include <OCRepresentation.h>
+
 namespace OC
 {
     class OCResource;
@@ -160,538 +158,7 @@ namespace OC
         Observe,
         ObserveAll
     };
-
-    // Helper function to escape character in a string.
-    std::string escapeString(const std::string& value);
-
-    typedef std::map<std::string, std::string> AttributeMap;
-
-    class OCRepresentation
-    {
-        private:
-        std::string m_uri;
-        AttributeMap m_attributeMap;
-        std::vector<std::string> m_resourceTypes;
-        std::vector<std::string> m_resourceInterfaces;
-        int errorCode;
-
-        std::vector<OCRepresentation> m_children;
-
-        public:
-        OCRepresentation() {}
-
-        bool erase(const std::string& str)
-        {
-            return m_attributeMap.erase(str) != 0;
-        }
-
-        std::string getUri(void) const
-        {
-            return m_uri;
-        }
-
-        template <typename T>
-        void setValue(const std::string& str, const T& val);
-
-        template <typename T>
-        bool getValue(const std::string& str, T& val) const;
-
-        template <typename T>
-        T getValue(const std::string& str) const;
-
-        bool hasAttribute(const std::string& str) const
-        {
-            return m_attributeMap.find(str) != m_attributeMap.end();
-        }
-
-        void setNULL(const std::string& str)
-        {
-            m_attributeMap[str] = "null";
-        }
-
-        bool isNULL(const std::string& str) const
-        {
-            auto x = m_attributeMap.find(str);
-
-            if(m_attributeMap.end() != x)
-            {
-                return x->second.compare("null") == 0;
-            }
-            else
-            {
-                std::ostringstream message;
-                message << "attribute: " << str << " doesn't exist\n";
-                throw OCException(message.str());
-            }
-
-            return false;
-        }
-
-        int numberOfAttributes() const
-        {
-            return m_attributeMap.size();
-        }
-
-        void setUri(std::string uri)
-        {
-            m_uri = uri;
-        }
-
-        std::vector<OCRepresentation> getChildren(void) const
-        {
-            return m_children;
-        }
-
-        void setChildren(const std::vector<OCRepresentation>& children)
-        {
-            m_children = children;
-        }
-
-        std::weak_ptr<OCResource> getResource() const
-        {
-            // TODO Needs to be implemented
-            std::weak_ptr<OCResource> wp;
-            return wp;
-        }
-
-        AttributeMap getAttributeMap() const
-        {
-            return m_attributeMap;
-        }
-
-        void setAttributeMap(const AttributeMap& map)
-        {
-            m_attributeMap = map;
-        }
-
-        std::string getJSONRepresentation(void) const
-        {
-            std::ostringstream json;
-
-            json << "{";
-
-            for(auto itr = m_attributeMap.begin(); itr!= m_attributeMap.end(); ++ itr)
-            {
-                if(itr != m_attributeMap.begin())
-                {
-                    json << ',';
-                }
-                json << "\""<<itr->first<<"\":"<< itr->second;
-            }
-            json << "}";
-
-            return json.str();
-        }
-
-        std::vector<std::string> getResourceTypes() const
-        {
-            return m_resourceTypes;
-        }
-
-        void setResourceTypes(const std::vector<std::string>& resourceTypes)
-        {
-            m_resourceTypes = resourceTypes;
-        }
-
-        std::vector<std::string> getResourceInterfaces(void) const
-        {
-            return m_resourceInterfaces;
-        }
-
-        void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
-        {
-            m_resourceInterfaces = resourceInterfaces;
-        }
-    };
-
-    OCRepresentation parseJSONToRepresentation(const std::string& str);
-
-    inline OCRepresentation parseJSONToRepresentation(const std::string& str)
-    {
-        OCRepresentation rep;
-
-        AttributeMap attributeMap;
-
-        std::stringstream requestStream;
-        requestStream << str;
-        boost::property_tree::ptree payload;
-        try
-        {
-            boost::property_tree::read_json(requestStream, payload);
-        }
-        catch(boost::property_tree::json_parser::json_parser_error &e)
-        {
-            throw OCException(OC::Exception::GENERAL_JSON_PARSE_FAILED);
-        }
-
-        for(auto& item: payload)
-        {
-            std::string name = item.first.data();
-            std::string value = item.second.data();
-
-            attributeMap[name] = value;
-        }
-
-        rep.setAttributeMap(attributeMap);
-
-        return rep;
-    }
-
-    typedef boost::variant<
-                int,
-                double,
-                bool,
-                OCRepresentation,
-                std::string,
-                std::vector<int>,
-                std::vector<double>,
-                std::vector<bool>,
-                std::vector<std::string>,
-                std::vector<OCRepresentation>
-                > AttributeValue;
-
-    template <typename T>
-    inline std::string getJSONFromVector(const std::vector<T>& v)
-    {
-        std::ostringstream json;
-
-        json << "\"[";
-        if(v.size() != 0)
-        {
-            std::copy(v.begin(), v.end() - 1, std::ostream_iterator<T>(json, ","));
-            json << v.back();
-        }
-        json << "]\"";
-
-        return json.str();
-    }
-
-    class ComposeVisitor : public boost::static_visitor<std::string>
-    {
-        public:
-
-            // TODO different int sizes
-            std::string operator() (const int i) const
-            {
-                return std::to_string(i);
-            }
-
-            std::string operator() (const double d) const
-            {
-                return std::to_string(d);
-            }
-
-            std::string operator() (const std::string& str) const
-            {
-                std::ostringstream json;
-                json << "\"";
-                json << str;
-                json << "\"";
-
-                return json.str();
-            }
-
-            std::string operator() (const bool b) const
-            {
-                if(b)
-                {
-                    return "true";
-                }
-                else
-                {
-                    return "false";
-                }
-            }
-
-            std::string operator() (const std::vector<int>& numbers) const
-            {
-                return getJSONFromVector(numbers);
-            }
-
-            std::string operator() (const std::vector<double>& numbers) const
-            {
-                return getJSONFromVector(numbers);
-            }
-
-            std::string operator() (const std::vector<bool>& bools) const
-            {
-                std::ostringstream json;
-                int first = 1;
-
-                json << "\"[";
-                for(auto b: bools)
-                {
-                    if(first)
-                    {
-                        b ? json << "true" : json << "false";
-                        first = 0;
-                    }
-                    else
-                    {
-                        b ? json << ",true" : json << ",false";
-                    }
-                }
-                json << "]\"";
-
-                return json.str();
-            }
-
-            std::string operator() (const std::vector<std::string>& strings) const
-            {
-                return getJSONFromVector(strings);
-            }
-
-            std::string operator() (const OCRepresentation& rep) const
-            {
-                std::ostringstream json;
-
-                json << "\"";
-
-                json << escapeString(rep.getJSONRepresentation());
-
-                json << "\"";
-
-                return json.str();
-            }
-
-            std::string operator() (const std::vector<OCRepresentation>& reps) const
-            {
-                std::ostringstream json;
-                int first = 1;
-
-                json << "\"[";
-                for(auto rep: reps)
-                {
-                    if(first)
-                    {
-                        first = 0;
-                        json << escapeString(rep.getJSONRepresentation());
-                    }
-                    else
-                    {
-                        json << ",";
-                        json << escapeString(rep.getJSONRepresentation());
-                    }
-                }
-                json << "]\"";
-
-                return json.str();
-            }
-
-
-    };
-
-    inline void split(std::string input, char delimiter, std::vector<std::string>& tokens)
-    {
-        std::stringstream ss(input);
-        std::string item;
-
-        while(std::getline(ss, item, delimiter))
-        {
-            tokens.push_back(item);
-        }
-    }
-
-    class ParseVisitor : public boost::static_visitor<void>
-    {
-        public:
-
-            ParseVisitor(std::string str): m_str(str)
-            {
-            }
-
-            void operator() (int& i) const
-            {
-                i = std::stoi(m_str);
-            }
-
-            void operator() (double& d) const
-            {
-                d = std::stod(m_str);
-            }
-
-            void operator() (std::string& str) const
-            {
-                str = m_str;
-            }
-
-            void operator() (bool& b) const
-            {
-                b = m_str.compare("true") == 0;
-            }
-
-            void operator() (std::vector<int>& numbers) const
-            {
-                numbers.clear();
-
-                if(m_str.length() >= 2)
-                {
-                    std::string str = m_str.substr(1, m_str.length()-2);
-
-                    std::vector<std::string> tokens;
-                    split(str, ',', tokens);
-
-                    for(auto s: tokens)
-                    {
-                        numbers.push_back(std::stoi(s));
-                    }
-                }
-                else
-                {
-                    throw OCException(OC::Exception::INVALID_ARRAY);
-                }
-
-            }
-
-            void operator() (std::vector<double>& numbers) const
-            {
-                numbers.clear();
-
-                if(m_str.length() >= 2)
-                {
-                    std::string str = m_str.substr(1, m_str.length()-2);
-                    std::vector<std::string> tokens;
-                    split(str, ',', tokens);
-
-                    for(auto s: tokens)
-                    {
-                        numbers.push_back(std::stod(s));
-                    }
-                }
-                else
-                {
-                    throw OCException(OC::Exception::INVALID_ARRAY);
-                }
-            }
-
-            void operator() (std::vector<bool>& bools) const
-            {
-                bools.clear();
-
-                if(m_str.length() >= 2)
-                {
-                    std::string str = m_str.substr(2, m_str.length()-3);
-
-                    std::vector<std::string> tokens;
-                    split(str, ',', tokens);
-
-                    for(auto s: tokens)
-                    {
-                        bools.push_back(s.compare("true") == 0);
-                    }
-                }
-                else
-                {
-                    throw OCException(OC::Exception::INVALID_ARRAY);
-                }
-
-            }
-
-            void operator() (std::vector<std::string>& strings) const
-            {
-                strings.clear();
-
-                if(m_str.length() >= 2)
-                {
-                    std::string str = m_str.substr(1, m_str.length()-2);
-
-                    std::vector<std::string> tokens;
-                    split(str, ',', tokens);
-
-                    for(auto s: tokens)
-                    {
-                        strings.push_back(s);
-                    }
-                }
-                else
-                {
-                    throw OCException(OC::Exception::INVALID_ARRAY);
-                }
-            }
-
-            void operator() (std::vector<OCRepresentation>& reps) const
-            {
-                reps.clear();
-
-                if(m_str.length() >= 2)
-                {
-                    std::string str = m_str.substr(1, m_str.length()-2);
-
-                    std::vector<std::string> tokens;
-                    split(str, ',', tokens);
-
-                    for(auto s: tokens)
-                    {
-                        reps.push_back(parseJSONToRepresentation(s));
-                    }
-                }
-                else
-                {
-                    throw OCException(OC::Exception::INVALID_ARRAY);
-                }
-            }
-
-            void operator() (OCRepresentation& rep) const
-            {
-                rep = parseJSONToRepresentation(m_str);
-            }
-
-        private:
-            std::string m_str;
-    };
-
-
-    inline std::string getJSON(const AttributeValue& v)
-    {
-        return boost::apply_visitor(ComposeVisitor(), v);
-    }
-
-    inline void parseJSON(AttributeValue& v, std::string str)
-    {
-        boost::apply_visitor(ParseVisitor(str), v);
-    }
-
-    template <typename T>
-    void OCRepresentation::setValue(const std::string& str, const T& val)
-    {
-        m_attributeMap[str] = getJSON(val);
-    }
-
-    template <typename T>
-    T OCRepresentation::getValue(const std::string& str) const
-    {
-        T val = T();
-
-        auto x = m_attributeMap.find(str);
-
-        if(m_attributeMap.end() != x)
-        {
-            AttributeValue v = val;
-            parseJSON(v, x->second);
-            val = boost::get<T>(v);
-        }
-
-        return val;
-    }
-
-    template <typename T>
-    bool OCRepresentation::getValue(const std::string& str, T& val) const
-    {
-        auto x = m_attributeMap.find(str);
-
-        if(m_attributeMap.end() != x)
-        {
-            AttributeValue v = val;
-            parseJSON(v, x->second);
-            val = boost::get<T>(v);
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
+    //
     // Typedef for header option vector
     // OCHeaderOption class is in HeaderOption namespace
     typedef std::vector<HeaderOption::OCHeaderOption> HeaderOptions;
@@ -729,10 +196,11 @@ namespace OC
 
     typedef std::function<void(std::shared_ptr<OCResource>)> FindCallback;
 
-    typedef std::function<OCEntityHandlerResult (const std::shared_ptr<OCResourceRequest>,
-                                const std::shared_ptr<OCResourceResponse>)> EntityHandler;
+    typedef std::function<OCEntityHandlerResult(
+                            const std::shared_ptr<OCResourceRequest>)> EntityHandler;
 
-    typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
+    typedef std::function<void(OCStackResult, const unsigned int,
+                                const std::string&)> SubscribeCallback;
 
     typedef std::function<void(const HeaderOptions&,
                                 const OCRepresentation&, const int)> GetCallback;
index 39d1792..61a0f48 100644 (file)
@@ -400,8 +400,14 @@ namespace OC
                         bool isObservable, const std::vector<std::string>& resourceTypes,
                         const std::vector<std::string>& interfaces);
 
-
-
+        /**
+        * Allows application entity handler to send response to an incoming request.
+        *
+        * @param pResponse - OCResourceResponse pointer that will permit to set values related
+        * to resource response. <br>
+        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        */
+        OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
     }
 }
 
index 47598d2..896ce3a 100644 (file)
@@ -423,6 +423,15 @@ namespace OC
                         bool isObservable, const std::vector<std::string>& resourceTypes,
                         const std::vector<std::string>& interfaces);
 
+        /**
+        * Allows application entity handler to send response to an incoming request.
+        *
+        * @param pResponse - OCResourceResponse pointer that will permit to set values related
+        * to resource response. <br>
+        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        */
+        OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
+
     private:
         PlatformConfig m_cfg;
 
@@ -442,14 +451,14 @@ namespace OC
         OCPlatform_impl(const PlatformConfig& config);
 
         /**
-        *  Private function to initalize the platfrom
+        * Private function to initalize the platfrom
         */
         void init(const PlatformConfig& config);
 
         /**
-         * Private constructor/operators to prevent copying
-         * of this object
-         */
+        * Private constructor/operators to prevent copying
+        * of this object
+        */
         OCPlatform_impl(const OCPlatform_impl& other)= delete;
         OCPlatform_impl& operator=(const OCPlatform_impl&) = delete;
         OCPlatform_impl& operator=(const OCPlatform_impl&&) = delete;
index 0a0ba16..fbfb7c5 100644 (file)
 
 /// @file OCRepresentation.h
 
-/// @brief  This file contains the declaration of classes and its members 
+/// @brief  This file contains the declaration of classes and its members
 ///         related to OCRepresentation
 
 #ifndef __OCREPRESENTATION_H
 #define __OCREPRESENTATION_H
 
 
-#include <OCApi.h>
-#include <OCResource.h>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+
+#include <AttributeValue.h>
+#include <StringConstants.h>
+
+#include <OCException.h>
+
+
+namespace cereal
+{
+    class access;
+}
 
 namespace OC
 {
-    
+
+    enum class InterfaceType
+    {
+        None,
+        LinkParent,
+        BatchParent,
+        DefaultParent,
+        LinkChild,
+        BatchChild,
+        DefaultChild
+    };
+
+    // The consumer requires resource info to be printed in 2 different ways, both with the "oc":[]
+    // and without.  This enum is used to differentiate between the two situations.  When the
+    // serialize is called with Include OC, we encode OC, otherwise we skip it and return just the
+    // contents of the array.
+    enum class OCInfoFormat
+    {
+        IncludeOC,
+        ExcludeOC
+    };
+
+    class MessageContainer
+    {
+        public:
+            void setJSONRepresentation(const std::string& payload);
+
+            void setJSONRepresentation(const unsigned char* payload);
+
+            std::string getJSONRepresentation(OCInfoFormat f) const;
+
+            const std::vector<OCRepresentation>& representations() const;
+
+            void addRepresentation(const OCRepresentation& rep);
+
+            const OCRepresentation& operator[](int index) const
+            {
+                return m_reps[index];
+            }
+
+            const OCRepresentation& back() const
+            {
+                return m_reps.back();
+            }
+        private:
+            std::vector<OCRepresentation> m_reps;
+    };
+    class OCRepresentation
+    {
+        public:
+            OCRepresentation();
+            std::string getJSONRepresentation() const;
+
+            void addChild(const OCRepresentation&);
+
+            void clearChildren();
+
+            const std::vector<OCRepresentation>& getChildren() const;
+
+            void setChildren(const std::vector<OCRepresentation>& children);
+
+            void setUri(const std::string& uri);
+
+            std::string getUri() const;
+
+            const std::vector<std::string>& getResourceTypes() const;
+
+            void setResourceTypes(const std::vector<std::string>& resourceTypes);
+
+            const std::vector<std::string>& getResourceInterfaces() const;
+
+            void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces);
+
+            bool empty() const;
+
+            int numberOfAttributes() const;
+
+            bool erase(const std::string& str);
+
+            template <typename T>
+            void setValue(const std::string& str, const T& val)
+            {
+                m_values[str] = val;
+            }
+
+            template <typename T>
+            bool getValue(const std::string& str, T& val) const
+            {
+                auto x = m_values.find(str);
+
+                if(x!= m_values.end())
+                {
+                    val = boost::get<T>(x->second);
+                    return true;
+                }
+                else
+                {
+                    val = T();
+                    return false;
+                }
+            }
+
+            template <typename T>
+            T getValue(const std::string& str) const
+            {
+                T val = T();
+                auto x = m_values.find(str);
+                if(x != m_values.end())
+                {
+                    val = boost::get<T>(x->second);
+                }
+                return val;
+            }
+
+            bool hasAttribute(const std::string& str) const;
+
+            void setNULL(const std::string& str);
+
+            bool isNULL(const std::string& str) const;
+        private:
+            friend class OCResourceResponse;
+            friend class cereal::access;
+
+            // the root node has a slightly different JSON version
+            // based on the interface type configured in ResourceResponse.
+            // This allows ResourceResponse to set it, so that the save function
+            // doesn't serialize things that it isn't supposed to serialize.
+            void setInterfaceType(InterfaceType ift)
+            {
+                m_interfaceType = ift;
+            }
+
+            // class used to wrap the 'prop' feature of the save/load
+            class Prop
+            {
+                public:
+                    Prop(std::vector<std::string>& resourceTypes,
+                            std::vector<std::string>& interfaces)
+                    : m_types(resourceTypes), m_interfaces(interfaces)
+                    {}
+
+                 /*   Prop(const std::vector<std::string>& resourceTypes,
+                            const std::vector<std::string>& interfaces)
+                    :m_types(resourceTypes),
+                    m_interfaces(interfaces)
+                    {}*/
+                private:
+                    friend class cereal::access;
+                    template <class Archive>
+                    void save(Archive& ar) const;
+
+                    template<class Archive>
+                    void load(Archive& ar);
+
+                    std::vector<std::string>& m_types;
+                    std::vector<std::string>& m_interfaces;
+            };
+            template<class Archive, class Val>
+            static void optional_load(Archive& ar, Val&& v);
+
+            template<class Archive>
+            void save(Archive& ar) const;
+
+            template<class Archive>
+            void load(Archive& ar);
+
+        private:
+            std::string m_uri;
+            std::vector<OCRepresentation> m_children;
+            std::map<std::string, AttributeValue> m_values;
+            std::vector<std::string> m_resourceTypes;
+            std::vector<std::string> m_interfaces;
+
+            InterfaceType m_interfaceType;
+    };
 } // namespace OC
 
+
 #endif //__OCREPRESENTATION_H
index 5d5802c..63c4253 100644 (file)
@@ -30,9 +30,6 @@
 #include <random>
 #include <algorithm>
 
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
 #include <OCApi.h>
 #include <ResourceInitException.h>
 #include <IClientWrapper.h>
@@ -52,8 +49,7 @@ namespace OC
     class OCResource
     {
     friend class OCPlatform_impl;
-    friend class InProcClientWrapper;
-
+    friend class ListenOCContainer;
     public:
         typedef std::shared_ptr<OCResource> Ptr;
         /**
index 890a4a7..a435b47 100644 (file)
 #ifndef __OCRESOURCEREQUEST_H
 #define __OCRESOURCEREQUEST_H
 
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
 #include "OCApi.h"
 #include "OCRepresentation.h"
 
+void formResourceRequest(OCEntityHandlerFlag,
+                         OCEntityHandlerRequest*,
+                         std::shared_ptr<OC::OCResourceRequest>);
+
+
 namespace OC
 {
     /**
@@ -77,7 +79,8 @@ namespace OC
 
         /**
         *  Provides the entire resource attribute representation
-        *  @return OCRepresentation reference containing the name value pairs representing the resource's attributes
+        *  @return OCRepresentation reference containing the name value pairs
+        *   representing the resource's attributes
         */
         const OCRepresentation& getResourceRepresentation() const {return m_representation;}
 
@@ -104,10 +107,35 @@ namespace OC
             return m_resourceUri;
         }
 
-        /** This API retrieves headerOptions which was sent from a client
+        /**
+        * This API retrieves headerOptions which was sent from a client
+        *
         * @return std::map HeaderOptions with the header options
         */
-        const HeaderOptions& getHeaderOptions() const {return m_headerOptions;}
+        const HeaderOptions& getHeaderOptions() const
+        {
+            return m_headerOptions;
+        }
+
+        /**
+        * This API retrieves the request handle
+        *
+        * @return OCRequestHandle
+        */
+        const OCRequestHandle& getRequestHandle() const
+        {
+            return m_requestHandle;
+        }
+
+        /**
+        * This API retrieves the resource handle
+        *
+        * return OCResourceHandle
+        */
+        const OCResourceHandle& getResourceHandle() const
+        {
+            return m_resourceHandle;
+        }
 
     private:
         std::string m_requestType;
@@ -117,79 +145,82 @@ namespace OC
         OCRepresentation m_representation;
         ObservationInfo m_observationInfo;
         HeaderOptions m_headerOptions;
+        OCRequestHandle m_requestHandle;
+        OCResourceHandle m_resourceHandle;
 
-    public:
-        // TODO: This is not a public API for app developers.
-        // This function will not be exposed in future
+
+    private:
+        friend void (::formResourceRequest)(OCEntityHandlerFlag, OCEntityHandlerRequest*,
+            std::shared_ptr<OC::OCResourceRequest>);
         void setRequestType(const std::string& requestType)
         {
             m_requestType = requestType;
         }
 
-        // TODO: This is not a public API for app developers.
-        // This function will not be exposed in future
         void setPayload(const std::string& requestPayload)
         {
-            AttributeMap attributeMap;
-            // TODO: The following JSON Parse implementation should be seperated into utitilites
-            // and used wherever required.
-            // e.g. parse(std::string& payload, Attributemap& attributeMap)
-
-            std::stringstream requestStream;
-            requestStream << requestPayload;
-            boost::property_tree::ptree root;
-            try
+            MessageContainer info;
+            info.setJSONRepresentation(requestPayload);
+
+            const std::vector<OCRepresentation>& reps = info.representations();
+            if(reps.size() >0)
             {
-                boost::property_tree::read_json(requestStream, root);
+                std::vector<OCRepresentation>::const_iterator itr = reps.begin();
+                std::vector<OCRepresentation>::const_iterator back = reps.end();
+                m_representation = *itr;
+                ++itr;
+
+                for(;itr != back; ++itr)
+                {
+                    m_representation.addChild(*itr);
+                }
             }
-            catch(boost::property_tree::json_parser::json_parser_error &e)
+            else
             {
-                //TOD: log this
-                return;
+                throw OCException(OC::Exception::INVALID_REPRESENTATION);
             }
-
-            // TODO this expects the representation oc:{} and not oc:[{}]
-            //      this representation is fine when setting for simple resource.
-            boost::property_tree::ptree payload = root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
-
-            for(auto& item: payload)
-            {
-                std::string name = item.first.data();
-                std::string value = item.second.data();
-
-                attributeMap[name] = value;
-            }
-
-            m_representation.setAttributeMap(attributeMap);
         }
 
-        // TODO: This is not a public API for app developers.
-        // This function will not be exposed in future
         void setQueryParams(QueryParamsMap& queryParams)
         {
             m_queryParameters = queryParams;
         }
 
-        // TODO: This is not a public API for app developers.
-        // This function will not be exposed in future
         void setRequestHandlerFlag(int requestHandlerFlag)
         {
             m_requestHandlerFlag = requestHandlerFlag;
         }
 
-        // TODO: This is not a public API for app developers.
-        // This function will not be exposed in future
         void setObservationInfo(const ObservationInfo& observationInfo)
         {
             m_observationInfo = observationInfo;
         }
 
-        // TODO: This is not a public API for app developers.
-        // This function will not be exposed in future
         void setHeaderOptions(const HeaderOptions& headerOptions)
         {
             m_headerOptions = headerOptions;
         }
+
+        /**
+        * This API allows to set request handle
+        * @param requestHandle - OCRequestHandle type used to set the
+        * request handle
+        */
+        void setRequestHandle(const OCRequestHandle& requestHandle)
+        {
+            m_requestHandle = requestHandle;
+        }
+
+        /**
+        * This API allows to set the resource handle
+        * @param resourceHandle - OCResourceHandle type used to set the
+        * resource handle
+        */
+        void setResourceHandle(const OCResourceHandle& resourceHandle)
+        {
+            m_resourceHandle = resourceHandle;
+        }
+
     };
  }// namespace OC
 
index 4cd371f..1c8e3fa 100644 (file)
@@ -35,6 +35,8 @@ using namespace std;
 
 namespace OC
 {
+    class InProcServerWrapper;
+
     /**
     *   @brief  OCResourceResponse provides APIs to set the response details
     */
@@ -43,14 +45,9 @@ namespace OC
     public:
         typedef std::shared_ptr<OCResourceResponse> Ptr;
 
-        /**
-        *  Default destructor
-        */
-        OCResourceResponse() {}
+        OCResourceResponse()
+        {}
 
-        /**
-        *  Virtual destructor
-        */
         virtual ~OCResourceResponse(void) {}
 
         /**
@@ -87,25 +84,44 @@ namespace OC
         }
 
         /**
+        * This API allows to set request handle
+        *
+        * @param requestHandle - OCRequestHandle type used to set the request handle
+        */
+        void setRequestHandle(const OCRequestHandle& requestHandle)
+        {
+            m_requestHandle = requestHandle;
+        }
+
+        /**
+        * This API allows to set the resource handle
+        *
+        * @param resourceHandle - OCResourceHandle type used to set the resource handle
+        */
+        void setResourceHandle(const OCResourceHandle& resourceHandle)
+        {
+            m_resourceHandle = resourceHandle;
+        }
+
+        /**
+        * This API allows to set the EntityHandler response result
+        *
+        * @param responseResult - OCEntityHandlerResult type to set the result value
+        */
+        void setResponseResult(const OCEntityHandlerResult& responseResult)
+        {
+            m_responseResult = responseResult;
+        }
+
+        /**
         *  API to set the entire resource attribute representation
         *  @param attributeMap reference containing the name value pairs representing
         *         the resource's attributes
         *  @param interface specifies the interface
         */
         void setResourceRepresentation(OCRepresentation& rep, std::string interface) {
-            if(!interface.compare(LINK_INTERFACE))
-            {
-                setResourceRepresentationLL(rep);
-            }
-            else if(!interface.compare(BATCH_INTERFACE))
-            {
-                setResourceRepresentationBatch(rep);
-            }
-            else
-            {
-                setResourceRepresentationDefault(rep);
-            }
-            // TODO other interfaces
+            m_interface = interface;
+            m_representation = rep;
         }
 
         /**
@@ -125,7 +141,8 @@ namespace OC
         */
         void setResourceRepresentation(OCRepresentation& rep) {
             // Call the default
-            setResourceRepresentationDefault(rep);
+            m_interface = DEFAULT_INTERFACE;
+            m_representation = rep;
         }
 
         /**
@@ -137,187 +154,62 @@ namespace OC
             // Call the above function
             setResourceRepresentation(rep);
         }
+    private:
+        std::string m_newResourceUri;
+        int m_errorCode;
+        HeaderOptions m_headerOptions;
+        std::string m_interface;
+        OCRepresentation m_representation;
+        OCRequestHandle m_requestHandle;
+        OCResourceHandle m_resourceHandle;
+        OCEntityHandlerResult m_responseResult;
 
-        /**
-        *  API to set the entire resource attribute representation (Linked List Interface))
-        *  @param attributeMap reference containing the name value pairs representing the resource's
-        *  attributes
-        */
-        void setResourceRepresentationLL(OCRepresentation& rep) {
-
-            // Default Set
-
-            ostringstream payload;
-
-            // Parent
-            payload << "{";
-            payload << "\"href\":";
-            payload << "\"" ;
-            payload << rep.getUri();
-            payload << "\"" ;
-            payload << "}";
+    private:
+        friend class InProcServerWrapper;
 
-            // Children stuff
-            std::vector<OCRepresentation> children = rep.getChildren();
+        std::string getPayload() const
+        {
+            MessageContainer inf;
+            OCRepresentation first(m_representation);
 
-            for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
+            if(m_interface==LINK_INTERFACE)
             {
-                payload << ",{\"href\":";
-
-                payload << "\"" ;
-                payload << oitr->getUri();
-                payload << "\"" ;
-
-                payload << ",\"prop\":{";
-
-                payload << "\"rt\":[";
-                std::vector<std::string> types = oitr->getResourceTypes();
-                for(auto itr = types.begin(); itr != types.end(); ++itr)
-                {
-                    if(itr != types.begin())
-                    {
-                        payload << ',';
-                    }
-
-                    payload << *itr;
-                }
-                payload << "],";
-
-                payload << "\"if\":[";
-                std::vector<std::string> interfaces = oitr->getResourceInterfaces();
-                for(auto itr = interfaces.begin(); itr != interfaces.end(); ++itr)
-                {
-                    if(itr != interfaces.begin())
-                    {
-                        payload << ',';
-                    }
-
-                    payload << "\"" << *itr << "\"";
-                }
-                payload << "]";
-
-                payload << "}}";
+                first.setInterfaceType(InterfaceType::LinkParent);
             }
-
-            m_payload = payload.str();
-        }
-
-        /**
-        *  API to set the entire resource attribute representation (Default))
-        *  @param attributeMap reference containing the name value pairs representing the resource's
-        *  attributes
-        */
-        void setResourceRepresentationDefault(OCRepresentation& rep) {
-
-            // Default Set
-
-            ostringstream payload;
-
-            // Parent
-            payload << "{";
-            payload << "\"href\":";
-            payload << "\"" ;
-            payload << rep.getUri();
-            payload << "\"" ;
-
-            payload << ",\"rep\":";
-
-            payload << rep.getJSONRepresentation();
-
-            payload << "}";
-
-            // Children stuff
-            std::vector<OCRepresentation> children = rep.getChildren();
-
-            for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
+            else if(m_interface==BATCH_INTERFACE)
             {
-                payload << ",{\"href\":";
+                first.setInterfaceType(InterfaceType::BatchParent);
+            }
+            else
+            {
+                first.setInterfaceType(InterfaceType::DefaultParent);
+            }
 
-                payload << "\"" ;
-                payload << oitr->getUri();
-                payload << "\"" ;
+            inf.addRepresentation(first);
 
-                payload << ",\"prop\":{";
+            for(const OCRepresentation& rep : m_representation.getChildren())
+            {
+                OCRepresentation cur(rep);
 
-                payload << "\"rt\":[";
-                std::vector<std::string> types = oitr->getResourceTypes();
-                for(auto itr = types.begin(); itr != types.end(); ++itr)
+                if(m_interface==LINK_INTERFACE)
                 {
-                    if(itr != types.begin())
-                    {
-                        payload << ',';
-                    }
-
-                    payload << "\"" << *itr << "\"";
+                    cur.setInterfaceType(InterfaceType::LinkChild);
                 }
-                payload << "],";
-
-                payload << "\"if\":[";
-                std::vector<std::string> interfaces = oitr->getResourceInterfaces();
-                for(auto itr = interfaces.begin(); itr != interfaces.end(); ++itr)
+                else if(m_interface==BATCH_INTERFACE)
                 {
-                    if(itr != interfaces.begin())
-                    {
-                        payload << ',';
-                    }
-
-                    payload << "\"" << *itr << "\"";
+                    cur.setInterfaceType(InterfaceType::BatchChild);
+                }
+                else
+                {
+                    cur.setInterfaceType(InterfaceType::DefaultChild);
                 }
-                payload << "]";
-
-                payload << "}}";
-            }
-
-            m_payload = payload.str();
-        }
-
-        /**
-        *  API to set the entire resource attribute representation (BATCH)
-        *  @param attributeMap reference containing the name value pairs representing the resource's
-        *  attributes
-        */
-        void setResourceRepresentationBatch(OCRepresentation& rep) {
-            ostringstream payload;
-
-            // Parent
-            payload << "{";
-            payload << "\"href\":";
-            payload << "\"" ;
-            payload << rep.getUri();
-            payload << "\"" ;
-            payload << "}";
-
-            std::vector<OCRepresentation> children = rep.getChildren();
-
-            for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
-            {
-                payload << ',';
-
-                payload << "{";
-
-                payload << "\"href\":";
-
-                payload << "\"" ;
-                payload << oitr->getUri();
-                payload << "\"" ;
-
-                payload << ",\"rep\":";
 
-                payload << oitr->getJSONRepresentation();
+                inf.addRepresentation(cur);
 
-                payload << "}";
             }
 
-            m_payload = payload.str();
+            return inf.getJSONRepresentation(OCInfoFormat::ExcludeOC);
         }
-
-    private:
-        std::string m_newResourceUri;
-        std::string m_payload;
-        int m_errorCode;
-        HeaderOptions m_headerOptions;
-
-    // TODO only stack should have visibility and apps should not
     public:
 
         /**
@@ -326,6 +218,13 @@ namespace OC
         int getErrorCode() const;
 
         /**
+         * Get the Response Representation
+         */
+        const OCRepresentation& getResourceRepresentation() const
+        {
+            return m_representation;
+        }
+        /**
         * This API allows to retrieve headerOptions from a response
         */
         const HeaderOptions& getHeaderOptions() const
@@ -334,14 +233,33 @@ namespace OC
         }
 
         /**
-        * Get the resource attribute representation
+        * This API retrieves the request handle
+        *
+        * @return OCRequestHandle value
         */
-        AttributeMap& getResourceRepresentation() const;
+        const OCRequestHandle& getRequestHandle() const
+        {
+            return m_requestHandle;
+        }
 
-        // TODO This should go away & just use getResourceRepresentation
-        std::string getPayload()
+        /**
+        * This API retrieves the resource handle
+        *
+        * @return OCResourceHandle value
+        */
+        const OCResourceHandle& getResourceHandle() const
+        {
+            return m_resourceHandle;
+        }
+
+        /**
+        * This API retrieves the entity handle response result
+        *
+        * @return OCEntityHandler result value
+        */
+        const OCEntityHandlerResult getResponseResult() const
         {
-            return m_payload;
+            return m_responseResult;
         }
     };
 
diff --git a/resource/include/OCSerialization.h b/resource/include/OCSerialization.h
new file mode 100644 (file)
index 0000000..f611407
--- /dev/null
@@ -0,0 +1,280 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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 <cereal/cereal.hpp>
+#include <cereal/types/memory.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/archives/json.hpp>
+
+#include <StringConstants.h>
+
+namespace OC
+{
+    class ListenOCContainer
+    {
+        private:
+        enum class OCSecureType
+        {
+            IPv4Secure,
+            IPv4
+        };
+
+        class ListenResourceContainer
+        {
+            class ListenResourcePropertiesContainer
+            {
+                friend class cereal::access;
+                friend class ListenResourceContainer;
+
+                template<class Archive>
+                void serialize(Archive& ar)
+                {
+                    try
+                    {
+                        m_observable=false;
+                        int obsTemp;
+                        ar(cereal::make_nvp(OC::Key::OBSERVABLEKEY, obsTemp));
+                        m_observable = obsTemp != 0;
+                    }
+                    catch(cereal::Exception&)
+                    {
+                        // we swallow this exception, since it means the key
+                        // doesn't exist, allowing these to be optional
+                        ar.setNextName(nullptr);
+                    }
+
+                    try
+                    {
+                        m_secure = false;
+                        int secureTemp;
+                        ar(cereal::make_nvp(OC::Key::SECUREKEY, secureTemp));
+                        m_secure = secureTemp != 0;
+
+                        m_port = -1;
+                        ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
+                    }
+                    catch(cereal::Exception&)
+                    {
+                        ar.setNextName(nullptr);
+                    }
+
+                    try
+                    {
+                        ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
+                    }
+                    catch(cereal::Exception&)
+                    {
+                        ar.setNextName(nullptr);
+                    }
+                    try
+                    {
+                        ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
+                    }
+                    catch(cereal::Exception&)
+                    {
+                        ar.setNextName(nullptr);
+                    }
+                }
+
+                bool m_observable;
+                std::vector<std::string> m_resourceTypes;
+                std::vector<std::string> m_interfaces;
+                bool m_secure;
+                int m_port;
+            };
+
+            public:
+            ListenResourceContainer() : m_loaded(false)
+            {}
+
+            private:
+            friend class cereal::access;
+            friend class ListenOCContainer;
+
+            template <class Archive>
+            void serialize(Archive& ar)
+            {
+                try
+                {
+                    ar(cereal::make_nvp(OC::Key::URIKEY, m_uri));
+                    m_loaded=true;
+                }
+                catch(cereal::Exception&)
+                {
+                    ar.setNextName(nullptr);
+                }
+                try
+                {
+                    ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
+                    m_loaded=true;
+                }
+                catch(cereal::Exception&)
+                {
+                    ar.setNextName(nullptr);
+                }
+            }
+
+
+            std::string m_uri;
+            bool m_loaded;
+            ListenResourcePropertiesContainer m_props;
+
+            bool loaded() const
+            {
+                return m_loaded;
+            }
+
+            bool observable() const
+            {
+                return m_props.m_observable;
+            }
+
+            OCSecureType secureType() const
+            {
+                return m_props.m_secure?OCSecureType::IPv4Secure :OCSecureType::IPv4;
+            }
+
+            int port() const
+            {
+                return m_props.m_port;
+            }
+
+            std::vector<std::string> resourceTypes() const
+            {
+                return m_props.m_resourceTypes;
+            }
+
+            std::vector<std::string> interfaces() const
+            {
+                return m_props.m_interfaces;
+            }
+        };
+
+        private:
+            friend class cereal::access;
+            template <class Archive>
+            void serialize(Archive& ar)
+            {
+                std::vector<ListenResourceContainer> resources;
+                ar(resources);
+            }
+        public:
+            ListenOCContainer(std::weak_ptr<IClientWrapper> cw, const OCDevAddr& address,
+                    std::stringstream& json):
+                m_clientWrapper(cw), m_address(address)
+            {
+                LoadFromJson(json);
+            }
+
+            const std::vector<std::shared_ptr<OCResource>>& Resources() const
+            {
+                return m_resources;
+            }
+
+        private:
+            std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
+            {
+                char stringAddress[DEV_ADDR_SIZE_MAX];
+                uint16_t port;
+
+                ostringstream os;
+
+                if(sec== OCSecureType::IPv4)
+                {
+                    os<<"coap://";
+                }
+                else if(sec == OCSecureType::IPv4Secure)
+                {
+                    os<<"coaps://";
+                }
+                else
+                {
+                    oclog() << "ConvertOCAddrToString():  invalid SecureType"<<std::flush;
+                    throw ResourceInitException(false, false, false, false, false, true);
+                }
+
+                if(0== OCDevAddrToString(&m_address, stringAddress))
+                {
+                    // nothing to do, successful case.
+                }
+                else
+                {
+                    oclog() << "ConvertOCAddrToString(): Invalid Ip"
+                        << std::flush;
+                    throw ResourceInitException(false, false, false, false, false, true);
+                }
+
+                os<<stringAddress;
+
+                if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
+                {
+                    port = static_cast<uint16_t>(secureport);
+                }
+                else if(sec == OCSecureType::IPv4 && 0==OCDevAddrToPort(&m_address, &port))
+                {
+                    // nothing to do, this is a successful case
+                }
+                else
+                {
+                    oclog() << "ConvertOCAddrToString() : Invalid Port"
+                        <<std::flush;
+                    throw ResourceInitException(false, false, false, false, true, false);
+                }
+
+                os <<":"<< static_cast<int>(port);
+
+                return os.str();
+            }
+
+            void LoadFromJson(std::stringstream& json)
+            {
+                cereal::JSONInputArchive archive(json);
+
+                std::vector<ListenResourceContainer> resources;
+                archive(cereal::make_nvp(OC::Key::OCKEY, resources));
+
+                m_resources.clear();
+
+                for(const auto& res : resources)
+                {
+                    try
+                    {
+                        if(res.loaded())
+                        {
+                            m_resources.push_back(std::shared_ptr<OCResource>(
+                                new OCResource(m_clientWrapper,
+                                    ConvertOCAddrToString(res.secureType(),res.port()),
+                                    res.m_uri, res.observable(), res.resourceTypes(),
+                                    res.interfaces())));
+                        }
+
+                    }
+                    catch(ResourceInitException& e)
+                    {
+                        oclog() << "listenCallback(): failed to create resource: " << e.what()
+                                << std::flush;
+                    }
+                }
+            }
+            std::vector<std::shared_ptr<OC::OCResource>> m_resources;
+            std::weak_ptr<IClientWrapper> m_clientWrapper;
+            OCDevAddr m_address;
+    };
+}
diff --git a/resource/include/OicJsonSerializer.hpp b/resource/include/OicJsonSerializer.hpp
new file mode 100644 (file)
index 0000000..d7eb98e
--- /dev/null
@@ -0,0 +1,847 @@
+/*! \file OicJsonSerializer.hpp
+    \brief JSON input and output archives.
+Note: this has been customized by Intel(R) for usage in the OIC project.
+Nearly the entire file is from Cereal (see copyright notice below) other than specified
+below
+Added:
+#include of AttributeValue Type
+JSONOutputArchive::saveValue() to add JSON null value
+loadAttributeValues to get attribute values out of a map (implemented in OCRepresentation)
+
+*/
+/*
+  Copyright (c) 2014, Randolph Voorhies, Shane Grant
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+      * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+      * Neither the name of cereal nor the
+        names of its contributors may be used to endorse or promote products
+        derived from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CEREAL_ARCHIVES_JSON_HPP_
+#define CEREAL_ARCHIVES_JSON_HPP_
+
+#include <AttributeValue.h>
+#include <cereal/cereal.hpp>
+#include <cereal/details/util.hpp>
+namespace cereal
+{
+  //! An exception thrown when rapidjson fails an internal assertion
+  /*! @ingroup Utility */
+  struct RapidJSONException : Exception
+  { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
+}
+
+// Override rapidjson assertions to throw exceptions by default
+#ifndef RAPIDJSON_ASSERT
+#define RAPIDJSON_ASSERT(x) if(!(x)){ \
+  throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
+#endif // RAPIDJSON_ASSERT
+
+#include <cereal/external/rapidjson/writer.h>
+#include <cereal/external/rapidjson/genericstream.h>
+#include <cereal/external/rapidjson/reader.h>
+#include <cereal/external/rapidjson/document.h>
+#include <cereal/external/base64.hpp>
+
+#include <limits>
+#include <sstream>
+#include <stack>
+#include <vector>
+#include <string>
+
+namespace cereal
+{
+  // ######################################################################
+  //! An output archive designed to save data to JSON
+  /*! This archive uses RapidJSON to build serialie data to JSON.
+
+      JSON archives provides a human readable output but at decreased
+      performance (both in time and space) compared to binary archives.
+
+      JSON benefits greatly from name-value pairs, which if present, will
+      name the nodes in the output.  If these are not present, each level
+      of the output will be given an automatically generated delimited name.
+
+      The precision of the output archive controls the number of decimals output
+      for floating point numbers and should be sufficiently large (i.e. at least 20)
+      if there is a desire to have binary equality between the numbers output and
+      those read in.  In general you should expect a loss of precision when going
+      from floating point to text and back.
+
+      JSON archives do not output the size information for any dynamically sized structure
+      and instead infer it from the number of children for a node.  This means that data
+      can be hand edited for dynamic sized structures and will still be readable.  This
+      is accomplished through the cereal::SizeTag object, which will cause the archive
+      to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates
+      that the container is variable sized and may be edited.
+
+      \ingroup Archives */
+  class JSONOutputArchive : public OutputArchive<JSONOutputArchive>
+  {
+    enum class NodeType { StartObject, InObject, StartArray, InArray };
+
+    typedef rapidjson::GenericWriteStream WriteStream;
+    typedef rapidjson::Writer<WriteStream> JSONWriter;
+
+    public:
+      /*! @name Common Functionality
+          Common use cases for directly interacting with an JSONOutputArchive */
+      //! @{
+
+      //! A class containing various advanced options for the JSON archive
+      class Options
+      {
+        public:
+          //! Default options
+          static Options Default(){ return Options(); }
+
+          //! Specify specific options for the JSONOutputArchive
+          /*! @param precision The precision used for floating point numbers*/
+          explicit Options( int precision = std::numeric_limits<double>::max_digits10) :
+            itsPrecision( precision ) { }
+
+        private:
+          friend class JSONOutputArchive;
+          int itsPrecision;
+      };
+
+      //! Construct, outputting to the provided stream
+      /*! @param stream The stream to output to.
+          @param options The JSON specific options to use.  See the Options struct
+                         for the values of default parameters */
+      JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
+        OutputArchive<JSONOutputArchive>(this),
+        itsWriteStream(stream),
+        itsWriter(itsWriteStream, options.itsPrecision),
+        itsNextName(nullptr)
+      {
+        itsNameCounter.push(0);
+        itsNodeStack.push(NodeType::StartObject);
+      }
+
+      //! Destructor, flushes the JSON
+      ~JSONOutputArchive()
+      {
+        itsWriter.EndObject();
+      }
+
+      //! Saves some binary data, encoded as a base64 string, with an optional name
+      /*! This will create a new node, optionally named, and insert a value that consists of
+          the data encoded as a base64 string */
+      void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
+      {
+        setNextName( name );
+        writeName();
+
+        auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
+        saveValue( base64string );
+      };
+
+      //! @}
+      /*! @name Internal Functionality
+          Functionality designed for use by those requiring control over the inner mechanisms of
+          the JSONOutputArchive */
+      //! @{
+
+      //! Starts a new node in the JSON output
+      /*! The node can optionally be given a name by calling setNextName prior
+          to creating the node
+
+          Nodes only need to be started for types that are themselves objects or arrays */
+      void startNode()
+      {
+        writeName();
+        itsNodeStack.push(NodeType::StartObject);
+        itsNameCounter.push(0);
+      }
+
+      //! Designates the most recently added node as finished
+      void finishNode()
+      {
+        // if we ended up serializing an empty object or array, writeName
+        // will never have been called - so start and then immediately end
+        // the object/array.
+        //
+        // We'll also end any object/arrays we happen to be in
+        switch(itsNodeStack.top())
+        {
+          case NodeType::StartArray:
+            itsWriter.StartArray();
+          case NodeType::InArray:
+            itsWriter.EndArray();
+            break;
+          case NodeType::StartObject:
+            itsWriter.StartObject();
+          case NodeType::InObject:
+            itsWriter.EndObject();
+            break;
+        }
+
+        itsNodeStack.pop();
+        itsNameCounter.pop();
+      }
+
+      //! Sets the name for the next node created with startNode
+      void setNextName( const char * name )
+      {
+        itsNextName = name;
+      }
+
+      //! Saves a null to the current node, added by Intel
+      void saveValue()                      { itsWriter.Null_();                                                         }
+      //! Saves a bool to the current node
+      void saveValue(bool b)                { itsWriter.Bool_(b);                                                         }
+      //! Saves an int to the current node
+      void saveValue(int i)                 { itsWriter.Int(i);                                                          }
+      //! Saves a uint to the current node
+      void saveValue(unsigned u)            { itsWriter.Uint(u);                                                         }
+      //! Saves an int64 to the current node
+      void saveValue(int64_t i64)           { itsWriter.Int64(i64);                                                      }
+      //! Saves a uint64 to the current node
+      void saveValue(uint64_t u64)          { itsWriter.Uint64(u64);                                                     }
+      //! Saves a double to the current node
+      void saveValue(double d)              { itsWriter.Double(d);                                                       }
+      //! Saves a string to the current node
+      void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
+      //! Saves a const char * to the current node
+      void saveValue(char const * s)        { itsWriter.String(s);                                                       }
+
+    public:
+#ifdef _MSC_VER
+      //! MSVC only long overload to current node
+      void saveValue( unsigned long lu ){ saveLong( lu ); };
+#else // _MSC_VER
+      //! Serialize a long if it would not be caught otherwise
+      template <class T> inline
+      typename std::enable_if<std::is_same<T, long>::value &&
+                              !std::is_same<T, std::int32_t>::value &&
+                              !std::is_same<T, std::int64_t>::value, void>::type
+      saveValue( T t )
+      {
+          saveLong( t );
+          return t;
+      }
+
+      //! Serialize an unsigned long if it would not be caught otherwise
+      template <class T> inline
+      typename std::enable_if<std::is_same<T, unsigned long>::value &&
+                              !std::is_same<T, std::uint32_t>::value &&
+                              !std::is_same<T, std::uint64_t>::value, void>::type
+      saveValue( T t )
+      {
+          saveLong( t );
+          return t;
+      }
+#endif // _MSC_VER
+
+      //! Save exotic arithmetic as strings to current node
+      /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */
+      template<class T> inline
+      typename std::enable_if<std::is_arithmetic<T>::value &&
+                              !std::is_same<T, long>::value &&
+                              !std::is_same<T, unsigned long>::value &&
+                              !std::is_same<T, std::int64_t>::value &&
+                              !std::is_same<T, std::uint64_t>::value &&
+                              (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
+      saveValue(T const & t)
+      {
+        std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
+        ss << t;
+        saveValue( ss.str() );
+        return t;
+      }
+
+      //! Write the name of the upcoming node and prepare object/array state
+      /*! Since writeName is called for every value that is output, regardless of
+          whether it has a name or not, it is the place where we will do a deferred
+          check of our node state and decide whether we are in an array or an object.
+
+          The general workflow of saving to the JSON archive is:
+
+            1. (optional) Set the name for the next node to be created, usually done by an NVP
+            2. Start the node
+            3. (if there is data to save) Write the name of the node (this function)
+            4. (if there is data to save) Save the data (with saveValue)
+            5. Finish the node
+          */
+      void writeName()
+      {
+        NodeType const & nodeType = itsNodeStack.top();
+
+        // Start up either an object or an array, depending on state
+        if(nodeType == NodeType::StartArray)
+        {
+          itsWriter.StartArray();
+          itsNodeStack.top() = NodeType::InArray;
+        }
+        else if(nodeType == NodeType::StartObject)
+        {
+          itsNodeStack.top() = NodeType::InObject;
+          itsWriter.StartObject();
+        }
+
+        // Array types do not output names
+        if(nodeType == NodeType::InArray) return;
+
+        if(itsNextName == nullptr)
+        {
+          std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
+          saveValue(name);
+        }
+        else
+        {
+          saveValue(itsNextName);
+          itsNextName = nullptr;
+        }
+      }
+
+      //! Designates that the current node should be output as an array, not an object
+      void makeArray()
+      {
+        itsNodeStack.top() = NodeType::StartArray;
+      }
+
+      //! @}
+
+    private:
+      WriteStream itsWriteStream;          //!< Rapidjson write stream
+      JSONWriter itsWriter;                //!< Rapidjson writer
+      char const * itsNextName;            //!< The next name
+      std::stack<uint32_t> itsNameCounter; //!< Counter for creating unique names for unnamed nodes
+      std::stack<NodeType> itsNodeStack;
+  }; // JSONOutputArchive
+
+  // ######################################################################
+  //! An input archive designed to load data from JSON
+  /*! This archive uses RapidJSON to read in a JSON archive.
+
+      Input JSON should have been produced by the JSONOutputArchive.  Data can
+      only be added to dynamically sized containers (marked by JSON arrays) -
+      the input archive will determine their size by looking at the number of child nodes.
+      Only JSON originating from a JSONOutputArchive is officially supported, but data
+      from other sources may work if properly formatted.
+
+      The JSONInputArchive does not require that nodes are loaded in the same
+      order they were saved by JSONOutputArchive.  Using name value pairs (NVPs),
+      it is possible to load in an out of order fashion or otherwise skip/select
+      specific nodes to load.
+
+      The default behavior of the input archive is to read sequentially starting
+      with the first node and exploring its children.  When a given NVP does
+      not match the read in name for a node, the archive will search for that
+      node at the current level and load it if it exists.  After loading an out of
+      order node, the archive will then proceed back to loading sequentially from
+      its new position.
+
+      Consider this simple example where loading of some data is skipped:
+
+      @code{cpp}
+      // imagine the input file has someData(1-9) saved in order at the top level node
+      ar( someData1, someData2, someData3 );        // XML loads in the order it sees in the file
+      ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not
+                                                    // match expected NVP name, so we search
+                                                    // for the given NVP and load that value
+      ar( someData7, someData8, someData9 );        // with no NVP given, loading resumes at its
+                                                    // current location, proceeding sequentially
+      @endcode
+
+      \ingroup Archives */
+  class JSONInputArchive : public InputArchive<JSONInputArchive>
+  {
+    private:
+      typedef rapidjson::GenericReadStream ReadStream;
+      typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
+      typedef JSONValue::ConstMemberIterator MemberIterator;
+      typedef JSONValue::ConstValueIterator ValueIterator;
+      typedef rapidjson::Document::GenericValue GenericValue;
+
+    public:
+      /*! @name Common Functionality
+          Common use cases for directly interacting with an JSONInputArchive */
+      //! @{
+
+      //! Construct, reading from the provided stream
+      /*! @param stream The stream to read from */
+      JSONInputArchive(std::istream & stream) :
+        InputArchive<JSONInputArchive>(this),
+        itsNextName( nullptr ),
+        itsReadStream(stream)
+      {
+        itsDocument.ParseStream<0>(itsReadStream);
+        itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
+      }
+
+      //! Loads some binary data, encoded as a base64 string
+      /*! This will automatically start and finish a node to load the data, and can be called directly by
+          users.
+
+          Note that this follows the same ordering rules specified in the class description in regards
+          to loading in/out of order */
+      void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
+      {
+        itsNextName = name;
+
+        std::string encoded;
+        loadValue( encoded );
+        auto decoded = base64::decode( encoded );
+
+        if( size != decoded.size() )
+          throw Exception("Decoded binary data size does not match specified size");
+
+        std::memcpy( data, decoded.data(), decoded.size() );
+        itsNextName = nullptr;
+      };
+
+      // Intel Added this as a custom parsing hook for the AttributeValue map
+      void loadAttributeValues(std::map<std::string, OC::AttributeValue>& map);
+
+    private:
+      //! @}
+      /*! @name Internal Functionality
+          Functionality designed for use by those requiring control over the inner mechanisms of
+          the JSONInputArchive */
+      //! @{
+
+      //! An internal iterator that handles both array and object types
+      /*! This class is a variant and holds both types of iterators that
+          rapidJSON supports - one for arrays and one for objects. */
+      class Iterator
+      {
+        public:
+          friend class cereal::JSONInputArchive;
+          Iterator() : itsIndex( 0 ), itsType(Null_) {}
+
+          Iterator(MemberIterator begin, MemberIterator end) :
+            itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
+          { }
+
+          Iterator(ValueIterator begin, ValueIterator end) :
+            itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
+          { }
+
+          //! Advance to the next node
+          Iterator & operator++()
+          {
+            ++itsIndex;
+            return *this;
+          }
+
+          //! Get the value of the current node
+          GenericValue const & value()
+          {
+            switch(itsType)
+            {
+              case Value : return itsValueItBegin[itsIndex];
+              case Member: return itsMemberItBegin[itsIndex].value;
+              default: throw cereal::Exception("Invalid Iterator Type!");
+            }
+          }
+
+          //! Get the name of the current node, or nullptr if it has no name
+          const char * name() const
+          {
+            if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
+              return itsMemberItBegin[itsIndex].name.GetString();
+            else
+              return nullptr;
+          }
+
+          //! Adjust our position such that we are at the node with the given name
+          /*! @throws Exception if no such named node exists */
+          inline void search( const char * searchName )
+          {
+            const auto len = std::strlen( searchName );
+            size_t index = 0;
+            for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
+              if( std::strncmp( searchName, it->name.GetString(), len ) == 0 )
+              {
+                itsIndex = index;
+                return;
+              }
+
+            throw Exception("JSON Parsing failed - provided NVP not found");
+          }
+
+        private:
+          MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
+          ValueIterator itsValueItBegin, itsValueItEnd;    //!< The value iterator (array)
+          size_t itsIndex;                                 //!< The current index of this iterator
+          enum Type {Value, Member, Null_} itsType;    //!< Whether this holds values (array) or members (objects) or nothing
+      };
+
+      //! Searches for the expectedName node if it doesn't match the actualName
+      /*! This needs to be called before every load or node start occurs.  This function will
+          check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual
+          next name given.  If the names do not match, it will search in the current level of the JSON for that name.
+          If the name is not found, an exception will be thrown.
+
+          Resets the NVP name after called.
+
+          @throws Exception if an expectedName is given and not found */
+      inline void search()
+      {
+        // The name an NVP provided with setNextName()
+        if( itsNextName )
+        {
+          // The actual name of the current node
+          auto const actualName = itsIteratorStack.back().name();
+
+          // Do a search if we don't see a name coming up, or if the names don't match
+          if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
+            itsIteratorStack.back().search( itsNextName );
+        }
+
+        itsNextName = nullptr;
+      }
+
+    public:
+      //! Starts a new node, going into its proper iterator
+      /*! This places an iterator for the next node to be parsed onto the iterator stack.  If the next
+          node is an array, this will be a value iterator, otherwise it will be a member iterator.
+
+          By default our strategy is to start with the document root node and then recursively iterate through
+          all children in the order they show up in the document.
+          We don't need to know NVPs to do this; we'll just blindly load in the order things appear in.
+
+          If we were given an NVP, we will search for it if it does not match our the name of the next node
+          that would normally be loaded.  This functionality is provided by search(). */
+      void startNode()
+      {
+        search();
+
+        if(itsIteratorStack.back().value().IsArray())
+          itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
+        else
+          itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
+      }
+
+      //! Finishes the most recently started node
+      void finishNode()
+      {
+        itsIteratorStack.pop_back();
+        ++itsIteratorStack.back();
+      }
+
+      //! Sets the name for the next node created with startNode
+      void setNextName( const char * name )
+      {
+        itsNextName = name;
+      }
+
+      //! Loads a value from the current node - small signed overload
+      template<class T> inline
+      typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int64_t), void>::type
+      loadValue(T & val)
+      {
+        search();
+
+        val = itsIteratorStack.back().value().GetInt();
+        ++itsIteratorStack.back();
+      }
+
+      //! Loads a value from the current node - small unsigned overload
+      template<class T> inline
+      typename std::enable_if<(std::is_unsigned<T>::value && sizeof(T) < sizeof(uint64_t)) &&
+                              !std::is_same<bool, T>::value, void>::type
+      loadValue(T & val)
+      {
+        search();
+
+        val = itsIteratorStack.back().value().GetUint();
+        ++itsIteratorStack.back();
+      }
+
+      //! Loads a value from the current node - bool overload
+      void loadValue(bool & val)        { search(); val = itsIteratorStack.back().value().GetBool_();   ++itsIteratorStack.back(); }
+      //! Loads a value from the current node - int64 overload
+      void loadValue(int64_t & val)     { search(); val = itsIteratorStack.back().value().GetInt64();  ++itsIteratorStack.back(); }
+      //! Loads a value from the current node - uint64 overload
+      void loadValue(uint64_t & val)    { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
+      //! Loads a value from the current node - float overload
+      void loadValue(float & val)       { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
+      //! Loads a value from the current node - double overload
+      void loadValue(double & val)      { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
+      //! Loads a value from the current node - string overload
+      void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
+
+    private:
+      //! Convert a string to a long long
+      void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
+      //! Convert a string to an unsigned long long
+      void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
+      //! Convert a string to a long double
+      void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
+
+    public:
+      //! Loads a value from the current node - long double and long long overloads
+      template<class T> inline
+      typename std::enable_if<std::is_arithmetic<T>::value &&
+                              !std::is_same<T, long>::value &&
+                              !std::is_same<T, unsigned long>::value &&
+                              !std::is_same<T, std::int64_t>::value &&
+                              !std::is_same<T, std::uint64_t>::value &&
+                              (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
+      loadValue(T & val)
+      {
+        std::string encoded;
+        loadValue( encoded );
+        stringToNumber( encoded, val );
+      }
+
+      //! Loads the size for a SizeTag
+      void loadSize(size_type & size)
+      {
+        size = (itsIteratorStack.rbegin() + 1)->value().Size();
+      }
+
+      //! @}
+
+    private:
+      const char * itsNextName;               //!< Next name set by NVP
+      ReadStream itsReadStream;               //!< Rapidjson write stream
+      std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
+      rapidjson::Document itsDocument;        //!< Rapidjson document
+  };
+
+  // ######################################################################
+  // JSONArchive prologue and epilogue functions
+  // ######################################################################
+
+  // ######################################################################
+  //! Prologue for NVPs for JSON archives
+  /*! NVPs do not start or finish nodes - they just set up the names */
+  template <class T> inline
+  void prologue( JSONOutputArchive &, NameValuePair<T> const & )
+  { }
+
+  //! Prologue for NVPs for JSON archives
+  template <class T> inline
+  void prologue( JSONInputArchive &, NameValuePair<T> const & )
+  { }
+
+  // ######################################################################
+  //! Epilogue for NVPs for JSON archives
+  /*! NVPs do not start or finish nodes - they just set up the names */
+  template <class T> inline
+  void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
+  { }
+
+  //! Epilogue for NVPs for JSON archives
+  /*! NVPs do not start or finish nodes - they just set up the names */
+  template <class T> inline
+  void epilogue( JSONInputArchive &, NameValuePair<T> const & )
+  { }
+
+  // ######################################################################
+  //! Prologue for SizeTags for JSON archives
+  /*! SizeTags are strictly ignored for JSON, they just indicate
+      that the current node should be made into an array */
+  template <class T> inline
+  void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
+  {
+    ar.makeArray();
+  }
+
+  //! Prologue for SizeTags for JSON archives
+  template <class T> inline
+  void prologue( JSONInputArchive &, SizeTag<T> const & )
+  { }
+
+  // ######################################################################
+  //! Epilogue for SizeTags for JSON archives
+  /*! SizeTags are strictly ignored for JSON */
+  template <class T> inline
+  void epilogue( JSONOutputArchive &, SizeTag<T> const & )
+  { }
+
+  //! Epilogue for SizeTags for JSON archives
+  template <class T> inline
+  void epilogue( JSONInputArchive &, SizeTag<T> const & )
+  { }
+
+  // ######################################################################
+  //! Prologue for all other types for JSON archives (except minimal types)
+  /*! Starts a new node, named either automatically or by some NVP,
+      that may be given data by the type about to be archived
+
+      Minimal types do not start or finish nodes */
+  template <class T> inline
+  typename std::enable_if<!std::is_arithmetic<T>::value &&
+                          !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
+  prologue( JSONOutputArchive & ar, T const & )
+  {
+    ar.startNode();
+  }
+
+  //! Prologue for all other types for JSON archives
+  template <class T> inline
+  typename std::enable_if<!std::is_arithmetic<T>::value &&
+                          !traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
+  prologue( JSONInputArchive & ar, T const & )
+  {
+    ar.startNode();
+  }
+
+  // ######################################################################
+  //! Epilogue for all other types other for JSON archives (except minimal types
+  /*! Finishes the node created in the prologue
+
+      Minimal types do not start or finish nodes */
+  template <class T> inline
+  typename std::enable_if<!std::is_arithmetic<T>::value &&
+                          !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
+  epilogue( JSONOutputArchive & ar, T const & )
+  {
+    ar.finishNode();
+  }
+
+  //! Epilogue for all other types other for JSON archives
+  template <class T> inline
+  typename std::enable_if<!std::is_arithmetic<T>::value &&
+                          !traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
+  epilogue( JSONInputArchive & ar, T const & )
+  {
+    ar.finishNode();
+  }
+
+  // ######################################################################
+  //! Prologue for arithmetic types for JSON archives
+  template <class T> inline
+  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+  prologue( JSONOutputArchive & ar, T const & )
+  {
+    ar.writeName();
+  }
+
+  //! Prologue for arithmetic types for JSON archives
+  template <class T> inline
+  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+  prologue( JSONInputArchive &, T const & )
+  { }
+
+  // ######################################################################
+  //! Epilogue for arithmetic types for JSON archives
+  template <class T> inline
+  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+  epilogue( JSONOutputArchive &, T const & )
+  { }
+
+  //! Epilogue for arithmetic types for JSON archives
+  template <class T> inline
+  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+  epilogue( JSONInputArchive &, T const & )
+  { }
+
+  // ######################################################################
+  //! Prologue for strings for JSON archives
+  template<class CharT, class Traits, class Alloc> inline
+  void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
+  {
+    ar.writeName();
+  }
+
+  //! Prologue for strings for JSON archives
+  template<class CharT, class Traits, class Alloc> inline
+  void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+  { }
+
+  // ######################################################################
+  //! Epilogue for strings for JSON archives
+  template<class CharT, class Traits, class Alloc> inline
+  void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+  { }
+
+  //! Epilogue for strings for JSON archives
+  template<class CharT, class Traits, class Alloc> inline
+  void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+  { }
+
+  // ######################################################################
+  // Common JSONArchive serialization functions
+  // ######################################################################
+
+  //! Serializing NVP types to JSON
+  template <class T> inline
+  void save( JSONOutputArchive & ar, NameValuePair<T> const & t )
+  {
+    ar.setNextName( t.name );
+    ar( t.value );
+  }
+
+  template <class T> inline
+  void load( JSONInputArchive & ar, NameValuePair<T> & t )
+  {
+    ar.setNextName( t.name );
+    ar( t.value );
+  }
+
+  //! Saving for arithmetic to JSON
+  template<class T> inline
+  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+  save(JSONOutputArchive & ar, T const & t)
+  {
+    ar.saveValue( t );
+  }
+
+  //! Loading arithmetic from JSON
+  template<class T> inline
+  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+  load(JSONInputArchive & ar, T & t)
+  {
+    ar.loadValue( t );
+  }
+
+  //! saving string to JSON
+  template<class CharT, class Traits, class Alloc> inline
+  void save(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
+  {
+    ar.saveValue( str );
+  }
+
+  //! loading string from JSON
+  template<class CharT, class Traits, class Alloc> inline
+  void load(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
+  {
+    ar.loadValue( str );
+  }
+
+  // ######################################################################
+  //! Saving SizeTags to JSON
+  template <class T> inline
+  void save( JSONOutputArchive &, SizeTag<T> const & )
+  {
+    // nothing to do here, we don't explicitly save the size
+  }
+
+  //! Loading SizeTags from JSON
+  template <class T> inline
+  void load( JSONInputArchive & ar, SizeTag<T> & st )
+  {
+    ar.loadSize( st.size );
+  }
+} // namespace cereal
+
+// register archives for polymorphic support
+CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
+CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
+
+#endif // CEREAL_ARCHIVES_JSON_HPP_
index 07f5c6a..dfae653 100644 (file)
@@ -28,9 +28,8 @@ namespace OC
     class OutOfProcClientWrapper : public IClientWrapper
     {
     public:
-        OutOfProcClientWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+        OutOfProcClientWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
                                 PlatformConfig cfg)
-         : IClientWrapper(owner)
         {}
 
         virtual OCStackResult ListenForResource(const std::string& serviceUrl,
@@ -69,12 +68,6 @@ namespace OC
             const std::string& uri,
             const HeaderOptions& headerOptions, QualityOfService QoS){return OC_STACK_NOTIMPL;}
 
-        virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
-            OCDevAddr& addr, const boost::property_tree::ptree resourceNode)
-        {
-            return nullptr;
-        }
-
         virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host,
             const std::string& resourceType, SubscribeCallback& presenceHandler)
         {return OC_STACK_NOTIMPL;}
index 9f3b09c..be51f3d 100644 (file)
@@ -28,9 +28,8 @@ namespace OC
     class OutOfProcServerWrapper : public IServerWrapper
     {
     public:
-        OutOfProcServerWrapper(OC::OCPlatform_impl& owner, PlatformConfig cfg)
-         : IServerWrapper(owner)
-        {};
+        OutOfProcServerWrapper(PlatformConfig cfg)
+        {}
 
         virtual OCStackResult registerResource(
                     OCResourceHandle& resourceHandle,
@@ -92,12 +91,17 @@ namespace OC
             return OC_STACK_NOTIMPL;
         }
 
-
         virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler)
         {
             //Not implemented yet
             return OC_STACK_NOTIMPL;
         }
+
+        virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+        {
+           //Not implemented yet
+           return OC_STACK_NOTIMPL;
+        }
     };
 }
 
index a3ebea6..c045b6c 100644 (file)
@@ -30,11 +30,32 @@ namespace OC
     class ResourceInitException : public std::exception
     {
     public:
-        ResourceInitException(bool missingUri, bool missingType, bool missingInterface, bool missingClientWrapper)
-        : m_missingUri(missingUri), m_missingType(missingType), m_missingInterface(missingInterface), m_missingClientWrapper(missingClientWrapper)
+        ResourceInitException(
+                bool missingUri,
+                bool missingType,
+                bool missingInterface,
+                bool missingClientWrapper,
+                bool invalidPort,
+                bool invalidIp)
+        : m_missingUri(missingUri),
+          m_missingType(missingType),
+          m_missingInterface(missingInterface),
+          m_missingClientWrapper(missingClientWrapper),
+          m_invalidPort(invalidPort),
+          m_invalidIp(invalidIp)
         {
         }
 
+        bool isInvalidPort() const
+        {
+            return m_invalidPort;
+        }
+
+        bool isInvalidIp() const
+        {
+            return m_invalidIp;
+        }
+
         bool isClientWrapperMissing() const
         {
             return m_missingClientWrapper;
@@ -79,6 +100,16 @@ namespace OC
                 ret += OC::InitException::MISSING_CLIENT_WRAPPER;
             }
 
+            if(isInvalidPort())
+            {
+                ret += OC::InitException::INVALID_PORT;
+            }
+
+            if(isInvalidIp())
+            {
+                ret += OC::InitException::INVALID_IP;
+            }
+
             return ret.c_str();
         }
 
@@ -88,6 +119,8 @@ namespace OC
         bool m_missingType;
         bool m_missingInterface;
         bool m_missingClientWrapper;
+        bool m_invalidPort;
+        bool m_invalidIp;
     };
 }
 
index e8b4b5a..b29fb0c 100644 (file)
@@ -91,8 +91,17 @@ namespace OC
         static const std::string INVALID_OPTION             = "Invalid option";
         static const std::string GENERAL_FAULT              = "General Fault";
         static const std::string MALFORMED_STACK_RESPONSE   = "Response from OC_STACK is malformed";
+        static const std::string VIRTUAL_DO_NOT_HANDLE      = "Virtual Do Not Handle";
+        static const std::string PERSISTENT_BUFFER_REQUIRED = "Persistent response buffer required";
+        static const std::string STACK_CONTINUE             = "Stack continue";
+        static const std::string INVALID_REQUEST_HANDLE     = "Invalid request handle";
         static const std::string UNKNOWN_ERROR              = "Unknown Error";
-
+        static const std::string INVALID_REPRESENTATION     = "Invalid Payload JSON";
+        static const std::string INVALID_JSON_TYPE          = "Unrecognized JSON Type ";
+        static const std::string INVALID_JSON_NUMERIC       = "Unrecognized JSON Numeric ";
+        static const std::string INVALID_JSON_ARRAY_DEPTH   = "Max JSON Array Depth exceeded";
+        static const std::string INVALID_JSON_TYPE_TAG      = "Invalid JSON Type Tag";
+        static const std::string INVALID_ATTRIBUTE          = "Invalid Attribute: ";
     }
 
     namespace Error
index 5aa23a2..2f15b80 100644 (file)
@@ -39,9 +39,9 @@ namespace OC
     public:
         typedef std::shared_ptr<IWrapperFactory> Ptr;
 
-        virtual IClientWrapper::Ptr CreateClientWrapper(OC::OCPlatform_impl& owner,
+        virtual IClientWrapper::Ptr CreateClientWrapper(
             std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0;
-        virtual IServerWrapper::Ptr CreateServerWrapper(OC::OCPlatform_impl& owner,
+        virtual IServerWrapper::Ptr CreateServerWrapper(
             std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0;
         virtual ~IWrapperFactory(){}
     };
@@ -52,28 +52,28 @@ namespace OC
     public:
         WrapperFactory(){}
 
-        virtual IClientWrapper::Ptr CreateClientWrapper(OC::OCPlatform_impl& owner,
+        virtual IClientWrapper::Ptr CreateClientWrapper(
             std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
         {
             switch(cfg.serviceType)
             {
             case ServiceType::InProc:
-                return std::make_shared<InProcClientWrapper>(owner, csdkLock, cfg);
+                return std::make_shared<InProcClientWrapper>(csdkLock, cfg);
                 break;
             case ServiceType::OutOfProc:
-                return std::make_shared<OutOfProcClientWrapper>(owner, csdkLock, cfg);
+                return std::make_shared<OutOfProcClientWrapper>(csdkLock, cfg);
                 break;
             }
                        return nullptr;
         }
 
-        virtual IServerWrapper::Ptr CreateServerWrapper(OC::OCPlatform_impl& owner,
+        virtual IServerWrapper::Ptr CreateServerWrapper(
             std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
         {
             switch(cfg.serviceType)
             {
             case ServiceType::InProc:
-                return std::make_shared<InProcServerWrapper>(owner, csdkLock, cfg);
+                return std::make_shared<InProcServerWrapper>(csdkLock, cfg);
                 break;
             case ServiceType::OutOfProc:
                 throw OC::OCException(OC::Exception::SVCTYPE_OUTOFPROC, OC_STACK_NOTIMPL);
index 3d3d3bd..a710781 100644 (file)
@@ -31,6 +31,9 @@ ifeq ($(PLATFORM), )
        PLATFORM := "linux"
 endif
 
+DEPEND_DIR:= $(ROOT_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 OUT_DIR          := $(ROOT_DIR)/$(BUILD)
 OBJ_DIR          := $(OUT_DIR)/obj
 
@@ -45,20 +48,34 @@ CXX_INC       += -I./csdk/ocsocket/include
 CXX_INC          += -I./csdk/ocrandom/include
 CXX_INC          += -I./csdk/logger/include
 CXX_INC          += -I./csdk/libcoap
-
+CXX_INC   += -I$(CEREAL_DIR)/include
 # Force metatargets to build:
-all.PHONY: prep_dirs c_sdk oc_logger_target liboc.a examples
+all.PHONY: applyDepPatches prep_dirs c_sdk oc_logger_target liboc.a examples
 
-buildScript_all.PHONY: prep_dirs oc_logger_target liboc.a
+buildScript_all.PHONY: applyDepPatches prep_dirs oc_logger_target liboc.a
 
 all:   all.PHONY
 
 buildScript_all:  buildScript_all.PHONY
 
-prep_dirs:
+prep_dirs: deps
        -mkdir -p $(OUT_DIR)
        -mkdir -p $(OBJ_DIR)
 
+# used to fetch all dependencies
+deps:
+       -mkdir -p $(DEPEND_DIR)
+#cereal fetch
+       if [ ! -d "$(CEREAL_DIR)" ]; then\
+               cd $(DEPEND_DIR) && git clone https://github.com/USCiLab/cereal.git;\
+               cd $(CEREAL_DIR) && git checkout 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;\
+       fi
+
+applyDepPatches: deps
+#reset git to the 'base version', so we can apply our patch without issues
+       cd $(CEREAL_DIR) && git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;
+       cd $(CEREAL_DIR) && git apply $(ROOT_DIR)/patches/cereal_gcc46.patch
+
 c_sdk:
        cd csdk && $(MAKE) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)"
 
@@ -70,8 +87,8 @@ cpp_sdk: prep_dirs c_sdk liboc.a
 examples: liboc.a
        cd examples && $(MAKE) apps "BUILD=$(BUILD)"
 
-liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o
-       ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o
+liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o OCRepresentation.o
+       ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o $(OBJ_DIR)/OCRepresentation.o
 
 OCPlatform_impl.o: src/OCPlatform_impl.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform_impl.cpp $(CXX_INC)
@@ -79,6 +96,9 @@ OCPlatform_impl.o: src/OCPlatform_impl.cpp
 OCPlatform.o: src/OCPlatform.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform.cpp $(CXX_INC)
 
+OCRepresentation.o: src/OCRepresentation.cpp
+       $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCRepresentation.cpp $(CXX_INC)
+
 OCResource.o: src/OCResource.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCResource.cpp $(CXX_INC)
 
index 465627b..0b18e4d 100644 (file)
@@ -1,33 +1,36 @@
 ##
-# liboctbstack (static library) build script
+# liboc_logger (share library) build script
 ##
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 
-# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-
-liboc_logger_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
+liboc_logger_env = lib_env.Clone()
 ######################################################################
 # Build flags
 ######################################################################
 liboc_logger_env.PrependUnique(CPPPATH = ['include'])
 
-if BUILD_TARGET == 'android':
+target_os = env.get('TARGET_OS')
+if target_os == 'android':
        liboc_logger_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        liboc_logger_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+       liboc_logger_env.AppendUnique(LIBS = ['gnustl_static', 'log'])
 
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
-       liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99'])
-       liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x'])
+if target_os not in ['arduino', 'windows', 'winrt']:
+       liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99', '-fPIC'])
+       liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x', '-fPIC'])
 
 ######################################################################
 # Source files and Targets
 ######################################################################
-liboc_logger_core = liboc_logger_env.StaticLibrary('oc_logger_core', 'c/oc_logger.c',  OBJPREFIX='core')
-liboc_logger = liboc_logger_env.StaticLibrary('oc_logger',
+liboc_logger_core = liboc_logger_env.SharedLibrary('oc_logger_core', 'c/oc_logger.c',  OBJPREFIX='core_')
+liboc_logger = liboc_logger_env.SharedLibrary('oc_logger',
                ['c/oc_logger.c', 'c/oc_console_logger.c', 'cpp/oc_ostream_logger.cpp'])
-i_loggers = liboc_logger_env.Install(BUILD_DIR, [liboc_logger_core, liboc_logger])
-Alias('liboc_logger', i_loggers)
-env.AppendUnique(TS = ['liboc_logger'])
\ No newline at end of file
+
+liboc_logger_env.InstallTarget([liboc_logger_core, liboc_logger], 'liboc_logger')
+
+if target_os not in ['ios']:
+       SConscript('examples/SConscript')
diff --git a/resource/oc_logger/examples/SConscript b/resource/oc_logger/examples/SConscript
new file mode 100644 (file)
index 0000000..d3205ba
--- /dev/null
@@ -0,0 +1,35 @@
+##
+# liboc_logger examples build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+examples_env.PrependUnique(CPPPATH = ['../include'])
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+examples_env.AppendUnique(LIBS = ['oc_logger', 'stdc++'])
+
+target_os = env.get('TARGET_OS')
+if target_os == 'android':
+       examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+       examples_env.AppendUnique(LIBS = ['gnustl_static'])
+
+if target_os not in ['arduino', 'windows', 'winrt']:
+       examples_env.AppendUnique(CFLAGS = Split('-Wall -std=c99 -Werror'))
+       examples_env.AppendUnique(CXXFLAGS = Split('-Wall -std=c++0x'))
+
+######################################################################
+# Source files and Targets
+######################################################################
+examples_c = examples_env.Program('examples_c', 'test_logging.c', OBJPREFIX='c_')
+examples_cpp = examples_env.Program('examples_cpp', 'test_logging.cpp')
+
+Alias('liboc_logger_examples', [examples_c, examples_cpp])
+examples_env.AppendTarget('liboc_logger_examples')
\ No newline at end of file
index 0128006..61a6a58 100644 (file)
@@ -92,5 +92,6 @@ int main()
  basic_demo();
  c_demo();
  alternative_demo();
+ return 0;
 }
 
diff --git a/resource/patches/cereal_gcc46.patch b/resource/patches/cereal_gcc46.patch
new file mode 100644 (file)
index 0000000..c4da84f
--- /dev/null
@@ -0,0 +1,485 @@
+From 17300ee96e42f8848d27db6fc97f04de293662d8 Mon Sep 17 00:00:00 2001
+From: Erich Keane <erich.keane@intel.com>
+Date: Thu, 6 Nov 2014 14:37:00 -0800
+Subject: [PATCH] Get this to work on g++4.6.3
+
+---
+ include/cereal/cereal.hpp                  |  2 +-
+ include/cereal/details/helpers.hpp         | 32 ++++++++--------
+ include/cereal/details/traits.hpp          | 61 +++++++++++++++++-------------
+ include/cereal/external/rapidjson/reader.h | 13 ++-----
+ include/cereal/external/rapidjson/writer.h | 12 ++----
+ include/cereal/types/common.hpp            | 19 +++++++---
+ include/cereal/types/memory.hpp            | 10 ++---
+ 7 files changed, 77 insertions(+), 72 deletions(-)
+
+diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp
+index b2858af..a219729 100644
+--- a/include/cereal/cereal.hpp
++++ b/include/cereal/cereal.hpp
+@@ -856,7 +856,7 @@ namespace cereal
+           std::uint32_t version;
+           process( make_nvp<ArchiveType>("cereal_class_version", version) );
+-          itsVersionedTypes.emplace_hint( lookupResult, hash, version );
++          itsVersionedTypes.insert( lookupResult, std::pair<std::size_t, std::uint32_t>(hash, version) );
+           return version;
+         }
+diff --git a/include/cereal/details/helpers.hpp b/include/cereal/details/helpers.hpp
+index e792d44..60e13c8 100644
+--- a/include/cereal/details/helpers.hpp
++++ b/include/cereal/details/helpers.hpp
+@@ -55,7 +55,7 @@ namespace cereal
+   /*! To ensure compatability between 32, 64, etc bit machines, we need to use
+    * a fixed size type instead of size_t, which may vary from machine to
+    * machine. */
+-  using size_type = uint64_t;
++   typedef uint64_t size_type;
+   // forward decls
+   class BinaryOutputArchive;
+@@ -138,12 +138,12 @@ namespace cereal
+       // otherwise, we store a reference.  If we were passed an array, don't
+       // decay the type - keep it as an array, and then proceed as normal
+       // with the RValue business
+-      using DT = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
++      typedef typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
+                                            typename std::remove_cv<T>::type,
+-                                           typename std::decay<T>::type>::type;
+-      using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
++                                           typename std::decay<T>::type>::type DT;
++      typedef typename std::conditional<std::is_rvalue_reference<T>::value,
+                                              DT,
+-                                             typename std::add_lvalue_reference<DT>::type>::type;
++                                             typename std::add_lvalue_reference<DT>::type>::type Type;
+       // prevent nested nvps
+       static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
+                      "Cannot pair a name to a NameValuePair" );
+@@ -207,9 +207,9 @@ namespace cereal
+   {
+     //! Internally store the pointer as a void *, keeping const if created with
+     //! a const pointer
+-    using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
++    typedef typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
+                                          const void *,
+-                                         void *>::type;
++                                         void *>::type PT;
+     BinaryData( T && d, uint64_t s ) : data(d), size(s) {}
+@@ -248,10 +248,10 @@ namespace cereal
+     private:
+       // If we get passed an RValue, we'll just make a local copy if it here
+       // otherwise, we store a reference
+-      using DT = typename std::decay<T>::type;
+-      using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
++      typedef typename std::decay<T>::type DT;
++      typedef typename std::conditional<std::is_rvalue_reference<T>::value,
+                                              DT,
+-                                             typename std::add_lvalue_reference<DT>::type>::type;
++                                             typename std::add_lvalue_reference<DT>::type>::type Type;
+     public:
+       SizeTag( T && sz ) : size(const_cast<Type>(sz)) {}
+@@ -283,17 +283,17 @@ namespace cereal
+   template <class Key, class Value>
+   struct MapItem
+   {
+-    using DecayKey = typename std::decay<Key>::type;
+-    using KeyType = typename std::conditional<
++    typedef typename std::decay<Key>::type DecayKey;
++    typedef typename std::conditional<
+       std::is_rvalue_reference<Key>::value,
+       DecayKey,
+-      typename std::add_lvalue_reference<DecayKey>::type>::type;
++      typename std::add_lvalue_reference<DecayKey>::type>::type KeyType;
+-    using DecayValue = typename std::decay<Value>::type;
+-    using ValueType =  typename std::conditional<
++    typedef typename std::decay<Value>::type DecayValue;
++    typedef  typename std::conditional<
+       std::is_rvalue_reference<Value>::value,
+       DecayValue,
+-      typename std::add_lvalue_reference<DecayValue>::type>::type;
++      typename std::add_lvalue_reference<DecayValue>::type>::type ValueType;
+     //! Construct a MapItem from a key and a value
+     /*! @internal */
+diff --git a/include/cereal/details/traits.hpp b/include/cereal/details/traits.hpp
+index 871886f..011054b 100644
+--- a/include/cereal/details/traits.hpp
++++ b/include/cereal/details/traits.hpp
+@@ -411,12 +411,12 @@ namespace cereal
+       };
+       template <class T, class A, bool Valid>
+-      struct get_member_save_minimal_type { using type = void; };
++      struct get_member_save_minimal_type { typedef void type; };
+       template <class T, class A>
+       struct get_member_save_minimal_type<T, A, true>
+       {
+-        using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>() ) );
++        typedef decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>() ) ) type;
+       };
+     } // end namespace detail
+@@ -428,7 +428,7 @@ namespace cereal
+         "cereal detected a non-const member save_minimal.  "
+         "save_minimal member functions must always be const" );
+-      using type = typename detail::get_member_save_minimal_type<T, A, check::value>::type;
++      typedef typename detail::get_member_save_minimal_type<T, A, check::value>::type type;
+       static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+         "cereal detected a member save_minimal with an invalid return type.  "
+         "return type must be arithmetic or string" );
+@@ -473,12 +473,12 @@ namespace cereal
+       };
+       template <class T, class A, bool Valid>
+-      struct get_member_versioned_save_minimal_type { using type = void; };
++      struct get_member_versioned_save_minimal_type { typedef void type; };
+       template <class T, class A>
+       struct get_member_versioned_save_minimal_type<T, A, true>
+       {
+-        using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) );
++        typedef decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) ) type;
+       };
+     } // end namespace detail
+@@ -490,7 +490,7 @@ namespace cereal
+         "cereal detected a versioned non-const member save_minimal.  "
+         "save_minimal member functions must always be const" );
+-      using type = typename detail::get_member_versioned_save_minimal_type<T, A, check::value>::type;
++      typedef typename detail::get_member_versioned_save_minimal_type<T, A, check::value>::type type;
+       static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+         "cereal detected a versioned member save_minimal with an invalid return type.  "
+         "return type must be arithmetic or string" );
+@@ -519,12 +519,12 @@ namespace cereal
+       };
+       template <class T, class A, bool Valid>
+-      struct get_non_member_save_minimal_type { using type = void; };
++      struct get_non_member_save_minimal_type { typedef void type; };
+       template <class T, class A>
+       struct get_non_member_save_minimal_type <T, A, true>
+       {
+-        using type = decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>() ) );
++        typedef decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>() ) ) type;
+       };
+     } // end namespace detail
+@@ -536,7 +536,7 @@ namespace cereal
+         "cereal detected a non-const type parameter in non-member save_minimal.  "
+         "save_minimal non-member functions must always pass their types as const" );
+-      using type = typename detail::get_non_member_save_minimal_type<T, A, check::value>::type;
++      typedef typename detail::get_non_member_save_minimal_type<T, A, check::value>::type type;
+       static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+         "cereal detected a non-member save_minimal with an invalid return type.  "
+         "return type must be arithmetic or string" );
+@@ -565,12 +565,12 @@ namespace cereal
+       };
+       template <class T, class A, bool Valid>
+-      struct get_non_member_versioned_save_minimal_type { using type = void; };
++      struct get_non_member_versioned_save_minimal_type { typedef void type; };
+       template <class T, class A>
+       struct get_non_member_versioned_save_minimal_type <T, A, true>
+       {
+-        using type = decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) );
++        typedef decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) ) type;
+       };
+     } // end namespace detail
+@@ -582,7 +582,7 @@ namespace cereal
+         "cereal detected a non-const type parameter in versioned non-member save_minimal.  "
+         "save_minimal non-member functions must always pass their types as const" );
+-      using type = typename detail::get_non_member_versioned_save_minimal_type<T, A, check::value>::type;
++      typedef typename detail::get_non_member_versioned_save_minimal_type<T, A, check::value>::type type;
+       static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+         "cereal detected a non-member versioned save_minimal with an invalid return type.  "
+         "return type must be arithmetic or string" );
+@@ -608,7 +608,7 @@ namespace cereal
+       template <class Source>
+       struct NoConvertConstRef : NoConvertBase
+       {
+-        using type = Source; //!< Used to get underlying type easily
++        typedef Source type; //!< Used to get underlying type easily
+         template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
+         operator Dest () = delete;
+@@ -626,7 +626,7 @@ namespace cereal
+       template <class Source>
+       struct NoConvertRef : NoConvertBase
+       {
+-        using type = Source; //!< Used to get underlying type easily
++        typedef Source type; //!< Used to get underlying type easily
+         template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
+         operator Dest () = delete;
+@@ -698,7 +698,7 @@ namespace cereal
+           "cereal detected member load_minimal but no valid member save_minimal.  "
+           "cannot evaluate correctness of load_minimal without valid save_minimal." );
+-        using SaveType = typename detail::get_member_save_minimal_type<T, A, true>::type;
++        typedef typename detail::get_member_save_minimal_type<T, A, true>::type SaveType;
+         const static bool value = has_member_load_minimal_impl<T, A>::value;
+         const static bool valid = has_member_load_minimal_type_impl<T, A, SaveType>::value;
+@@ -759,7 +759,7 @@ namespace cereal
+           "cereal detected member versioned load_minimal but no valid member versioned save_minimal.  "
+           "cannot evaluate correctness of load_minimal without valid save_minimal." );
+-        using SaveType = typename detail::get_member_versioned_save_minimal_type<T, A, true>::type;
++        typedef typename detail::get_member_versioned_save_minimal_type<T, A, true>::type SaveType;
+         const static bool value = has_member_versioned_load_minimal_impl<T, A>::value;
+         const static bool valid = has_member_versioned_load_minimal_type_impl<T, A, SaveType>::value;
+@@ -814,8 +814,8 @@ namespace cereal
+           "cereal detected non-member load_minimal but no valid non-member save_minimal.  "
+           "cannot evaluate correctness of load_minimal without valid save_minimal." );
+-        using SaveType = typename detail::get_non_member_save_minimal_type<T, A, true>::type;
+-        using check = has_non_member_load_minimal_impl<T, A, SaveType>;
++        typedef typename detail::get_non_member_save_minimal_type<T, A, true>::type SaveType;
++        typedef has_non_member_load_minimal_impl<T, A, SaveType> check;
+         static const bool value = check::exists;
+         static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member load_minimal and save_minimal functions.  "
+@@ -866,8 +866,8 @@ namespace cereal
+           "cereal detected non-member versioned load_minimal but no valid non-member versioned save_minimal.  "
+           "cannot evaluate correctness of load_minimal without valid save_minimal." );
+-        using SaveType = typename detail::get_non_member_versioned_save_minimal_type<T, A, true>::type;
+-        using check = has_non_member_versioned_load_minimal_impl<T, A, SaveType>;
++        typedef typename detail::get_non_member_versioned_save_minimal_type<T, A, true>::type SaveType;
++        typedef has_non_member_versioned_load_minimal_impl<T, A, SaveType> check;;
+         static const bool value = check::exists;
+         static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member versioned load_minimal and save_minimal functions.  "
+@@ -1182,9 +1182,16 @@ namespace cereal
+       };
+     }
++    // works around the lack of decltype inheritance in GCC 4.6
++    template<class T>
++    struct shared_wrapper
++    {
++       typedef decltype(detail::shared_from_this_wrapper::check(std::declval<T>())) type;
++
++    };
+     //! Determine if T or any base class of T has inherited from std::enable_shared_from_this
+     template<class T>
+-    struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>()))
++    struct has_shared_from_this : shared_wrapper<T>::type
+     { };
+     //! Get the type of the base class of T which inherited from std::enable_shared_from_this
+@@ -1192,10 +1199,10 @@ namespace cereal
+     struct get_shared_from_this_base
+     {
+       private:
+-        using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
++        typedef decltype(detail::shared_from_this_wrapper::get(std::declval<T>())) PtrType;
+       public:
+         //! The type of the base of T that inherited from std::enable_shared_from_this
+-        using type = typename std::decay<typename PtrType::element_type>::type;
++        typedef typename std::decay<typename PtrType::element_type>::type type;
+     };
+     // ######################################################################
+@@ -1209,14 +1216,14 @@ namespace cereal
+     template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
+     struct strip_minimal
+     {
+-      using type = T;
++      typedef T type;
+     };
+     //! Specialization for types wrapped in a NoConvert
+     template <class T>
+     struct strip_minimal<T, true>
+     {
+-      using type = typename T::type;
++      typedef typename T::type type;
+     };
+   } // namespace traits
+@@ -1232,10 +1239,12 @@ namespace cereal
+       { return nullptr; }
+     };
++    template<class T>
++    struct is_default_constructible : std::is_constructible<T>{};
+     template <class T, class A>
+     struct Construct<T, A, false, false>
+     {
+-      static_assert( std::is_default_constructible<T>::value,
++      static_assert( is_default_constructible<T>::value,
+                      "Trying to serialize a an object with no default constructor. \n\n "
+                      "Types must either be default constructible or define either a member or non member Construct function. \n "
+                      "Construct functions generally have the signature: \n\n "
+diff --git a/include/cereal/external/rapidjson/reader.h b/include/cereal/external/rapidjson/reader.h
+index 7790907..3ee838c 100644
+--- a/include/cereal/external/rapidjson/reader.h
++++ b/include/cereal/external/rapidjson/reader.h
+@@ -402,20 +402,13 @@ private:
+       }
+   // cereal Temporary until constexpr support is added in RTM
+-#ifdef _MSC_VER
++//#ifdef _MSC_VER
+   template <class Ch>
+   bool characterOk( Ch c )
+   {
+     return c < 256;
+   }
+-
+-  template <>
+-  bool characterOk<char>( Ch )
+-  {
+-    return true;
+-  }
+-
+-#else
++/*#else
+   // As part of a fix for GCC 4.7
+   template <class T>
+   static constexpr int to_int( T t ){ return t; }
+@@ -432,7 +425,7 @@ private:
+     characterOk(Ch c)
+   { return c < 256; }
+ #endif
+-
++*/
+       // Parse string, handling the prefix and suffix double quotes and escaping.
+       template<unsigned parseFlags, typename Stream, typename Handler>
+       void ParseString(Stream& stream, Handler& handler) {
+diff --git a/include/cereal/external/rapidjson/writer.h b/include/cereal/external/rapidjson/writer.h
+index 0f87255..e02c27a 100644
+--- a/include/cereal/external/rapidjson/writer.h
++++ b/include/cereal/external/rapidjson/writer.h
+@@ -177,20 +177,14 @@ protected:
+       }
+   // cereal Temporary until constexpr support is added in RTM
+-#ifdef _MSC_VER
++//#ifdef _MSC_VER
+   template <class Ch>
+   bool characterOk( Ch c )
+   {
+     return c < 256;
+   }
+-  template <>
+-  bool characterOk<char>( Ch )
+-  {
+-    return true;
+-  }
+-
+-#else
++/*#else
+   // As part of a fix for GCC 4.7
+   template <class T>
+   static constexpr int to_int( T t ){ return t; }
+@@ -206,7 +200,7 @@ protected:
+   typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type
+     characterOk(Ch c)
+   { return c < 256; }
+-#endif
++#endif*/
+       //! \todo Optimization with custom double-to-string converter.
+       void WriteDouble(double d) {
+diff --git a/include/cereal/types/common.hpp b/include/cereal/types/common.hpp
+index abb8bfd..5c014cd 100644
+--- a/include/cereal/types/common.hpp
++++ b/include/cereal/types/common.hpp
+@@ -55,6 +55,15 @@ namespace cereal
+     namespace
+     {
++      template<class en>
++      struct underlying_type
++      {
++          typedef typename std::conditional<
++                  en(-1)<en(0),
++                  typename std::make_signed<en>::type,
++                  typename std::make_unsigned<en>::type
++                  > ::type type;
++      };
+       //! Gets the underlying type of an enum
+       /*! @internal */
+       template <class T, bool IsEnum>
+@@ -64,7 +73,7 @@ namespace cereal
+       /*! Specialization for when we actually have an enum
+           @internal */
+       template <class T>
+-      struct enum_underlying_type<T, true> { using type = typename std::underlying_type<T>::type; };
++      struct enum_underlying_type<T, true> { typedef typename underlying_type<T>::type type; };
+     } // anon namespace
+     //! Checks if a type is an enum
+@@ -78,13 +87,13 @@ namespace cereal
+     class is_enum
+     {
+       private:
+-        using DecayedT  = typename std::decay<T>::type;
+-        using StrippedT = typename ::cereal::traits::strip_minimal<DecayedT>::type;
++        typedef typename std::decay<T>::type DecayedT;
++        typedef typename ::cereal::traits::strip_minimal<DecayedT>::type StrippedT;
+       public:
+         static const bool value = std::is_enum<StrippedT>::value;
+-        using type = StrippedT;
+-        using base_type = typename enum_underlying_type<StrippedT, value>::type;
++        typedef StrippedT type;
++        typedef typename enum_underlying_type<StrippedT, value>::type base_type;
+     };
+   }
+diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp
+index bf56c92..d2357ff 100644
+--- a/include/cereal/types/memory.hpp
++++ b/include/cereal/types/memory.hpp
+@@ -115,9 +115,9 @@ namespace cereal
+     class EnableSharedStateHelper
+     {
+       // typedefs for parent type and storage type
+-      using BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type;
+-      using ParentType = std::enable_shared_from_this<BaseType>;
+-      using StorageType = typename std::aligned_storage<sizeof(ParentType)>::type;
++      typedef typename ::cereal::traits::get_shared_from_this_base<T>::type BaseType;
++      typedef std::enable_shared_from_this<BaseType> ParentType;
++      typedef typename std::aligned_storage<sizeof(ParentType)>::type StorageType;
+       public:
+         //! Saves the state of some type inheriting from enable_shared_from_this
+@@ -257,7 +257,7 @@ namespace cereal
+     {
+       // Storage type for the pointer - since we can't default construct this type,
+       // we'll allocate it using std::aligned_storage and use a custom deleter
+-      using ST = typename std::aligned_storage<sizeof(T)>::type;
++      typedef typename std::aligned_storage<sizeof(T)>::type ST;
+       // Valid flag - set to true once construction finishes
+       //  This prevents us from calling the destructor on
+@@ -345,7 +345,7 @@ namespace cereal
+     {
+       // Storage type for the pointer - since we can't default construct this type,
+       // we'll allocate it using std::aligned_storage
+-      using ST = typename std::aligned_storage<sizeof(T)>::type;
++      typedef typename std::aligned_storage<sizeof(T)>::type ST;
+       // Allocate storage - note the ST type so that deleter is correct if
+       //                    an exception is thrown before we are initialized
+-- 
+1.9.3
+
diff --git a/resource/releaseNotes/Dec6th2014.txt b/resource/releaseNotes/Dec6th2014.txt
new file mode 100644 (file)
index 0000000..266bacf
--- /dev/null
@@ -0,0 +1,238 @@
+Release notes
+****************************************************************************
+Release date: Dec 6th, 2014.
+OS: Ubuntu 12.0.4 and above
+Requires boost version 1.55 to build.
+Code buildable in gcc 4.6.3 and above.
+NOTE: Boost is not distributed but should be installed in the Ubuntu machine.
+*****************************************************************************
+
+Release commit number: de31af
+
+What is new?
+
+Features:
+---------
+
+Slow Response:
+--------------
+This release includes slow response feature which allows a resource entity handler to provide
+a 'slow response' to a client request. If a request is received but the server cannot response
+immediately (example, response data is not available), then the server can response at a later
+time. The same API is used for both immediate and slow response.
+
+GET/PUT request on the batch interface of a collection resource using the default collection
+entity handler will result in each pointed resource’s entity handler being invoked, after which:
+a) if all pointed resources of the collection are local and not-slow, an aggregated
+response will be sent
+b) if collection includes slow local resource(s), an aggregated response is sent only after
+the slowest resource’s entity handler responds with a payload. If one or more slow resource
+entity handlers do not respond, no response is sent to the request, i.e. there is no timeout
+mechanism in current release
+
+Samples demonstrating slow response:
+simpleserver and simpleclient in C++
+ocserverslow and occlientslow in C
+
+Security:
+----------
+1. OCStack is compiled with security only if a valid libtinydtls.a is available
+under oic-resource/resource/csdk/tinydtls directory.
+2. This release provides an API to set device identity and PSK credentials.
+3. Security is NOT supported for Arduino platform.
+
+JSON serialization using Cereal libray
+--------------------------------------
+This release includes modifications which consists of using
+open source library cereal to perform JSON serialization
+and de-serialization in C++ layer. (NOTE: previously we were
+using boost::property tree for JSON parsing)
+
+NOTE: For a nested (array of array of array..) JSON value, we limit to 3-level deep nesting.
+Refer AttributeValue.h for more details.
+
+------------
+API changes:
+------------
+
+--------------------------------------------
+Class OCPlatform (Header file: OCPlatform.h)
+--------------------------------------------
+
+*****************
+sendResponse API
+*****************
+
+This new API allows the application entity handler to send response to a request.
+This API is used in sending a response immediately (if available) or in cases of
+slow response. Due to this change, signature of application entity handler has
+been modified. This introduces changes in application entity handler code.
+Please see below.
+All C++ samples demonstrate the use of sendResponse API.
+
+--------------------------------------------
+Header file: OCApi.h
+--------------------------------------------
+
+typedef std::function<OCEntityHandlerResult(
+    const std::shared_ptr<OCResourceRequest>)> EntityHandler;
+
+Signature of application entity handler has changed. New signature consists only of
+one parameter which is OCResourceRequest pointer. Response is formed and sent via
+sendResponse API. All C++ samples are updated to showcase this modification.
+
+----------------------------------------------------------
+Class OCResourceRequest (Header file: OCResourceRequest.h)
+----------------------------------------------------------
+
+********************
+getRequestHandle API
+********************
+
+This new API allows the application entity handler to retrieve request handle
+from the incoming request.
+All C++ samples demonstrate the use of getRequestHandle API.
+
+*********************
+getResourceHandle API
+*********************
+
+This new API allows the application entity handler to retrieve resource handle
+from the incoming request.
+All C++ samples demonstrate the use of getResourceHandle API.
+
+-------------------------------------------------------------
+Class OCResourceResponse (Header file: OCResourceResponse.h)
+-------------------------------------------------------------
+
+********************
+setRequestHandle API
+********************
+
+This new API allows the application entity handler to set request handle in
+the response.
+All C++ samples demonstrate the use of setRequestHandle API.
+
+*********************
+setResourceHandle API
+*********************
+
+This new API allows the application entity handler to set resource handle in
+the response.
+All C++ samples demonstrate the use of setResourceHandle API.
+
+*********************
+setResponseResult API
+*********************
+
+This new API allows the application entity handler to set result in
+the response.
+All C++ samples demonstrate the use of setResponseResult API.
+
+-------------------------------------------------------------
+Header file: OCStack.h
+-------------------------------------------------------------
+
+***************************
+OCDoResponse API
+***************************
+
+This new C API allows the application entity handler to send response to a request.
+This API is used in sending a response immediately (if available) or in cases of
+slow response.
+
+-------------------------------------------------------------
+Header file: OCSecurity.h
+-------------------------------------------------------------
+
+***************************
+OCSetDtlsPskCredentials API
+***************************
+
+This new API allows to set DTLS PSK credentials.
+
+------------
+Notes:
+------------
+
+Known issues:
+-------------
+1. When observation is used, server shutdown causes an error (segmentation fault).
+
+Active discovery-
+1. In case of unicast presence with rt, only one rt is permitted per IP address for
+subscribePresence. If multiple subscriptions are done, only first subscribePresence’s rt is used.
+2. For multicast presence, server shutdown (ungraceful) scenario is not notified to the client,
+but graceful shutdowns are notified.
+3. IOT 85
+
+Issues Fixed:
+-------------
+1. IOT 65 (Stopping presence subscription gets infinite callback to handlePresence)
+2. IOT 79 (3 Presence Notifications when a resource is created on the server)
+
+General notes:
+--------------
+Maximum length of URI supported is 64 bytes (sent from the client)
+Maximum length of query supported is 64 bytes (sent from the client)
+Maximum length of request from client and response from server for Arduino is is 256 bytes
+Maximum length of request from client and response from server for non-Ardunio is is 1024 bytes
+
+OIC base supports Arduino WiFi shield.
+This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library.
+Please refer to oic-resource/csdk/README file for building OIC base with WiFi support.
+
+-------------
+How to build:
+-------------
+
+REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo.
+If the code is not cloned:
+Clone the oic-resource repo using this command: git clone oic:oic-resource
+
+NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the
+latest code.
+
+In repo oic-resource, root folder consists of 'resource' folder.  Inside OIC folder there
+is a Makefile.
+
+Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK,
+core(i.e base) and samples.
+
+Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK,
+core(i.e base) and samples.
+
+--------
+Samples:
+--------
+
+A basic sample for hosting a resource on a server and a sample for client for discovering resources
+are provided here:
+Simple server sample location: oic-resource/examples/simpleserver.cpp
+Simple client sample location: oic-resource/examples/simpleclient.cpp
+Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp
+Simpleserver and simpleclient samples also provide examples for doing POST operation.
+Simpleserver also demonstrates slow response case for a GET request.
+
+Garage samples provide usage of OCRepresentation, get/set attribute values
+oic-resource/examples/garageclient.cpp
+oic-resource/examples/garageserver.cpp
+
+Fridge samples provide usage of constructResourceObject API, std bind
+(for mapping request and responses), default
+device entity handler, header options support and Delete operation.
+oic-resource/examples/fridgeclient.cpp
+oic-resource/examples/fridgeserver.cpp
+
+Presence samples provides examples to use presence APIs
+Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp
+Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp
+
+Room samples provides examples to use resource collection.
+oic-resource/examples/roomclient.cpp
+oic-resource/examples/roomserver.cpp
+
+After building the code in oic-resource, executables for samples are in directory named
+'oic-resource/samples/release'.
+After building the code in oic-resource, executables are in directory named 'oic-resource/release'.
+
index 6225119..e9580b2 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#include <new>
-
 #include "InProcClientWrapper.h"
 #include "ocstack.h"
 
 #include "OCPlatform.h"
 #include "OCResource.h"
-
+#include <OCSerialization.h>
 using namespace std;
 
 namespace OC
 {
-    InProcClientWrapper::InProcClientWrapper(OC::OCPlatform_impl& owner,
+    InProcClientWrapper::InProcClientWrapper(
         std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
-            : IClientWrapper(owner),
-              m_threadRun(false), m_csdkLock(csdkLock),
-              m_owner(owner),
+            : m_threadRun(false), m_csdkLock(csdkLock),
               m_cfg { cfg }
     {
         // if the config type is server, we ought to never get called.  If the config type
@@ -62,7 +58,12 @@ namespace OC
             m_listeningThread.join();
         }
 
-        OCStop();
+        // only stop if we are the ones who actually called 'init'.  We are counting
+        // on the server to do the stop.
+        if(m_cfg.mode == ModeType::Client)
+        {
+            OCStop();
+        }
     }
 
     void InProcClientWrapper::listeningFunc()
@@ -91,90 +92,11 @@ namespace OC
         }
     }
 
-    std::string InProcClientWrapper::convertOCAddrToString(OCDevAddr& addr,
-        OCSecureType type, const std::string &portStr)
-    {
-        // TODO: we currently assume this is a IPV4 address, need to figure out the actual value
-
-        uint8_t a, b, c, d;
-        uint16_t port;
-
-        if(OCDevAddrToIPv4Addr(&addr, &a, &b, &c, &d) ==0 && OCDevAddrToPort(&addr, &port)==0)
-        {
-            ostringstream os;
-            if(type == OCSecureType::IPV4)
-            {
-                os << "coap://" << static_cast<int>(a) << '.' <<
-                    static_cast<int>(b) << '.' << static_cast<int>(c) <<
-                    '.' << static_cast<int>(d) << ':' <<static_cast<int>(port);
-            }
-            else if(type == OCSecureType::IPV4Secure)
-            {
-                 os << "coaps://" << static_cast<int>(a) <<'.' <<
-                    static_cast<int>(b) <<'.' << static_cast<int>(c) <<
-                    '.' << static_cast<int>(d) << ':' << portStr;
-            }
-            return os.str();
-        }
-        else
-        {
-            return OC::Error::INVALID_IP;
-        }
-    }
-
-    struct ListenContext
-    {
-        FindCallback              callback;
-        IClientWrapper::Ptr       clientWrapper;
-    };
-
-
-    std::shared_ptr<OCResource> InProcClientWrapper::parseOCResource(
-        IClientWrapper::Ptr clientWrapper, OCDevAddr& addr,
-        const boost::property_tree::ptree resourceNode)
-    {
-        std::string uri = resourceNode.get<std::string>(OC::Key::URIKEY, "");
-        bool obs = resourceNode.get<int>(OC::Key::OBSERVABLEKEY,0) == 1;
-        std::vector<std::string> rTs;
-        std::vector<std::string> ifaces;
-
-        boost::property_tree::ptree properties =
-            resourceNode.get_child(OC::Key::PROPERTYKEY, boost::property_tree::ptree());
-
-        boost::property_tree::ptree rT =
-            properties.get_child(OC::Key::RESOURCETYPESKEY, boost::property_tree::ptree());
-        for(auto itr : rT)
-        {
-            rTs.push_back(itr.second.data());
-        }
-        bool secure = properties.get<int>(OC::Key::SECUREKEY,0) == 1;
-
-        boost::property_tree::ptree iF =
-            properties.get_child(OC::Key::INTERFACESKEY, boost::property_tree::ptree());
-        for(auto itr : iF)
-        {
-            ifaces.push_back(itr.second.data());
-        }
-
-        std::string host;
-        if(secure)
-        {
-            string port = properties.get<string>(OC::Key::PORTKEY,"");
-            host= convertOCAddrToString(addr, OCSecureType::IPV4Secure, port);
-        }
-        else
-        {
-            host= convertOCAddrToString(addr, OCSecureType::IPV4);
-        }
-
-        return std::shared_ptr<OCResource>(
-            new OCResource(clientWrapper, host, uri, obs, rTs, ifaces));
-    }
-
     OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle,
         OCClientResponse* clientResponse)
     {
-        ListenContext* context = static_cast<ListenContext*>(ctx);
+        ClientCallbackContext::ListenContext* context =
+            static_cast<ClientCallbackContext::ListenContext*>(ctx);
 
         if(clientResponse->result != OC_STACK_OK)
         {
@@ -185,51 +107,43 @@ namespace OC
             return OC_STACK_KEEP_TRANSACTION;
         }
 
+        auto clientWrapper = context->clientWrapper.lock();
+
+        if(!clientWrapper)
+        {
+            oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
+                    << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
         std::stringstream requestStream;
         requestStream << clientResponse->resJSONPayload;
 
-        boost::property_tree::ptree root;
-
         try
         {
-                boost::property_tree::read_json(requestStream, root);
-        }
-        catch(boost::property_tree::json_parser::json_parser_error &e)
-        {
-                oclog() << "listenCallback(): read_json() failed: " << e.what()
-                        << std::flush;
+            ListenOCContainer container(clientWrapper, *clientResponse->addr,
+                    requestStream);
 
-                return OC_STACK_KEEP_TRANSACTION;
-        }
-
-        boost::property_tree::ptree payload =
-                root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
+            // loop to ensure valid construction of all resources
+            for(auto resource : container.Resources())
+            {
+                std::thread exec(context->callback, resource);
+                exec.detach();
+            }
 
-        for(auto payloadItr : payload)
+        }
+        catch(const std::exception& e)
         {
-                try
-                {
-                    std::shared_ptr<OCResource> resource =
-                        context->clientWrapper->parseOCResource(context->clientWrapper,
-                        *clientResponse->addr,
-                        payloadItr.second);
-
-                    // Note: the call to detach allows the underlying thread to continue until
-                    // completion and allows us to destroy the exec object. This is apparently NOT
-                    // a memory leak, as the thread will apparently take care of itself.
-                    // Additionally, the only parameter here is a shared ptr, so OCResource will be
-                    // disposed of properly upon completion of the callback handler.
-                    std::thread exec(context->callback,resource);
-                    exec.detach();
-                }
-                catch(ResourceInitException& e)
-                {
-                    oclog() << "listenCallback(): failed to create resource: " << e.what()
-                            << std::flush;
-                }
+            oclog() << "listenCallback failed to parse a malformed message: "
+                    << e.what()
+                    << std::endl <<std::endl
+                    << clientResponse->result
+                    << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
         }
 
         return OC_STACK_KEEP_TRANSACTION;
+
     }
 
     OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl,
@@ -239,13 +153,13 @@ namespace OC
 
         OCCallbackData cbdata = {0};
 
-        ListenContext* context = new ListenContext();
+        ClientCallbackContext::ListenContext* context = new ClientCallbackContext::ListenContext();
         context->callback = callback;
         context->clientWrapper = shared_from_this();
 
         cbdata.context =  static_cast<void*>(context);
         cbdata.cb = listenCallback;
-        cbdata.cd = [](void* c){delete static_cast<ListenContext*>(c);};
+        cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ListenContext*>(c);};
 
         auto cLock = m_csdkLock.lock();
         if(cLock)
@@ -261,129 +175,37 @@ namespace OC
         }
         else
         {
+            delete context;
             result = OC_STACK_ERROR;
         }
         return result;
     }
 
-    struct GetContext
-    {
-        GetCallback callback;
-    };
-
-    struct SetContext
-    {
-        PutCallback callback;
-    };
-
-
     OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
     {
-        std::stringstream requestStream;
-        requestStream<<clientResponse->resJSONPayload;
-        if(strlen((char*)clientResponse->resJSONPayload) == 0)
+        if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0')
         {
             return OCRepresentation();
         }
 
-        boost::property_tree::ptree root;
-        try
-        {
-            boost::property_tree::read_json(requestStream, root);
-        }
-        catch(boost::property_tree::json_parser::json_parser_error &e)
+        MessageContainer oc;
+        oc.setJSONRepresentation(clientResponse->resJSONPayload);
+
+        std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
+        if(it == oc.representations().end())
         {
             return OCRepresentation();
         }
-        boost::property_tree::ptree payload = root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
-        OCRepresentation root_resource;
-        std::vector<OCRepresentation> children;
-        bool isRoot = true;
-        for ( auto payloadItr : payload)
-        {
-            OCRepresentation child;
-            try
-            {
-                auto resourceNode = payloadItr.second;
-                std::string uri = resourceNode.get<std::string>(OC::Key::URIKEY, "");
-
-                if (isRoot)
-                {
-                    root_resource.setUri(uri);
-                }
-                else
-                {
-                    child.setUri(uri);
-                }
-
-                if( resourceNode.count(OC::Key::PROPERTYKEY) != 0 )
-                {
-                    std::vector<std::string> rTs;
-                    std::vector<std::string> ifaces;
-                    boost::property_tree::ptree properties =
-                        resourceNode.get_child(OC::Key::PROPERTYKEY, boost::property_tree::ptree());
-
-                    boost::property_tree::ptree rT =
-                        properties.get_child(OC::Key::RESOURCETYPESKEY,
-                                                boost::property_tree::ptree());
-                    for(auto itr : rT)
-                    {
-                        rTs.push_back(itr.second.data());
-                    }
-
-                    boost::property_tree::ptree iF =
-                        properties.get_child(OC::Key::INTERFACESKEY, boost::property_tree::ptree());
-                    for(auto itr : iF)
-                    {
-                        ifaces.push_back(itr.second.data());
-                    }
-                    if (isRoot)
-                    {
-                        root_resource.setResourceInterfaces(ifaces);
-                        root_resource.setResourceTypes(rTs);
-                    }
-                    else
-                    {
-                        child.setResourceInterfaces(ifaces);
-                        child.setResourceTypes(rTs);
-                    }
-                }
-
-                if( resourceNode.count(OC::Key::REPKEY) != 0 )
-                {
-                    boost::property_tree::ptree rep =
-                        resourceNode.get_child(OC::Key::REPKEY, boost::property_tree::ptree());
-                    AttributeMap attrs;
-                    for( auto item : rep)
-                    {
-                        std::string name = item.first.data();
-                        std::string value = item.second.data();
-                        attrs[name] = value;
-                    }
-                    if (isRoot)
-                    {
-                        root_resource.setAttributeMap(attrs);
-                    }
-                    else
-                    {
-                        child.setAttributeMap(attrs);
-                    }
-                }
-
-                if (!isRoot)
-                    children.push_back(child);
-            }
-            catch (...)
-            {
-                // TODO
-            }
 
-            isRoot = false;
-         }
+        // first one is considered the root, everything else is considered a child of this one.
+        OCRepresentation root = *it;
+        ++it;
 
-         root_resource.setChildren(children);
+        std::for_each(it, oc.representations().end(),
+                [&root](const OCRepresentation& repItr)
+                {root.addChild(repItr);});
+        return root;
 
-        return root_resource;
     }
 
     void parseServerHeaderOptions(OCClientResponse* clientResponse,
@@ -415,7 +237,8 @@ namespace OC
     OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle,
         OCClientResponse* clientResponse)
     {
-        GetContext* context = static_cast<GetContext*>(ctx);
+        ClientCallbackContext::GetContext* context =
+            static_cast<ClientCallbackContext::GetContext*>(ctx);
 
         OCRepresentation rep;
         HeaderOptions serverHeaderOptions;
@@ -438,11 +261,11 @@ namespace OC
         OCStackResult result;
         OCCallbackData cbdata = {0};
 
-        GetContext* ctx = new GetContext();
+        ClientCallbackContext::GetContext* ctx = new ClientCallbackContext::GetContext();
         ctx->callback = callback;
         cbdata.context = static_cast<void*>(ctx);
         cbdata.cb = &getResourceCallback;
-        cbdata.cd = [](void* c){delete static_cast<GetContext*>(c);};
+        cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::GetContext*>(c);};
 
         auto cLock = m_csdkLock.lock();
 
@@ -464,6 +287,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
         return result;
@@ -473,7 +297,8 @@ namespace OC
     OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle,
         OCClientResponse* clientResponse)
     {
-        SetContext* context = static_cast<SetContext*>(ctx);
+        ClientCallbackContext::SetContext* context =
+            static_cast<ClientCallbackContext::SetContext*>(ctx);
         OCRepresentation attrs;
         HeaderOptions serverHeaderOptions;
 
@@ -521,14 +346,9 @@ namespace OC
 
     std::string InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
     {
-        ostringstream payload;
-        // TODO need to change the format to "{"oc":[]}"
-        payload << "{\"oc\":";
-
-        payload << rep.getJSONRepresentation();
-
-        payload << "}";
-        return payload.str();
+        MessageContainer ocInfo;
+        ocInfo.addRepresentation(rep);
+        return ocInfo.getJSONRepresentation(OCInfoFormat::IncludeOC);
     }
 
     OCStackResult InProcClientWrapper::PostResourceRepresentation(const std::string& host,
@@ -539,10 +359,10 @@ namespace OC
         OCStackResult result;
         OCCallbackData cbdata = {0};
 
-        SetContext* ctx = new SetContext();
+        ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
         ctx->callback = callback;
         cbdata.cb = &setResourceCallback;
-        cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+        cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
         cbdata.context = static_cast<void*>(ctx);
 
         // TODO: in the future the cstack should be combining these two strings!
@@ -567,6 +387,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
 
@@ -582,10 +403,10 @@ namespace OC
         OCStackResult result;
         OCCallbackData cbdata = {0};
 
-        SetContext* ctx = new SetContext();
+        ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
         ctx->callback = callback;
         cbdata.cb = &setResourceCallback;
-        cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+        cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
         cbdata.context = static_cast<void*>(ctx);
 
         // TODO: in the future the cstack should be combining these two strings!
@@ -611,22 +432,18 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
 
         return result;
     }
 
-    struct DeleteContext
-    {
-        DeleteCallback callback;
-    };
-
     OCStackApplicationResult deleteResourceCallback(void* ctx, OCDoHandle handle,
         OCClientResponse* clientResponse)
     {
-        DeleteContext* context = static_cast<DeleteContext*>(ctx);
-        OCRepresentation attrs;
+        ClientCallbackContext::DeleteContext* context =
+            static_cast<ClientCallbackContext::DeleteContext*>(ctx);
         HeaderOptions serverHeaderOptions;
 
         if(clientResponse->result == OC_STACK_OK)
@@ -645,10 +462,10 @@ namespace OC
         OCStackResult result;
         OCCallbackData cbdata = {0};
 
-        DeleteContext* ctx = new DeleteContext();
+        ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext();
         ctx->callback = callback;
         cbdata.cb = &deleteResourceCallback;
-        cbdata.cd = [](void* c){delete static_cast<DeleteContext*>(c);};
+        cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::DeleteContext*>(c);};
         cbdata.context = static_cast<void*>(ctx);
 
         ostringstream os;
@@ -672,21 +489,18 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
 
         return result;
     }
 
-    struct ObserveContext
-    {
-        ObserveCallback callback;
-    };
-
     OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle,
         OCClientResponse* clientResponse)
     {
-        ObserveContext* context = static_cast<ObserveContext*>(ctx);
+        ClientCallbackContext::ObserveContext* context =
+            static_cast<ClientCallbackContext::ObserveContext*>(ctx);
         OCRepresentation attrs;
         HeaderOptions serverHeaderOptions;
         uint32_t sequenceNumber = clientResponse->sequenceNumber;
@@ -709,11 +523,11 @@ namespace OC
         OCStackResult result;
         OCCallbackData cbdata = {0};
 
-        ObserveContext* ctx = new ObserveContext();
+        ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext();
         ctx->callback = callback;
         cbdata.context = static_cast<void*>(ctx);
         cbdata.cb = &observeResourceCallback;
-        cbdata.cd = [](void* c){delete static_cast<ObserveContext*>(c);};
+        cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ObserveContext*>(c);};
 
         OCMethod method;
         if (observeType == ObserveType::Observe)
@@ -749,6 +563,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             return OC_STACK_ERROR;
         }
 
@@ -768,7 +583,8 @@ namespace OC
             OCHeaderOption options[MAX_HEADER_OPTIONS];
 
             assembleHeaderOptions(options, headerOptions);
-            result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options, headerOptions.size());
+            result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options,
+                    headerOptions.size());
         }
         else
         {
@@ -778,18 +594,31 @@ namespace OC
         return result;
     }
 
-    struct SubscribePresenceContext
-    {
-        SubscribeCallback callback;
-    };
-
     OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
-        OCClientResponse* clientResponse)
+            OCClientResponse* clientResponse)
     {
-        SubscribePresenceContext* context = static_cast<SubscribePresenceContext*>(ctx);
-        std::thread exec(context->callback, clientResponse->result, clientResponse->sequenceNumber);
+        char stringAddress[DEV_ADDR_SIZE_MAX];
+        ostringstream os;
+        uint16_t port;
 
-        exec.detach();
+        if(OCDevAddrToString(clientResponse->addr, stringAddress) == 0 &&
+                OCDevAddrToPort(clientResponse->addr, &port) == 0)
+        {
+            os<<stringAddress<<":"<<port;
+
+            ClientCallbackContext::SubscribePresenceContext* context =
+                static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
+
+            std::thread exec(context->callback, clientResponse->result,
+                    clientResponse->sequenceNumber, os.str());
+
+            exec.detach();
+        }
+        else
+        {
+            oclog() << "subscribePresenceCallback(): OCDevAddrToString() or OCDevAddrToPort() "
+                    <<"failed"<< std::flush;
+        }
         return OC_STACK_KEEP_TRANSACTION;
     }
 
@@ -799,11 +628,13 @@ namespace OC
     {
         OCCallbackData cbdata = {0};
 
-        SubscribePresenceContext* ctx = new SubscribePresenceContext();
+        ClientCallbackContext::SubscribePresenceContext* ctx =
+            new ClientCallbackContext::SubscribePresenceContext();
         ctx->callback = presenceHandler;
         cbdata.cb = &subscribePresenceCallback;
         cbdata.context = static_cast<void*>(ctx);
-        cbdata.cd = [](void* c){delete static_cast<SubscribePresenceContext*>(c);};
+        cbdata.cd = [](void* c)
+            {delete static_cast<ClientCallbackContext::SubscribePresenceContext*>(c);};
         auto cLock = m_csdkLock.lock();
 
         std::ostringstream os;
@@ -815,7 +646,10 @@ namespace OC
         }
 
         if(!cLock)
+        {
+            delete ctx;
             return OC_STACK_ERROR;
+        }
 
         return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
                             OC_LOW_QOS, &cbdata, NULL, 0);
index c057c7d..c92a036 100644 (file)
@@ -47,6 +47,9 @@ void formResourceRequest(OCEntityHandlerFlag flag,
                          OCEntityHandlerRequest * entityHandlerRequest,
                          std::shared_ptr<OCResourceRequest> pRequest)
 {
+    pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
+    pRequest->setResourceHandle(entityHandlerRequest->resource);
+
     if(flag & OC_INIT_FLAG)
     {
         pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
@@ -116,66 +119,17 @@ void formResourceRequest(OCEntityHandlerFlag flag,
     {
         pRequest->setRequestHandlerFlag(
                    OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
-        if(entityHandlerRequest->obsInfo)
+
+        if(entityHandlerRequest)
         {
             OC::ObservationInfo observationInfo;
-            observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo->action;
-            observationInfo.obsId = entityHandlerRequest->obsInfo->obsId;
+            observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
+            observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
             pRequest->setObservationInfo(observationInfo);
         }
     }
 }
 
-void processResourceResponse(OCEntityHandlerFlag flag,
-                             OCEntityHandlerRequest * entityHandlerRequest,
-                             std::shared_ptr<OCResourceResponse> pResponse)
-{
-    if(flag & OC_REQUEST_FLAG)
-    {
-        // TODO we could use const reference
-        std::string payLoad;
-        HeaderOptions serverHeaderOptions;
-
-        if(pResponse)
-        {
-            payLoad = pResponse->getPayload();
-            serverHeaderOptions = pResponse->getHeaderOptions();
-        }
-        else
-        {
-            throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
-        }
-
-        if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen)
-        {
-            int i = 0;
-            entityHandlerRequest->numSendVendorSpecificHeaderOptions =
-                        serverHeaderOptions.size();
-            for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
-            {
-                entityHandlerRequest->sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
-                entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionID =
-                        static_cast<uint16_t>(it->getOptionID());
-                entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionLength =
-                        (it->getOptionData()).length() + 1;
-                memcpy(entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionData,
-                        (it->getOptionData()).c_str(),
-                        (it->getOptionData()).length() + 1);
-                i++;
-            }
-
-            strncpy((char*)entityHandlerRequest->resJSONPayload,
-                        payLoad.c_str(),
-                        entityHandlerRequest->resJSONPayloadLen);
-        }
-        else
-        {
-            throw OCException(OC::Exception::STR_PAYLOAD_OVERFLOW, OC_STACK_MALFORMED_RESPONSE);
-        }
-    }
-
-}
-
 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
                                                   OCEntityHandlerRequest * entityHandlerRequest,
                                                   char* uri)
@@ -191,7 +145,6 @@ OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
     }
 
     auto pRequest = std::make_shared<OC::OCResourceRequest>();
-    auto pResponse = std::make_shared<OC::OCResourceResponse>();
 
     formResourceRequest(flag, entityHandlerRequest, pRequest);
 
@@ -199,7 +152,7 @@ OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
 
     if(defaultDeviceEntityHandler)
     {
-        result = defaultDeviceEntityHandler(pRequest, pResponse);
+        result = defaultDeviceEntityHandler(pRequest);
     }
     else
     {
@@ -207,8 +160,6 @@ OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
         return OC_EH_ERROR;
     }
 
-    processResourceResponse(flag, entityHandlerRequest, pResponse);
-
     return result;
 }
 
@@ -227,7 +178,6 @@ OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
     }
 
     auto pRequest = std::make_shared<OC::OCResourceRequest>();
-    auto pResponse = std::make_shared<OC::OCResourceResponse>();
 
     formResourceRequest(flag, entityHandlerRequest, pRequest);
 
@@ -251,15 +201,7 @@ OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
         // Call CPP Application Entity Handler
         if(entityHandlerEntry->second)
         {
-            result = entityHandlerEntry->second(pRequest, pResponse);
-
-            if(OC_EH_RESOURCE_CREATED == result)
-            {
-                std::string createdUri = pResponse->getNewResourceUri();
-                strncpy(reinterpret_cast<char*>(entityHandlerRequest->newResourceUri),
-                        createdUri.c_str(),
-                        createdUri.length() + 1);
-            }
+            result = entityHandlerEntry->second(pRequest);
         }
         else
         {
@@ -273,17 +215,14 @@ OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
         return OC_EH_ERROR;
     }
 
-    processResourceResponse(flag, entityHandlerRequest, pResponse);
-
     return result;
 }
 
 namespace OC
 {
-    InProcServerWrapper::InProcServerWrapper(OC::OCPlatform_impl& owner,
+    InProcServerWrapper::InProcServerWrapper(
         std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
-     : IServerWrapper(owner),
-       m_csdkLock(csdkLock)
+     : m_csdkLock(csdkLock)
     {
         OCMode initType;
 
@@ -446,6 +385,7 @@ namespace OC
 
         return result;
     }
+
     OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
                                         (EntityHandler entityHandler)
     {
@@ -573,6 +513,74 @@ namespace OC
         return result;
     }
 
+    OCStackResult InProcServerWrapper::sendResponse(
+        const std::shared_ptr<OCResourceResponse> pResponse)
+    {
+        auto cLock = m_csdkLock.lock();
+        OCStackResult result = OC_STACK_ERROR;
+
+        if(!pResponse)
+        {
+            result = OC_STACK_MALFORMED_RESPONSE;
+            throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
+        }
+        else
+        {
+            OCEntityHandlerResponse response;
+            std::string payLoad;
+            HeaderOptions serverHeaderOptions;
+
+            payLoad = pResponse->getPayload();
+            serverHeaderOptions = pResponse->getHeaderOptions();
+
+            response.requestHandle = pResponse->getRequestHandle();
+            response.resourceHandle = pResponse->getResourceHandle();
+            response.ehResult = pResponse->getResponseResult();
+            response.payload = (unsigned char*) payLoad.c_str();
+            response.payloadSize = payLoad.length() + 1;
+            response.persistentBufferFlag = 0;
+
+            response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
+            int i = 0;
+            for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
+            {
+                response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
+                response.sendVendorSpecificHeaderOptions[i].optionID =
+                    static_cast<uint16_t>(it->getOptionID());
+                response.sendVendorSpecificHeaderOptions[i].optionLength =
+                    (it->getOptionData()).length() + 1;
+                memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
+                    (it->getOptionData()).c_str(),
+                    (it->getOptionData()).length() + 1);
+                i++;
+            }
+
+            if(OC_EH_RESOURCE_CREATED == response.ehResult)
+            {
+                std::string createdUri = pResponse->getNewResourceUri();
+                strncpy(reinterpret_cast<char*>(response.resourceUri),
+                        createdUri.c_str(),
+                        createdUri.length() + 1);
+            }
+
+            if(cLock)
+            {
+                std::lock_guard<std::recursive_mutex> lock(*cLock);
+                result = OCDoResponse(&response);
+            }
+            else
+            {
+                result = OC_STACK_ERROR;
+            }
+
+            if(result != OC_STACK_OK)
+            {
+                oclog() << "Error sending response\n";
+            }
+            return result;
+        }
+    }
+
     InProcServerWrapper::~InProcServerWrapper()
     {
         if(m_processThread.joinable())
index 612dc1d..97381e5 100644 (file)
@@ -63,20 +63,22 @@ std::string OC::OCException::reason(const OCStackResult sr)
             return OC::Exception::NO_OBSERVERS;
         case OC_STACK_OBSERVER_NOT_FOUND:
             return OC::Exception::OBSV_NO_FOUND;
-        case OC_STACK_OBSERVER_NOT_ADDED:
-            return OC::Exception::OBSV_NOT_ADDED;
-        case OC_STACK_OBSERVER_NOT_REMOVED:
-            return OC::Exception::OBSV_NOT_REMOVED;
 #ifdef WITH_PRESENCE
         case OC_STACK_PRESENCE_STOPPED:
             return OC::Exception::PRESENCE_STOPPED;
-        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-            return OC::Exception::PRESENCE_NOT_HANDLED;
 #endif
+        case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+            return OC::Exception::VIRTUAL_DO_NOT_HANDLE;
         case OC_STACK_INVALID_OPTION:
             return OC::Exception::INVALID_OPTION;
         case OC_STACK_MALFORMED_RESPONSE:
             return OC::Exception::MALFORMED_STACK_RESPONSE;
+        case OC_STACK_PERSISTENT_BUFFER_REQUIRED:
+            return OC::Exception::PERSISTENT_BUFFER_REQUIRED;
+        case OC_STACK_CONTINUE:
+            return OC::Exception::STACK_CONTINUE;
+        case OC_STACK_INVALID_REQUEST_HANDLE:
+            return OC::Exception::INVALID_REQUEST_HANDLE;
         case OC_STACK_ERROR:
             return OC::Exception::GENERAL_FAULT;
     }
index 4390a4f..f26ffc7 100644 (file)
@@ -189,5 +189,10 @@ namespace OC
         {
             return OCPlatform_impl::Instance().unsubscribePresence(presenceHandle);
         }
+
+        OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+        {
+            return OCPlatform_impl::Instance().sendResponse(pResponse);
+        }
     } // namespace OCPlatform
 } //namespace OC
index 4671c2b..e99cea7 100644 (file)
@@ -68,16 +68,16 @@ namespace OC
         switch(config.mode)
         {
             case ModeType::Server:
-                m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config);
+                m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
                 break;
 
             case ModeType::Client:
-                m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config);
+                m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
                 break;
 
             case ModeType::Both:
-                m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config);
-                m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config);
+                m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
+                m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
                 break;
          }
     }
@@ -113,23 +113,23 @@ namespace OC
     }
 
     OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle,
-                                                ObservationIds& observationIds,
-                                                const std::shared_ptr<OCResourceResponse> pResponse)
+                                       ObservationIds& observationIds,
+                                       const std::shared_ptr<OCResourceResponse> pResponse)
     {
         return notifyListOfObservers(resourceHandle, observationIds, pResponse, m_cfg.QoS);
     }
 
     OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle,
-                                                ObservationIds& observationIds,
-                                                const std::shared_ptr<OCResourceResponse> pResponse,
-                                                QualityOfService QoS)
+                                       ObservationIds& observationIds,
+                                       const std::shared_ptr<OCResourceResponse> pResponse,
+                                       QualityOfService QoS)
     {
         if(!pResponse)
         {
          return result_guard(OC_STACK_ERROR);
         }
 
-        std::string payload(pResponse->getPayload());
+        std::string payload(pResponse->getResourceRepresentation().getJSONRepresentation());
 
         return result_guard(
                    OCNotifyListOfObservers(resourceHandle,
@@ -293,4 +293,9 @@ namespace OC
                              ref(presenceHandle));
     }
 
+    OCStackResult OCPlatform_impl::sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+    {
+        return checked_guard(m_server, &IServerWrapper::sendResponse,
+                             pResponse);
+    }
 } //namespace OC
diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp
new file mode 100644 (file)
index 0000000..460e9ac
--- /dev/null
@@ -0,0 +1,638 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCRepresentation.cpp
+
+/// @brief  This file contains the implementation of classes and its members
+///         related to OCRepresentation
+
+
+#include <OCRepresentation.h>
+
+#include <cereal/cereal.hpp>
+#include <cereal/types/map.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/types/utility.hpp>
+#include <OicJsonSerializer.hpp>
+#include <algorithm>
+
+// code needed to serialize a string::Attribute value map
+namespace OC
+{
+    namespace detail
+    {
+        template<class Archive>
+        class WriteAttributeValue : public boost::static_visitor<>
+        {
+            public:
+                WriteAttributeValue(const std::string& name, Archive& ar)
+                    :m_name(name), m_archive(ar)
+                {}
+
+                template<class T>
+                void operator()(const T& value) const
+                {
+                    m_archive(cereal::make_nvp(m_name, value));
+                }
+            private:
+                std::string m_name;
+                Archive& m_archive;
+        };
+    }
+}
+
+namespace cereal
+{
+    // take no action when serializing the null type, because the 'save' below
+    // doesn't use the visitor for this type.
+    template <class Archive>
+    void serialize(Archive&, OC::NullType t)
+    {}
+
+    template<class Archive>
+    void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
+    {
+        for(const auto& kv : vals)
+        {
+            const auto& k = kv.first;
+            const auto& v = kv.second;
+
+            if(v.which() != OC::AttributeValueNullIndex)
+            {
+                OC::detail::WriteAttributeValue<Archive> writer(k,ar);
+                boost::apply_visitor(writer, v);
+            }
+            else
+            {
+                ar.setNextName(k.c_str());
+                ar.writeName();
+                ar.saveValue();
+            }
+        }
+    }
+
+    template<class Archive>
+    void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
+    {
+        ar.loadAttributeValues(vals);
+    }
+}
+
+namespace OC
+{
+    typedef cereal::JSONOutputArchive OutputArchiveType;
+    typedef cereal::JSONInputArchive InputArchiveType;
+
+    void MessageContainer::setJSONRepresentation(const std::string& payload)
+    {
+        std::stringstream os(payload);
+        {
+            InputArchiveType archive(os);
+            archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+        }
+    }
+
+    void MessageContainer::setJSONRepresentation(const unsigned char* payload)
+    {
+        setJSONRepresentation(std::string(reinterpret_cast<const char*>(payload)));
+    }
+
+    std::string MessageContainer::getJSONRepresentation(OCInfoFormat f) const
+    {
+        std::stringstream os;
+
+        // note: the block is required because cereal closes the JSON string
+        // upon destruction, so the archive needs to be destroyed before accessing
+        // the data
+        {
+            if(f == OCInfoFormat::IncludeOC)
+            {
+                OutputArchiveType archive(os);
+                archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+            }
+            else if(f== OCInfoFormat::ExcludeOC)
+            {
+                bool firstPrinted = false;
+                for(std::vector<OCRepresentation>::size_type i = 0; i< m_reps.size();++i)
+                {
+                    if(!m_reps[i].empty())
+                    {
+                        if(firstPrinted)
+                        {
+                            os<<',';
+                        }
+                        firstPrinted=true;
+                        os << m_reps[i].getJSONRepresentation();
+                    }
+                }
+            }
+        }
+        return os.str();
+    }
+
+    const std::vector<OCRepresentation>& MessageContainer::representations() const
+    {
+        return m_reps;
+    }
+
+    void MessageContainer::addRepresentation(const OCRepresentation& rep)
+    {
+        m_reps.push_back(rep);
+    }
+}
+
+namespace OC
+{
+    OCRepresentation::OCRepresentation()
+    :m_interfaceType(InterfaceType::None)
+    { }
+    std::string OCRepresentation::getJSONRepresentation() const
+    {
+        std::stringstream os;
+
+        // note: the block is required because cereal closes the JSON string
+        // upon destruction, so the archive needs to be destroyed before accessing
+        // the data
+        {
+            OutputArchiveType archive (os);
+            save(archive);
+        }
+
+        return os.str();
+    }
+
+    void OCRepresentation::addChild(const OCRepresentation& rep)
+    {
+        m_children.push_back(rep);
+    }
+
+    void OCRepresentation::clearChildren()
+    {
+        m_children.clear();
+    }
+
+    const std::vector<OCRepresentation>& OCRepresentation::getChildren() const
+    {
+        return m_children;
+    }
+
+    void OCRepresentation::setUri(const std::string& uri)
+    {
+        m_uri = uri;
+    }
+
+    std::string OCRepresentation::getUri() const
+    {
+        return m_uri;
+    }
+
+    const std::vector<std::string>& OCRepresentation::getResourceTypes() const
+    {
+        return m_resourceTypes;
+    }
+
+    void OCRepresentation::setResourceTypes(const std::vector<std::string>& resourceTypes)
+    {
+        m_resourceTypes = resourceTypes;
+    }
+
+    const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
+    {
+        return m_interfaces;
+    }
+
+    void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
+    {
+        m_interfaces = resourceInterfaces;
+    }
+
+    bool OCRepresentation::hasAttribute(const std::string& str) const
+    {
+        return m_values.find(str) != m_values.end();
+    }
+
+    bool OCRepresentation::empty() const
+    {
+        // This logic is meant to determine whether based on the JSON serialization rules
+        // if this object will result in empty JSON.  URI is only serialized if there is valid
+        // data, ResourceType and Interfaces are only serialized if we are a nothing, a
+        // child of a default or link item.
+        // Our values array is only printed in the if we are the child of a Batch resource,
+        // the parent in a 'default' situation, or not in a child/parent relationship.
+        if(!m_uri.empty())
+        {
+            return false;
+        }
+        else if ((m_interfaceType == InterfaceType::None
+                        || m_interfaceType==InterfaceType::DefaultChild
+                        || m_interfaceType==InterfaceType::LinkChild)
+                    && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+        {
+            return false;
+        }
+        else if((m_interfaceType == InterfaceType::None
+                        || m_interfaceType == InterfaceType::BatchChild
+                        || m_interfaceType == InterfaceType::DefaultParent)
+                    && m_values.size()>0)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    int OCRepresentation::numberOfAttributes() const
+    {
+        return m_values.size();
+    }
+
+    bool OCRepresentation::erase(const std::string& str)
+    {
+        return m_values.erase(str);
+    }
+
+    void OCRepresentation::setNULL(const std::string& str)
+    {
+        m_values[str] = OC::NullType();
+    }
+
+    bool OCRepresentation::isNULL(const std::string& str) const
+    {
+        auto x = m_values.find(str);
+
+        if(m_values.end() != x)
+        {
+            return x->second.which() == AttributeValueNullIndex;
+        }
+        else
+        {
+            throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str);
+        }
+    }
+}
+
+namespace OC
+{
+    template <class Archive, class Val>
+    void OCRepresentation::optional_load(Archive& ar, Val&& v)
+    {
+        try
+        {
+            ar(v);
+        }
+        catch(cereal::Exception& e)
+        {
+            ar.setNextName(nullptr);
+            // Loading a key that doesn't exist results in an exception
+            // Since "Not Found" is a valid condition for us, we swallow
+            // this exception and the archive will not load anything
+        }
+    }
+
+    template<class Archive>
+    void OCRepresentation::save(Archive& ar) const
+    {
+        // printed for all interface types
+        if(!m_uri.empty())
+        {
+            ar(cereal::make_nvp(Key::URIKEY, m_uri));
+        }
+
+        if((m_interfaceType == InterfaceType::None
+                    || m_interfaceType==InterfaceType::DefaultChild
+                    || m_interfaceType==InterfaceType::LinkChild)
+                && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+        {
+            // The Prop object requires that it refer to non-const vectors
+            // so that it can alter them in the 'load' case.  In the save case
+            // (initiated here) it will not modify the object.  So, to keep the
+            // compiler happy, removing the 'const' context here is necessary.
+            const std::vector<std::string>& rt(m_resourceTypes);
+            const std::vector<std::string>& intf(m_interfaces);
+            Prop temp(const_cast<std::vector<std::string>&>(rt),
+                    const_cast<std::vector<std::string>&>(intf));
+            ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
+        }
+
+        // printed only for BatchChildren and DefaultParent
+        if((m_interfaceType == InterfaceType::None
+                    || m_interfaceType == InterfaceType::BatchChild
+                    || m_interfaceType == InterfaceType::DefaultParent)
+                && m_values.size()>0)
+        {
+            ar(cereal::make_nvp(Key::REPKEY, m_values));
+        }
+    }
+
+    template<class Archive>
+    void OCRepresentation::load(Archive& ar)
+    {
+        optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
+        {
+            Prop temp(m_resourceTypes, m_interfaces);
+            optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
+        }
+        optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
+    }
+
+    template<class Archive>
+    void OCRepresentation::Prop::save(Archive& ar) const
+    {
+        if(m_types.size() > 0)
+        {
+            ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+        }
+
+        if(m_interfaces.size()>0)
+        {
+            ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+        }
+    }
+
+    template<class Archive>
+    void OCRepresentation::Prop::load(Archive& ar)
+    {
+        optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+        optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+    }
+}
+
+// note: the below is used to load an AttributeValue map out of JSON
+namespace OC
+{
+    namespace detail
+    {
+        enum class typeTag:uint8_t
+        {
+            NOTHING = 0,
+            _string,
+            _int,
+            _double,
+            _bool,
+            _representation
+        };
+
+        typedef rapidjson::Document::GenericValue GenericValue;
+
+        AttributeValue parseAttributeValue(const GenericValue& v);
+        AttributeValue parseAttributeValue(const GenericValue& v,
+                const unsigned int curLevel, unsigned int& maxDepth, typeTag& t);
+        AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t);
+        AttributeValue parseAttributeValueArray(const GenericValue& v,
+                const unsigned int curLevel, unsigned int& maxDepth, typeTag& t);
+        AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t);
+
+        AttributeValue parseAttributeValue(const GenericValue& v)
+        {
+            // base entrance, start everything at '0'
+            unsigned int max_depth {0};
+            typeTag t {typeTag::NOTHING};
+
+            return parseAttributeValue(v, 0, max_depth, t);
+        }
+
+        AttributeValue parseAttributeValue(const GenericValue& v,
+                const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+        {
+            if(v.IsObject())
+            {
+                return parseAttributeValueObject(v, t);
+            }
+            else if(v.IsArray())
+            {
+                return parseAttributeValueArray(v, curLevel + 1, maxDepth, t);
+            }
+            else
+            {
+                return parseAttributeValuePrimitive(v,t);
+            }
+        }
+
+        AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t)
+        {
+            typedef rapidjson::Value::ConstMemberIterator CMI;
+            t = typeTag::_representation;
+            OC::OCRepresentation rep;
+
+            for(CMI itr = v.MemberBegin(); itr!= v.MemberEnd(); ++itr)
+            {
+                std::string keyName = itr->name.GetString();
+
+                if(keyName == OC::Key::URIKEY)
+                {
+                    rep.setUri(boost::get<std::string>(parseAttributeValue(itr->value)));
+                }
+                else if (keyName == OC::Key::PROPERTYKEY)
+                {
+                    for(CMI itr2 = itr->value.MemberBegin();
+                            itr->value.MemberEnd()!=itr2;
+                            ++itr2)
+                    {
+                        if(keyName == OC::Key::RESOURCETYPESKEY)
+                        {
+                            rep.setResourceTypes(
+                                    boost::get<std::vector<std::string>>(
+                                        parseAttributeValue(itr->value)));
+                        }
+                        else if(keyName == OC::Key::PROPERTYKEY)
+                        {
+                            rep.setResourceInterfaces(
+                                    boost::get<std::vector<std::string>>(
+                                        parseAttributeValue(itr->value)));
+                        }
+                    }
+                }
+                else if (keyName == OC::Key::REPKEY)
+                {
+                    for(CMI itr2 = itr->value.MemberBegin();
+                            itr->value.MemberEnd()!=itr2;
+                            ++itr2)
+                    {
+                        rep.setValue(itr2->name.GetString(),
+                                parseAttributeValue(itr2->value));
+                    }
+                }
+            }
+
+            return rep;
+        }
+
+        AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t)
+        {
+            if(v.IsString())
+            {
+                t = typeTag::_string;
+                return std::string(v.GetString());
+            }
+            else if (v.IsNumber())
+            {
+                if(v.IsDouble())
+                {
+                    t = typeTag::_double;
+                    return double(v.GetDouble());
+                }
+                else if (v.IsInt())
+                {
+                    t = typeTag::_int;
+                    return int(v.GetInt());
+                }
+                else
+                {
+                    throw OC::OCException(OC::Exception::INVALID_JSON_NUMERIC
+                            + std::to_string(v.GetType()));
+                }
+            }
+            else if(v.IsBool_())
+            {
+                t=typeTag::_bool;
+                return bool(v.GetBool_());
+            }
+            else if(v.IsNull_())
+            {
+                return OC::NullType();
+            }
+            else
+            {
+                throw OC::OCException(OC::Exception::INVALID_JSON_TYPE
+                        + std::to_string(v.GetType()));
+            }
+        }
+
+        std::vector<AttributeValue> gatherArrayContents(const GenericValue& v,
+                const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+        {
+            std::vector<AttributeValue> out;
+
+            std::transform(v.Begin(), v.End(), back_inserter(out),
+                    [curLevel, &maxDepth, &t](const GenericValue& x)
+                    {
+                        return parseAttributeValue(x, curLevel, maxDepth, t);
+                    });
+            return out;
+        }
+
+        template<class OutT>
+        struct valueToConcrete
+        {
+            OutT operator()(const AttributeValue& v)
+            {
+                return boost::get<OutT>(v);
+            }
+
+        };
+
+        template <class OutSeqT>
+        OutSeqT valuesToConcreteVectors(const std::vector<AttributeValue>& vs)
+        {
+            OutSeqT ret;
+
+            std::transform(begin(vs),end(vs), back_inserter(ret),
+                valueToConcrete<typename OutSeqT::value_type>());
+            return ret;
+        }
+
+        template<class valueType>
+        AttributeValue remapArrayDepth(const unsigned int curLevel,
+                const std::vector<OC::AttributeValue>& vs)
+        {
+            switch(curLevel)
+            {
+                default:
+                    throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH);
+                    break;
+                case 1:
+                    return valuesToConcreteVectors<std::vector<valueType>>(vs);
+                    break;
+                case 2:
+                    return valuesToConcreteVectors<std::vector<std::vector<valueType>>>(vs);
+                    break;
+                case 3:
+                    return valuesToConcreteVectors
+                        <std::vector<std::vector<std::vector<valueType>>>>(vs);
+                    break;
+            }
+        }
+
+        AttributeValue convertArrayToConcretes(const typeTag t,
+                const unsigned int curLevel, const std::vector<OC::AttributeValue>& vs)
+        {
+            // This function converts a std::vector of AttributeValue to a std::vector
+            // of concrete types.  Since we don't use a recursive Variant, we need
+            // to get back to a 'base' primitive type
+            switch(t)
+            {
+                default:
+                case typeTag::NOTHING:
+                    throw OC::OCException(OC::Exception::INVALID_JSON_TYPE_TAG);
+                    break;
+                case typeTag::_string:
+                    return remapArrayDepth<std::string>(curLevel, vs);
+                    break;
+                case typeTag::_int:
+                    return remapArrayDepth<int>(curLevel, vs);
+                    break;
+                case typeTag::_double:
+                    return remapArrayDepth<double>(curLevel, vs);
+                    break;
+                case typeTag::_bool:
+                    return remapArrayDepth<bool>(curLevel, vs);
+                    break;
+                case typeTag::_representation:
+                    return remapArrayDepth<OCRepresentation>(curLevel, vs);
+                    break;
+            }
+        }
+
+        AttributeValue parseAttributeValueArray(const GenericValue& v,
+                const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+        {
+            const unsigned int max_level = 3;
+
+            if(curLevel > max_level)
+            {
+                throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH);
+            }
+
+            if(curLevel > maxDepth)
+            {
+                maxDepth = curLevel;
+            }
+
+            auto arrayItems = gatherArrayContents(v, curLevel, maxDepth, t);
+            const int remapLevel = maxDepth - (curLevel -1);
+            return convertArrayToConcretes(t, remapLevel, arrayItems);
+        }
+    }
+}
+
+namespace cereal
+{
+   void JSONInputArchive::loadAttributeValues(std::map<std::string, OC::AttributeValue>& map)
+   {
+       for(auto&b = itsIteratorStack.back();
+           b.Member && b.itsMemberItEnd != b.itsMemberItBegin+b.itsIndex;
+           ++b)
+       {
+           std::string key = b.itsMemberItBegin[b.itsIndex].name.GetString();
+           const GenericValue& v = itsIteratorStack.back().value();
+           map[key] = OC::detail::parseAttributeValue(v);
+       }
+   }
+}
index 8f094b3..df5ff60 100644 (file)
@@ -43,7 +43,7 @@ OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper, const std::s
         m_clientWrapper.expired())
     {
         throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
-                interfaces.empty(), m_clientWrapper.expired());
+                interfaces.empty(), m_clientWrapper.expired(), false, false);
     }
 }
 
index 002d7fe..c55d8f9 100644 (file)
@@ -201,11 +201,8 @@ OCStackResult result_guard(const OCStackResult r)
     case OC_STACK_SLOW_RESOURCE:
     case OC_STACK_NO_OBSERVERS:
     case OC_STACK_OBSERVER_NOT_FOUND:
-    case OC_STACK_OBSERVER_NOT_ADDED:
-    case OC_STACK_OBSERVER_NOT_REMOVED:
 #ifdef WITH_PRESENCE
     case OC_STACK_PRESENCE_STOPPED:
-    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
 #endif
 
     break;
index 2447934..7ec0c8e 100644 (file)
@@ -1,13 +1,13 @@
 ##
-# OCLib (static library) build script
+# OCLib (share library) build script
 ##
-Import('env', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 
 # Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-
-oclib_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
+oclib_env = lib_env.Clone()
 ######################################################################
 # Build flags
 ######################################################################
@@ -21,26 +21,33 @@ oclib_env.AppendUnique(CPPPATH = [
                '../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
-       oclib_env.AppendUnique(CXXFLAGS = ['-std=c++11', '-Wall'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       oclib_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC'])
 
-if BUILD_TARGET == 'android':
+if target_os == 'android':
        oclib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        oclib_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+       oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger', 'boost_thread-gcc-mt-1_49', 'gnustl_static', 'log'])
+
+if target_os in ['darwin', 'ios']:
+       oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger'])
 
 ######################################################################
 # Source files and Targets
 ######################################################################
 oclib_src = [
                'OCPlatform.cpp',
+               'OCPlatform_impl.cpp',
                'OCResource.cpp',
                'OCUtilities.cpp',
                'OCException.cpp',
+               'OCRepresentation.cpp',
                'InProcServerWrapper.cpp',
                'InProcClientWrapper.cpp'
        ]
 
-oclib = oclib_env.StaticLibrary('oc', oclib_src)
-i_ocl = oclib_env.Install(BUILD_DIR, oclib)
-Alias('liboc', i_ocl)
-env.AppendUnique(TS = ['liboc'])
\ No newline at end of file
+oclib = oclib_env.SharedLibrary('oc', oclib_src)
+oclib_env.InstallTarget(oclib, 'liboc')
index 2cf1cfc..a22bc36 100644 (file)
@@ -4,75 +4,66 @@
 #Note: The paths must keep consistent with oic-utilities
 ######################################################################
 import os
+import platform
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'SRC_TOP_DIR')
+Import('env', 'lib_env')
 
-# Add 'OIC_UTILS' build option for user to set oic-utilities project path
-default_dir = os.path.abspath(SRC_TOP_DIR + '/../oic-utilities')
-OIC_UTILS = ARGUMENTS.get('OIC_UTILS', default_dir)
-if not os.path.exists(OIC_UTILS):
-       print '''
-*********************************** Error: ************************************
-*   oic-utilities project directory(OIC_UTILS) isn't set properly, please set *
-* enviornment variable OIC_UTILS or set it in command line:                   *
-*     # scons  OIC_UTILS=<path to oic-utilities> ...                          *
-*******************************************************************************
-'''
-       Exit(1)
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
 
-if env.get('OIC_UTILS') is None:
-       vars = Variables()
-       vars.Add(PathVariable('OIC_UTILS', 'oic-utilities project path', OIC_UTILS))
-       vars.Update(env)
-       Help(vars.GenerateHelpText(env))
-       Export('OIC_UTILS')
+if target_os not in ['linux', 'darwin']:
+       utils_path = env.get('OIC_UTILS')
 
-       ######################################################################
-       # Check dependent packages (Linux)
-       ######################################################################
-       if BUILD_TARGET == 'linux':
-               # Delete the temp files of configuration
-               if env.GetOption('clean'):
-                       if os.path.exists(SRC_TOP_DIR + 'config.log'):
-                               Execute(Delete(SRC_TOP_DIR + 'config.log'))
-                               Execute(Delete(SRC_TOP_DIR + '.sconsign.dblite'))
-                               Execute(Delete(SRC_TOP_DIR + '.sconf_temp'))
-               elif not env.GetOption('help'):
-                       conf = Configure(env)
+######################################################################
+# Check dependent packages (Linux only)
+######################################################################
+if target_os == 'linux':
+       if not env.GetOption('help'):
+               if not target_arch == platform.machine():
+                       print '''
+*********************************** Warning ***********************************
+* You are trying cross build, please make sure (%s) version libraries are
+* installed!                                                                 *
+*******************************************************************************
+''' % target_arch
 
-                       if not conf.CheckLib('boost_program_options'):
-                               print 'Did not find boost_program_options, exiting!'
-                               Exit(1)
+               conf = Configure(lib_env)
 
-                       conf.Finish()
+               if not conf.CheckLib('boost_program_options'):
+                       print 'Did not find boost_program_options, exiting!'
+                       Exit(1)
 
-       ######################################################################
-       # The 'include' path of third party libraries
-       ######################################################################
+               conf.Finish()
 
-       if BUILD_TARGET == 'android':
-               env.AppendUnique(CPPPATH = [OIC_UTILS + '/android/boost/include'])
+######################################################################
+# The 'include' path of third party libraries
+######################################################################
+if target_os == 'android':
+       lib_env.AppendUnique(CPPPATH = [utils_path + '/android/boost/include'])
 
-       ######################################################################
-       # The path of third party libraries binary
-       ######################################################################
-       if BUILD_TARGET == 'android':
-               arch = TARGET_CPU_ARCH
-               if arch == 'armeabi-v7a-hard':
-                       arch = 'armeabi-v7a'
+######################################################################
+# The path of third party libraries binary
+######################################################################
+if target_os == 'android':
+       if target_arch == 'armeabi-v7a-hard':
+               target_arch = 'armeabi-v7a'
 
-               if arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+       if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+               if not env.GetOption('help') and not env.GetOption('clean'):
                        print '''
 *********************************** Warning ***********************************
-* current only x86, armeabi, armeabi-v7a libraries are offered!               *
+* current only x86, armeabi, armeabi-v7a libraries are provided!              *
 *******************************************************************************
 '''
-               else:
-                       env.AppendUnique(LIBPATH = [OIC_UTILS + '/android/boost/libs/' + arch])
+       else:
+               lib_env.AppendUnique(LIBPATH = [utils_path + '/android/boost/libs/' + target_arch])
+               # Too much boost warning, suppress the warning
+               lib_env.AppendUnique(CCFLAGS = ['-w'])
 
-       elif BUILD_TARGET == 'ios':
-               env.AppendUnique(FRAMEWORKPATH = [OIC_UTILS + '/ios/frameworks/'])
-               env.AppendUnique(FRAMEWORKS = ['boost'])
-       elif BUILD_TARGET == 'darwin':
-               env.AppendUnique(CPPPATH = ['/usr/local/include'])
-               env.AppendUnique(LIBPATH = ['/usr/local/lib'])
\ No newline at end of file
+elif target_os == 'ios':
+       lib_env.AppendUnique(FRAMEWORKPATH = [utils_path + '/ios/frameworks/'])
+       lib_env.AppendUnique(FRAMEWORKS = ['boost'])
+elif target_os == 'darwin':
+       lib_env.AppendUnique(CPPPATH = ['/usr/local/include'])
+       lib_env.AppendUnique(LIBPATH = ['/usr/local/lib'])
\ No newline at end of file
index e8283c0..5461731 100644 (file)
@@ -38,6 +38,10 @@ include $(ROOT_DIR)/../csdk/local.properties
 
 OUT_DIR          := $(BUILD)
 
+ifeq ($(ROOT_DIR),)
+       ROOT_DIR:=$(PWD)
+endif
+
 INC_DIRS  := -I../include/
 INC_DIRS  += -I../oc_logger/include
 INC_DIRS  += -I../csdk/stack/include
index 1b9c601..e299b43 100644 (file)
@@ -35,8 +35,7 @@ using namespace OC;
 using namespace std;
 
 // Entity handler used for register and find test
-OCEntityHandlerResult entityHandler_rf(std::shared_ptr<OCResourceRequest> request,
-                    std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler_rf(std::shared_ptr<OCResourceRequest> request)
 {
     return OC_EH_OK;
 }
diff --git a/scons_script_how_to.txt b/scons_script_how_to.txt
new file mode 100644 (file)
index 0000000..c210419
--- /dev/null
@@ -0,0 +1,235 @@
+== How to write iotivity build script ==
+
+Iotivity projects are built with Scons. Scons is a cross-platform build tool,
+it's quite similar to 'make'. 'SConstruct' is the entrance of scons build, it's
+equivalent to 'Makefile' to 'make'.
+
+This document only a brief reference. Detail about how to write scons script,
+please refer to:
+       http://www.scons.org/doc/production/HTML/scons-user.html#
+
+== Background: How to control source code compiling ==
+
+Environment is a base conception of Scons. An environment is a collection of
+values that can affect how a program is built.
+
+e.g. There is a C file named hello.c, enter the following into a file named
+SConstruct:
+       env = Environment()
+       env.Program('H', 'hello.c')
+
+When run Scons in console, following will be executed:
+cc -o hello.o -c hello.c
+cc -o H hello.o
+
+If you would like keep debug information in the binary, '-g' flag should be added
+when build the source code. To do this, append a C compiler flags as following:
+       env = Environment()
+       env.AppendUnique(CFLAGS = ['-g'])
+       env.Program('H', 'hello.c')
+
+When run Scons, following will be executed:
+cc -o hello.o -c -g hello.c
+cc -o H hello.o
+
+In above example, 'CFLAGS' is changed. Following list the frequently used keys:
+
+CFLAGS: General options that are passed to the C compiler
+CCFLAGS: General options that are passed to the C & C++ compiler
+CXXFLAGS: General options that are passed to the C++ compiler
+CPPPATH: The directories that the preprocessor will search for include headers.
+CPPDEFINES: Platform independent specification of C preprocessor definitions.
+
+Note: CPPPATH and CPPDEFINES is common for all compiler. But others are
+compiler specific, when change the key value, it may requried to specify the
+target platform(actually the compiler).
+
+e.g.
+       env.AppendUnique(CPPPATH = ['.', 'include'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG', 'VER_TEST'])
+Above two lines are fine for all target platform. but below line:
+       env.AppenUnique(CXXFLAGS = ['-g'])
+is only fine for gcc compiler, as '-g' is a gcc flag, other compiler may don't
+understand it. so it may should be:
+       if target_os not in ['windows', 'winrt']:
+               env.AppenUnique(CXXFLAGS = ['-g'])
+
+Still take the hello.c as example. Assume hello.h is in ./include/ directory,
+#include "hello.h"
+int main(int argc, char** argv)
+{
+#ifdef LANG_FR
+    printf("Bonjour\n");
+#else
+       printf("Hello\n");
+#endif
+}
+
+The Scons configure file should as following:
+       env = Environment()
+       env.AppendUnique(CFLAGS = ['-g'])
+       env.AppendUnique(CPPPATH = ['include'])
+       env.AppendUnique(CPPDEFINES = ['LANG_FR'])
+       env.Program('H', 'hello.c')
+
+When run Scons, following will be executed:
+cc -o hello.o -c -g -Iinclude -DLANG_FR hello.c
+cc -o H hello.o
+
+=== Get extra information ===
+
+In above example, 'target_os' is used. How to get it?
+
+User can build iotivity project on linux / windows / MAC OSX for various
+targets(Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...). Most
+platform specific configures have been done in the common scripts whitch are in
+build_common. The common scripts prepare an environment named 'env' with
+target platform specific configuration.
+
+When write iotivity project build script, you can get this environment as
+following:
+       Import('env')
+
+You can use 'env' directly after import it. You can also clone a new environment
+and update its keys.
+
+       new_env1 = Clone('env')
+       new_env2 = Clone('env')
+       new_env1.AppendUnqiue(xxx = [...])
+       new_env2.AppendUnqiue(xxx = [...])
+
+The 'env' environment contains platform specific configuration, besides, there is
+some common information. You can get the information with following line:
+       env.get('XXX')
+
+XXX is the information name, below are the extra information added by iotivity
+common scrirpts:
+BUILD_DIR: the path of the build directory
+SRC_DIR: the path of the top directory of the source code
+OIC_UTILS: the path of oic-utilities project
+RELEASE: boolean. True - release build, False - debug build
+TARGET_OS: the name of the target OS. The possible value depends on the host
+       platform. Bellow is the list of host and possible target OS. (darwin means
+       MAC OSX)
+               linux: linux / android / arduino
+(the line means on linux, you can build the project for linux/android/arduino)
+               windows: windows / winrt / android / arduino
+               darwin: darwin / ios / android / arduino
+
+TARGET_ARCH: the target CPU arch. Its possible value depend on the target OS
+       Bellow list the target OS and allowed CPU architecture.
+               linux: x86 / x86_64 / arm / arm64
+(above line means if the target OS is linux, the CPU arch can be x86/x86_64/arm/arm64)
+               android: x86 / x86_64 / armeabi / armeabi-v7a / armeabi-v7a-hard / arm64-v8a
+               windows: x86 / amd64 / arm
+               winrt: arm
+               darwin: i386 / x86_64
+               ios: i386 / x86_64 / armv7 / armv7s / arm64,
+               arduino: avr / arm
+
+=== Extra functions ===
+
+For convenience, in the common scripts, some extra functions are added.
+
+PrintTargets(): print all targets in the help information.
+AppendTarget(target): add 'target' into targets list, when use PrintTargets,
+       the 'target' will be print.
+InstallTarget(files, name): it takes the same action as AppendTarget, besides,
+       it installs the 'files' to BUILD_DIR.
+
+Following functions are only for Arduino:
+ImportLib(lib): Arduino IDE includes many libraries. To control the binary size,
+by default, no library is used. If your project use some libraries, you can
+import the lib with this function. 'lib' is the name of the lib to import.
+The include path will be auto added to the environment and the library will be
+built and linked into the final binary.
+
+CreateBin('bin', src): For Arduino, after build the program, it's required to
+be converted into specific format (e.g .hex). This function will genearate the
+required .hex (and .eep if target arch is avr) file.
+
+UploadHelp(): For different board, the upload command line is different, this
+function print the recommended upload command line. You can see the recommended
+upload command line in the help information.
+
+==== Scripts Hierarchy ====
+
+Scons provides a function 'SConscript(scripts, [exports, variant_dir, duplicate])'
+It tells scons to execute one or more subsidiary configuration files(A script,
+usually named SConscript). Take below project hierarchy as example to show how
+to organize the scripts.
+
+               prj
+               |-------prj_1
+               |               |--------sub_prj_11
+               |               |--------sub_prj_..
+               |               |--------sub_prj_1n
+               |-------prj_2
+               |
+               | ... ...
+               |
+               |-------prj_n
+
+As above project hierarchy, in 'SConstruct' file in the 'prj' directory, there
+should include some lines like these:
+
+#Please change this part according to the organization of your projects.
+#Note: To make the output is in build_dir, the path of the scripts should
+#be relevant to build_dir
+SConscript(build_dir + 'prj_1/SConscript')
+SConscript(build_dir + 'prj_2/SConscript')
+... ...
+SConscript(build_dir + 'prj_n/SConscript')
+
+
+It's the same, in the 'prj_1/SConscript', there should include lines like
+these:
+SConscript('sub_prj_11/SConscript')
+... ...
+SConscript('sub_prj_1n/SConscript')
+
+The path is relevant to 'prj_1/SConscript'. You can also use the full path
+build_dir + 'prj_1/sub_prj_1x/SConscript', but it's not recommended.
+
+Above just to show a usual way to manage subsidiary scripts. You don't need
+restrictly follow it.
+
+==== The content of a typical script ====
+
+After run the scripts in build_common (usally it's done at the beginning of
+SConstruct), an global environment 'env' is exported, 'env' has include the
+default configuration of the target OS and arch. 'env' is used in all projects,
+should avoid to change its keys. To avoid change 'env', usually clone 'env' and
+update it accroding to the requirement of cuurent sub project. Then specify the
+target(usually binary) to build.
+
+Below is an example:
+       # import the global enviroment 'env'
+       Import('env')
+
+       # Clone a new enviroment from 'env'
+       new_env = env.Clone()
+
+       # Update the new enviroment, usally include add header file paths,
+       # library path, libs to link and other compiler flags. This part is
+       # optional. If not present, the default configuration will be used
+       new_env.AppeneUnique(xxx = [ .... ])
+
+       # Specify the target(application, library, object or others) to build
+       ts = new_env.Program('progam_name', [source_list])
+
+       # Install the target (optional)
+       new_env.InstallTarget(ts, 'target_name')
+or
+       new_env.Alias('target_name', ts)
+       new_env.AppendTarget('target_name')
+
+==== Tips ====
+1. library order: if A lib use B lib, both A and B are linked to target T, the
+       when specify libraries, A should in front of B, otherwise there may be link
+       error.
+2. On android:
+       (1)'pthread' is in libc. So don't use '-lpthread' for android
+       (2)By default 'rtti' and 'exception' is disabled, to enable it, you need
+       add flags '-frtti' and '-fexceptions'
+       (3)If STL is used, need link 'gnustl_static' library
diff --git a/service/SConscript b/service/SConscript
new file mode 100644 (file)
index 0000000..4f49777
--- /dev/null
@@ -0,0 +1,25 @@
+##
+# 'service' sub-project main build script
+#
+##
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os != 'arduino':
+       # Build things manager project
+       SConscript('things-manager/SConscript')
+
+       # Build soft sensor manager project
+       SConscript('soft-sensor-manager/SConscript')
+
+       # Build protocol plugin project
+       # protocol-plugin use 'sys/inotify.h', this header file doesn't
+       # exist on MAC OSX
+       if target_os not in ['darwin', 'ios']:
+               SConscript('protocol-plugin/SConscript')
+
+       # Build notification manager project
+       SConscript('notification-manager/SConscript')
+else:
+       SConscript('notification-manager/SampleApp/arduino/SConscript')
diff --git a/service/notification-manager/SConscript b/service/notification-manager/SConscript
new file mode 100644 (file)
index 0000000..a5e52dd
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+notimgr_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+notimgr_env.AppendUnique(CPPPATH = ['NotificationManager/include'])
+notimgr_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap'])
+
+if target_os not in ['windows', 'winrt']:
+       notimgr_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+if target_os == 'linux':
+       notimgr_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+       notimgr_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       notimgr_env.AppendUnique(LIBS = ['gnustl_static'])
+       notimgr_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+       if not env.get('RELEASE'):
+               notimgr_env.AppendUnique(LIBS = ['log'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+NOTI_SRC_DIR = 'NotificationManager/src/'
+notimgr_src = [
+               NOTI_SRC_DIR + 'LinuxMain.cpp',
+               NOTI_SRC_DIR + 'NotificationManager.cpp',
+               NOTI_SRC_DIR + 'RegistrationManager.cpp',
+               NOTI_SRC_DIR + 'ResourceManager.cpp',
+               NOTI_SRC_DIR + 'VirtualRepresentation.cpp']
+
+notificationmanager = notimgr_env.Program('noti_manager', notimgr_src)
+
+notimgr_env.InstallTarget(notificationmanager, 'notificationmanager')
+
+# Go to build sample apps
+SConscript('SampleApp/SConscript')
diff --git a/service/notification-manager/SampleApp/SConscript b/service/notification-manager/SampleApp/SConscript
new file mode 100644 (file)
index 0000000..d59dc6d
--- /dev/null
@@ -0,0 +1,10 @@
+##
+# Examples build script
+##
+Import('env')
+
+target_os = env.get('TARGET_OS')
+if target_os == 'linux':
+       SConscript('linux/SConscript')
+elif target_os == 'arduino':
+       SConscript('arduino/SConscript')
\ No newline at end of file
diff --git a/service/notification-manager/SampleApp/arduino/SConscript b/service/notification-manager/SampleApp/arduino/SConscript
new file mode 100644 (file)
index 0000000..04602f6
--- /dev/null
@@ -0,0 +1,33 @@
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+notimgr_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+resource_path = env.get('SRC_DIR') + '/resource'
+
+notimgr_env.AppendUnique(CPPPATH = [
+               resource_path + '/oc_logger/include',
+               resource_path + '/csdk/stack/include',
+               resource_path + '/csdk/ocsocket/include',
+               resource_path + '/csdk/logger/include'
+               ])
+
+notimgr_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+notimgr_env.PrependUnique(LIBS = ['octbstack', 'coap'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+thserver = notimgr_env.Program('thserver', 'thserver.cpp')
+notimgr_env.CreateBin('thserver')
+
+i_thserver = notimgr_env.Install(env.get('BUILD_DIR'), thserver)
+
+Alias('thserver_arduino', i_thserver)
+env.AppendTarget('thserver_arduino')
\ No newline at end of file
diff --git a/service/notification-manager/SampleApp/linux/SConscript b/service/notification-manager/SampleApp/linux/SConscript
new file mode 100644 (file)
index 0000000..be46453
--- /dev/null
@@ -0,0 +1,22 @@
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+notimgr_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+notimgr_env.AppendUnique(CPPPATH = ['../../NotificationManager/include'])
+notimgr_env.AppendUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap', 'pthread'])
+notimgr_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+sampleprovider = notimgr_env.Program('sampleprovider', 'sampleProvider/SampleProvider.cpp')
+sampleconsumer = notimgr_env.Program('sampleconsumer', 'sampleConsumer/SampleConsumer.cpp')
\ No newline at end of file
diff --git a/service/protocol-plugin/SConscript b/service/protocol-plugin/SConscript
new file mode 100644 (file)
index 0000000..d8db971
--- /dev/null
@@ -0,0 +1,13 @@
+##
+# protocol plugin build script
+##
+Import('env')
+
+SConscript('lib/cpluff/SConscript')
+SConscript('plugin-manager/SConscript')
+
+#The code include pthread_cancel method, can't build on android
+if env.get('TARGET_OS') != 'android':
+       SConscript('plugins/SConscript')
+
+SConscript('sample-app/SConscript')
index 7def475..53f0396 100644 (file)
@@ -20,14 +20,14 @@ plugins:
        cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE)
 
 sample-app:
-       cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE)
-       cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/fan-control/fanclient release/
+       cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE)
+       cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libpmimpl.so $(PROTOCOL_ROOT)sample-app/linux/mqtt/
+       cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/mqtt/mqttclient release/
        
 
 clean:
        cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE) clean
        cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE) clean
        cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE) clean
-       cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE) clean
-       cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE) clean
+       cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE) clean
        rm -rf release
diff --git a/service/protocol-plugin/lib/cpluff/SConscript b/service/protocol-plugin/lib/cpluff/SConscript
new file mode 100644 (file)
index 0000000..58e79f7
--- /dev/null
@@ -0,0 +1,31 @@
+##
+#c-pluff build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+cpluff_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+cpluff_env.AppendUnique(CPPPATH = ['libcpluff/'])
+if target_os not in ['windows', 'winrt']:
+       cpluff_env.AppendUnique(CFLAGS = ['-g','-fPIC', '-DPIC',
+                               '-DDLOPEN_POSIX',
+                               '-DCP_HOST=\\"' + platform.platform() + '\\"',
+                               '-DCP_SHREXT=\\".so\\"',
+                               '-DCP_FNAMESEP_CHAR=\\"\'/\'\\"',
+                               '-DCP_THREADS=\\"Posix\\"'])
+       cpluff_env.AppendUnique(LIBS = ['dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+cpluff_src = [f for f in env.Glob('libcpluff/*.c') if os.path.basename(f.path) not in ['thread_windows.c']]
+cpluff_src.extend(env.Glob('kazlib/*.c'))
+
+cpluff = cpluff_env.StaticLibrary('cpluff', cpluff_src)
+cpluff_env.InstallTarget(cpluff, 'libcpluff')
\ No newline at end of file
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml.hpp
new file mode 100644 (file)
index 0000000..9ddf195
--- /dev/null
@@ -0,0 +1,2601 @@
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+    #include <cstdlib>      // For std::size_t
+    #include <cassert>      // For assert
+    #include <new>          // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4). 
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+    #pragma warning(push)
+    #pragma warning(disable:4127)   // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+    
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+    //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, 
+    //! this function is called to notify user about the error.
+    //! It must be defined by the user.
+    //! <br><br>
+    //! This function cannot return. If it does, the results are undefined.
+    //! <br><br>
+    //! A very simple definition might look like that:
+    //! <pre>
+    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+    //! {
+    //!     std::cout << "Parse error: " << what << "\n";
+    //!     std::abort();
+    //! }
+    //! </pre>
+    //! \param what Human readable description of the error.
+    //! \param where Pointer to character data where error was detected.
+    void parse_error_handler(const char *what, void *where);
+}
+
+#else
+    
+#include <exception>    // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+    //! Parse error exception. 
+    //! This exception is thrown by the parser when an error occurs. 
+    //! Use what() function to get human-readable error message. 
+    //! Use where() function to get a pointer to position within source text where error was detected.
+    //! <br><br>
+    //! If throwing exceptions by the parser is undesirable, 
+    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+    //! This function must be defined by the user.
+    //! <br><br>
+    //! This class derives from <code>std::exception</code> class.
+    class parse_error: public std::exception
+    {
+    
+    public:
+    
+        //! Constructs parse error
+        parse_error(const char *what, void *where)
+            : m_what(what)
+            , m_where(where)
+        {
+        }
+
+        //! Gets human readable description of error.
+        //! \return Pointer to null terminated description of the error.
+        virtual const char *what() const throw()
+        {
+            return m_what;
+        }
+
+        //! Gets pointer to character data where error happened.
+        //! Ch should be the same as char type of xml_document that produced the error.
+        //! \return Pointer to location within the parsed string where error occured.
+        template<class Ch>
+        Ch *where() const
+        {
+            return reinterpret_cast<Ch *>(m_where);
+        }
+
+    private:  
+
+        const char *m_what;
+        void *m_where;
+
+    };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+    // Size of static memory block of memory_pool.
+    // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+    // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+    #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+    // Size of dynamic memory block of memory_pool.
+    // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+    // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+    #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+    // Memory allocation alignment.
+    // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+    // All memory allocations for nodes, attributes and strings will be aligned to this value.
+    // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+    #define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+    // Forward declarations
+    template<class Ch> class xml_node;
+    template<class Ch> class xml_attribute;
+    template<class Ch> class xml_document;
+    
+    //! Enumeration listing all node types produced by the parser.
+    //! Use xml_node::type() function to query node type.
+    enum node_type
+    {
+        node_document,      //!< A document node. Name and value are empty.
+        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
+        node_data,          //!< A data node. Name is empty. Value contains data text.
+        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
+        node_comment,       //!< A comment node. Name is empty. Value contains comment text.
+        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+        node_pi             //!< A PI node. Name contains target. Value contains instructions.
+    };
+
+    ///////////////////////////////////////////////////////////////////////
+    // Parsing flags
+
+    //! Parse flag instructing the parser to not create data nodes. 
+    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_data_nodes = 0x1;            
+
+    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+    //! Can be combined with other flags by use of | operator.
+    //! Note that child data nodes of element node take precendence over its value when printing. 
+    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_element_values = 0x2;
+    
+    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+    //! By default zero terminators are placed, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_string_terminators = 0x4;
+    
+    //! Parse flag instructing the parser to not translate entities in the source text.
+    //! By default entities are translated, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_entity_translation = 0x8;
+    
+    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+    //! By default, UTF-8 handling is enabled.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_utf8 = 0x10;
+    
+    //! Parse flag instructing the parser to create XML declaration node.
+    //! By default, declaration node is not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_declaration_node = 0x20;
+    
+    //! Parse flag instructing the parser to create comments nodes.
+    //! By default, comment nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_comment_nodes = 0x40;
+    
+    //! Parse flag instructing the parser to create DOCTYPE node.
+    //! By default, doctype node is not created.
+    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_doctype_node = 0x80;
+    
+    //! Parse flag instructing the parser to create PI nodes.
+    //! By default, PI nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_pi_nodes = 0x100;
+    
+    //! Parse flag instructing the parser to validate closing tag names. 
+    //! If not set, name inside closing tag is irrelevant to the parser.
+    //! By default, closing tags are not validated.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_validate_closing_tags = 0x200;
+    
+    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+    //! By default, whitespace is not trimmed. 
+    //! This flag does not cause the parser to modify source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_trim_whitespace = 0x400;
+
+    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+    //! By default, whitespace is not normalized. 
+    //! If this flag is specified, source text will be modified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_normalize_whitespace = 0x800;
+
+    // Compound flags
+    
+    //! Parse flags which represent default behaviour of the parser. 
+    //! This is always equal to 0, so that all other flags can be simply ored together.
+    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+    //! This also means that meaning of each flag is a <i>negation</i> of the default setting. 
+    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+    //! and using the flag will disable it.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_default = 0;
+    
+    //! A combination of parse flags that forbids any modifications of the source text. 
+    //! This also results in faster parsing. However, note that the following will occur:
+    //! <ul>
+    //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+    //! <li>entities will not be translated</li>
+    //! <li>whitespace will not be normalized</li>
+    //! </ul>
+    //! See xml_document::parse() function.
+    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+    
+    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+    
+    //! A combination of parse flags resulting in largest amount of data being extracted. 
+    //! This usually results in slowest parsing.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internals
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Struct that contains lookup tables for the parser
+        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+        template<int Dummy>
+        struct lookup_tables
+        {
+            static const unsigned char lookup_whitespace[256];              // Whitespace table
+            static const unsigned char lookup_node_name[256];               // Node name table
+            static const unsigned char lookup_text[256];                    // Text table
+            static const unsigned char lookup_text_pure_no_ws[256];         // Text table
+            static const unsigned char lookup_text_pure_with_ws[256];       // Text table
+            static const unsigned char lookup_attribute_name[256];          // Attribute name table
+            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
+            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
+            static const unsigned char lookup_digits[256];                  // Digits
+            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
+        };
+
+        // Find length of the string
+        template<class Ch>
+        inline std::size_t measure(const Ch *p)
+        {
+            const Ch *tmp = p;
+            while (*tmp) 
+                ++tmp;
+            return tmp - p;
+        }
+
+        // Compare strings for equality
+        template<class Ch>
+        inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+        {
+            if (size1 != size2)
+                return false;
+            if (case_sensitive)
+            {
+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (*p1 != *p2)
+                        return false;
+            }
+            else
+            {
+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+                        return false;
+            }
+            return true;
+        }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////
+    // Memory pool
+    
+    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+    //! In most cases, you will not need to use this class directly. 
+    //! However, if you need to create nodes manually or modify names/values of nodes, 
+    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. 
+    //! Not only is this faster than allocating them by using <code>new</code> operator, 
+    //! but also their lifetime will be tied to the lifetime of document, 
+    //! possibly simplyfing memory management. 
+    //! <br><br>
+    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. 
+    //! You can also call allocate_string() function to allocate strings.
+    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called, 
+    //! or when the pool is destroyed.
+    //! <br><br>
+    //! It is also possible to create a standalone memory_pool, and use it 
+    //! to allocate nodes, whose lifetime will not be tied to any document.
+    //! <br><br>
+    //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. 
+    //! Until static memory is exhausted, no dynamic memory allocations are done.
+    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+    //! by using global <code>new[]</code> and <code>delete[]</code> operators. 
+    //! This behaviour can be changed by setting custom allocation routines. 
+    //! Use set_allocator() function to set them.
+    //! <br><br>
+    //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+    //! This value defaults to the size of pointer on target architecture.
+    //! <br><br>
+    //! To obtain absolutely top performance from the parser,
+    //! it is important that all nodes are allocated from a single, contiguous block of memory.
+    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+    //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code> 
+    //! to obtain best wasted memory to performance compromise.
+    //! To do it, define their values before rapidxml.hpp file is included.
+    //! \param Ch Character type of created nodes. 
+    template<class Ch = char>
+    class memory_pool
+    {
+        
+    public:
+
+        //! \cond internal
+        typedef void *(alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
+        typedef void (free_func)(void *);              // Type of user-defined function used to free memory
+        //! \endcond
+        
+        //! Constructs empty pool with default allocator functions.
+        memory_pool()
+            : m_alloc_func(0)
+            , m_free_func(0)
+        {
+            init();
+        }
+
+        //! Destroys pool and frees all the memory. 
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Nodes allocated from the pool are no longer valid.
+        ~memory_pool()
+        {
+            clear();
+        }
+
+        //! Allocates a new node from the pool, and optionally assigns name and value to it. 
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param type Type of node to create.
+        //! \param name Name to assign to the node, or 0 to assign no name.
+        //! \param value Value to assign to the node, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated node. This pointer will never be NULL.
+        xml_node<Ch> *allocate_node(node_type type, 
+                                    const Ch *name = 0, const Ch *value = 0, 
+                                    std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+            xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+            if (name)
+            {
+                if (name_size > 0)
+                    node->name(name, name_size);
+                else
+                    node->name(name);
+            }
+            if (value)
+            {
+                if (value_size > 0)
+                    node->value(value, value_size);
+                else
+                    node->value(value);
+            }
+            return node;
+        }
+
+        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param name Name to assign to the attribute, or 0 to assign no name.
+        //! \param value Value to assign to the attribute, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated attribute. This pointer will never be NULL.
+        xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0, 
+                                              std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+            xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+            if (name)
+            {
+                if (name_size > 0)
+                    attribute->name(name, name_size);
+                else
+                    attribute->name(name);
+            }
+            if (value)
+            {
+                if (value_size > 0)
+                    attribute->value(value, value_size);
+                else
+                    attribute->value(value);
+            }
+            return attribute;
+        }
+
+        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+        //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+        //! \return Pointer to allocated char array. This pointer will never be NULL.
+        Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+        {
+            assert(source || size);     // Either source or size (or both) must be specified
+            if (size == 0)
+                size = internal::measure(source) + 1;
+            Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+            if (source)
+                for (std::size_t i = 0; i < size; ++i)
+                    result[i] = source[i];
+            return result;
+        }
+
+        //! Clones an xml_node and its hierarchy of child nodes and attributes.
+        //! Nodes and attributes are allocated from this memory pool.
+        //! Names and values are not cloned, they are shared between the clone and the source.
+        //! Result node can be optionally specified as a second parameter, 
+        //! in which case its contents will be replaced with cloned source node.
+        //! This is useful when you want to clone entire document.
+        //! \param source Node to clone.
+        //! \param result Node to put results in, or 0 to automatically allocate result node
+        //! \return Pointer to cloned node. This pointer will never be NULL.
+        xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+        {
+            // Prepare result node
+            if (result)
+            {
+                result->remove_all_attributes();
+                result->remove_all_nodes();
+                result->type(source->type());
+            }
+            else
+                result = allocate_node(source->type());
+
+            // Clone name and value
+            result->name(source->name(), source->name_size());
+            result->value(source->value(), source->value_size());
+
+            // Clone child nodes and attributes
+            for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+                result->append_node(clone_node(child));
+            for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+            return result;
+        }
+
+        //! Clears the pool. 
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Any nodes or strings allocated from the pool will no longer be valid.
+        void clear()
+        {
+            while (m_begin != m_static_memory)
+            {
+                char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+                if (m_free_func)
+                    m_free_func(m_begin);
+                else
+                    delete[] m_begin;
+                m_begin = previous_begin;
+            }
+            init();
+        }
+
+        //! Sets or resets the user-defined memory allocation functions for the pool.
+        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+        //! Allocation function must not return invalid pointer on failure. It should either throw,
+        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program. 
+        //! If it returns invalid pointer, results are undefined.
+        //! <br><br>
+        //! User defined allocation functions must have the following forms:
+        //! <br><code>
+        //! <br>void *allocate(std::size_t size);
+        //! <br>void free(void *pointer);
+        //! </code><br>
+        //! \param af Allocation function, or 0 to restore default function
+        //! \param ff Free function, or 0 to restore default function
+        void set_allocator(alloc_func *af, free_func *ff)
+        {
+            assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
+            m_alloc_func = af;
+            m_free_func = ff;
+        }
+
+    private:
+
+        struct header
+        {
+            char *previous_begin;
+        };
+
+        void init()
+        {
+            m_begin = m_static_memory;
+            m_ptr = align(m_begin);
+            m_end = m_static_memory + sizeof(m_static_memory);
+        }
+        
+        char *align(char *ptr)
+        {
+            std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+            return ptr + alignment;
+        }
+        
+        char *allocate_raw(std::size_t size)
+        {
+            // Allocate
+            void *memory;   
+            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
+            {
+                memory = m_alloc_func(size);
+                assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+            }
+            else
+            {
+                memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+                if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+                    RAPIDXML_PARSE_ERROR("out of memory", 0);
+#endif
+            }
+            return static_cast<char *>(memory);
+        }
+        
+        void *allocate_aligned(std::size_t size)
+        {
+            // Calculate aligned pointer
+            char *result = align(m_ptr);
+
+            // If not enough memory left in current pool, allocate a new pool
+            if (result + size > m_end)
+            {
+                // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+                std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+                if (pool_size < size)
+                    pool_size = size;
+                
+                // Allocate
+                std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
+                char *raw_memory = allocate_raw(alloc_size);
+                    
+                // Setup new pool in allocated memory
+                char *pool = align(raw_memory);
+                header *new_header = reinterpret_cast<header *>(pool);
+                new_header->previous_begin = m_begin;
+                m_begin = raw_memory;
+                m_ptr = pool + sizeof(header);
+                m_end = raw_memory + alloc_size;
+
+                // Calculate aligned pointer again using new pool
+                result = align(m_ptr);
+            }
+
+            // Update pool and return aligned pointer
+            m_ptr = result + size;
+            return result;
+        }
+
+        char *m_begin;                                      // Start of raw memory making up current pool
+        char *m_ptr;                                        // First free byte in current pool
+        char *m_end;                                        // One past last available byte in current pool
+        char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
+        alloc_func *m_alloc_func;                           // Allocator function, or 0 if default is to be used
+        free_func *m_free_func;                             // Free function, or 0 if default is to be used
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML base
+
+    //! Base class for xml_node and xml_attribute implementing common functions: 
+    //! name(), name_size(), value(), value_size() and parent().
+    //! \param Ch Character type to use
+    template<class Ch = char>
+    class xml_base
+    {
+
+    public:
+        
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        // Construct a base with empty name, value and parent
+        xml_base()
+            : m_name(0)
+            , m_value(0)
+            , m_parent(0)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+    
+        //! Gets name of the node. 
+        //! Interpretation of name depends on type of node.
+        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use name_size() function to determine length of the name.
+        //! \return Name of node, or empty string if node has no name.
+        Ch *name() const
+        {
+            return m_name ? m_name : nullstr();
+        }
+
+        //! Gets size of node name, not including terminator character.
+        //! This function works correctly irrespective of whether name is or is not zero terminated.
+        //! \return Size of node name, in characters.
+        std::size_t name_size() const
+        {
+            return m_name ? m_name_size : 0;
+        }
+
+        //! Gets value of node. 
+        //! Interpretation of value depends on type of node.
+        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use value_size() function to determine length of the value.
+        //! \return Value of node, or empty string if node has no value.
+        Ch *value() const
+        {
+            return m_value ? m_value : nullstr();
+        }
+
+        //! Gets size of node value, not including terminator character.
+        //! This function works correctly irrespective of whether value is or is not zero terminated.
+        //! \return Size of node value, in characters.
+        std::size_t value_size() const
+        {
+            return m_value ? m_value_size : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+    
+        //! Sets name of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it. 
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of name must be specified separately, because name does not have to be zero terminated.
+        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! \param name Name of node to set. Does not have to be zero terminated.
+        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+        void name(const Ch *name, std::size_t size)
+        {
+            m_name = const_cast<Ch *>(name);
+            m_name_size = size;
+        }
+
+        //! Sets name of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+        //! \param name Name of node to set. Must be zero terminated.
+        void name(const Ch *name)
+        {
+            this->name(name, internal::measure(name));
+        }
+
+        //! Sets value of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it. 
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of value must be specified separately, because it does not have to be zero terminated.
+        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! <br><br>
+        //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+        //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+        //! \param value value of node to set. Does not have to be zero terminated.
+        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+        void value(const Ch *value, std::size_t size)
+        {
+            m_value = const_cast<Ch *>(value);
+            m_value_size = size;
+        }
+
+        //! Sets value of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+        //! \param value Vame of node to set. Must be zero terminated.
+        void value(const Ch *value)
+        {
+            this->value(value, internal::measure(value));
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets node parent.
+        //! \return Pointer to parent node, or 0 if there is no parent.
+        xml_node<Ch> *parent() const
+        {
+            return m_parent;
+        }
+
+    protected:
+
+        // Return empty string
+        static Ch *nullstr()
+        {
+            static Ch zero = Ch('\0');
+            return &zero;
+        }
+
+        Ch *m_name;                         // Name of node, or 0 if no name
+        Ch *m_value;                        // Value of node, or 0 if no value
+        std::size_t m_name_size;            // Length of node name, or undefined of no name
+        std::size_t m_value_size;           // Length of node value, or undefined if no value
+        xml_node<Ch> *m_parent;             // Pointer to parent node, or 0 if none
+
+    };
+
+    //! Class representing attribute node of XML document. 
+    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. 
+    //! Thus, this text must persist in memory for the lifetime of attribute.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_attribute: public xml_base<Ch>
+    {
+
+        friend class xml_node<Ch>;
+    
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        //! Constructs an empty attribute with the specified type. 
+        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+        xml_attribute()
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets document of which attribute is a child.
+        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+        xml_document<Ch> *document() const
+        {
+            if (xml_node<Ch> *node = this->parent())
+            {
+                while (node->parent())
+                    node = node->parent();
+                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+            }
+            else
+                return 0;
+        }
+
+        //! Gets previous attribute, optionally matching attribute name. 
+        //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return this->m_parent ? m_prev_attribute : 0;
+        }
+
+        //! Gets next attribute, optionally matching attribute name. 
+        //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return this->m_parent ? m_next_attribute : 0;
+        }
+
+    private:
+
+        xml_attribute<Ch> *m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+        xml_attribute<Ch> *m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+    
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML node
+
+    //! Class representing a node of XML document. 
+    //! Each node may have associated name and value strings, which are available through name() and value() functions. 
+    //! Interpretation of name and value depends on type of the node.
+    //! Type of node can be determined by using type() function.
+    //! <br><br>
+    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. 
+    //! Thus, this text must persist in the memory for the lifetime of node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_node: public xml_base<Ch>
+    {
+
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        //! Constructs an empty node with the specified type. 
+        //! Consider using memory_pool of appropriate document to allocate nodes manually.
+        //! \param type Type of node to construct.
+        xml_node(node_type type)
+            : m_type(type)
+            , m_first_node(0)
+            , m_first_attribute(0)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+    
+        //! Gets type of node.
+        //! \return Type of node.
+        node_type type() const
+        {
+            return m_type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets document of which node is a child.
+        //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+        xml_document<Ch> *document() const
+        {
+            xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+            while (node->parent())
+                node = node->parent();
+            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+        }
+
+        //! Gets first child node, optionally matching node name.
+        //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                        return child;
+                return 0;
+            }
+            else
+                return m_first_node;
+        }
+
+        //! Gets last child node, optionally matching node name. 
+        //! Behaviour is undefined if node has no children.
+        //! Use first_node() to test if node has children.
+        //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(m_first_node);  // Cannot query for last child if node has no children
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                        return child;
+                return 0;
+            }
+            else
+                return m_last_node;
+        }
+
+        //! Gets previous sibling node, optionally matching node name. 
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                        return sibling;
+                return 0;
+            }
+            else
+                return m_prev_sibling;
+        }
+
+        //! Gets next sibling node, optionally matching node name. 
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                        return sibling;
+                return 0;
+            }
+            else
+                return m_next_sibling;
+        }
+
+        //! Gets first attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return m_first_attribute;
+        }
+
+        //! Gets last attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return m_first_attribute ? m_last_attribute : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+    
+        //! Sets type of node.
+        //! \param type Type of node to set.
+        void type(node_type type)
+        {
+            m_type = type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node manipulation
+
+        //! Prepends a new child node.
+        //! The prepended child becomes the first child, and all existing children are moved one position back.
+        //! \param child Node to prepend.
+        void prepend_node(xml_node<Ch> *child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+            if (first_node())
+            {
+                child->m_next_sibling = m_first_node;
+                m_first_node->m_prev_sibling = child;
+            }
+            else
+            {
+                child->m_next_sibling = 0;
+                m_last_node = child;
+            }
+            m_first_node = child;
+            child->m_parent = this;
+            child->m_prev_sibling = 0;
+        }
+
+        //! Appends a new child node. 
+        //! The appended child becomes the last child.
+        //! \param child Node to append.
+        void append_node(xml_node<Ch> *child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+            if (first_node())
+            {
+                child->m_prev_sibling = m_last_node;
+                m_last_node->m_next_sibling = child;
+            }
+            else
+            {
+                child->m_prev_sibling = 0;
+                m_first_node = child;
+            }
+            m_last_node = child;
+            child->m_parent = this;
+            child->m_next_sibling = 0;
+        }
+
+        //! Inserts a new child node at specified place inside the node. 
+        //! All children after and including the specified node are moved one position back.
+        //! \param where Place where to insert the child, or 0 to insert at the back.
+        //! \param child Node to insert.
+        void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+        {
+            assert(!where || where->parent() == this);
+            assert(child && !child->parent() && child->type() != node_document);
+            if (where == m_first_node)
+                prepend_node(child);
+            else if (where == 0)
+                append_node(child);
+            else
+            {
+                child->m_prev_sibling = where->m_prev_sibling;
+                child->m_next_sibling = where;
+                where->m_prev_sibling->m_next_sibling = child;
+                where->m_prev_sibling = child;
+                child->m_parent = this;
+            }
+        }
+
+        //! Removes first child node. 
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_first_node()
+        {
+            assert(first_node());
+            xml_node<Ch> *child = m_first_node;
+            m_first_node = child->m_next_sibling;
+            if (child->m_next_sibling)
+                child->m_next_sibling->m_prev_sibling = 0;
+            else
+                m_last_node = 0;
+            child->m_parent = 0;
+        }
+
+        //! Removes last child of the node. 
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_last_node()
+        {
+            assert(first_node());
+            xml_node<Ch> *child = m_last_node;
+            if (child->m_prev_sibling)
+            {
+                m_last_node = child->m_prev_sibling;
+                child->m_prev_sibling->m_next_sibling = 0;
+            }
+            else
+                m_first_node = 0;
+            child->m_parent = 0;
+        }
+
+        //! Removes specified child from the node
+        // \param where Pointer to child to be removed.
+        void remove_node(xml_node<Ch> *where)
+        {
+            assert(where && where->parent() == this);
+            assert(first_node());
+            if (where == m_first_node)
+                remove_first_node();
+            else if (where == m_last_node)
+                remove_last_node();
+            else
+            {
+                where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+                where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all child nodes (but not attributes).
+        void remove_all_nodes()
+        {
+            for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+                node->m_parent = 0;
+            m_first_node = 0;
+        }
+
+        //! Prepends a new attribute to the node.
+        //! \param attribute Attribute to prepend.
+        void prepend_attribute(xml_attribute<Ch> *attribute)
+        {
+            assert(attribute && !attribute->parent());
+            if (first_attribute())
+            {
+                attribute->m_next_attribute = m_first_attribute;
+                m_first_attribute->m_prev_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_next_attribute = 0;
+                m_last_attribute = attribute;
+            }
+            m_first_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_prev_attribute = 0;
+        }
+
+        //! Appends a new attribute to the node.
+        //! \param attribute Attribute to append.
+        void append_attribute(xml_attribute<Ch> *attribute)
+        {
+            assert(attribute && !attribute->parent());
+            if (first_attribute())
+            {
+                attribute->m_prev_attribute = m_last_attribute;
+                m_last_attribute->m_next_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_prev_attribute = 0;
+                m_first_attribute = attribute;
+            }
+            m_last_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_next_attribute = 0;
+        }
+
+        //! Inserts a new attribute at specified place inside the node. 
+        //! All attributes after and including the specified attribute are moved one position back.
+        //! \param where Place where to insert the attribute, or 0 to insert at the back.
+        //! \param attribute Attribute to insert.
+        void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+        {
+            assert(!where || where->parent() == this);
+            assert(attribute && !attribute->parent());
+            if (where == m_first_attribute)
+                prepend_attribute(attribute);
+            else if (where == 0)
+                append_attribute(attribute);
+            else
+            {
+                attribute->m_prev_attribute = where->m_prev_attribute;
+                attribute->m_next_attribute = where;
+                where->m_prev_attribute->m_next_attribute = attribute;
+                where->m_prev_attribute = attribute;
+                attribute->m_parent = this;
+            }
+        }
+
+        //! Removes first attribute of the node. 
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_first_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch> *attribute = m_first_attribute;
+            if (attribute->m_next_attribute)
+            {
+                attribute->m_next_attribute->m_prev_attribute = 0;
+            }
+            else
+                m_last_attribute = 0;
+            attribute->m_parent = 0;
+            m_first_attribute = attribute->m_next_attribute;
+        }
+
+        //! Removes last attribute of the node. 
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_last_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch> *attribute = m_last_attribute;
+            if (attribute->m_prev_attribute)
+            {
+                attribute->m_prev_attribute->m_next_attribute = 0;
+                m_last_attribute = attribute->m_prev_attribute;
+            }
+            else
+                m_first_attribute = 0;
+            attribute->m_parent = 0;
+        }
+
+        //! Removes specified attribute from node.
+        //! \param where Pointer to attribute to be removed.
+        void remove_attribute(xml_attribute<Ch> *where)
+        {
+            assert(first_attribute() && where->parent() == this);
+            if (where == m_first_attribute)
+                remove_first_attribute();
+            else if (where == m_last_attribute)
+                remove_last_attribute();
+            else
+            {
+                where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+                where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all attributes of node.
+        void remove_all_attributes()
+        {
+            for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+                attribute->m_parent = 0;
+            m_first_attribute = 0;
+        }
+        
+    private:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Restrictions
+
+        // No copying
+        xml_node(const xml_node &);
+        void operator =(const xml_node &);
+    
+        ///////////////////////////////////////////////////////////////////////////
+        // Data members
+    
+        // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+        // This is required for maximum performance, as it allows the parser to omit initialization of 
+        // unneded/redundant values.
+        //
+        // The rules are as follows:
+        // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+        // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+        // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+        node_type m_type;                       // Type of node; always valid
+        xml_node<Ch> *m_first_node;             // Pointer to first child node, or 0 if none; always valid
+        xml_node<Ch> *m_last_node;              // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+        xml_attribute<Ch> *m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid
+        xml_attribute<Ch> *m_last_attribute;    // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+        xml_node<Ch> *m_prev_sibling;           // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+        xml_node<Ch> *m_next_sibling;           // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML document
+    
+    //! This class represents root of the DOM hierarchy. 
+    //! It is also an xml_node and a memory_pool through public inheritance.
+    //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+    //! parse() function allocates memory for nodes and attributes by using functions of xml_document, 
+    //! which are inherited from memory_pool.
+    //! To access root node of the document, use the document itself, as if it was an xml_node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+    {
+    
+    public:
+
+        //! Constructs empty XML document
+        xml_document()
+            : xml_node<Ch>(node_document)
+        {
+        }
+
+        //! Parses zero-terminated XML string according to given flags.
+        //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+        //! The string must persist for the lifetime of the document.
+        //! In case of error, rapidxml::parse_error exception will be thrown.
+        //! <br><br>
+        //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+        //! Make sure that data is zero-terminated.
+        //! <br><br>
+        //! Document can be parsed into multiple times. 
+        //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+        //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+        template<int Flags>
+        void parse(Ch *text)
+        {
+            assert(text);
+            
+            // Remove current contents
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            
+            // Parse BOM, if any
+            parse_bom<Flags>(text);
+            
+            // Parse children
+            while (1)
+            {
+                // Skip whitespace before node
+                skip<whitespace_pred, Flags>(text);
+                if (*text == 0)
+                    break;
+
+                // Parse and append new child
+                if (*text == Ch('<'))
+                {
+                    ++text;     // Skip '<'
+                    if (xml_node<Ch> *node = parse_node<Flags>(text))
+                        this->append_node(node);
+                }
+                else
+                    RAPIDXML_PARSE_ERROR("expected <", text);
+            }
+
+        }
+
+        //! Clears the document by deleting all nodes and clearing the memory pool.
+        //! All nodes owned by document pool are destroyed.
+        void clear()
+        {
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            memory_pool<Ch>::clear();
+        }
+        
+    private:
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal character utility functions
+        
+        // Detect whitespace character
+        struct whitespace_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect node name character
+        struct node_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute name character
+        struct attribute_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA)
+        struct text_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_no_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_with_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                    return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+                if (Quote == Ch('\"'))
+                    return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pure_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                    return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+                if (Quote == Ch('\"'))
+                    return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Insert coded character, using UTF8 or 8-bit ASCII
+        template<int Flags>
+        static void insert_coded_character(Ch *&text, unsigned long code)
+        {
+            if (Flags & parse_no_utf8)
+            {
+                // Insert 8-bit ASCII character
+                // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+                text[0] = static_cast<unsigned char>(code);
+                text += 1;
+            }
+            else
+            {
+                // Insert UTF8 sequence
+                if (code < 0x80)    // 1 byte sequence
+                {
+                       text[0] = static_cast<unsigned char>(code);
+                    text += 1;
+                }
+                else if (code < 0x800)  // 2 byte sequence
+                {
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xC0);
+                    text += 2;
+                }
+                   else if (code < 0x10000)    // 3 byte sequence
+                {
+                       text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xE0);
+                    text += 3;
+                }
+                   else if (code < 0x110000)   // 4 byte sequence
+                {
+                       text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xF0);
+                    text += 4;
+                }
+                else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+                {
+                    RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+                }
+            }
+        }
+
+        // Skip characters until predicate evaluates to true
+        template<class StopPred, int Flags>
+        static void skip(Ch *&text)
+        {
+            Ch *tmp = text;
+            while (StopPred::test(*tmp))
+                ++tmp;
+            text = tmp;
+        }
+
+        // Skip characters until predicate evaluates to true while doing the following:
+        // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
+        // - condensing whitespace sequences to single space character
+        template<class StopPred, class StopPredPure, int Flags>
+        static Ch *skip_and_expand_character_refs(Ch *&text)
+        {
+            // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+            if (Flags & parse_no_entity_translation && 
+                !(Flags & parse_normalize_whitespace) &&
+                !(Flags & parse_trim_whitespace))
+            {
+                skip<StopPred, Flags>(text);
+                return text;
+            }
+            
+            // Use simple skip until first modification is detected
+            skip<StopPredPure, Flags>(text);
+
+            // Use translation skip
+            Ch *src = text;
+            Ch *dest = src;
+            while (StopPred::test(*src))
+            {
+                // If entity translation is enabled    
+                if (!(Flags & parse_no_entity_translation))
+                {
+                    // Test if replacement is needed
+                    if (src[0] == Ch('&'))
+                    {
+                        switch (src[1])
+                        {
+
+                        // &amp; &apos;
+                        case Ch('a'): 
+                            if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+                            {
+                                *dest = Ch('&');
+                                ++dest;
+                                src += 5;
+                                continue;
+                            }
+                            if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+                            {
+                                *dest = Ch('\'');
+                                ++dest;
+                                src += 6;
+                                continue;
+                            }
+                            break;
+
+                        // &quot;
+                        case Ch('q'): 
+                            if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+                            {
+                                *dest = Ch('"');
+                                ++dest;
+                                src += 6;
+                                continue;
+                            }
+                            break;
+
+                        // &gt;
+                        case Ch('g'): 
+                            if (src[2] == Ch('t') && src[3] == Ch(';'))
+                            {
+                                *dest = Ch('>');
+                                ++dest;
+                                src += 4;
+                                continue;
+                            }
+                            break;
+
+                        // &lt;
+                        case Ch('l'): 
+                            if (src[2] == Ch('t') && src[3] == Ch(';'))
+                            {
+                                *dest = Ch('<');
+                                ++dest;
+                                src += 4;
+                                continue;
+                            }
+                            break;
+
+                        // &#...; - assumes ASCII
+                        case Ch('#'): 
+                            if (src[2] == Ch('x'))
+                            {
+                                unsigned long code = 0;
+                                src += 3;   // Skip &#x
+                                while (1)
+                                {
+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+                                    if (digit == 0xFF)
+                                        break;
+                                    code = code * 16 + digit;
+                                    ++src;
+                                }
+                                insert_coded_character<Flags>(dest, code);    // Put character in output
+                            }
+                            else
+                            {
+                                unsigned long code = 0;
+                                src += 2;   // Skip &#
+                                while (1)
+                                {
+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+                                    if (digit == 0xFF)
+                                        break;
+                                    code = code * 10 + digit;
+                                    ++src;
+                                }
+                                insert_coded_character<Flags>(dest, code);    // Put character in output
+                            }
+                            if (*src == Ch(';'))
+                                ++src;
+                            else
+                                RAPIDXML_PARSE_ERROR("expected ;", src);
+                            continue;
+
+                        // Something else
+                        default:
+                            // Ignore, just copy '&' verbatim
+                            break;
+
+                        }
+                    }
+                }
+                
+                // If whitespace condensing is enabled
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Test if condensing is needed                 
+                    if (whitespace_pred::test(*src))
+                    {
+                        *dest = Ch(' '); ++dest;    // Put single space in dest
+                        ++src;                      // Skip first whitespace char
+                        // Skip remaining whitespace chars
+                        while (whitespace_pred::test(*src))
+                            ++src;
+                        continue;
+                    }
+                }
+
+                // No replacement, only copy character
+                *dest++ = *src++;
+
+            }
+
+            // Return new end
+            text = src;
+            return dest;
+
+        }
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal parsing functions
+        
+        // Parse BOM, if any
+        template<int Flags>
+        void parse_bom(Ch *&text)
+        {
+            // UTF-8?
+            if (static_cast<unsigned char>(text[0]) == 0xEF && 
+                static_cast<unsigned char>(text[1]) == 0xBB && 
+                static_cast<unsigned char>(text[2]) == 0xBF)
+            {
+                text += 3;      // Skup utf-8 bom
+            }
+        }
+
+        // Parse XML declaration (<?xml...)
+        template<int Flags>
+        xml_node<Ch> *parse_xml_declaration(Ch *&text)
+        {
+            // If parsing of declaration is disabled
+            if (!(Flags & parse_declaration_node))
+            {
+                // Skip until end of declaration
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 2;    // Skip '?>'
+                return 0;
+            }
+
+            // Create declaration
+            xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+            // Skip whitespace before attributes or ?>
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse declaration attributes
+            parse_node_attributes<Flags>(text, declaration);
+            
+            // Skip ?>
+            if (text[0] != Ch('?') || text[1] != Ch('>'))
+                RAPIDXML_PARSE_ERROR("expected ?>", text);
+            text += 2;
+            
+            return declaration;
+        }
+
+        // Parse XML comment (<!--...)
+        template<int Flags>
+        xml_node<Ch> *parse_comment(Ch *&text)
+        {
+            // If parsing of comments is disabled
+            if (!(Flags & parse_comment_nodes))
+            {
+                // Skip until end of comment
+                while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 3;     // Skip '-->'
+                return 0;      // Do not produce comment node
+            }
+
+            // Remember value start
+            Ch *value = text;
+
+            // Skip until end of comment
+            while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                ++text;
+            }
+
+            // Create comment node
+            xml_node<Ch> *comment = this->allocate_node(node_comment);
+            comment->value(value, text - value);
+            
+            // Place zero terminator after comment value
+            if (!(Flags & parse_no_string_terminators))
+                *text = Ch('\0');
+            
+            text += 3;     // Skip '-->'
+            return comment;
+        }
+
+        // Parse DOCTYPE
+        template<int Flags>
+        xml_node<Ch> *parse_doctype(Ch *&text)
+        {
+            // Remember value start
+            Ch *value = text;
+
+            // Skip to >
+            while (*text != Ch('>'))
+            {
+                // Determine character type
+                switch (*text)
+                {
+                
+                // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+                // This works for all W3C test files except for 2 most wicked
+                case Ch('['):
+                {
+                    ++text;     // Skip '['
+                    int depth = 1;
+                    while (depth > 0)
+                    {
+                        switch (*text)
+                        {
+                            case Ch('['): ++depth; break;
+                            case Ch(']'): --depth; break;
+                            case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                                                       default: break;
+                        }
+                        ++text;
+                    }
+                    break;
+                }
+                
+                // Error on end of text
+                case Ch('\0'):
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                
+                // Other character, skip it
+                default:
+                    ++text;
+
+                }
+            }
+            
+            // If DOCTYPE nodes enabled
+            if (Flags & parse_doctype_node)
+            {
+                // Create a new doctype node
+                xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+                doctype->value(value, text - value);
+                
+                // Place zero terminator after value
+                if (!(Flags & parse_no_string_terminators))
+                    *text = Ch('\0');
+
+                text += 1;      // skip '>'
+                return doctype;
+            }
+            else
+            {
+                text += 1;      // skip '>'
+                return 0;
+            }
+
+        }
+
+        // Parse PI
+        template<int Flags>
+        xml_node<Ch> *parse_pi(Ch *&text)
+        {
+            // If creation of PI nodes is enabled
+            if (Flags & parse_pi_nodes)
+            {
+                // Create pi node
+                xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+                // Extract PI target name
+                Ch *name = text;
+                skip<node_name_pred, Flags>(text);
+                if (text == name)
+                    RAPIDXML_PARSE_ERROR("expected PI target", text);
+                pi->name(name, text - name);
+                
+                // Skip whitespace between pi target and pi
+                skip<whitespace_pred, Flags>(text);
+
+                // Remember start of pi
+                Ch *value = text;
+                
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+
+                // Set pi value (verbatim, no entity expansion or whitespace normalization)
+                pi->value(value, text - value);     
+                
+                // Place zero terminator after name and value
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    pi->name()[pi->name_size()] = Ch('\0');
+                    pi->value()[pi->value_size()] = Ch('\0');
+                }
+                
+                text += 2;                          // Skip '?>'
+                return pi;
+            }
+            else
+            {
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 2;    // Skip '?>'
+                return 0;
+            }
+        }
+
+        // Parse and append data
+        // Return character that ends data.
+        // This is necessary because this character might have been overwritten by a terminating 0
+        template<int Flags>
+        Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+        {
+            // Backup to contents start if whitespace trimming is disabled
+            if (!(Flags & parse_trim_whitespace))
+                text = contents_start;     
+            
+            // Skip until end of data
+            Ch *value = text, *end;
+            if (Flags & parse_normalize_whitespace)
+                end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);   
+            else
+                end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+            // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+            if (Flags & parse_trim_whitespace)
+            {
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+                    if (*(end - 1) == Ch(' '))
+                        --end;
+                }
+                else
+                {
+                    // Backup until non-whitespace character is found
+                    while (whitespace_pred::test(*(end - 1)))
+                        --end;
+                }
+            }
+            
+            // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+            // Create new data node
+            if (!(Flags & parse_no_data_nodes))
+            {
+                xml_node<Ch> *data = this->allocate_node(node_data);
+                data->value(value, end - value);
+                node->append_node(data);
+            }
+
+            // Add data to parent node if no data exists yet
+            if (!(Flags & parse_no_element_values)) 
+                if (*node->value() == Ch('\0'))
+                    node->value(value, end - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+            {
+                Ch ch = *text;
+                *end = Ch('\0');
+                return ch;      // Return character that ends data; this is required because zero terminator overwritten it
+            }
+
+            // Return character that ends data
+            return *text;
+        }
+
+        // Parse CDATA
+        template<int Flags>
+        xml_node<Ch> *parse_cdata(Ch *&text)
+        {
+            // If CDATA is disabled
+            if (Flags & parse_no_data_nodes)
+            {
+                // Skip until end of cdata
+                while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 3;      // Skip ]]>
+                return 0;       // Do not produce CDATA node
+            }
+
+            // Skip until end of cdata
+            Ch *value = text;
+            while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                ++text;
+            }
+
+            // Create new cdata node
+            xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+            cdata->value(value, text - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+                *text = Ch('\0');
+
+            text += 3;      // Skip ]]>
+            return cdata;
+        }
+        
+        // Parse element node
+        template<int Flags>
+        xml_node<Ch> *parse_element(Ch *&text)
+        {
+            // Create element node
+            xml_node<Ch> *element = this->allocate_node(node_element);
+
+            // Extract element name
+            Ch *name = text;
+            skip<node_name_pred, Flags>(text);
+            if (text == name)
+                RAPIDXML_PARSE_ERROR("expected element name", text);
+            element->name(name, text - name);
+            
+            // Skip whitespace between element name and attributes or >
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse attributes, if any
+            parse_node_attributes<Flags>(text, element);
+
+            // Determine ending type
+            if (*text == Ch('>'))
+            {
+                ++text;
+                parse_node_contents<Flags>(text, element);
+            }
+            else if (*text == Ch('/'))
+            {
+                ++text;
+                if (*text != Ch('>'))
+                    RAPIDXML_PARSE_ERROR("expected >", text);
+                ++text;
+            }
+            else
+                RAPIDXML_PARSE_ERROR("expected >", text);
+
+            // Place zero terminator after name
+            if (!(Flags & parse_no_string_terminators))
+                element->name()[element->name_size()] = Ch('\0');
+
+            // Return parsed element
+            return element;
+        }
+
+        // Determine node type, and parse it
+        template<int Flags>
+        xml_node<Ch> *parse_node(Ch *&text)
+        {
+            // Parse proper node type
+            switch (text[0])
+            {
+
+            // <...
+            default: 
+                // Parse and append element node
+                return parse_element<Flags>(text);
+
+            // <?...
+            case Ch('?'): 
+                ++text;     // Skip ?
+                if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+                    (text[1] == Ch('m') || text[1] == Ch('M')) && 
+                    (text[2] == Ch('l') || text[2] == Ch('L')) &&
+                    whitespace_pred::test(text[3]))
+                {
+                    // '<?xml ' - xml declaration
+                    text += 4;      // Skip 'xml '
+                    return parse_xml_declaration<Flags>(text);
+                }
+                else
+                {
+                    // Parse PI
+                    return parse_pi<Flags>(text);
+                }
+            
+            // <!...
+            case Ch('!'): 
+
+                // Parse proper subset of <! node
+                switch (text[1])    
+                {
+                
+                // <!-
+                case Ch('-'):
+                    if (text[2] == Ch('-'))
+                    {
+                        // '<!--' - xml comment
+                        text += 3;     // Skip '!--'
+                        return parse_comment<Flags>(text);
+                    }
+                    break;
+
+                // <![
+                case Ch('['):
+                    if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') && 
+                        text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+                    {
+                        // '<![CDATA[' - cdata
+                        text += 8;     // Skip '![CDATA['
+                        return parse_cdata<Flags>(text);
+                    }
+                    break;
+
+                // <!D
+                case Ch('D'):
+                    if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') && 
+                        text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') && 
+                        whitespace_pred::test(text[8]))
+                    {
+                        // '<!DOCTYPE ' - doctype
+                        text += 9;      // skip '!DOCTYPE '
+                        return parse_doctype<Flags>(text);
+                    }
+                                       break;
+                               
+                               default:
+                                       break;
+
+                }   // switch
+
+                // Attempt to skip other, unrecognized node types starting with <!
+                ++text;     // Skip !
+                while (*text != Ch('>'))
+                {
+                    if (*text == 0)
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                ++text;     // Skip '>'
+                return 0;   // No node recognized
+
+            }
+        }
+
+        // Parse contents of the node - children, data etc.
+        template<int Flags>
+        void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+        {
+            // For all children and text
+            while (1)
+            {
+                // Skip whitespace between > and node contents
+                Ch *contents_start = text;      // Store start of node contents before whitespace is skipped
+                skip<whitespace_pred, Flags>(text);
+                Ch next_char = *text;
+
+            // After data nodes, instead of continuing the loop, control jumps here.
+            // This is because zero termination inside parse_and_append_data() function
+            // would wreak havoc with the above code.
+            // Also, skipping whitespace after data nodes is unnecessary.
+            after_data_node:    
+                
+                // Determine what comes next: node closing, child node, data node, or 0?
+                switch (next_char)
+                {
+                
+                // Node closing or child node
+                case Ch('<'):
+                    if (text[1] == Ch('/'))
+                    {
+                        // Node closing
+                        text += 2;      // Skip '</'
+                        if (Flags & parse_validate_closing_tags)
+                        {
+                            // Skip and validate closing tag name
+                            Ch *closing_name = text;
+                            skip<node_name_pred, Flags>(text);
+                            if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+                                RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+                        }
+                        else
+                        {
+                            // No validation, just skip name
+                            skip<node_name_pred, Flags>(text);
+                        }
+                        // Skip remaining whitespace after node name
+                        skip<whitespace_pred, Flags>(text);
+                        if (*text != Ch('>'))
+                            RAPIDXML_PARSE_ERROR("expected >", text);
+                        ++text;     // Skip '>'
+                        return;     // Node closed, finished parsing contents
+                    }
+                    else
+                    {
+                        // Child node
+                        ++text;     // Skip '<'
+                        if (xml_node<Ch> *child = parse_node<Flags>(text))
+                            node->append_node(child);
+                    }
+                    break;
+
+                // End of data - error
+                case Ch('\0'):
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+                // Data node
+                default:
+                    next_char = parse_and_append_data<Flags>(node, text, contents_start);
+                    goto after_data_node;   // Bypass regular processing after data nodes
+
+                }
+            }
+        }
+        
+        // Parse XML attributes of the node
+        template<int Flags>
+        void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+        {
+            // For all attributes 
+            while (attribute_name_pred::test(*text))
+            {
+                // Extract attribute name
+                Ch *name = text;
+                ++text;     // Skip first character of attribute name
+                skip<attribute_name_pred, Flags>(text);
+                if (text == name)
+                    RAPIDXML_PARSE_ERROR("expected attribute name", name);
+
+                // Create new attribute
+                xml_attribute<Ch> *attribute = this->allocate_attribute();
+                attribute->name(name, text - name);
+                node->append_attribute(attribute);
+
+                // Skip whitespace after attribute name
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip =
+                if (*text != Ch('='))
+                    RAPIDXML_PARSE_ERROR("expected =", text);
+                ++text;
+
+                // Add terminating zero after name
+                if (!(Flags & parse_no_string_terminators))
+                    attribute->name()[attribute->name_size()] = 0;
+
+                // Skip whitespace after =
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip quote and remember if it was ' or "
+                Ch quote = *text;
+                if (quote != Ch('\'') && quote != Ch('"'))
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                ++text;
+
+                // Extract attribute value and expand char refs in it
+                Ch *value = text, *end;
+                const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
+                if (quote == Ch('\''))
+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+                else
+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+                
+                // Set attribute value
+                attribute->value(value, end - value);
+                
+                // Make sure that end quote is present
+                if (*text != quote)
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                ++text;     // Skip quote
+
+                // Add terminating zero after value
+                if (!(Flags & parse_no_string_terminators))
+                    attribute->value()[attribute->value_size()] = 0;
+
+                // Skip whitespace after attribute value
+                skip<whitespace_pred, Flags>(text);
+            }
+        }
+
+    };
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Whitespace (space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
+             1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
+        };
+
+        // Node name (anything but space \n \r \t / > ? \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_node_name[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) (anything but < \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled 
+        // (anything but < \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+        // (anything but < \0 & space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote (anything but ' \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote that does not require processing (anything but ' \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote (anything but " \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote that does not require processing (anything but " \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Digits (dec and hex, 255 denotes end of numeric character reference)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_digits[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
+             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3
+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
+        };
+    
+        // Upper case conversion
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_upcase[256] = 
+        {
+          // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
+           0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
+           16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
+           32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
+           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
+           64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
+           96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127,  // 7
+           128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,  // 8
+           144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,  // 9
+           160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,  // A
+           176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,  // B
+           192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,  // C
+           208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,  // D
+           224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,  // E
+           240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255   // F
+        };
+    }
+    //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+    #pragma warning(pop)
+#endif
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp
new file mode 100644 (file)
index 0000000..52ebc29
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
+#define RAPIDXML_ITERATORS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
+
+#include "rapidxml.hpp"
+
+namespace rapidxml
+{
+
+    //! Iterator of child nodes of xml_node
+    template<class Ch>
+    class node_iterator
+    {
+    
+    public:
+
+        typedef typename xml_node<Ch> value_type;
+        typedef typename xml_node<Ch> &reference;
+        typedef typename xml_node<Ch> *pointer;
+        typedef std::ptrdiff_t difference_type;
+        typedef std::bidirectional_iterator_tag iterator_category;
+        
+        node_iterator()
+            : m_node(0)
+        {
+        }
+
+        node_iterator(xml_node<Ch> *node)
+            : m_node(node->first_node())
+        {
+        }
+        
+        reference operator *() const
+        {
+            assert(m_node);
+            return *m_node;
+        }
+
+        pointer operator->() const
+        {
+            assert(m_node);
+            return m_node;
+        }
+
+        node_iterator& operator++()
+        {
+            assert(m_node);
+            m_node = m_node->next_sibling();
+            return *this;
+        }
+
+        node_iterator operator++(int)
+        {
+            node_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        node_iterator& operator--()
+        {
+            assert(m_node && m_node->previous_sibling());
+            m_node = m_node->previous_sibling();
+            return *this;
+        }
+
+        node_iterator operator--(int)
+        {
+            node_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        bool operator ==(const node_iterator<Ch> &rhs)
+        {
+            return m_node == rhs.m_node;
+        }
+
+        bool operator !=(const node_iterator<Ch> &rhs)
+        {
+            return m_node != rhs.m_node;
+        }
+
+    private:
+
+        xml_node<Ch> *m_node;
+
+    };
+
+    //! Iterator of child attributes of xml_node
+    template<class Ch>
+    class attribute_iterator
+    {
+    
+    public:
+
+        typedef typename xml_attribute<Ch> value_type;
+        typedef typename xml_attribute<Ch> &reference;
+        typedef typename xml_attribute<Ch> *pointer;
+        typedef std::ptrdiff_t difference_type;
+        typedef std::bidirectional_iterator_tag iterator_category;
+        
+        attribute_iterator()
+            : m_attribute(0)
+        {
+        }
+
+        attribute_iterator(xml_node<Ch> *node)
+            : m_attribute(node->first_attribute())
+        {
+        }
+        
+        reference operator *() const
+        {
+            assert(m_attribute);
+            return *m_attribute;
+        }
+
+        pointer operator->() const
+        {
+            assert(m_attribute);
+            return m_attribute;
+        }
+
+        attribute_iterator& operator++()
+        {
+            assert(m_attribute);
+            m_attribute = m_attribute->next_attribute();
+            return *this;
+        }
+
+        attribute_iterator operator++(int)
+        {
+            attribute_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        attribute_iterator& operator--()
+        {
+            assert(m_attribute && m_attribute->previous_attribute());
+            m_attribute = m_attribute->previous_attribute();
+            return *this;
+        }
+
+        attribute_iterator operator--(int)
+        {
+            attribute_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        bool operator ==(const attribute_iterator<Ch> &rhs)
+        {
+            return m_attribute == rhs.m_attribute;
+        }
+
+        bool operator !=(const attribute_iterator<Ch> &rhs)
+        {
+            return m_attribute != rhs.m_attribute;
+        }
+
+    private:
+
+        xml_attribute<Ch> *m_attribute;
+
+    };
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp
new file mode 100644 (file)
index 0000000..f929b3c
--- /dev/null
@@ -0,0 +1,422 @@
+#ifndef RAPIDXML_PRINT_HPP_INCLUDED
+#define RAPIDXML_PRINT_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
+
+#include "rapidxml.hpp"
+
+// Only include streams if not disabled
+#ifndef RAPIDXML_NO_STREAMS
+    #include <ostream>
+    #include <iterator>
+#endif
+
+namespace rapidxml
+{
+
+    ///////////////////////////////////////////////////////////////////////
+    // Printing flags
+
+    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internal
+
+    //! \cond internal
+    namespace internal
+    {
+        
+        ///////////////////////////////////////////////////////////////////////////
+        // Internal character operations
+    
+        // Copy characters from given range to given output iterator
+        template<class OutIt, class Ch>
+        inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
+        {
+            while (begin != end)
+                *out++ = *begin++;
+            return out;
+        }
+        
+        // Copy characters from given range to given output iterator and expand
+        // characters into references (&lt; &gt; &apos; &quot; &amp;)
+        template<class OutIt, class Ch>
+        inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
+        {
+            while (begin != end)
+            {
+                if (*begin == noexpand)
+                {
+                    *out++ = *begin;    // No expansion, copy character
+                }
+                else
+                {
+                    switch (*begin)
+                    {
+                    case Ch('<'):
+                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('>'): 
+                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('\''): 
+                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
+                        break;
+                    case Ch('"'): 
+                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('&'): 
+                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
+                        break;
+                    default:
+                        *out++ = *begin;    // No expansion, copy character
+                    }
+                }
+                ++begin;    // Step to next character
+            }
+            return out;
+        }
+
+        // Fill given output iterator with repetitions of the same character
+        template<class OutIt, class Ch>
+        inline OutIt fill_chars(OutIt out, int n, Ch ch)
+        {
+            for (int i = 0; i < n; ++i)
+                *out++ = ch;
+            return out;
+        }
+
+        // Find character
+        template<class Ch, Ch ch>
+        inline bool find_char(const Ch *begin, const Ch *end)
+        {
+            while (begin != end)
+                if (*begin++ == ch)
+                    return true;
+            return false;
+        }
+
+        template<class OutIt, class Ch>
+        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
+
+        // Print children of the node                               
+        template<class OutIt, class Ch>
+        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
+                out = print_node(out, child, flags, indent);
+            return out;
+        }
+
+        // Print attributes of the node
+        template<class OutIt, class Ch>
+        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
+        {
+            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+            {
+                if (attribute->name() && attribute->value())
+                {
+                    // Print attribute name
+                    *out = Ch(' '), ++out;
+                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
+                    *out = Ch('='), ++out;
+                    // Print attribute value using appropriate quote type
+                    if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
+                    {
+                        *out = Ch('\''), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+                        *out = Ch('\''), ++out;
+                    }
+                    else
+                    {
+                        *out = Ch('"'), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+                        *out = Ch('"'), ++out;
+                    }
+                }
+            }
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_data);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_cdata);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'); ++out;
+            *out = Ch('!'); ++out;
+            *out = Ch('['); ++out;
+            *out = Ch('C'); ++out;
+            *out = Ch('D'); ++out;
+            *out = Ch('A'); ++out;
+            *out = Ch('T'); ++out;
+            *out = Ch('A'); ++out;
+            *out = Ch('['); ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch(']'); ++out;
+            *out = Ch(']'); ++out;
+            *out = Ch('>'); ++out;
+            return out;
+        }
+
+        // Print element node
+        template<class OutIt, class Ch>
+        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_element);
+
+            // Print element name and attributes, if any
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            out = print_attributes(out, node, flags);
+            
+            // If node is childless
+            if (node->value_size() == 0 && !node->first_node())
+            {
+                // Print childless node tag ending
+                *out = Ch('/'), ++out;
+                *out = Ch('>'), ++out;
+            }
+            else
+            {
+                // Print normal node tag ending
+                *out = Ch('>'), ++out;
+
+                // Test if node contains a single data node only (and no other nodes)
+                xml_node<Ch> *child = node->first_node();
+                if (!child)
+                {
+                    // If node has no children, only print its value without indenting
+                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+                }
+                else if (child->next_sibling() == 0 && child->type() == node_data)
+                {
+                    // If node has a sole data child, only print its value without indenting
+                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
+                }
+                else
+                {
+                    // Print all children with full indenting
+                    if (!(flags & print_no_indenting))
+                        *out = Ch('\n'), ++out;
+                    out = print_children(out, node, flags, indent + 1);
+                    if (!(flags & print_no_indenting))
+                        out = fill_chars(out, indent, Ch('\t'));
+                }
+
+                // Print node end
+                *out = Ch('<'), ++out;
+                *out = Ch('/'), ++out;
+                out = copy_chars(node->name(), node->name() + node->name_size(), out);
+                *out = Ch('>'), ++out;
+            }
+            return out;
+        }
+
+        // Print declaration node
+        template<class OutIt, class Ch>
+        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            // Print declaration start
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            *out = Ch('x'), ++out;
+            *out = Ch('m'), ++out;
+            *out = Ch('l'), ++out;
+
+            // Print attributes
+            out = print_attributes(out, node, flags);
+            
+            // Print declaration end
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            
+            return out;
+        }
+
+        // Print comment node
+        template<class OutIt, class Ch>
+        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_comment);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print doctype node
+        template<class OutIt, class Ch>
+        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_doctype);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('D'), ++out;
+            *out = Ch('O'), ++out;
+            *out = Ch('C'), ++out;
+            *out = Ch('T'), ++out;
+            *out = Ch('Y'), ++out;
+            *out = Ch('P'), ++out;
+            *out = Ch('E'), ++out;
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print pi node
+        template<class OutIt, class Ch>
+        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_pi);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+        ///////////////////////////////////////////////////////////////////////////
+                // Internal printing operations
+
+                // Print node
+                template<class OutIt, class Ch>
+                inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+                {
+                    // Print proper node type
+                    switch (node->type())
+                    {
+
+                    // Document
+                    case node_document:
+                        out = print_children(out, node, flags, indent);
+                        break;
+
+                    // Element
+                    case node_element:
+                        out = print_element_node(out, node, flags, indent);
+                        break;
+
+                    // Data
+                    case node_data:
+                        out = print_data_node(out, node, flags, indent);
+                        break;
+
+                    // CDATA
+                    case node_cdata:
+                        out = print_cdata_node(out, node, flags, indent);
+                        break;
+
+                    // Declaration
+                    case node_declaration:
+                        out = print_declaration_node(out, node, flags, indent);
+                        break;
+
+                    // Comment
+                    case node_comment:
+                        out = print_comment_node(out, node, flags, indent);
+                        break;
+
+                    // Doctype
+                    case node_doctype:
+                        out = print_doctype_node(out, node, flags, indent);
+                        break;
+
+                    // Pi
+                    case node_pi:
+                        out = print_pi_node(out, node, flags, indent);
+                        break;
+
+                        // Unknown
+                    default:
+                        assert(0);
+                        break;
+                    }
+
+                    // If indenting not disabled, add line break after node
+                    if (!(flags & print_no_indenting))
+                        *out = Ch('\n'), ++out;
+
+                    // Return modified iterator
+                    return out;
+                }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Printing
+
+    //! Prints XML to given output iterator.
+    //! \param out Output iterator to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output iterator pointing to position immediately after last character of printed text.
+    template<class OutIt, class Ch> 
+    inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
+    {
+        return internal::print_node(out, &node, flags, 0);
+    }
+
+#ifndef RAPIDXML_NO_STREAMS
+
+    //! Prints XML to given output stream.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output stream.
+    template<class Ch> 
+    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
+    {
+        print(std::ostream_iterator<Ch>(out), node, flags);
+        return out;
+    }
+
+    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed.
+    //! \return Output stream.
+    template<class Ch> 
+    inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
+    {
+        return print(out, node);
+    }
+
+#endif
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp
new file mode 100644 (file)
index 0000000..37c2953
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef RAPIDXML_UTILS_HPP_INCLUDED
+#define RAPIDXML_UTILS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
+//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <fstream>
+#include <stdexcept>
+
+namespace rapidxml
+{
+
+    //! Represents data loaded from a file
+    template<class Ch = char>
+    class file
+    {
+        
+    public:
+        
+        //! Loads file into the memory. Data will be automatically destroyed by the destructor.
+        //! \param filename Filename to load.
+        file(const char *filename)
+        {
+            using namespace std;
+
+            // Open stream
+            basic_ifstream<Ch> stream(filename, ios::binary);
+            if (!stream)
+                throw runtime_error(string("cannot open file ") + filename);
+            stream.unsetf(ios::skipws);
+            
+            // Determine stream size
+            stream.seekg(0, ios::end);
+            size_t size = stream.tellg();
+            stream.seekg(0);   
+            
+            // Load data and add terminating 0
+            m_data.resize(size + 1);
+            stream.read(&m_data.front(), static_cast<streamsize>(size));
+            m_data[size] = 0;
+        }
+
+        //! Loads file into the memory. Data will be automatically destroyed by the destructor
+        //! \param stream Stream to load from
+        file(std::basic_istream<Ch> &stream)
+        {
+            using namespace std;
+
+            // Load data and add terminating 0
+            stream.unsetf(ios::skipws);
+            m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
+            if (stream.fail() || stream.bad())
+                throw runtime_error("error reading stream");
+            m_data.push_back(0);
+        }
+        
+        //! Gets file data.
+        //! \return Pointer to data of file.
+        Ch *data()
+        {
+            return &m_data.front();
+        }
+
+        //! Gets file data.
+        //! \return Pointer to data of file.
+        const Ch *data() const
+        {
+            return &m_data.front();
+        }
+
+        //! Gets file data size.
+        //! \return Size of file data, in characters.
+        std::size_t size() const
+        {
+            return m_data.size();
+        }
+
+    private:
+
+        std::vector<Ch> m_data;   // File data
+
+    };
+
+    //! Counts children of node. Time complexity is O(n).
+    //! \return Number of children of node
+    template<class Ch>
+    inline std::size_t count_children(xml_node<Ch> *node)
+    {
+        xml_node<Ch> *child = node->first_node();
+        std::size_t count = 0;
+        while (child)
+        {
+            ++count;
+            child = child->next_sibling();
+        }
+        return count;
+    }
+
+    //! Counts attributes of node. Time complexity is O(n).
+    //! \return Number of attributes of node
+    template<class Ch>
+    inline std::size_t count_attributes(xml_node<Ch> *node)
+    {
+        xml_attribute<Ch> *attr = node->first_attribute();
+        std::size_t count = 0;
+        while (attr)
+        {
+            ++count;
+            attr = attr->next_attribute();
+        }
+        return count;
+    }
+
+}
+
+#endif
diff --git a/service/protocol-plugin/plugin-manager/SConscript b/service/protocol-plugin/plugin-manager/SConscript
new file mode 100644 (file)
index 0000000..1e7d42b
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# plugin-manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+plugin_manager_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+plugin_manager_env.AppendUnique(CPPPATH = [
+               '../lib/cpluff/libcpluff',
+               'src'
+               ])
+
+if target_os not in ['windows', 'winrt']:
+       plugin_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall',
+               '-fpermissive', '-Wsign-compare'])
+
+if target_os == 'android':
+       plugin_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       plugin_manager_env.AppendUnique(LIBS = ['boost_thread-gcc-mt-1_49', 'gnustl_static'])
+
+plugin_manager_env.AppendUnique(LIBS = ['oc', 'octbstack', 'expat', 'dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+ppm_src = ['src/Plugin.cpp', 'src/PluginManager.cpp']
+ppm = plugin_manager_env.StaticLibrary('ppm', ppm_src)
+
+pmimpl_src = [
+               'src/CpluffAdapter.cpp',
+               'src/FelixAdapter.cpp',
+               'src/Plugin.cpp',
+               'src/PluginManagerImpl.cpp']
+
+pmimpl_env = plugin_manager_env.Clone()
+pmimpl_env.PrependUnique(CCFLAGS = ['-fPIC'])
+pmimpl_env.PrependUnique(LIBS = File(env.get('BUILD_DIR') + '/libcpluff.a'))
+pmimpl = pmimpl_env.SharedLibrary('pmimpl', pmimpl_src)
+
+plugin_manager_env.InstallTarget([ppm, pmimpl], 'libppm')
index f6187f4..453451f 100644 (file)
@@ -1,12 +1,13 @@
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall
-
-CPLUFF_DIR = ../../../lib/cpluff/libcpluff
+LIB = ../../../lib
+CPLUFF_DIR = $(LIB)/cpluff/libcpluff
 
 SRC = ../../src/
 
 CXX_INC    = -I. -I$(CPLUFF_DIR)
+CXX_INC += -I$(LIB)/rapidxml 
 
 LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
 CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a 
@@ -22,8 +23,8 @@ PluginManager.o : $(SRC)PluginManager.cpp
        $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp 
 
 
-libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CPLUFF_DIR)/.libs/libcpluff.a 
-       $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CXX_LIBS) $(LINK_LIB)  
+libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CPLUFF_DIR)/.libs/libcpluff.a 
+       $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CXX_LIBS) $(LINK_LIB)  
 
 PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
        $(CXX) $(CXX_INC)  -fPIC  -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManagerImpl.cpp
@@ -31,6 +32,9 @@ PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
 Plugin.o : $(SRC)Plugin.cpp
        $(CXX) $(CXX_INC)  -fPIC  -c $(SRC)Plugin.cpp
 
+Config.o : $(SRC)Config.cpp
+       $(CXX) $(CXX_INC)  -fPIC  -c $(SRC)Config.cpp
+
 CpluffAdapter.o  : $(SRC)CpluffAdapter.cpp
        $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)CpluffAdapter.cpp
 
diff --git a/service/protocol-plugin/plugin-manager/src/Config.cpp b/service/protocol-plugin/plugin-manager/src/Config.cpp
new file mode 100644 (file)
index 0000000..528c7dd
--- /dev/null
@@ -0,0 +1,157 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.cpp
+
+/// @brief
+
+
+#include "Config.h"
+
+
+using namespace OIC;
+using namespace rapidxml;
+using namespace std;
+
+Config *Config::s_configinstance = NULL;
+
+Config::Config()
+{
+    if (loadConfigFile("./pluginmanager.xml") != PM_S_OK)
+    {
+        fprintf(stderr, "PM Configuration file is not exist current Folder.\n" );
+        exit(EXIT_FAILURE);
+    }
+}
+
+Config::~Config(void)
+{
+    s_configinstance->deleteinstance();
+    s_configinstance = NULL;
+}
+
+PMRESULT Config::loadConfigFile(const std::string configfilepath)
+{
+    // Read the xml file
+    std::ifstream xmlFile(configfilepath.c_str());
+    xml_document<> doc;
+    //into a vector
+    std::vector<char> buffer((istreambuf_iterator<char>(xmlFile)), istreambuf_iterator<char>());
+    buffer.push_back('\0');
+
+    // Parse the buffer using the xml file parsing library into doc
+    parsing(buffer, &doc);
+
+    // Find our root node
+    xml_node<> *root_node = doc.first_node("pluginManager");
+    xml_node<> *pluginInfo = root_node->first_node("pluginInfo");
+
+    getXmlData(pluginInfo, "pluginPath");
+    getXmlData(pluginInfo, "maxMEM");
+    getXmlData(pluginInfo, "version");
+    getXmlData(pluginInfo, "name");
+
+    return PM_S_OK;
+}
+
+PMRESULT Config::parsing(std::vector<char> buffer, xml_document<> *doc)
+{
+    // Parse the buffer using the xml file parsing library into doc
+    try
+    {
+        doc->parse<0>(&buffer[0]);
+    }
+    catch (rapidxml::parse_error err)
+    {
+        //print errors to screen
+        fprintf(stderr, "PM Configuration file parsing error \n");
+        exit(EXIT_FAILURE); //then exit
+    }
+    return PM_S_OK;
+}
+
+PMRESULT Config::getXmlData(xml_node<> *pluginInfo, std::string key)
+{
+    xml_attribute<> *iAttr = NULL;
+    std::string value  = "";
+    if (iAttr = pluginInfo->first_attribute(key.c_str()))
+    {
+        value = iAttr->value();
+        setValue(key, value);
+        return PM_S_OK;
+    }
+    else
+    {
+        return PM_S_FALSE;
+    }
+}
+
+void Config::setValue(const std::string key, const std::string value)
+{
+    m_configurationMap.insert( std::pair<std::string, std::string>(key, value));
+}
+
+std::string  Config::getValue(const std::string key)
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find(key.c_str());
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
+
+std::string  Config::getVersion()
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find("version");
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
+
+std::string  Config::getPluginPath()
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find("pluginPath");
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
\ No newline at end of file
diff --git a/service/protocol-plugin/plugin-manager/src/Config.h b/service/protocol-plugin/plugin-manager/src/Config.h
new file mode 100644 (file)
index 0000000..33f7f39
--- /dev/null
@@ -0,0 +1,122 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.h
+
+/// @brief
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include <map>
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rapidxml.hpp"
+#include <fstream>
+#include <vector>
+
+using namespace rapidxml;
+
+namespace OIC
+{
+
+    enum PMRESULT
+    {
+        PM_S_OK
+        , PM_S_FALSE
+        , PM_E_POINTER
+        , PM_E_OUTOFMEMORY
+        , PM_E_FAIL
+        , PM_E_NOINTERFACE
+        , PM_E_NOTIMPL
+    };
+    /**
+    * @brief    Configuration class
+    *
+    *
+    */
+    class Config
+    {
+        public:
+            /**
+            * A function to register pluins in the path.
+            * This function will load plugins in plugin manager table.
+            *
+            * @param path plugin file path to be registered.
+            * @return int, 1 is success, 0 is fail.
+            *
+            * NOTE:
+            *
+            */
+            /**
+            *
+            * new Singleton pattern instance.
+            *
+            * @return config pointer Address.
+            */
+            static Config *Getinstance()
+            {
+                if (NULL == s_configinstance)
+                {
+                    s_configinstance = new Config();
+                }
+
+                return s_configinstance;
+            }
+            std::string  getPluginPath();
+            std::string  getVersion();
+            std::string  getValue(const std::string key);
+
+        private:
+            static Config *s_configinstance;
+            typedef std::map<std::string, std::string> configmap;
+            configmap m_configurationMap;
+            /**
+            * Constructor for Config.
+            * During construction time, configuration file  will be loaded.
+            *
+            */
+            Config();
+
+            /**
+            * Virtual destructor
+            */
+            virtual ~Config(void);
+
+            /**
+            * delete Singleton pattern instance.
+            */
+            static void deleteinstance()
+            {
+                if (NULL != s_configinstance)
+                {
+                    delete s_configinstance;
+                    s_configinstance = NULL;
+                }
+            }
+            void setValue(const std::string key, const std::string value);
+            PMRESULT loadConfigFile(const std::string configfilepath);
+            PMRESULT parsing(std::vector<char> buffer, xml_document<> *doc);
+            PMRESULT getXmlData(  xml_node<> *pluginInfo, std::string key);
+    };
+}
+
+#endif
\ No newline at end of file
index b3d60e4..addc2a7 100644 (file)
@@ -34,14 +34,27 @@ CpluffAdapter::CpluffAdapter()
     m_context = cp_create_context(&m_status);
     m_cp_plugins = nullptr;
     m_plugin = nullptr;
-    registerAllPlugin("../../../plugins");
+
+    config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path does not exist\n");
+        pluginpath = "";
+    }
+    registerAllPlugin(pluginpath);
 }
 
 CpluffAdapter::~CpluffAdapter(void)
 {
     cp_release_info(m_context, m_cp_plugins);
-    m_thread_g.interrupt_all();
-    m_thread_g.join_all();
+    //Auto plugin detection is disabled
+    //m_thread_g.interrupt_all();
+    //m_thread_g.join_all();
     s_pinstance->deleteinstance();
     s_pinstance = nullptr;
 }
@@ -57,7 +70,12 @@ int CpluffAdapter::installPlugin(const std::string path)
     }
     else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
     {
-        printf("cp_install_plugin failed\n");
+        if (m_status == CP_ERR_CONFLICT)
+        {
+            printf("Plugin is already installed or conflicts symbol.\n");
+        }
+        printf("cp_install_plugin failed : %d \n" , m_status);
+
         return false;
     }
 
@@ -70,8 +88,7 @@ int CpluffAdapter::findPluginRecursive(const std::string path)
     File_list file_list;
     getFileList(file_list, path);
     File_list::iterator itr;
-    int flag = FALSE;
-
+    int flag = TRUE;
     for (itr = file_list.begin(); itr != file_list.end(); itr++)
     {
         if (itr->second == true)
@@ -91,9 +108,10 @@ int CpluffAdapter::findPluginRecursive(const std::string path)
                 }
             }
             std::string filename = filepath.substr(0, count );
-            //char *temp_char = const_cast<char *>(filename.c_str());
-            flag = installPlugin(filename);
-            //printf("plugin file path %s \n", plugin->plugin_path);
+            if (!installPlugin(filename))
+            {
+                printf("installPlugin failed path : %s \n", filename.c_str());
+            }
         }
     }
 
@@ -110,7 +128,7 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
     }
     else
     {
-        printPluginList(m_cp_plugins);
+        printPluginList();
     }
 
     for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
@@ -176,7 +194,8 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
         }
         if (plugin_compare_flag)
         {
-            m_plugins.push_back(*plugin);
+            //Auto plugin detection is disabled
+            /*
             try
             {
                 boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
@@ -188,6 +207,8 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
             {
                 printf("thread throw exception\n");
             }
+            */
+            m_plugins.push_back(*plugin);
             delete(plugin);
         }
         //printf("plugin size = %d\n",m_plugins.size());
@@ -208,11 +229,10 @@ int CpluffAdapter::registerPlugin(const std::string path)
     }
 
     //non recursive
-
-    flag = installPlugin(path);
-
-    flag = loadPluginInfoToManager(path);
-
+    if (installPlugin(path))
+    {
+        flag = loadPluginInfoToManager(path);
+    }
     return flag;
 }
 
@@ -227,11 +247,10 @@ int CpluffAdapter::registerAllPlugin(const std::string path)
     }
 
     //recursive
-
-    flag = findPluginRecursive(path);
-
-    flag = loadPluginInfoToManager(path);
-
+    if (findPluginRecursive(path))
+    {
+        flag = loadPluginInfoToManager(path);
+    }
     return flag;
 }
 
@@ -403,7 +422,7 @@ const char *CpluffAdapter::state_to_string(int state)
     }
 }
 
-void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+void CpluffAdapter::printPluginList()
 {
     const char format[] = "  %-30s %-15s %-15s %-20s\n";
     printf("\n====== Plugins List ======\n");
@@ -491,7 +510,8 @@ bool CpluffAdapter::isStarted(Plugin *plugin)
     }
     return FALSE;
 }
-
+//Auto plugin detection is disabled
+/*
 void CpluffAdapter::observePluginPath(void *str)
 {
     //printf("start observePluginPath\n");
@@ -568,7 +588,7 @@ void CpluffAdapter::observePluginPath(void *str)
     ( void ) close( fd );
     //printf("observePluginPath end\n");
 }
-
+*/
 const std::string CpluffAdapter::getState(const std::string plugID)
 {
     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
index ec565d3..e0b934f 100644 (file)
@@ -38,6 +38,7 @@
 #include <internal.h>
 
 #include "Plugin.h"
+#include "Config.h"
 
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     (int)( 1024 * ( EVENT_SIZE + 16 ) )
@@ -160,6 +161,13 @@ namespace OIC
             */
             const std::string getState(const std::string plugID);
 
+            /**
+            * print whole plugin info.
+            *
+            * @param cpluff plugins
+            */
+            void printPluginList();
+
 
             /**
             *
@@ -181,15 +189,14 @@ namespace OIC
 
         private:
 
+            Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             cp_context_t *m_context;
             cp_status_t m_status;
             cp_plugin_info_t **m_cp_plugins;
             cp_plugin_info_t *m_plugin;
-            boost::thread m_file_detect_thread;
-            boost::thread_group m_thread_g;
-            std::string m_path;
+            //boost::thread_group m_thread_g;
             static CpluffAdapter *s_pinstance;
 
             /**
@@ -222,7 +229,7 @@ namespace OIC
             * @param plugin file path.
             * @return void
             */
-            void observePluginPath(void *);
+            //void observePluginPath(void *);
 
 
             /**
@@ -243,13 +250,6 @@ namespace OIC
             bool getFileList(File_list &list, const std::string strDir);
 
             /**
-            * print whole plugin info.
-            *
-            * @param cpluff plugins
-            */
-            void printPluginList(cp_plugin_info_t **plugins);
-
-            /**
             * install plugin using c-pluff.
             *
             * @param Root path.
index 0247e74..50a92e2 100644 (file)
@@ -30,7 +30,18 @@ FelixAdapter *FelixAdapter::s_pinstance;
 
 FelixAdapter::FelixAdapter()
 {
-
+    config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path is not exist\n");
+        pluginpath = "";
+    }
+    registerAllPlugin(pluginpath);
 }
 
 FelixAdapter::~FelixAdapter(void)
@@ -113,12 +124,12 @@ bool FelixAdapter::isStarted(Plugin *plugin)
 {
     return FALSE;
 }
-
+/*
 void FelixAdapter::observePluginPath(void *str)
 {
 
 }
-
+*/
 const std::string FelixAdapter::getState(const std::string plugID)
 {
     return "";
index 3842184..7c6398c 100644 (file)
@@ -38,6 +38,7 @@
 #include <internal.h>
 
 #include "Plugin.h"
+#include "Config.h"
 
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     (int)( 1024 * ( EVENT_SIZE + 16 ) )
@@ -180,7 +181,7 @@ namespace OIC
 
 
         private:
-
+            Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             boost::thread m_file_detect_thread;
@@ -224,7 +225,7 @@ namespace OIC
             * @param plugin file path.
             * @return void
             */
-            void observePluginPath(void *);
+            //void observePluginPath(void *);
 
             /**
             * Get whole "SO" file list.
index d77f68f..7ef312c 100644 (file)
@@ -136,16 +136,6 @@ namespace OIC
             return false;
         }
     }
-
-    std::vector<std::string> Plugin::getSupportedType(void)
-    {
-        return m_supportedType;
-    }
-
-    void Plugin::addSupportedType(const std::string rscType)
-    {
-        m_supportedType.push_back(rscType);
-    }
 }
 
 
index bd823d8..5b1e3a6 100644 (file)
@@ -141,22 +141,6 @@ namespace OIC
             */
             bool operator==(Plugin &plugin);
 
-            /**
-            * Get supported resourc type
-            *
-            *
-            * @return vector of surported resource type
-            */
-            std::vector<std::string> getSupportedType(void);
-            /**
-            * Add supported resource type for a plugin
-            *
-            * @param resource type string
-            * @return void
-            *
-            */
-            void addSupportedType(const std::string rscType);
-
         private:
             std::map<std::string, AttributeValue> m_attributeMap;
             std::vector<std::string> m_supportedType;
index 7c158ca..c3abdb8 100644 (file)
@@ -56,18 +56,17 @@ int PluginManager::stopPlugins(const std::string key, const std::string value)
     return pluginManagerImpl->stopPlugins(key, value);
 }
 
-int PluginManager::startPlugins(Plugin *const plugin)
+int PluginManager::rescanPlugin()
 {
-    printf("PluginManager::startPlugins\n");
-    return pluginManagerImpl->startPlugins(plugin);
+    return pluginManagerImpl->rescanPlugin();
 }
 
-int PluginManager::stopPlugins(Plugin *const plugin)
+std::vector<Plugin> PluginManager::getPlugins(void)
 {
-    return pluginManagerImpl->stopPlugins(plugin);
+    return pluginManagerImpl->getAllPlugins();
 }
 
-std::vector<Plugin> PluginManager::getPlugins(void)
+std::string PluginManager::getState(const std::string plugID)
 {
-    return pluginManagerImpl->getAllPlugins();
+    return pluginManagerImpl->getState(plugID);
 }
\ No newline at end of file
index 41a631e..2ae8b73 100644 (file)
@@ -68,23 +68,13 @@ namespace OIC
             int stopPlugins(const std::string key, const std::string value);
 
             /**
-            * Start plugin
-            * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+            * Rescan Plugin.
+            * This function will call rescan function of plugins in the configuration folder
             *
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            int startPlugins(Plugin *const plugin);
-
-
-            /**
-            * Stop Plugin.
-            * This function will call stop function of plugin and unload dynamic plugin library from memory.
-            *
-            * @param Plugin
-            * @return int, 1 is success, 0 is fail.
-            */
-            int stopPlugins(Plugin *const plugin);
+            int rescanPlugin();
 
             /**
             * Get Plugin list.
@@ -95,6 +85,14 @@ namespace OIC
             */
             std::vector<Plugin> getPlugins(void);
 
+            /**
+            * Get Plugin state.
+            *
+            * @param Plugin ID
+            * @return Plugin state.
+            */
+            std::string getState(const std::string plugID);
+
         private:
             PluginManagerImpl *pluginManagerImpl;
             void (*destroy)(PluginManagerImpl *);
index d501786..2795e83 100644 (file)
@@ -110,6 +110,23 @@ int PluginManagerImpl::unregisterAllPlugin()
     return flag;
 }
 
+int PluginManagerImpl::rescanPlugin()
+{
+    Config *config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path does not exist\n");
+        pluginpath = "";
+    }
+    int result = registerAllPlugin(pluginpath);
+    return result;
+}
+
 
 std::vector<Plugin> &PluginManagerImpl::getAllPlugins(void)
 {
index f42236a..3beb8e8 100644 (file)
@@ -120,7 +120,7 @@ namespace OIC
             * @param Plugin ID
             * @return Plugin state.
             */
-            std::string getState(const std::string plugID);
+            virtual std::string getState(const std::string plugID);
 
             /**
             * Start  plugins by resource type
@@ -145,7 +145,7 @@ namespace OIC
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            virtual int startPlugins(Plugin *const plugin);
+            int startPlugins(Plugin *const plugin);
 
 
             /**
@@ -155,7 +155,16 @@ namespace OIC
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            virtual int stopPlugins(Plugin *const plugin);
+            int stopPlugins(Plugin *const plugin);
+
+            /**
+            * Rescan Plugin.
+            * This function will call rescan function of plugins in the configuration folder
+            *
+            * @param Plugin
+            * @return int, 1 is success, 0 is fail.
+            */
+            virtual int rescanPlugin();
 
             /**
             * get all plugins which currently registered.
diff --git a/service/protocol-plugin/plugins/SConscript b/service/protocol-plugin/plugins/SConscript
new file mode 100644 (file)
index 0000000..0d9e0cf
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Plugins build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+plugins_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+plugins_env.AppendUnique(CPPPATH = ['../lib/cpluff/libcpluff'])
+
+if target_os not in ['windows', 'winrt']:
+       plugins_env.AppendUnique(CXXFLAGS = ['-g3', '-Wall', '-pthread', '-std=c++0x'])
+       plugins_env.AppendUnique(LINKFLAGS = ['-fPIC'])
+
+       if target_os not in ['arduino', 'android']:
+               plugins_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+       plugins_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       plugins_env.AppendUnique(LIBS = ['gnustl_static'])
+       plugins_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+mqtt_fan_src = Glob('mqtt-fan/src/' + '*.cpp')
+fanserver = plugins_env.SharedLibrary('fanserver_mqtt_plugin', mqtt_fan_src)
+
+mqtt_light_src = Glob('mqtt-light/src/' + '*.cpp')
+lightserver = plugins_env.SharedLibrary('lightserver_mqtt_plugin', mqtt_light_src)
+
+SConscript('mqtt-fan/lib/SConscript')
index bf4db27..248e35c 100644 (file)
@@ -1,13 +1,15 @@
-include ../../../../config.mk
-
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall -pthread
 
+TOP_DIR = ../../../../../..
 LIB_DIR = ../../../../../../resource
 
 SRC_DIR = ../../src
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -17,9 +19,11 @@ CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
 CXX_INC += -I$(BOOST_DIR) 
 CXX_INC += -I../../lib 
 CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC          += -I../csdk/libcoap
+CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+CXX_LIBS  := ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
 
 .PHONY: lib release_build ./release/fanserver_mqtt_plugin.so 
 
@@ -34,7 +38,7 @@ release_build:
        cp plugin.xml release
 
 ./release/fanserver_mqtt_plugin.so: ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o
-       $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS)  -L../../lib -lmosquitto -lssl -lrt
+       $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS)  -L../../lib -L$(TOP_DIR)/out/linux/x86/release -lmosquitto -lssl -lrt -loc -loctbstack -loc_logger -lcoap
 
 ./release/obj/fanserver_mqtt_plugin.o: $(SRC_DIR)/fanserver_mqtt_plugin.cpp
        $(CXX) $(CXX_INC) -fPIC -o ./release/obj/fanserver_mqtt_plugin.o -c $(SRC_DIR)/fanserver_mqtt_plugin.cpp 
diff --git a/service/protocol-plugin/plugins/mqtt-fan/lib/SConscript b/service/protocol-plugin/plugins/mqtt-fan/lib/SConscript
new file mode 100644 (file)
index 0000000..a5695c2
--- /dev/null
@@ -0,0 +1,27 @@
+##
+# mosquitto build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+mosquitto_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+mosquitto_env.AppendUnique(CPPPATH = ['./'])
+if target_os not in ['windows', 'winrt']:
+       mosquitto_env.AppendUnique(CFLAGS = ['-Wall', '-ggdb', '-fPIC',
+                       '-DWITH_TLS', '-DWITH_TLS_PSK', '-DWITH_THREADING'])
+######################################################################
+# Source files and Targets
+######################################################################
+mosquitto_src = env.Glob('*.c')
+
+mosquitto = mosquitto_env.StaticLibrary('mosquitto', mosquitto_src)
+mosquitto_env.InstallTarget(mosquitto, 'libmosquitto')
+
+SConscript('cpp/SConscript')
diff --git a/service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript b/service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript
new file mode 100644 (file)
index 0000000..55e2333
--- /dev/null
@@ -0,0 +1,24 @@
+##
+# mosquittopp build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+mosquittopp_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+mosquittopp_env.AppendUnique(CPPPATH = ['./', '../'])
+if target_os not in ['windows', 'winrt']:
+       mosquittopp_env.AppendUnique(CFLAGS = ['-Wall', '-ggdb', '-O2', '-fPIC'])
+
+mosquittopp_env.AppendUnique(LIBS = ['mosquitto', 'ssl', 'crypto'])
+######################################################################
+# Source files and Targets
+######################################################################
+mosquittopp = mosquittopp_env.SharedLibrary('mosquittopp', 'mosquittopp.cpp')
+mosquittopp_env.InstallTarget(mosquittopp, 'libmosquittopp')
index 544679a..12111e0 100644 (file)
@@ -45,23 +45,22 @@ struct tm *tblock;           // Define a structure for time block
 
 int gObservation = 0;
 void *ChangeFanRepresentation (void *param);
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 
 // Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'fanResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
 
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
 
 // Forward declaring the entityHandler
-// void entityHandler(std::shared_ptr<OCResourceRequest> request,
-//                    std::shared_ptr<OCResourceResponse> response);
-
 /// This class represents a single resource named 'fanResource'. This resource has
 /// two simple properties named 'state' and 'power'
 typedef struct plugin_data_t plugin_data_t;
@@ -114,7 +113,7 @@ class FanResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
 
             // This will internally create and register the resource.
             OCStackResult result = OCPlatform::registerResource(
@@ -136,7 +135,7 @@ class FanResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
 
             OCResourceHandle resHandle;
 
@@ -251,13 +250,10 @@ class FanResource
     private:
         // This is just a sample implementation of entity handler.
         // Entity handler can be implemented in several ways by the manufacturer
-        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                            std::shared_ptr<OCResourceResponse> response)
+        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
         {
-            OCEntityHandlerResult result = OC_EH_OK;
-
             cout << "\tIn Server CPP entity handler:\n";
-
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
             if (request)
             {
                 // Get the request type and request flag
@@ -272,40 +268,52 @@ class FanResource
                 }
                 if (requestFlag & RequestHandlerFlag::RequestFlag)
                 {
-                    cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+                    cout << "\t\trequestFlag : Request   ===  Handle by FanServer\n";
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
 
                     // If the request type is GET
                     if (requestType == "GET")
                     {
                         cout << "\t\t\trequestType : GET\n";
-
-                        if (response)
+                        if (isSlowResponse) // Slow response case
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            static int startedThread = 0;
+                            if (!startedThread)
+                            {
+                                std::thread t(handleSlowResponse, (void *)this, request);
+                                startedThread = 1;
+                                t.detach();
+                            }
+                            ehResult = OC_EH_SLOW;
+                        }
+                        else // normal response case.
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_OK);
+                            pResponse->setResourceRepresentation(get());
+                            if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                            {
+                                ehResult = OC_EH_OK;
+                            }
                         }
                     }
                     else if (requestType == "PUT")
                     {
                         cout << "\t\t\trequestType : PUT\n";
-
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to PUT request
-
                         // Update the fanResource
                         put(rep);
-
-                        if (response)
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get());
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            ehResult = OC_EH_OK;
                         }
-
                     }
                     else if (requestType == "POST")
                     {
@@ -314,26 +322,19 @@ class FanResource
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to POST request
-
                         OCRepresentation rep_post = post(rep);
-
-                        if (response)
+                        pResponse->setResourceRepresentation(rep_post);
+                        pResponse->setErrorCode(200);
+                        if (rep_post.hasAttribute("createduri"))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(rep_post);
-
-                            if (rep_post.hasAttribute("createduri"))
-                            {
-                                result = OC_EH_RESOURCE_CREATED;
-
-                                response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                            }
-
+                            pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                            pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                         }
 
-                        // POST request operations
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
                     }
                     else if (requestType == "DELETE")
                     {
@@ -370,6 +371,7 @@ class FanResource
                         pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
                         startedThread = 1;
                     }
+                    ehResult = OC_EH_OK;
                 }
             }
             else
@@ -377,7 +379,7 @@ class FanResource
                 std::cout << "Request invalid" << std::endl;
             }
 
-            return result;
+            return ehResult;
         }
 };
 
@@ -436,34 +438,36 @@ void *ChangeFanRepresentation (void *param)
     return NULL;
 }
 
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    FanResource *fanPtr = (FanResource *) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(fanPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
+
 
 //int start_fanserver(void*)                // 1
 void *start_fanserver(void *d)      // 2
 {
-    /*PlatformConfig cfg;
-    cfg.ipAddress = "192.168.2.5";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;*/
-    // PlatformConfig cfg
-    // {
-    //     OC::ServiceType::InProc,
-    //     OC::ModeType::Server,
-    //     "192.168.2.5",
-    //     56832,
-    //     OC::QualityOfService::NonConfirmable
-    // };
-
-    // Create PlatformConfig object
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-
     // Create PlatformConfig object
     PlatformConfig cfg
     {
         OC::ServiceType::InProc,
-        OC::ModeType::Server,
+        OC::ModeType::Both,
         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
         0,         // Uses randomly available port
         OC::QualityOfService::LowQos
@@ -487,18 +491,9 @@ void *start_fanserver(void *d)      // 2
             printf("Mosquitto is working\n");
         }
 
-        //plugin_data_t *data = (plugin_data_t *)d;
-        //OCPlatform *platform = (OCPlatform*)data->str;
-        //myFanResource.m_platform = (OCPlatform*)data->str;
-        //OCPlatform platform(cfg);
-        // Invoke createResource function of class fan.
-
-        //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
         printf("Mosquitto Connection is done\n");
         myFanResource.createResource();
-        //myFanResource.addType(std::string("core.fan"));
-        //myFanResource.addInterface(std::string("oc.mi.ll"));
         // Get time of day
         timer = time(NULL);
         // Converts date/time to a structure
index 9b2aca2..788b7cf 100644 (file)
@@ -1,13 +1,15 @@
-include ../../../../config.mk
-
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall -pthread
 
+TOP_DIR = ../../../../../..
 LIB_DIR = ../../../../../../resource
 
 SRC_DIR = ../../src
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -17,9 +19,11 @@ CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
 CXX_INC += -I$(BOOST_DIR) 
 CXX_INC += -I../../lib 
 CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC          += -I../csdk/libcoap
+CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+CXX_LIBS  := ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
 
 .PHONY: lib release_build ./release/lightserver_mqtt_plugin.so 
 
@@ -34,7 +38,7 @@ release_build:
        cp plugin.xml release
 
 ./release/lightserver_mqtt_plugin.so: ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o
-       $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS)  -L../../lib -lmosquitto -lssl -lrt
+       $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS)  -L../../lib  -L$(TOP_DIR)/out/linux/x86/release -lmosquitto -lssl -lrt -loc -loctbstack -loc_logger -lcoap
 
 ./release/obj/lightserver_mqtt_plugin.o: $(SRC_DIR)/lightserver_mqtt_plugin.cpp
        $(CXX) $(CXX_INC) -fPIC -o ./release/obj/lightserver_mqtt_plugin.o -c $(SRC_DIR)/lightserver_mqtt_plugin.cpp 
index 93bad63..9f30718 100644 (file)
@@ -43,18 +43,19 @@ struct tm *tblock;           // Define a structure for time block
 
 int gObservation = 0;
 void *ChangeLightRepresentation (void *param);
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 // Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
 
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
 
 // Forward declaring the entityHandler
 // void entityHandler(std::shared_ptr<OCResourceRequest> request,
@@ -112,7 +113,7 @@ class LightResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
 
             // This will internally create and register the resource.
             OCStackResult result = OCPlatform::registerResource(
@@ -134,7 +135,7 @@ class LightResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
 
             OCResourceHandle resHandle;
 
@@ -249,13 +250,10 @@ class LightResource
     private:
         // This is just a sample implementation of entity handler.
         // Entity handler can be implemented in several ways by the manufacturer
-        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                            std::shared_ptr<OCResourceResponse> response)
+        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
         {
-            OCEntityHandlerResult result = OC_EH_OK;
-
             cout << "\tIn Server CPP entity handler:\n";
-
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
             if (request)
             {
                 // Get the request type and request flag
@@ -270,40 +268,52 @@ class LightResource
                 }
                 if (requestFlag & RequestHandlerFlag::RequestFlag)
                 {
-                    cout << "\t\trequestFlag : Request ===  Handle by LightServer\n";
+                    cout << "\t\trequestFlag : Request ===  Handle by FanServer\n";
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
 
                     // If the request type is GET
                     if (requestType == "GET")
                     {
                         cout << "\t\t\trequestType : GET\n";
-
-                        if (response)
+                        if (isSlowResponse) // Slow response case
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            static int startedThread = 0;
+                            if (!startedThread)
+                            {
+                                std::thread t(handleSlowResponse, (void *)this, request);
+                                startedThread = 1;
+                                t.detach();
+                            }
+                            ehResult = OC_EH_SLOW;
+                        }
+                        else // normal response case.
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_OK);
+                            pResponse->setResourceRepresentation(get());
+                            if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                            {
+                                ehResult = OC_EH_OK;
+                            }
                         }
                     }
                     else if (requestType == "PUT")
                     {
                         cout << "\t\t\trequestType : PUT\n";
-
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to PUT request
-
                         // Update the lightResource
                         put(rep);
-
-                        if (response)
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get());
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            ehResult = OC_EH_OK;
                         }
-
                     }
                     else if (requestType == "POST")
                     {
@@ -312,26 +322,19 @@ class LightResource
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to POST request
-
                         OCRepresentation rep_post = post(rep);
-
-                        if (response)
+                        pResponse->setResourceRepresentation(rep_post);
+                        pResponse->setErrorCode(200);
+                        if (rep_post.hasAttribute("createduri"))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(rep_post);
-
-                            if (rep_post.hasAttribute("createduri"))
-                            {
-                                result = OC_EH_RESOURCE_CREATED;
-
-                                response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                            }
-
+                            pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                            pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                         }
 
-                        // POST request operations
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
                     }
                     else if (requestType == "DELETE")
                     {
@@ -368,6 +371,7 @@ class LightResource
                         pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                         startedThread = 1;
                     }
+                    ehResult = OC_EH_OK;
                 }
             }
             else
@@ -375,7 +379,7 @@ class LightResource
                 std::cout << "Request invalid" << std::endl;
             }
 
-            return result;
+            return ehResult;
         }
 };
 
@@ -434,36 +438,36 @@ void *ChangeLightRepresentation (void *param)
     return NULL;
 }
 
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    LightResource *lightPtr = (LightResource *) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(lightPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
 
 
 //int start_lightserver(void*)                // 1
 void *start_lightserver(void *d)      // 2
 {
-    /*PlatformConfig cfg;
-    cfg.ipAddress = "192.168.2.5";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;*/
-    // PlatformConfig cfg
-    // {
-    //     OC::ServiceType::InProc,
-    //     OC::ModeType::Server,
-    //     "192.168.2.5",
-    //     56832,
-    //     OC::QualityOfService::NonConfirmable
-    // };
-
-    // Create PlatformConfig object
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-
     // Create PlatformConfig object
     PlatformConfig cfg
     {
         OC::ServiceType::InProc,
-        OC::ModeType::Server,
+        OC::ModeType::Both,
         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
         0,         // Uses randomly available port
         OC::QualityOfService::LowQos
@@ -487,18 +491,9 @@ void *start_lightserver(void *d)      // 2
             printf("Mosquitto is working\n");
         }
 
-        //plugin_data_t *data = (plugin_data_t *)d;
-        //OCPlatform *platform = (OCPlatform*)data->str;
-        //myLightResource.m_platform = (OCPlatform*)data->str;
-        //OCPlatform platform(cfg);
-        // Invoke createResource function of class light.
-
-        //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
         printf("Mosquitto Connection is done\n");
         myLightResource.createResource();
-        //myLightResource.addType(std::string("core.light"));
-        //myLightResource.addInterface(std::string("oc.mi.ll"));
         // Get time of day
         timer = time(NULL);
         // Converts date/time to a structure
index 935bc7e..351756b 100644 (file)
@@ -1,20 +1,75 @@
 
+This guide will help you setup your developing environment for Protocol plug-in Manager and Protocol plug-ins in Ubuntu. 
+
+1. Preparings
+Before starting, following tools should be installed. 
+
+Automake
+Automake is a tool for automatically generating Makefile.in files compiliant with the GNU Coding Standards. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+$ sudo apt-get install automake
+
+Libtool
+GNU libtool is a generic library support script. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install libtool
+
+gettext
+GNU `gettext' utilities are a set of tools that provides a framework to help other GNU packages produce multi-lingual messages. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install gettext
+
+Expat
+Expat is a stream-oriented XML parser library. This library is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install expat
+
+Building and Using Protocol Plug-in Manager
+
+Once the source code is downloaded into a specific folder, oic in this context, you may follow the steps to build and execute Protocol Plug-in Manager.
+The path for Protocol Plugin is as following;
+
+~/oic/oic-resource/service/protocol-plugin $_
+
+The Protocol Plug-in directory includes following sub directories;
+
+/plugin-manager        Directory for Plug-in Manager
+/plugins       Directory for Reference Plugins  
+/lib           Directory for Common Library
+/sample-app    Directory for Iotivity Sample Application
+/doc           Directory for Developers Document
+/build         Directory for Building and Binary Release
+
+
+2. Compiling C-Pluff library 
+Before building Protocol-Plugin Manager, C-Pluff library should be compiled as follows.
+
+~/oic/oic-service/protocol-plugin/lib/cpluff$ aclocal
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoconf
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoheader
+~/oic/oic-service/protocol-plugin/lib/cpluff$ automake
+~/oic/oic-service/protocol-plugin/lib/cpluff$ ./configure
+~/oic/oic-service/protocol-plugin/lib/cpluff$ make
+
+3. Run make
+By running make in the protocol-plugin path, protocol-plugin manager, all plugins and sample applications will be created. 
+NOTE: To build plugins in 64-bit Ubuntu Linux, OCLib.a and libcoap.a library should be re-compiled with ?fPIC option.
+~/oic/oic-service/protocol-plugin/build/linux$make
+
+
+4. Using Plugins 
 This version of protocol plug-in source code has following functionality.
 
-1. provides plug-in manager which can register, unregister, start and stop plug-in library.
-2. provides plug-in library which can communicate with MQTT protocol FAN.
-3. provides OIC Sample Client which can turn on/off FAN.
+1) provides plug-in manager which can start and stop plug-in library.
+2) provides plug-in library which can communicate with MQTT protocol Fan and Light.
+3) provides OIC Sample Client which can get info about Fan and Light with configuration file(pluginmanager.xml).
 
 So, to test a plug-in, follow below steps.
 
-1. Locate shared plug-in library and XML file in a specific folder.
-2. Register the plug-in with directory path input from plug-in manager sample.
-3. Start the plug-in from plug-in manager sample.
-4. Run OIC sample client.
-
-If you have any questions about protocol plug-in component, please contact with following addresses.
+1) Locate shared plug-in library and XML file in a specific folder.
+2) Register the plug-in with directory path input from plug-in manager sample.
+3) Start the plug-in from plug-in manager sample.
+4) Run OIC sample client.
+   ex)service/protocol-plugin/sample-app/linux/mqtt$./mqttclient
+  (mqtt broker is already installed in the local system.)
 
-kc7576.park@samsung.com
-heesung84.kim@samsung.com
-junho13.lee@samsung.com
-yh_.joo@samsung.com
\ No newline at end of file
diff --git a/service/protocol-plugin/sample-app/SConscript b/service/protocol-plugin/sample-app/SConscript
new file mode 100644 (file)
index 0000000..413dd94
--- /dev/null
@@ -0,0 +1,10 @@
+##
+#sample-app build script
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os == 'linux':
+       SConscript('linux/SConscript')
diff --git a/service/protocol-plugin/sample-app/linux/SConscript b/service/protocol-plugin/sample-app/linux/SConscript
new file mode 100644 (file)
index 0000000..339d4bb
--- /dev/null
@@ -0,0 +1,28 @@
+##
+#sample-app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+sample_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+sample_env.AppendUnique(CPPPATH = ['../../plugin-manager/src/',
+                               '../../lib/cpluff/libcpluff/'])
+if target_os not in ['windows', 'winrt']:
+       sample_env.AppendUnique(CXXFLAGS = ['-Wall', '-pthread', '-std=c++0x'])
+
+sample_env.AppendUnique(LIBS = ['oc', 'oc_logger', 'octbstack', 'coap', 'ppm', 'pmimpl', 'dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+fanclient = sample_env.Program('fanclient', 'fan-control/fanclient.cpp')
+
+Alias('fanclient', fanclient)
+env.AppendTarget('fanclient')
\ No newline at end of file
diff --git a/service/protocol-plugin/sample-app/linux/fan-control/Makefile b/service/protocol-plugin/sample-app/linux/fan-control/Makefile
deleted file mode 100644 (file)
index 6b5d664..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-CXX = g++
-
-CXX_FLAGS = -std=c++0x -Wall -pthread
-
-LIB_DIR = ../../../../../resource
-
-CXX_INC := -I$(LIB_DIR)/include/ 
-CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
-CXX_INC += -I$(BOOST_DIR) 
-CXX_INC += -I../../lib
-CXX_INC += -I../../../lib/cpluff/libcpluff
-CXX_INC += -I../../../plugin-manager/src
-
-LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
-LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
-
-.PHONY: fanclient
-
-all: .PHONY
-
-fanclient: fanclient.o
-       $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(CXX_LIBS) $(LINK_LIB)
-
-fanclient.o: fanclient.cpp
-       $(CXX) $(CXX_FLAGS) -c fanclient.cpp $(CXX_INC)
-
-       
-clean:
-       rm -f *.o
-       rm -f fanclient 
diff --git a/service/protocol-plugin/sample-app/linux/mqtt/Makefile b/service/protocol-plugin/sample-app/linux/mqtt/Makefile
new file mode 100644 (file)
index 0000000..131e83a
--- /dev/null
@@ -0,0 +1,42 @@
+CXX = g++
+
+CXX_FLAGS = -std=c++0x -Wall -pthread
+
+TOP_DIR = ../../../../..
+LIB_DIR = ../../../../../resource
+
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
+CXX_INC := -I$(LIB_DIR)/include/ 
+CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
+CXX_INC += -I$(BOOST_DIR) 
+CXX_INC += -I../../lib
+CXX_INC += -I../../../lib/cpluff/libcpluff
+CXX_INC += -I../../../plugin-manager/src
+CXX_INC   += -I$(CEREAL_DIR)/include
+CXX_INC += -I../../../lib/rapidxml 
+
+LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
+CXX_LIBS  := ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread -L$(TOP_DIR)/out/linux/x86/release -loc -loctbstack -loc_logger -lcoap
+
+.PHONY: mqttclient
+
+all: .PHONY
+
+mqttclient: mqttclient.o
+       $(CXX) $(CXX_FLAGS) -o mqttclient mqttclient.o $(CXX_LIBS) $(LINK_LIB)
+
+mqttclient.o: mqttclient.cpp
+       $(CXX) $(CXX_FLAGS) -c mqttclient.cpp $(CXX_INC)
+
+       
+clean:
+       rm -f *.o
+       rm -f *.so
+       rm -f mqttclient
@@ -32,7 +32,8 @@
 using namespace OC;
 using namespace OIC;
 
-std::shared_ptr<OCResource> curResource;
+std::shared_ptr<OCResource> curFanResource;
+std::shared_ptr<OCResource> curLightResource;
 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
 
 time_t timer;                // Define the timer
@@ -78,7 +79,7 @@ void onObserve(const HeaderOptions headerOptions, const OCRepresentation &rep,
         if (observe_count() > 30)
         {
             std::cout << "Cancelling Observe..." << std::endl;
-            OCStackResult result = curResource->cancelObserve();
+            OCStackResult result = curFanResource->cancelObserve();
 
             std::cout << "Cancel result: " << result << std::endl;
             sleep(10);
@@ -120,7 +121,7 @@ void onPost2(const HeaderOptions &headerOptions, const OCRepresentation &rep, co
         else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
             std::cout << endl << "ObserveAll is used." << endl << endl;
 
-        curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
+        //curFanResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
 
     }
     else
@@ -162,7 +163,7 @@ void onPost(const HeaderOptions &headerOptions, const OCRepresentation &rep, con
         rep2.setValue("state", myfan.m_state);
         rep2.setValue("power", myfan.m_power);
 
-        curResource->post(rep2, QueryParamsMap(), &onPost2);
+        curFanResource->post(rep2, QueryParamsMap(), &onPost2);
     }
     else
     {
@@ -206,7 +207,7 @@ void onPut(const HeaderOptions &headerOptions, const OCRepresentation &rep, cons
         std::cout << "\tpower: " << myfan.m_power << std::endl;
         std::cout << "\tname: " << myfan.m_name << std::endl;
 
-        postFanRepresentation(curResource);
+        postFanRepresentation(curFanResource);
     }
     else
     {
@@ -251,7 +252,7 @@ void onGet(const HeaderOptions &headerOptions, const OCRepresentation &rep, cons
         std::cout << "\tpower: " << myfan.m_power << std::endl;
         std::cout << "\tname: " << myfan.m_name << std::endl;
 
-        putFanRepresentation(curResource);
+        putFanRepresentation(curFanResource);
     }
     else
     {
@@ -288,7 +289,7 @@ void getLightRepresentation(std::shared_ptr<OCResource> resource)
 // Callback to found resources
 void foundResourceFan(std::shared_ptr<OCResource> resource)
 {
-    if (curResource)
+    if (curFanResource)
     {
         std::cout << "Found another resource, ignoring" << std::endl;
     }
@@ -325,7 +326,7 @@ void foundResourceFan(std::shared_ptr<OCResource> resource)
 
             if (resourceURI == "/a/fan")
             {
-                curResource = resource;
+                curFanResource = resource;
                 // Call a local function which will internally invoke get API on the resource pointer
                 getFanRepresentation(resource);
             }
@@ -346,7 +347,7 @@ void foundResourceFan(std::shared_ptr<OCResource> resource)
 // Callback to found resources
 void foundResourceLight(std::shared_ptr<OCResource> resource)
 {
-    if (curResource)
+    if (curLightResource)
     {
         std::cout << "Found another resource, ignoring" << std::endl;
     }
@@ -383,7 +384,7 @@ void foundResourceLight(std::shared_ptr<OCResource> resource)
 
             if (resourceURI == "/a/light")
             {
-                curResource = resource;
+                curLightResource = resource;
                 // Call a local function which will internally invoke get API on the resource pointer
                 getLightRepresentation(resource);
             }
@@ -425,7 +426,9 @@ void client1()
     std::cout << "Finding Fan Resource... time : " << asctime(tblock) << std::endl;
     while (1)
     {
-        // client1 related operations
+        std::cout << "Get Fan Resource....." << std::endl;
+        sleep(5);
+        getFanRepresentation(curFanResource);
     }
 }
 
@@ -449,7 +452,9 @@ void client2()
 
     while (1)
     {
-        // client2 related operations
+        std::cout << "Get Light Resource....." << std::endl;
+        sleep(5);
+        getLightRepresentation(curLightResource);
     }
 }
 
@@ -457,6 +462,11 @@ void client2()
 
 int main(int argc, char *argv[])
 {
+    std::string name;
+    std::string key = "Name";
+    std::string  state = "";
+    std::string  id = "";
+
     if (argc == 1)
     {
         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
@@ -494,41 +504,83 @@ int main(int argc, char *argv[])
 
         std::cout << "Created Platform..." << std::endl;
 
-
         PluginManager *m_pm = new PluginManager();
 
+        std::cout << "==== 1st TEST CASE ===" << std::endl;
         std::cout << "======================" << std::endl;
-
         std::cout << "start light Plugin by Resource Type"  << std::endl;
+
         m_pm->startPlugins("ResourceType", "oic.light");
 
         sleep(2);
 
+        std::cout << "\n==== 2nd TEST CASE =====" << std::endl;
         std::cout << "======================" << std::endl;
-        std::cout << "get Plugin List" << std::endl;
+        std::cout << "Get Plugin List\n" << std::endl;
         std::vector<Plugin> user_plugin;
+
         user_plugin = m_pm->getPlugins();
+
         for (unsigned int i = 0; i < user_plugin.size(); i++)
         {
-            printf("value Name = %s\n", user_plugin[i].getName().c_str());
-            printf("value ID = %s\n", user_plugin[i].getID().c_str());
+            std::cout << "value Name = " << user_plugin[i].getName() << std::endl;
+            std::cout << "value ID = " << user_plugin[i].getID() << std::endl;
+            id =  user_plugin[i].getID();
         }
-
+        std::cout << "\n===== 3rd TEST CASE =====" << std::endl;
         std::cout << "======================" << std::endl;
-        std::cout << "start Fan Plugin by Name" << std::endl;
-        m_pm->startPlugins("Name", "mqtt-fan");
+        std::cout << "Start Fan Plugin by Name\n" << std::endl;
+
+        name = user_plugin[0].getName().c_str();
+        m_pm->startPlugins(key, name);
+
+        sleep(5);
+
+        std::cout << "\n====== 4th TEST CASE ======" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Get Plugin Status\n" << std::endl;
+
+        state = m_pm->getState(id);
 
+        std::cout << "last plugin status :  " << state << std::endl;
+        std::cout << "sleep 15 seconds please add new plugin in the plugin folder  " << std::endl;
 
+        sleep(15);
+
+        std::cout << "\n====  5th TEST CASE  ====" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Rescan Plugins.........\n" << std::endl;
+
+        m_pm->rescanPlugin();
+
+        std::cout << "\n====  6th TEST CASE  ====" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Try to start new resource type.........\n" << std::endl;
+        std::cout << "start oic.test resource" <<  std::endl;
+
+        sleep(5);
+
+        int flag = m_pm->startPlugins("ResourceType", "oic.test");
+
+        if (!flag)
+            std::cout << "There are no resouce type. Start plugin failed" << std::endl;
         // Start each client in a seperate thread
-//        std::thread t1(client1);
-//        t1.detach();
 
-///*
-//        sleep(5);
+        sleep(10);
+
+        std::cout << "\n====== 7th TEST CASE =======" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << " start client to find resource" << std::endl;
+
+        std::thread t1(client1);
+        t1.detach();
+
+        sleep(5);
+
         // Start each client in a seperate thread
-//        std::thread t2(client2);
-//        t2.detach();
-//*/
+        std::thread t2(client2);
+        t2.detach();
+
         while (true)
         {
             // some operations
diff --git a/service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml b/service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml
new file mode 100644 (file)
index 0000000..c90bb9f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pluginManager>
+    <pluginInfo        
+        pluginPath="../../../plugins"        
+        maxMEM="64M"
+        maxPlugin=""
+        version="1.0"
+        name="pluginmanager">
+    </pluginInfo>
+    <specailpluginInfo>
+    </specailpluginInfo>
+</pluginManager>
diff --git a/service/soft-sensor-manager/SConscript b/service/soft-sensor-manager/SConscript
new file mode 100644 (file)
index 0000000..c7416e0
--- /dev/null
@@ -0,0 +1,107 @@
+##
+# soft-sensor-manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+soft_sensor_manager_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+# As in the source code, it includes arduino Time library (C++)
+# It requires compile the .c with g++
+if target_os == 'arduino':
+       soft_sensor_manager_env.Replace(CC = env.get('CXX'))
+       soft_sensor_manager_env.Replace(CFLAGS = env.get('CXXFLAGS'))
+
+######################################################################
+# Build flags
+######################################################################
+if target_os not in ['windows', 'winrt']:
+       soft_sensor_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-DLINUX'])
+       if target_os != 'android':
+               soft_sensor_manager_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+#######################################################################
+## build SSM SDK
+#######################################################################
+sdk_env = soft_sensor_manager_env.Clone()
+sdk_env.AppendUnique(CPPPATH = ['SSMCore/include'])
+sdk_env.AppendUnique(CPPPATH = ['SSMCore/src'])
+sdk_env.AppendUnique(CPPPATH = ['SDK/include'])
+
+ssm_sdk_cpp_src = [
+               Glob('SDK/src/*.cpp')
+               ]
+
+env.AppendTarget('libSSMSDK')
+libssmsdk = sdk_env.StaticLibrary(
+               target = 'libSSMSDK',
+               source = [ssm_sdk_cpp_src]
+               )               
+sdk_env.InstallTarget(libssmsdk, 'libSSMCORE')
+
+######################################################################
+# build DiscomfortIndexSensor plugin
+######################################################################
+DiscomfortIndexSensor_env = soft_sensor_manager_env.Clone()
+
+DiscomfortIndexSensor_env.AppendUnique(CCFLAGS = ['-fPIC'])
+DISCOMFORTINDEXSENSOR_DIR = 'SoftSensorPlugin/DiscomfortIndexSensor/'
+DiscomfortIndexSensor_env.AppendUnique(CPPPATH = [
+               DISCOMFORTINDEXSENSOR_DIR + 'include',
+               'SSMCore/src/SSMInterface/'
+               ])
+
+DiscomfortIndexSensor_src = [ Glob(DISCOMFORTINDEXSENSOR_DIR + 'src/*.cpp')]
+
+DiscomfortIndexSensor = DiscomfortIndexSensor_env.SharedLibrary('DiscomfortIndexSensor', DiscomfortIndexSensor_src)
+DiscomfortIndexSensor_env.InstallTarget(DiscomfortIndexSensor, 'libDiscomfortIndexSensor')
+
+######################################################################
+# build SSM CORE
+######################################################################
+ssmcore_env = soft_sensor_manager_env.Clone()
+
+ssmcore_env.AppendUnique(CPPPATH = [
+               'SSMCore/include/',
+               'SSMCore/src/',
+               'SSMCore/src/Common/'
+               'SSMCore/src/QueryProcessor/'
+               'SSMCore/src/SensorProcessor/'
+               'SSMCore/src/SSMInterface/'
+               ])
+
+import os.path
+
+if target_os != 'android':
+       SSMINTERFACE_PATH = 'SSMCore/src/SSMInterface/'
+       omit_src = ['SSMCore_JNI.cpp']
+       ssminterface_src = [f for f in env.Glob(SSMINTERFACE_PATH + '*.cpp') if os.path.basename(f.path) not in omit_src]
+else :
+       ssminterface_src = Glob(SSMINTERFACE_PATH + '*.cpp')
+
+ssm_core_cpp_src = [
+               Glob('SSMCore/src/Common/*.cpp'),
+               Glob('SSMCore/src/QueryProcessor/*.cpp'),
+               Glob('SSMCore/src/SensorProcessor/*.cpp'),
+               ssminterface_src,
+               ]
+
+ssm_core_c_src = [
+               'SSMCore/src/Common/sqlite3.c'
+]
+
+libssmcore = ssmcore_env.StaticLibrary(
+               target = 'SSMCore',
+               source = [ssm_core_cpp_src, ssm_core_c_src]
+               )
+
+ssmcore_env.InstallTarget(libssmcore, 'libSSMCORE')
+
+#######################################################################
+## build SampleApp
+#######################################################################
+SConscript('SampleApp/SConscript')
\ No newline at end of file
index cd76579..323937b 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../build/linux/root_path.inc
 -include ../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -6,12 +6,14 @@ SRC_PATH=../../src
 INC_PATH=../../include
 RST_NAME=release
 
+GAR=ar
+
 # Insert your project name.
-TARGET=SDKlib
+TARGET=${SSM_LIB}
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I../../ -I${INC_PATH}/ -I${FD_SSMCORE}/include -I${FD_SSMCORE}/src -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 CXX_LIB= 
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@@ -30,7 +32,7 @@ pre_job:
        @echo " "
 
 ${TARGET}: ${OBJLIST}
-       @cp -Rdp ./*.o ./${RST_NAME}/ 
+       ${GAR} -r ./${RST_NAME}/$@  ./*.o
        @cp -Rdp ${INC_PATH}/*.h ./${RST_NAME}/
        @echo " " 
 
index f425b3d..0eca527 100644 (file)
@@ -45,14 +45,14 @@ class ISSMClientListener
     public:
         /**
          * @brief   onRegisterQuery is a pure virtual operation which should be implemented in applications to get callback messages.
-         * @param [in] attributeMap - A data map in which SoftSensorManager service sends sensor data with cqid.
+         * @param [in] jsonData - A data map in which SoftSensorManager service sends sensor data with cqid.
          * @param [in] eCode - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
          *                          SSMClient can callback message to the appication.
          * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
          * @return  SSMReturn
 
          */
-        virtual void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode) = 0;
+        virtual void onRegisterQuery(const std::string &jsonData, SSMReturn &eCode) = 0;
         virtual ~ISSMClientListener()
         {
         }
index 1ee47bd..dd9d899 100644 (file)
@@ -168,7 +168,6 @@ class SSMClient
 {
     private:
         SSMReturn m_retResponse;
-        OCPlatform *m_pPlatform;
         CSemaphore m_sem;
         /**
          * @brief SoftSensorManager Resource.
@@ -177,7 +176,7 @@ class SSMClient
         /**
          * @brief attribute map .
          */
-        AttributeMap m_responseAttributeMap;
+        std::map<std::string, std::string> m_responseAttributeMap;
         /**
          * @brief query engine.
          */
@@ -233,11 +232,16 @@ class SSMClient
 
         // friend option. for callback from SSMResource
         void onFoundResource(std::shared_ptr< OCResource > resource);
-        void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onRegisterQuery(const OCRepresentation &rep, const int eCode);
-        void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
-        void onObserve(const OCRepresentation &rep, const int &eCode);
+        void onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                 const int eCode);
+        void onReleaseQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                  const int eCode);
+        void onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                             const int eCode);
+        void onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                               const int eCode);
+        void onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int &eCode,
+                       const int &sequenceNumber);
 };
 
 #endif /* RESOURCECLIENT_H_ */
diff --git a/service/soft-sensor-manager/SDK/src/InprocSSMCore.cpp b/service/soft-sensor-manager/SDK/src/InprocSSMCore.cpp
new file mode 100644 (file)
index 0000000..358f807
--- /dev/null
@@ -0,0 +1,121 @@
+#include "SSMInterface.h"
+#include "SSMInterface/SSMCore.h"
+#include "Common/PlatformLayer.h"
+
+class SSMCoreEventReceiver : public IQueryEngineEvent
+{
+    public:
+        SSMCoreEventReceiver()
+        {
+        }
+
+        SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult)
+        {
+            SSMRESULT res = SSM_E_FAIL;
+
+            m_mtxListener.lock();
+
+            if (m_mapListener.find(cqid) == m_mapListener.end())
+            {
+                SSM_CLEANUP_ASSERT(res);
+            }
+
+            m_mapListener[cqid]->onQueryEngineEvent(cqid, pResult);
+
+            res = SSM_S_OK;
+
+CLEANUP:
+            m_mtxListener.unlock();
+            return res;
+        }
+
+        void lockListener()
+        {
+            m_mtxListener.lock();
+        }
+
+        void unlockListener()
+        {
+            m_mtxListener.unlock();
+        }
+
+        void addListener(IN int cqid, IN IQueryEngineEvent *pEngineEvent)
+        {
+            m_mapListener[cqid] = pEngineEvent;
+        }
+
+        void removeListener(IN int cqid)
+        {
+            m_mapListener.erase(cqid);
+        }
+
+    private:
+        CSimpleMutex                        m_mtxListener;
+        std::map<int, IQueryEngineEvent *>   m_mapListener;
+};
+
+IQueryEngine                        *g_pQueryEngineInstance = NULL;
+SSMCoreEventReceiver                *g_pEventReceiver = NULL;
+
+SSMInterface::SSMInterface()
+{
+    std::string xmlDescription = "<SSMCore>"
+                                 "<Device>"
+                                 "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
+                                 "<Name>MyPC</Name>"
+                                 "<Type>PC</Type>"
+                                 "</Device>"
+                                 "</SSMCore>";
+
+    SSMRESULT res = SSM_E_FAIL;
+
+    g_pEventReceiver = new SSMCoreEventReceiver();
+    SSM_CLEANUP_NULL_ASSERT(g_pEventReceiver);
+    SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
+    SSM_CLEANUP_ASSERT(StartSSMCore());
+    SSM_CLEANUP_ASSERT(CreateQueryEngine(&g_pQueryEngineInstance));
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->registerQueryEvent(g_pEventReceiver));
+CLEANUP:
+    ;
+}
+
+SSMInterface::~SSMInterface()
+{
+    SSMRESULT res = SSM_E_FAIL;
+
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->unregisterQueryEvent(g_pEventReceiver));
+    ReleaseQueryEngine(g_pQueryEngineInstance);
+    g_pQueryEngineInstance = NULL;
+    SSM_CLEANUP_ASSERT(StopSSMCore());
+    SSM_CLEANUP_ASSERT(TerminateSSMCore());
+
+CLEANUP:
+    SAFE_DELETE(g_pEventReceiver);
+}
+
+SSMRESULT SSMInterface::registerQuery(IN std::string queryString, IN IQueryEngineEvent *listener,
+                                      IN int &cqid)
+{
+    SSMRESULT res = SSM_E_FAIL;
+
+    g_pEventReceiver->lockListener();
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->executeContextQuery(queryString, &cqid));
+    g_pEventReceiver->addListener(cqid, listener);
+
+CLEANUP:
+    g_pEventReceiver->unlockListener();
+    return res;
+}
+
+SSMRESULT SSMInterface::unregisterQuery(IN int cqid)
+{
+    SSMRESULT res = SSM_E_FAIL;
+
+    g_pEventReceiver->lockListener();
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->killContextQuery(cqid));
+    g_pEventReceiver->removeListener(cqid);
+
+CLEANUP:
+    g_pEventReceiver->unlockListener();
+    return res;
+}
\ No newline at end of file
index 174456c..572e513 100644 (file)
@@ -29,17 +29,11 @@ const char *SSM_RESOURCE_URI = "/service/SoftSensorManager";
 
 #define SSM_RESOURCE_TYPE       = "core.SoftSensorManager"
 
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               5683
-#define COAP_MODE               ModeType::Client
-#define COAP_SRVTYPE            ServiceType::InProc
-
 #define COAP_SERVER_ADDR        "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
 
 SSMClient::SSMClient()
 {
     m_sem.create(100000);
-    m_pPlatform = NULL;
     m_appListener = NULL;
     m_retResponse = SSM_ERROR;
     _findResource();
@@ -49,34 +43,30 @@ SSMClient::SSMClient()
 SSMClient::~SSMClient()
 {
     _releaseQueryEngine(m_queryEngineId);
-    if (m_pPlatform)
-    {
-        delete m_pPlatform;
-        m_pPlatform = NULL;
-    }
 }
 
 void SSMClient::_findResource()
 {
     // Create PlatformConfig object
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+    PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+                       "0.0.0.0", 0, OC::QualityOfService::LowQos);
 
     // Create a OCPlatform instance.
     // Note: Platform creation is synchronous call.
     try
     {
-        m_pPlatform = new OCPlatform(cfg);
+        OCPlatform::Configure(cfg);
 
         // Find all resources
         OCStackResult result;
-        if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
-                                                std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
+        if ((result = OCPlatform::findResource("", COAP_SERVER_ADDR,
+                                               std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
             != OC_STACK_OK)
         {
-            delete m_pPlatform;
-            m_pPlatform = NULL;
+            std::cout << "Faile to Find Resource... " << std::endl;
             return;
         }
+        std::cout << "Find Resource... " << std::endl;
 
         m_sem.wait();
 
@@ -91,20 +81,13 @@ void SSMClient::_createQueryEngine(void)
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("CreateQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    rep.setAttributeMap(requestAttributeMap);
+    rep.setValue("command", std::string("CreateQueryEngine"));
 
     if (m_SSMResource->put(rep, queryParamsMap,
                            std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
+                                     std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
     {
         return;
     }
@@ -116,25 +99,14 @@ void SSMClient::_releaseQueryEngine(std::string queryEngineId)
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("ReleaseQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    rep.setAttributeMap(requestAttributeMap);
+    rep.setValue("command", std::string("ReleaseQueryEngine"));
+    rep.setValue("queryEngineId", queryEngineId);
 
     m_SSMResource->put(rep, queryParamsMap,
                        std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
-                                 std::placeholders::_2));
+                                 std::placeholders::_2, std::placeholders::_3));
 
     m_sem.wait();
 }
@@ -144,39 +116,25 @@ SSMReturn SSMClient::registerQuery(std::string queryString, ISSMClientListener *
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues contextQueryValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("ExecuteContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
 
-    contextQueryValue.push_back(queryString);
-
-    requestAttributeMap["contextQuery"] = contextQueryValue;
+    rep.setValue("command", std::string("ExecuteContextQuery"));
+    rep.setValue("queryEngineId", m_queryEngineId);
+    rep.setValue("contextQuery", queryString);
 
     m_appListener = listener;
 
-    rep.setAttributeMap(requestAttributeMap);
-
     if (m_SSMResource->put(rep, queryParamsMap,
                            std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
+                                     std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
         return SSM_ERROR_NETWORK;
 
     m_sem.wait();
 
     if (m_retResponse == SSM_SUCCESS)
     {
-        cqid = m_responseAttributeMap["CQID"].back();
+        cqid = m_responseAttributeMap["CQID"];
     }
 
     return m_retResponse;
@@ -186,30 +144,15 @@ SSMReturn SSMClient::unregisterQuery(std::string cqid)
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues cqidValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("KillContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    cqidValue.push_back(cqid);
-
-    requestAttributeMap["CQID"] = cqidValue;
-
-    rep.setAttributeMap(requestAttributeMap);
+    rep.setValue("command", std::string("KillContextQuery"));
+    rep.setValue("queryEngineId", m_queryEngineId);
+    rep.setValue("CQID", cqid);
 
     if (m_SSMResource->put(rep, queryParamsMap,
                            std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
+                                     std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
         return SSM_ERROR_NETWORK;
 
     m_sem.wait();
@@ -246,7 +189,8 @@ void SSMClient::onFoundResource(std::shared_ptr< OCResource > resource)
     m_sem.release();
 }
 
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                    const int eCode)
 {
     if (eCode != 0)
     {
@@ -254,15 +198,14 @@ void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode
         goto CLEANUP;
     }
 
-    m_responseAttributeMap = rep.getAttributeMap();
-    m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
-    m_responseAttributeMap["queryEngineId"].pop_back();
+    m_queryEngineId = rep.getValue<std::string>("queryEngineId");
     m_retResponse = SSM_SUCCESS;
 
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                const int eCode)
 {
     QueryParamsMap queryParamsMap;
 
@@ -272,23 +215,27 @@ void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
         goto CLEANUP;
     }
 
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
+    if (rep.hasAttribute("error"))
     {
         m_retResponse = SSM_ERROR_QUERY_PARSING;
         goto CLEANUP;
     }
 
     m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
-                           std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
+                           std::bind(&SSMClient::onObserve, this, std::placeholders::_1,
+                                     std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
+
+    m_responseAttributeMap.clear();
+
+    m_responseAttributeMap["CQID"] = rep.getValue<std::string>("CQID");
 
     m_retResponse = SSM_SUCCESS;
 
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                  const int eCode)
 {
     if (eCode != 0)
     {
@@ -296,20 +243,21 @@ void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
         goto CLEANUP;
     }
 
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
+    if (rep.hasAttribute("error"))
     {
         m_retResponse = SSM_ERROR_NO_QUERY;
         goto CLEANUP;
     }
 
+    m_responseAttributeMap.clear();
+
     m_retResponse = SSM_SUCCESS;
 
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onReleaseQueryEngine(const HeaderOptions &headerOptions,
+                                     const OCRepresentation &rep, const int eCode)
 {
     if (eCode != 0)
     {
@@ -317,14 +265,13 @@ void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCod
         goto CLEANUP;
     }
 
-    m_responseAttributeMap = rep.getAttributeMap();
-
     m_retResponse = SSM_SUCCESS;
 
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
+void SSMClient::onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                          const int &eCode, const int &sequenceNumber)
 {
     SSMReturn ret = SSM_SUCCESS;
 
@@ -333,5 +280,5 @@ void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
         ret = SSM_ERROR_NETWORK;
     }
 
-    m_appListener->onRegisterQuery(rep.getAttributeMap(), ret);
+    m_appListener->onRegisterQuery(rep.getJSONRepresentation(), ret);
 }
index dbec597..f6a3f19 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../build/linux/root_path.inc
 -include ../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -7,13 +7,13 @@ INC_PATH=../../include
 RST_NAME=release
 
 # Insert your project name.
-TARGET=SSMCoreUbuntu
+TARGET=${SSMCORE_LIB}
 EXCLUDE_LIST=SSMCore_JNI.cpp
 
 # C++ type Compile Flag define.
 CXX=g++
-CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -DMODEL_DIRECTORY=${MODEL_DIR} -DHIGH_LOCATION=${HIGH_LOCATION} -ldl
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST} -I${SRC_PATH} -I${SRC_PATH}/Common -I${SRC_PATH}/QueryProcessor -I${SRC_PATH}/SensorProcessor -I${SRC_PATH}/SSMInterface
+CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -ldl
+CXX_INC=-I${INC_PATH}/ -I${SRC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 CXX_LIB=-L""
 
 CXX_SRCPATH=${wildcard ${SRC_PATH}/**/*.cpp}
@@ -34,8 +34,8 @@ GCC_OBJLIST=${GCC_USESRCS:.c=.o}
 
 # Linker FLAGS define.
 LD_FLAGS=-std=c++0x -Wall -DLINUX
-GAR=ar
-LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} -lpthread -ldl 
+GAR=ar
+# LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} ${IOT_LOG_DIR}/lib/${IOT_LOG_LIB} -lpthread -ldl 
 
 
 # Force metatargets to build:
@@ -51,8 +51,8 @@ pre_job:
        @echo "${MODEL_DIR}"
        
 ${TARGET}: ${GCC_OBJLIST} ${CXX_OBJLIST}
-       $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}             
-       ${GAR} -r ./${RST_NAME}/$@  ./*.o
+       # $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}           
+       ${GAR} -r ./${RST_NAME}/$@  ./*.o
        @echo " "
 
 %.o : ${SRC_PATH}/**/%.c 
@@ -70,6 +70,7 @@ ${TARGET}: ${GCC_OBJLIST} ${CXX_OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
+       cp -Rdp ${INC_PATH}/SSMInterface.h ${OUTPUTS_DIR}/
        cp -Rdp ${SRC_PATH}/SSMInterface/SSMModelDefinition.h ${OUTPUTS_DIR}/
        @echo "---------------- SSMCore Build Successful. ---------------"
        @echo "Enter to ${RST_NAME} folder."
diff --git a/service/soft-sensor-manager/SSMCore/include/SSMInterface.h b/service/soft-sensor-manager/SSMCore/include/SSMInterface.h
new file mode 100644 (file)
index 0000000..b126130
--- /dev/null
@@ -0,0 +1,195 @@
+#ifndef _SSMInterface_H_
+#define _SSMInterface_H_
+
+#include <string>
+#include <vector>
+
+enum SSMRESULT
+{
+    SSM_S_OK
+    , SSM_S_FALSE
+    , SSM_E_POINTER
+    , SSM_E_OUTOFMEMORY
+    , SSM_E_FAIL
+    , SSM_E_NOINTERFACE
+    , SSM_E_NOTIMPL
+};
+
+/**
+* @class    IModelData
+* @brief    IModelData Interface
+*            This class represents context model data package
+*
+* @see
+*/
+class IModelData
+{
+    public:
+        /**
+        * @fn     getDataId
+        * @brief Get affected DataId. ContextModel has plenty of data so \n
+        *         returned data is matched from given condition
+        *
+        * @param None
+        *
+        * @return int
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual int getDataId() = 0;
+
+        /**
+        * @fn     GetPropertyCount
+        * @brief ContextModel has at least one property that contains data \n
+        *         property is described from its specification.
+        *
+        * @param None
+        *
+        * @return int
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual int getPropertyCount() = 0;
+
+        /**
+        * @fn     getPropertyName
+        * @brief Retrieve propertyName
+        *
+        * @param [in] int propertyIndex - index of property to read
+        *
+        * @return std::string
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual std::string getPropertyName(int propertyIndex) = 0;
+
+        /**
+        * @fn     getPropertyValue
+        * @brief Retrieve propertyValue
+        *
+        * @param [in] int propertyIndex - index of property to read
+        *
+        * @return std::string
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual std::string getPropertyValue(int propertyIndex) = 0;
+
+        /**
+        * @fn     getPropertyValueByName
+        * @brief Retrieve propertyValue using given name
+        *
+        * @param [in] std::string propertyName - property name looking for
+        *
+        * @return std::string
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual std::string getPropertyValueByName(std::string propertyName) = 0;
+    protected:
+        virtual ~IModelData() {};
+};
+
+/**
+* @class    IDataReader
+* @brief    IDataReader Interface
+*            This class represents context model data package's reader
+*
+* @see
+*/
+class IDataReader
+{
+    public:
+        /**
+        * @fn     getAffectedModels
+        * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
+        *
+        * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT getAffectedModels(std::vector<std::string> *pAffectedModels) = 0;
+
+        /**
+        * @fn     getModelDataCount
+        * @brief Get affected data count. There are multiple data can exist from given condition.
+        *
+        * @param [in] std::string modelName - affected ContextModel name
+        *
+        * @param [out] int *pDataCount - affected dataId count
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT getModelDataCount(std::string modelName, int *pDataCount) = 0;
+
+        /**
+        * @fn     getModelData
+        * @brief Get actual Context Model data
+        *
+        * @param [in] std::string modelName - affected ContextModel name
+        *
+        *
+        * @param [in] int dataIndex - affected dataId index
+        *
+        *
+        * @param [out] IModelData **ppModelData - affected ContextModel data reader
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT getModelData(std::string modelName, int dataIndex, IModelData **ppModelData) = 0;
+    protected:
+        virtual ~IDataReader() {};
+};
+
+/**
+* @class    IQueryEngineEvent
+* @brief    IQueryEngineEvent Interface
+*            This class represents Query Engine's event that contains results
+*
+* @see
+*/
+class IQueryEngineEvent
+{
+    public:
+        /**
+        * @fn     onQueryEngineEvent
+        * @brief Transmit result of SSMCore to Application layer
+        *
+        * @param [in] int cqid - entered ContextQuery ID
+        *
+        * @param [in] IDataReader *pResult - result of SSMCore
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult) = 0;
+    protected:
+        virtual ~IQueryEngineEvent() {};
+};
+
+class SSMInterface
+{
+    public:
+        SSMInterface();
+        ~SSMInterface();
+
+        SSMRESULT registerQuery(std::string queryString, IQueryEngineEvent *listener, int &cqid);
+        SSMRESULT unregisterQuery(int cqid);
+};
+#endif
\ No newline at end of file
index dd9fe3e..e0db5b2 100644 (file)
@@ -113,21 +113,21 @@ class IContextRepository : public IBase
                 ;
 
         /**
-        * @fn           setCurrentDeviceInfo
-        * @brief        set device information
+        * @fn           initRepository
+        * @brief        initialize repository using given info
         *
         * @param        [in] std::string name - Device name
         * @param        [in] std::string type - Device Type
         * @param        [in] std::string pathSoftSensors - SoftSensors Repository path
         * @param        [in] std::string pathDescription - SoftSensors Description path
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        virtual void setCurrentDeviceInfo(IN std::string name, IN std::string type,
-                                          IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
+        virtual SSMRESULT initRepository(IN std::string name, IN std::string type,
+                                         IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
 
         virtual SSMRESULT registerResourceFinderEvent(IN IResourceEvent *pResourceEvent) = 0;
         virtual SSMRESULT startResourceFinder() = 0;
@@ -1123,16 +1123,15 @@ class IContextExecutor : public IBase
                                        IEvent *pEvent) = 0;
 };
 
-static const OID OID_IResponseReactor = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
+static const OID OID_ISensingEngine = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
 /**
- * @class    IResponseReactor
- * @brief    Interface for implement of reactor pattern
- *           Delegate requested context to context executor layer.
+ * @class    ISensingEngine
+ * @brief    Class for implementing main abstration of SensorProcessor
  *
  *
  * @see
  */
-class IResponseReactor : public IBase
+class ISensingEngine : public IBase
     , public IEvent
 {
     public:
@@ -1149,7 +1148,8 @@ class IResponseReactor : public IBase
         * @exception
         * @see
         */
-        virtual void registerContext(TypeofEvent callType, ISSMResource *pSSMResouce, IEvent *pEvent) = 0;
+        virtual SSMRESULT registerContext(TypeofEvent callType, ISSMResource *pSSMResouce,
+                                          IEvent *pEvent) = 0;
 
         /**
         * @fn     unregisterContext
@@ -1164,8 +1164,8 @@ class IResponseReactor : public IBase
         * @exception
         * @see
         */
-        virtual void unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
-                                       IEvent *pEvent) = 0;
+        virtual SSMRESULT unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+                                            IEvent *pEvent) = 0;
 
         /**
         * @fn    getList
@@ -1178,7 +1178,7 @@ class IResponseReactor : public IBase
         * @exception
         * @see
         */
-        virtual void getList(std::vector<ISSMResource *> *pList) = 0;
+        virtual SSMRESULT getList(std::vector<ISSMResource *> *pList) = 0;
 };
 
 class IResourceFinderEvent
@@ -1199,13 +1199,6 @@ class IResourceFinder : public IBase
         virtual SSMRESULT stopObserveResource(IN ISSMResource *pSensor) = 0;
 };
 
-static const OID OID_IResourceConnectivity = { 0x8e42b098, 0x9aa5, 0x43f3, { 0x84, 0xa, 0x21, 0x44, 0xc9, 0x4c, 0xc7, 0x99 } };
-class IResourceConnectivity : public IBase
-{
-    public:
-        virtual void *getPlatform() = 0;
-};
-
 /**
 * @class    ISoftSensorManager
 * @brief    ISoftSensorManager Interface
index 531e1be..5e458e0 100644 (file)
 #include <map>
 #include <fstream>
 
-#define LOCATION_SSM_DB ":memory:"
-#define RAPIDXML_STATIC_POOL_SIZE 4*1024
-
 #if defined(WIN32)
+
 #include <Windows.h>
 #include <Shlwapi.h>
-
 #pragma comment(lib, "Shlwapi.lib")
 #pragma comment(lib, "../Outputs/sqlite3.lib")
 
 #elif defined(LINUX)
+
 #include <stdio.h>
 #include <errno.h>
 #include <sys/time.h>
 #include <dlfcn.h>
 #include <semaphore.h>
 
-#elif defined(ANDROID)
+#if defined(ANDROID)
+
 #include <android/log.h>
 
 #elif defined(TIZEN)
-#include <FBase.h>
 
 #endif
 
-#define DEFAULT_PATH_SOFT_SENSORS "SoftSensorDescription.xml"
+#endif
 
-//#define LOCATION_SSM_DB_DUMP "myBackup.db"
+
+#define LOCATION_SSM_DB ":memory:"
+#define RAPIDXML_STATIC_POOL_SIZE 4*1024
+#define DEFAULT_PATH_SOFT_SENSORS "SoftSensorDescription.xml"
 #define LOCATION_SSM_DB_DUMP ""
+//#define LOCATION_SSM_DB_DUMP "myBackup.db"
 
-#if defined(WIN32) || defined(LINUX)
 
-#define REPORT_MESSAGE(tag, msg) {printf("[%s] %s\n", tag, msg);}
+#if defined(WIN32)
 
-#define SSM_VOID_ASSERT(Exp, STRErrorMsg) \
-    { \
-    if(!(Exp)) \
-        { \
-        printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, STRErrorMsg); \
-        assert(0); \
-        return; \
-        } \
-    }
+#define PRINT_LOG(strError) printf("[SSM] %s:%d %s\n", __FUNCTION__, __LINE__, strError)
+#define REPORT_MESSAGE(tag, msg) printf("[%s] %s\n", tag, msg)
 
-#define SSM_RESULT_ASSERT(Exp, STRErrorMsg, Result) \
-    { \
-    if(!(Exp)) \
-        { \
-        printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, STRErrorMsg); \
-        assert(0); \
-        return Result; \
-        } \
-    }
+#elif defined(LINUX)
 
-#define SSM_CLEANUP_ASSERT(Exp) \
-    { \
-    if((res = (Exp)) != SSM_S_OK) \
-        { \
-        printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, GetSSMError(res)); \
-        assert(0); \
-        goto CLEANUP; \
-        } \
-    }
+#if defined(ANDROID)
 
-#define SSM_CLEANUP_COND_ASSERT(Exp, Cond, STRErrorMsg) \
-    { \
-    if(Exp != Cond) \
-        { \
-        printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, STRErrorMsg); \
-        assert(0); \
-        goto CLEANUP; \
-        } \
-    }
+void ReportMessage(const char *tag, const char *msg);
+#define REPORT_MESSAGE(tag, msg) ReportMessage(tag, msg)
+#define PRINT_LOG(strError) __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d %s", __PRETTY_FUNCTION__, __LINE__, strError)
 
-#define SSM_CLEANUP_NULL_ASSERT(Val) \
-    { \
-    if(!(Val)) \
-        { \
-        printf("[SSM] %s:%d Return message: NULL value\n", __FUNCTION__, __LINE__); \
-        assert(Val); \
-        goto CLEANUP; \
-        } \
-    }
+#elif defined(TIZEN)
 
-#elif defined(ANDROID)
+#define REPORT_MESSAGE(tag, msg) printf("[%s] %s\n", tag, msg)
+#define PRINT_LOG(strError) printf("[SSM] %s:%d %s\n", __FUNCTION__, __LINE__, strError)
 
-void ReportMessage(const char *tag, const char *msg);
-#define REPORT_MESSAGE(tag, msg) {ReportMessage(tag, msg);}
+#else //Default linux
 
-#define SSM_VOID_ASSERT(Exp, STRErrorMsg) \
-    { \
-        if(!(Exp)) \
-        { \
-            __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, STRErrorMsg); \
-            assert(0); \
-            return; \
-        } \
-    }
+#define REPORT_MESSAGE(tag, msg) printf("[%s] %s\n", tag, msg)
+#define PRINT_LOG(strError) printf("[SSM] %s:%d %s\n", __FUNCTION__, __LINE__, strError)
 
-#define SSM_RESULT_ASSERT(Exp, STRErrorMsg, Result) \
-    { \
-        if(!(Exp)) \
-        { \
-            __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, STRErrorMsg); \
-            assert(0); \
-            return Result; \
-        } \
-    }
-
-#define SSM_CLEANUP_ASSERT(Exp) \
-    { \
-        if((res = (Exp)) != SSM_S_OK) \
-        { \
-            __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, GetSSMError(res)); \
-            assert(0); \
-            goto CLEANUP; \
-        } \
-    }
+#endif
 
-#define SSM_CLEANUP_COND_ASSERT(Exp, Cond, STRErrorMsg) \
-    { \
-        if(Exp != Cond) \
-        { \
-            __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, STRErrorMsg); \
-            assert(0); \
-            goto CLEANUP; \
-        } \
-    }
+#endif
 
-#define SSM_CLEANUP_NULL_ASSERT(Val) \
-    { \
-        if(!(Val)) \
-        { \
-            __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: NULL value", __PRETTY_FUNCTION__, __LINE__); \
-            assert(Val); \
-            goto CLEANUP; \
-        } \
-    }
 
-#elif defined(TIZEN)
-#define REPORT_MESSAGE(tag, msg)
 
 #define SSM_VOID_ASSERT(Exp, STRErrorMsg) \
     { \
     if(!(Exp)) \
         { \
-        AppLog("%s", STRErrorMsg); \
+        PRINT_LOG(STRErrorMsg); \
         assert(0); \
         return; \
         } \
@@ -172,7 +92,7 @@ void ReportMessage(const char *tag, const char *msg);
     { \
     if(!(Exp)) \
         { \
-        AppLog("%s", STRErrorMsg); \
+        PRINT_LOG(STRErrorMsg); \
         assert(0); \
         return Result; \
         } \
@@ -182,7 +102,7 @@ void ReportMessage(const char *tag, const char *msg);
     { \
     if((res = (Exp)) != SSM_S_OK) \
         { \
-        AppLog("%s", GetSSMError(res)); \
+        PRINT_LOG(GetSSMError(res)); \
         assert(0); \
         goto CLEANUP; \
         } \
@@ -192,7 +112,7 @@ void ReportMessage(const char *tag, const char *msg);
     { \
     if(Exp != Cond) \
         { \
-        AppLog("%s", STRErrorMsg); \
+        PRINT_LOG(STRErrorMsg); \
         assert(0); \
         goto CLEANUP; \
         } \
@@ -202,14 +122,12 @@ void ReportMessage(const char *tag, const char *msg);
     { \
     if(!(Val)) \
         { \
-        AppLog("NULL value"); \
+        PRINT_LOG("NULL value"); \
         assert(Val); \
         goto CLEANUP; \
         } \
     }
 
-#endif
-
 #define CLEAN_STACKVARIABLE(val) memset(&val, 0, sizeof(val))
 #define SAFE_RELEASE(p) {if(p != NULL){p->release();p = NULL;}else{;/*NULL*/}}
 #define SAFE_DELETE(p) {if(p != NULL){delete p;p = NULL;}else{;/*NULL*/}}
index bb86402..4a8e050 100644 (file)
@@ -1,3 +1,22 @@
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed 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 "ThreadManager.h"
 
 CSimpleMutex::CSimpleMutex()
index e398838..d697b68 100644 (file)
@@ -135,8 +135,8 @@ extern "C" {
 ** function is provided for use in DLLs since DLL users usually do not have
 ** direct access to string constants within the DLL.  ^The
 ** sqlite3_libversion_number() function returns an integer equal to
-** [SQLITE_VERSION_NUMBER].  ^The sqlite3_sourceid() function returns 
-** a pointer to a string constant whose value is the same as the 
+** [SQLITE_VERSION_NUMBER].  ^The sqlite3_sourceid() function returns
+** a pointer to a string constant whose value is the same as the
 ** [SQLITE_SOURCE_ID] C preprocessor macro.
 **
 ** See also: [sqlite_version()] and [sqlite_source_id()].
@@ -149,20 +149,20 @@ SQLITE_API int sqlite3_libversion_number(void);
 /*
 ** CAPI3REF: Run-Time Library Compilation Options Diagnostics
 **
-** ^The sqlite3_compileoption_used() function returns 0 or 1 
-** indicating whether the specified option was defined at 
-** compile time.  ^The SQLITE_ prefix may be omitted from the 
-** option name passed to sqlite3_compileoption_used().  
+** ^The sqlite3_compileoption_used() function returns 0 or 1
+** indicating whether the specified option was defined at
+** compile time.  ^The SQLITE_ prefix may be omitted from the
+** option name passed to sqlite3_compileoption_used().
 **
 ** ^The sqlite3_compileoption_get() function allows iterating
 ** over the list of options that were defined at compile time by
 ** returning the N-th compile time option string.  ^If N is out of range,
-** sqlite3_compileoption_get() returns a NULL pointer.  ^The SQLITE_ 
-** prefix is omitted from any strings returned by 
+** sqlite3_compileoption_get() returns a NULL pointer.  ^The SQLITE_
+** prefix is omitted from any strings returned by
 ** sqlite3_compileoption_get().
 **
 ** ^Support for the diagnostic functions sqlite3_compileoption_used()
-** and sqlite3_compileoption_get() may be omitted by specifying the 
+** and sqlite3_compileoption_get() may be omitted by specifying the
 ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
 **
 ** See also: SQL functions [sqlite_compileoption_used()] and
@@ -183,7 +183,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N);
 ** SQLite can be compiled with or without mutexes.  When
 ** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
 ** are enabled and SQLite is threadsafe.  When the
-** [SQLITE_THREADSAFE] macro is 0, 
+** [SQLITE_THREADSAFE] macro is 0,
 ** the mutexes are omitted.  Without the mutexes, it is not safe
 ** to use SQLite concurrently from more than one thread.
 **
@@ -240,18 +240,18 @@ typedef struct sqlite3 sqlite3;
 **
 ** ^The sqlite3_int64 and sqlite_int64 types can store integer values
 ** between -9223372036854775808 and +9223372036854775807 inclusive.  ^The
-** sqlite3_uint64 and sqlite_uint64 types can store integer values 
+** sqlite3_uint64 and sqlite_uint64 types can store integer values
 ** between 0 and +18446744073709551615 inclusive.
 */
 #ifdef SQLITE_INT64_TYPE
-  typedef SQLITE_INT64_TYPE sqlite_int64;
-  typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+typedef SQLITE_INT64_TYPE sqlite_int64;
+typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
 #elif defined(_MSC_VER) || defined(__BORLANDC__)
-  typedef __int64 sqlite_int64;
-  typedef unsigned __int64 sqlite_uint64;
+typedef __int64 sqlite_int64;
+typedef unsigned __int64 sqlite_uint64;
 #else
-  typedef long long int sqlite_int64;
-  typedef unsigned long long int sqlite_uint64;
+typedef long long int sqlite_int64;
+typedef unsigned long long int sqlite_uint64;
 #endif
 typedef sqlite_int64 sqlite3_int64;
 typedef sqlite_uint64 sqlite3_uint64;
@@ -285,7 +285,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** destructors are called is arbitrary.
 **
 ** Applications should [sqlite3_finalize | finalize] all [prepared statements],
-** [sqlite3_blob_close | close] all [BLOB handles], and 
+** [sqlite3_blob_close | close] all [BLOB handles], and
 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
 ** sqlite3_close_v2() is called on a [database connection] that still has
@@ -305,15 +305,15 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
 ** argument is a harmless no-op.
 */
-SQLITE_API int sqlite3_close(sqlite3*);
-SQLITE_API int sqlite3_close_v2(sqlite3*);
+SQLITE_API int sqlite3_close(sqlite3 *);
+SQLITE_API int sqlite3_close_v2(sqlite3 *);
 
 /*
 ** The type for a callback function.
 ** This is legacy and deprecated.  It is included for historical
 ** compatibility and is not documented.
 */
-typedef int (*sqlite3_callback)(void*,int,char**, char**);
+typedef int (*sqlite3_callback)(void *, int, char **, char **);
 
 /*
 ** CAPI3REF: One-Step Query Execution Interface
@@ -321,7 +321,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** The sqlite3_exec() interface is a convenience wrapper around
 ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
 ** that allows an application to run multiple statements of SQL
-** without having to use a lot of C code. 
+** without having to use a lot of C code.
 **
 ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
 ** semicolon-separate SQL statements passed into its 2nd argument,
@@ -361,7 +361,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** from [sqlite3_column_name()].
 **
 ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
-** to an empty string, or a pointer that contains only whitespace and/or 
+** to an empty string, or a pointer that contains only whitespace and/or
 ** SQL comments, then no SQL statements are evaluated and the database
 ** is not changed.
 **
@@ -377,11 +377,11 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** </ul>
 */
 SQLITE_API int sqlite3_exec(
-  sqlite3*,                                  /* An open database */
-  const char *sql,                           /* SQL to be evaluated */
-  int (*callback)(void*,int,char**,char**),  /* Callback function */
-  void *,                                    /* 1st argument to callback */
-  char **errmsg                              /* Error msg written here */
+    sqlite3 *,                                 /* An open database */
+    const char *sql,                           /* SQL to be evaluated */
+    int (*callback)(void *, int, char **, char **), /* Callback function */
+    void *,                                    /* 1st argument to callback */
+    char **errmsg                              /* Error msg written here */
 );
 
 /*
@@ -614,7 +614,7 @@ SQLITE_API int sqlite3_exec(
 /*
 ** CAPI3REF: OS Interface Open File Handle
 **
-** An [sqlite3_file] object represents an open file in the 
+** An [sqlite3_file] object represents an open file in the
 ** [sqlite3_vfs | OS interface layer].  Individual OS interface
 ** implementations will
 ** want to subclass this object by appending additional fields
@@ -623,8 +623,9 @@ SQLITE_API int sqlite3_exec(
 ** I/O operations on the open file.
 */
 typedef struct sqlite3_file sqlite3_file;
-struct sqlite3_file {
-  const struct sqlite3_io_methods *pMethods;  /* Methods for an open file */
+struct sqlite3_file
+{
+    const struct sqlite3_io_methods *pMethods;  /* Methods for an open file */
 };
 
 /*
@@ -636,7 +637,7 @@ struct sqlite3_file {
 ** This object defines the methods used to perform various operations
 ** against the open file represented by the [sqlite3_file] object.
 **
-** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element 
+** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
 ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
 ** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed.  The
 ** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
@@ -718,30 +719,31 @@ struct sqlite3_file {
 ** database corruption.
 */
 typedef struct sqlite3_io_methods sqlite3_io_methods;
-struct sqlite3_io_methods {
-  int iVersion;
-  int (*xClose)(sqlite3_file*);
-  int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-  int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
-  int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
-  int (*xSync)(sqlite3_file*, int flags);
-  int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
-  int (*xLock)(sqlite3_file*, int);
-  int (*xUnlock)(sqlite3_file*, int);
-  int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
-  int (*xFileControl)(sqlite3_file*, int op, void *pArg);
-  int (*xSectorSize)(sqlite3_file*);
-  int (*xDeviceCharacteristics)(sqlite3_file*);
-  /* Methods above are valid for version 1 */
-  int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
-  int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
-  void (*xShmBarrier)(sqlite3_file*);
-  int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
-  /* Methods above are valid for version 2 */
-  int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
-  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
-  /* Methods above are valid for version 3 */
-  /* Additional methods may be added in future releases */
+struct sqlite3_io_methods
+{
+    int iVersion;
+    int (*xClose)(sqlite3_file *);
+    int (*xRead)(sqlite3_file *, void *, int iAmt, sqlite3_int64 iOfst);
+    int (*xWrite)(sqlite3_file *, const void *, int iAmt, sqlite3_int64 iOfst);
+    int (*xTruncate)(sqlite3_file *, sqlite3_int64 size);
+    int (*xSync)(sqlite3_file *, int flags);
+    int (*xFileSize)(sqlite3_file *, sqlite3_int64 *pSize);
+    int (*xLock)(sqlite3_file *, int);
+    int (*xUnlock)(sqlite3_file *, int);
+    int (*xCheckReservedLock)(sqlite3_file *, int *pResOut);
+    int (*xFileControl)(sqlite3_file *, int op, void *pArg);
+    int (*xSectorSize)(sqlite3_file *);
+    int (*xDeviceCharacteristics)(sqlite3_file *);
+    /* Methods above are valid for version 1 */
+    int (*xShmMap)(sqlite3_file *, int iPg, int pgsz, int, void volatile **);
+    int (*xShmLock)(sqlite3_file *, int offset, int n, int flags);
+    void (*xShmBarrier)(sqlite3_file *);
+    int (*xShmUnmap)(sqlite3_file *, int deleteFlag);
+    /* Methods above are valid for version 2 */
+    int (*xFetch)(sqlite3_file *, sqlite3_int64 iOfst, int iAmt, void **pp);
+    int (*xUnfetch)(sqlite3_file *, sqlite3_int64 iOfst, void *p);
+    /* Methods above are valid for version 3 */
+    /* Additional methods may be added in future releases */
 };
 
 /*
@@ -770,7 +772,7 @@ struct sqlite3_io_methods {
 ** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
 ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
 ** extends and truncates the database file in chunks of a size specified
-** by the user. The fourth argument to [sqlite3_file_control()] should 
+** by the user. The fourth argument to [sqlite3_file_control()] should
 ** point to an integer (type int) containing the new chunk-size to use
 ** for the nominated database. Allocating database file space in large
 ** chunks (say 1MB at a time), may reduce file-system fragmentation and
@@ -787,11 +789,11 @@ struct sqlite3_io_methods {
 ** SQLite and sent to all VFSes in place of a call to the xSync method
 ** when the database connection has [PRAGMA synchronous] set to OFF.)^
 ** Some specialized VFSes need this signal in order to operate correctly
-** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
+** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
 ** VFSes do not need this signal and should silently ignore this opcode.
 ** Applications should not call [sqlite3_file_control()] with this
 ** opcode as doing so may disrupt the operation of the specialized VFSes
-** that do require it.  
+** that do require it.
 **
 ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
@@ -838,13 +840,13 @@ struct sqlite3_io_methods {
 ** <li>[[SQLITE_FCNTL_OVERWRITE]]
 ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
 ** a write transaction to indicate that, unless it is rolled back for some
-** reason, the entire database file will be overwritten by the current 
+** reason, the entire database file will be overwritten by the current
 ** transaction. This is used by VACUUM operations.
 **
 ** <li>[[SQLITE_FCNTL_VFSNAME]]
 ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
 ** all [VFSes] in the VFS stack.  The names are of all VFS shims and the
-** final bottom-level VFS are written into memory obtained from 
+** final bottom-level VFS are written into memory obtained from
 ** [sqlite3_malloc()] and the result is stored in the char* variable
 ** that the fourth parameter of [sqlite3_file_control()] points to.
 ** The caller is responsible for freeing the memory when done.  As with
@@ -854,7 +856,7 @@ struct sqlite3_io_methods {
 ** is intended for diagnostic use only.
 **
 ** <li>[[SQLITE_FCNTL_PRAGMA]]
-** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] 
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
 ** file control is sent to the open [sqlite3_file] object corresponding
 ** to the database file to which the pragma statement refers. ^The argument
 ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
@@ -865,7 +867,7 @@ struct sqlite3_io_methods {
 ** of the char** argument point to a string obtained from [sqlite3_mprintf()]
 ** or the equivalent and that string will become the result of the pragma or
 ** the error message if the pragma fails. ^If the
-** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal 
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
 ** [PRAGMA] processing continues.  ^If the [SQLITE_FCNTL_PRAGMA]
 ** file control returns [SQLITE_OK], then the parser assumes that the
 ** VFS has handled the PRAGMA itself and the parser generates a no-op
@@ -903,7 +905,7 @@ struct sqlite3_io_methods {
 ** The argument is a pointer to a value of type sqlite3_int64 that
 ** is an advisory maximum number of bytes in the file to memory map.  The
 ** pointer is overwritten with the old value.  The limit is not changed if
-** the value originally pointed to is negative, and so the current limit 
+** the value originally pointed to is negative, and so the current limit
 ** can be queried by passing in a pointer to a negative number.  This
 ** file-control is used internally to implement [PRAGMA mmap_size].
 **
@@ -987,14 +989,14 @@ typedef struct sqlite3_mutex sqlite3_mutex;
 ** the [sqlite3_file] can safely store a pointer to the
 ** filename if it needs to remember the filename for some reason.
 ** If the zFilename parameter to xOpen is a NULL pointer then xOpen
-** must invent its own temporary name for the file.  ^Whenever the 
+** must invent its own temporary name for the file.  ^Whenever the
 ** xFilename parameter is NULL it will also be the case that the
 ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
 **
 ** The flags argument to xOpen() includes all bits set in
 ** the flags argument to [sqlite3_open_v2()].  Or if [sqlite3_open()]
 ** or [sqlite3_open16()] is used, then flags includes at least
-** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. 
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
 ** If xOpen() opens a file read-only then it sets *pOutFlags to
 ** include [SQLITE_OPEN_READONLY].  Other bits in *pOutFlags may be set.
 **
@@ -1036,10 +1038,10 @@ typedef struct sqlite3_mutex sqlite3_mutex;
 ** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
 ** with the [SQLITE_OPEN_CREATE] flag, which are both directly
 ** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
-** API.  The SQLITE_OPEN_EXCLUSIVE flag, when paired with the 
+** API.  The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
 ** SQLITE_OPEN_CREATE, is used to indicate that file should always
 ** be created, and that it is an error if it already exists.
-** It is <i>not</i> used to indicate the file should be opened 
+** It is <i>not</i> used to indicate the file should be opened
 ** for exclusive access.
 **
 ** ^At least szOsFile bytes of memory are allocated by SQLite
@@ -1077,16 +1079,16 @@ typedef struct sqlite3_mutex sqlite3_mutex;
 ** method returns a Julian Day Number for the current date and time as
 ** a floating point value.
 ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
-** Day Number multiplied by 86400000 (the number of milliseconds in 
-** a 24-hour day).  
+** Day Number multiplied by 86400000 (the number of milliseconds in
+** a 24-hour day).
 ** ^SQLite will use the xCurrentTimeInt64() method to get the current
-** date and time if that method is available (if iVersion is 2 or 
+** date and time if that method is available (if iVersion is 2 or
 ** greater and the function pointer is not NULL) and will fall back
 ** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
 **
 ** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
 ** are not used by the SQLite core.  These optional interfaces are provided
-** by some VFSes to facilitate testing of the VFS code. By overriding 
+** by some VFSes to facilitate testing of the VFS code. By overriding
 ** system calls with functions under its control, a test program can
 ** simulate faults and error conditions that would otherwise be difficult
 ** or impossible to induce.  The set of system calls that can be overridden
@@ -1098,43 +1100,44 @@ typedef struct sqlite3_mutex sqlite3_mutex;
 */
 typedef struct sqlite3_vfs sqlite3_vfs;
 typedef void (*sqlite3_syscall_ptr)(void);
-struct sqlite3_vfs {
-  int iVersion;            /* Structure version number (currently 3) */
-  int szOsFile;            /* Size of subclassed sqlite3_file */
-  int mxPathname;          /* Maximum file pathname length */
-  sqlite3_vfs *pNext;      /* Next registered VFS */
-  const char *zName;       /* Name of this virtual file system */
-  void *pAppData;          /* Pointer to application-specific data */
-  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
-               int flags, int *pOutFlags);
-  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
-  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
-  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
-  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
-  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
-  void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
-  void (*xDlClose)(sqlite3_vfs*, void*);
-  int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
-  int (*xSleep)(sqlite3_vfs*, int microseconds);
-  int (*xCurrentTime)(sqlite3_vfs*, double*);
-  int (*xGetLastError)(sqlite3_vfs*, int, char *);
-  /*
-  ** The methods above are in version 1 of the sqlite_vfs object
-  ** definition.  Those that follow are added in version 2 or later
-  */
-  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
-  /*
-  ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
-  ** Those below are for version 3 and greater.
-  */
-  int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
-  sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
-  const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
-  /*
-  ** The methods above are in versions 1 through 3 of the sqlite_vfs object.
-  ** New fields may be appended in figure versions.  The iVersion
-  ** value will increment whenever this happens. 
-  */
+struct sqlite3_vfs
+{
+    int iVersion;            /* Structure version number (currently 3) */
+    int szOsFile;            /* Size of subclassed sqlite3_file */
+    int mxPathname;          /* Maximum file pathname length */
+    sqlite3_vfs *pNext;      /* Next registered VFS */
+    const char *zName;       /* Name of this virtual file system */
+    void *pAppData;          /* Pointer to application-specific data */
+    int (*xOpen)(sqlite3_vfs *, const char *zName, sqlite3_file *,
+                 int flags, int *pOutFlags);
+    int (*xDelete)(sqlite3_vfs *, const char *zName, int syncDir);
+    int (*xAccess)(sqlite3_vfs *, const char *zName, int flags, int *pResOut);
+    int (*xFullPathname)(sqlite3_vfs *, const char *zName, int nOut, char *zOut);
+    void *(*xDlOpen)(sqlite3_vfs *, const char *zFilename);
+    void (*xDlError)(sqlite3_vfs *, int nByte, char *zErrMsg);
+    void (*(*xDlSym)(sqlite3_vfs *, void *, const char *zSymbol))(void);
+    void (*xDlClose)(sqlite3_vfs *, void *);
+    int (*xRandomness)(sqlite3_vfs *, int nByte, char *zOut);
+    int (*xSleep)(sqlite3_vfs *, int microseconds);
+    int (*xCurrentTime)(sqlite3_vfs *, double *);
+    int (*xGetLastError)(sqlite3_vfs *, int, char *);
+    /*
+    ** The methods above are in version 1 of the sqlite_vfs object
+    ** definition.  Those that follow are added in version 2 or later
+    */
+    int (*xCurrentTimeInt64)(sqlite3_vfs *, sqlite3_int64 *);
+    /*
+    ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
+    ** Those below are for version 3 and greater.
+    */
+    int (*xSetSystemCall)(sqlite3_vfs *, const char *zName, sqlite3_syscall_ptr);
+    sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs *, const char *zName);
+    const char *(*xNextSystemCall)(sqlite3_vfs *, const char *zName);
+    /*
+    ** The methods above are in versions 1 through 3 of the sqlite_vfs object.
+    ** New fields may be appended in figure versions.  The iVersion
+    ** value will increment whenever this happens.
+    */
 };
 
 /*
@@ -1177,7 +1180,7 @@ struct sqlite3_vfs {
 ** </ul>
 **
 ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
-** was given no the corresponding lock.  
+** was given no the corresponding lock.
 **
 ** The xShmLock method can transition between unlocked and SHARED or
 ** between unlocked and EXCLUSIVE.  It cannot transition between SHARED
@@ -1319,14 +1322,14 @@ SQLITE_API int sqlite3_config(int, ...);
 ** [database connection] (specified in the first argument).
 **
 ** The second argument to sqlite3_db_config(D,V,...)  is the
-** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code 
+** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
 ** that indicates what aspect of the [database connection] is being configured.
 ** Subsequent arguments vary depending on the configuration verb.
 **
 ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
 ** the call is considered successful.
 */
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API int sqlite3_db_config(sqlite3 *, int op, ...);
 
 /*
 ** CAPI3REF: Memory Allocation Routines
@@ -1337,7 +1340,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
 ** This object is used in only one place in the SQLite interface.
 ** A pointer to an instance of this object is the argument to
 ** [sqlite3_config()] when the configuration option is
-** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].  
+** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
 ** By creating an instance of this object
 ** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
 ** during configuration, an application can specify an alternative
@@ -1367,7 +1370,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
 ** allocators round up memory allocations at least to the next multiple
 ** of 8.  Some allocators round up to a larger multiple or to a power of 2.
 ** Every memory allocation request coming in through [sqlite3_malloc()]
-** or [sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0, 
+** or [sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0,
 ** that causes the corresponding memory allocation to fail.
 **
 ** The xInit method initializes the memory allocator.  (For example,
@@ -1392,15 +1395,16 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
 ** call to xShutdown().
 */
 typedef struct sqlite3_mem_methods sqlite3_mem_methods;
-struct sqlite3_mem_methods {
-  void *(*xMalloc)(int);         /* Memory allocation function */
-  void (*xFree)(void*);          /* Free a prior allocation */
-  void *(*xRealloc)(void*,int);  /* Resize an allocation */
-  int (*xSize)(void*);           /* Return the size of an allocation */
-  int (*xRoundup)(int);          /* Round up request size to allocation size */
-  int (*xInit)(void*);           /* Initialize the memory allocator */
-  void (*xShutdown)(void*);      /* Deinitialize the memory allocator */
-  void *pAppData;                /* Argument to xInit() and xShutdown() */
+struct sqlite3_mem_methods
+{
+    void *(*xMalloc)(int);         /* Memory allocation function */
+    void (*xFree)(void *);         /* Free a prior allocation */
+    void *(*xRealloc)(void *, int); /* Resize an allocation */
+    int (*xSize)(void *);          /* Return the size of an allocation */
+    int (*xRoundup)(int);          /* Round up request size to allocation size */
+    int (*xInit)(void *);          /* Initialize the memory allocator */
+    void (*xShutdown)(void *);     /* Deinitialize the memory allocator */
+    void *pAppData;                /* Argument to xInit() and xShutdown() */
 };
 
 /*
@@ -1425,7 +1429,7 @@ struct sqlite3_mem_methods {
 ** by a single thread.   ^If SQLite is compiled with
 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
 ** it is not possible to change the [threading mode] from its default
-** value of Single-thread and so [sqlite3_config()] will return 
+** value of Single-thread and so [sqlite3_config()] will return
 ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
 ** configuration option.</dd>
 **
@@ -1476,9 +1480,9 @@ struct sqlite3_mem_methods {
 ** tracks memory usage, for example. </dd>
 **
 ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
-** <dd> ^This option takes single argument of type int, interpreted as a 
-** boolean, which enables or disables the collection of memory allocation 
-** statistics. ^(When memory allocation statistics are disabled, the 
+** <dd> ^This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. ^(When memory allocation statistics are disabled, the
 ** following SQLite interfaces become non-operational:
 **   <ul>
 **   <li> [sqlite3_memory_used()]
@@ -1504,12 +1508,12 @@ struct sqlite3_mem_methods {
 ** N should be set to twice the expected maximum number of threads.
 ** ^SQLite will never require a scratch buffer that is more than 6
 ** times the database page size. ^If SQLite needs needs additional
-** scratch memory beyond what is provided by this configuration option, then 
+** scratch memory beyond what is provided by this configuration option, then
 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
 **
 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
-** the database page cache with the default page cache implementation.  
+** the database page cache with the default page cache implementation.
 ** This configuration should not be used if an application-define page
 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
 ** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1595,7 +1599,7 @@ struct sqlite3_mem_methods {
 ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
 ** global [error log].
 ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
-** function with a call signature of void(*)(void*,int,const char*), 
+** function with a call signature of void(*)(void*,int,const char*),
 ** and a pointer to void. ^If the function pointer is not NULL, it is
 ** invoked by [sqlite3_log()] to process each logging event.  ^If the
 ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1669,7 +1673,7 @@ struct sqlite3_mem_methods {
 ** [SQLITE_FCNTL_MMAP_SIZE] file control.  The maximum allowed mmap size
 ** cannot be changed at run-time.  Nor may the maximum allowed mmap size
 ** exceed the compile-time maximum mmap size set by the
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.  
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.
 ** If either argument to this option is negative, then that argument is
 ** changed to its compile-time default.
 ** </dl>
@@ -1685,7 +1689,7 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
 #define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
 #define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
+/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
 #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
 #define SQLITE_CONFIG_PCACHE       14  /* no-op */
 #define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
@@ -1712,7 +1716,7 @@ struct sqlite3_mem_methods {
 **
 ** <dl>
 ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
-** <dd> ^This option takes three additional arguments that determine the 
+** <dd> ^This option takes three additional arguments that determine the
 ** [lookaside memory allocator] configuration for the [database connection].
 ** ^The first argument (the third parameter to [sqlite3_db_config()] is a
 ** pointer to a memory buffer to use for lookaside memory.
@@ -1730,7 +1734,7 @@ struct sqlite3_mem_methods {
 ** when the "current value" returned by
 ** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.
 ** Any attempt to change the lookaside memory configuration when lookaside
-** memory is in use leaves the configuration unchanged and returns 
+** memory is in use leaves the configuration unchanged and returns
 ** [SQLITE_BUSY].)^</dd>
 **
 ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
@@ -1767,7 +1771,7 @@ struct sqlite3_mem_methods {
 ** [extended result codes] feature of SQLite. ^The extended result
 ** codes are disabled by default for historical compatibility.
 */
-SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
+SQLITE_API int sqlite3_extended_result_codes(sqlite3 *, int onoff);
 
 /*
 ** CAPI3REF: Last Insert Rowid
@@ -1789,7 +1793,7 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
 ** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
 ** method, then this routine will return the [rowid] of the inserted
 ** row as long as the trigger or virtual table method is running.
-** But once the trigger or virtual table method ends, the value returned 
+** But once the trigger or virtual table method ends, the value returned
 ** by this routine reverts to what it was before the trigger or virtual
 ** table method began.)^
 **
@@ -1816,7 +1820,7 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
 ** unpredictable and might not equal either the old or the new
 ** last insert [rowid].
 */
-SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3 *);
 
 /*
 ** CAPI3REF: Count The Number Of Rows Modified
@@ -1840,7 +1844,7 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
 ** mechanisms do not count as direct row changes.)^
 **
 ** A "trigger context" is a scope of execution that begins and
-** ends with the script of a [CREATE TRIGGER | trigger]. 
+** ends with the script of a [CREATE TRIGGER | trigger].
 ** Most SQL statements are
 ** evaluated outside of any trigger.  This is the "top level"
 ** trigger context.  If a trigger fires from the top level, a
@@ -1870,7 +1874,7 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
 ** while [sqlite3_changes()] is running then the value returned
 ** is unpredictable and not meaningful.
 */
-SQLITE_API int sqlite3_changes(sqlite3*);
+SQLITE_API int sqlite3_changes(sqlite3 *);
 
 /*
 ** CAPI3REF: Total Number Of Rows Modified
@@ -1883,7 +1887,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
 ** the count does not include changes used to implement [REPLACE] constraints,
 ** do rollbacks or ABORT processing, or [DROP TABLE] processing.  The
 ** count does not include rows of views that fire an [INSTEAD OF trigger],
-** though if the INSTEAD OF trigger makes changes of its own, those changes 
+** though if the INSTEAD OF trigger makes changes of its own, those changes
 ** are counted.)^
 ** ^The sqlite3_total_changes() function counts the changes as soon as
 ** the statement that makes them is completed (when the statement handle
@@ -1896,7 +1900,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
 ** while [sqlite3_total_changes()] is running then the value
 ** returned is unpredictable and not meaningful.
 */
-SQLITE_API int sqlite3_total_changes(sqlite3*);
+SQLITE_API int sqlite3_total_changes(sqlite3 *);
 
 /*
 ** CAPI3REF: Interrupt A Long-Running Query
@@ -1923,7 +1927,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
 **
 ** ^The sqlite3_interrupt(D) call is in effect until all currently running
 ** SQL statements on [database connection] D complete.  ^Any new SQL statements
-** that are started after the sqlite3_interrupt() call and before the 
+** that are started after the sqlite3_interrupt() call and before the
 ** running statements reaches zero are interrupted as if they had been
 ** running prior to the sqlite3_interrupt() call.  ^New SQL statements
 ** that are started after the running statement count reaches zero are
@@ -1935,7 +1939,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
 ** If the database connection closes while [sqlite3_interrupt()]
 ** is running then bad things will likely happen.
 */
-SQLITE_API void sqlite3_interrupt(sqlite3*);
+SQLITE_API void sqlite3_interrupt(sqlite3 *);
 
 /*
 ** CAPI3REF: Determine If An SQL Statement Is Complete
@@ -1958,7 +1962,7 @@ SQLITE_API void sqlite3_interrupt(sqlite3*);
 ** ^These routines do not parse the SQL statements thus
 ** will not detect syntactically incorrect SQL.
 **
-** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior 
+** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
 ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
 ** automatically by sqlite3_complete16().  If that initialization fails,
 ** then the return value from sqlite3_complete16() will be non-zero
@@ -2033,11 +2037,11 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 ** The busy callback should not take any actions which modify the
 ** database connection that invoked the busy handler.  Any such actions
 ** result in undefined behavior.
-** 
+**
 ** A busy handler must not close the database connection
 ** or [prepared statement] that invoked the busy handler.
 */
-SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+SQLITE_API int sqlite3_busy_handler(sqlite3 *, int(*)(void *, int), void *);
 
 /*
 ** CAPI3REF: Set A Busy Timeout
@@ -2057,7 +2061,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** was defined  (using [sqlite3_busy_handler()]) prior to calling
 ** this routine, that other busy handler is cleared.)^
 */
-SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+SQLITE_API int sqlite3_busy_timeout(sqlite3 *, int ms);
 
 /*
 ** CAPI3REF: Convenience Routines For Running Queries
@@ -2132,12 +2136,12 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
 ** [sqlite3_errmsg()].
 */
 SQLITE_API int sqlite3_get_table(
-  sqlite3 *db,          /* An open database */
-  const char *zSql,     /* SQL to be evaluated */
-  char ***pazResult,    /* Results of the query */
-  int *pnRow,           /* Number of result rows written here */
-  int *pnColumn,        /* Number of result columns written here */
-  char **pzErrmsg       /* Error msg written here */
+    sqlite3 *db,          /* An open database */
+    const char *zSql,     /* SQL to be evaluated */
+    char ***pazResult,    /* Results of the query */
+    int *pnRow,           /* Number of result rows written here */
+    int *pnColumn,        /* Number of result columns written here */
+    char **pzErrmsg       /* Error msg written here */
 );
 SQLITE_API void sqlite3_free_table(char **result);
 
@@ -2235,10 +2239,10 @@ SQLITE_API void sqlite3_free_table(char **result);
 ** addition that after the string has been read and copied into
 ** the result, [sqlite3_free()] is called on the input string.)^
 */
-SQLITE_API char *sqlite3_mprintf(const char*,...);
-SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
-SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
-SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+SQLITE_API char *sqlite3_mprintf(const char *, ...);
+SQLITE_API char *sqlite3_vmprintf(const char *, va_list);
+SQLITE_API char *sqlite3_snprintf(int, char *, const char *, ...);
+SQLITE_API char *sqlite3_vsnprintf(int, char *, const char *, va_list);
 
 /*
 ** CAPI3REF: Memory Allocation Subsystem
@@ -2311,8 +2315,8 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
 ** [sqlite3_free()] or [sqlite3_realloc()].
 */
 SQLITE_API void *sqlite3_malloc(int);
-SQLITE_API void *sqlite3_realloc(void*, int);
-SQLITE_API void sqlite3_free(void*);
+SQLITE_API void *sqlite3_realloc(void *, int);
+SQLITE_API void sqlite3_free(void *);
 
 /*
 ** CAPI3REF: Memory Allocator Statistics
@@ -2383,7 +2387,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
 ** requested is ok.  ^When the callback returns [SQLITE_DENY], the
 ** [sqlite3_prepare_v2()] or equivalent call that triggered the
 ** authorizer will fail with an error message explaining that
-** access is denied. 
+** access is denied.
 **
 ** ^The first parameter to the authorizer callback is a copy of the third
 ** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
@@ -2430,7 +2434,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
 ** database connections for the meaning of "modify" in this paragraph.
 **
 ** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
-** statement might be re-prepared during [sqlite3_step()] due to a 
+** statement might be re-prepared during [sqlite3_step()] due to a
 ** schema change.  Hence, the application should ensure that the
 ** correct authorizer callback remains in place during the [sqlite3_step()].
 **
@@ -2441,9 +2445,9 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
 ** sqlite3_prepare_v2() to reprepare a statement after a schema change.
 */
 SQLITE_API int sqlite3_set_authorizer(
-  sqlite3*,
-  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
-  void *pUserData
+    sqlite3 *,
+    int (*xAuth)(void *, int, const char *, const char *, const char *, const char *),
+    void *pUserData
 );
 
 /*
@@ -2543,9 +2547,9 @@ SQLITE_API int sqlite3_set_authorizer(
 ** sqlite3_profile() function is considered experimental and is
 ** subject to change in future versions of SQLite.
 */
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
-   void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
+SQLITE_API void *sqlite3_trace(sqlite3 *, void(*xTrace)(void *, const char *), void *);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3 *,
+        void(*xProfile)(void *, const char *, sqlite3_uint64), void *);
 
 /*
 ** CAPI3REF: Query Progress Callbacks
@@ -2556,8 +2560,8 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
 ** database connection D.  An example use for this
 ** interface is to keep a GUI updated during a large query.
 **
-** ^The parameter P is passed through as the only parameter to the 
-** callback function X.  ^The parameter N is the number of 
+** ^The parameter P is passed through as the only parameter to the
+** callback function X.  ^The parameter N is the number of
 ** [virtual machine instructions] that are evaluated between successive
 ** invocations of the callback X.
 **
@@ -2577,12 +2581,12 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
 ** database connections for the meaning of "modify" in this paragraph.
 **
 */
-SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+SQLITE_API void sqlite3_progress_handler(sqlite3 *, int, int(*)(void *), void *);
 
 /*
 ** CAPI3REF: Opening A New Database Connection
 **
-** ^These routines open an SQLite database file as specified by the 
+** ^These routines open an SQLite database file as specified by the
 ** filename argument. ^The filename argument is interpreted as UTF-8 for
 ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
 ** order for sqlite3_open16(). ^(A [database connection] handle is usually
@@ -2607,7 +2611,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** except that it accepts two additional parameters for additional control
 ** over the new database connection.  ^(The flags parameter to
 ** sqlite3_open_v2() can take one of
-** the following three values, optionally combined with the 
+** the following three values, optionally combined with the
 ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
 ** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
 **
@@ -2675,17 +2679,17 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** information.
 **
 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
-** authority, then it must be either an empty string or the string 
-** "localhost". ^If the authority is not an empty string or "localhost", an 
-** error is returned to the caller. ^The fragment component of a URI, if 
+** authority, then it must be either an empty string or the string
+** "localhost". ^If the authority is not an empty string or "localhost", an
+** error is returned to the caller. ^The fragment component of a URI, if
 ** present, is ignored.
 **
 ** ^SQLite uses the path component of the URI as the name of the disk file
-** which contains the database. ^If the path begins with a '/' character, 
-** then it is interpreted as an absolute path. ^If the path does not begin 
+** which contains the database. ^If the path begins with a '/' character,
+** then it is interpreted as an absolute path. ^If the path does not begin
 ** with a '/' (meaning that the authority section is omitted from the URI)
-** then the path is interpreted as a relative path. 
-** ^On windows, the first component of an absolute path 
+** then the path is interpreted as a relative path.
+** ^On windows, the first component of an absolute path
 ** is a drive specification (e.g. "C:").
 **
 ** [[core URI query parameters]]
@@ -2704,13 +2708,13 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **
 **   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
 **     "rwc", or "memory". Attempting to set it to any other value is
-**     an error)^. 
-**     ^If "ro" is specified, then the database is opened for read-only 
-**     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
-**     third argument to sqlite3_open_v2(). ^If the mode option is set to 
-**     "rw", then the database is opened for read-write (but not create) 
-**     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
-**     been set. ^Value "rwc" is equivalent to setting both 
+**     an error)^.
+**     ^If "ro" is specified, then the database is opened for read-only
+**     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
+**     third argument to sqlite3_open_v2(). ^If the mode option is set to
+**     "rw", then the database is opened for read-write (but not create)
+**     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
+**     been set. ^Value "rwc" is equivalent to setting both
 **     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.  ^If the mode option is
 **     set to "memory" then a pure [in-memory database] that never reads
 **     or writes from disk is used. ^It is an error to specify a value for
@@ -2720,7 +2724,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
 **     "private". ^Setting it to "shared" is equivalent to setting the
 **     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
-**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
+**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is
 **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
 **     a URI filename, its value overrides any behavior requested by setting
@@ -2736,35 +2740,35 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **
 ** <table border="1" align=center cellpadding=5>
 ** <tr><th> URI filenames <th> Results
-** <tr><td> file:data.db <td> 
+** <tr><td> file:data.db <td>
 **          Open the file "data.db" in the current directory.
 ** <tr><td> file:/home/fred/data.db<br>
-**          file:///home/fred/data.db <br> 
-**          file://localhost/home/fred/data.db <br> <td> 
+**          file:///home/fred/data.db <br>
+**          file://localhost/home/fred/data.db <br> <td>
 **          Open the database file "/home/fred/data.db".
-** <tr><td> file://darkstar/home/fred/data.db <td> 
+** <tr><td> file://darkstar/home/fred/data.db <td>
 **          An error. "darkstar" is not a recognized authority.
-** <tr><td style="white-space:nowrap"> 
+** <tr><td style="white-space:nowrap">
 **          file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
 **     <td> Windows only: Open the file "data.db" on fred's desktop on drive
-**          C:. Note that the %20 escaping in this example is not strictly 
+**          C:. Note that the %20 escaping in this example is not strictly
 **          necessary - space characters can be used literally
 **          in URI filenames.
-** <tr><td> file:data.db?mode=ro&cache=private <td> 
+** <tr><td> file:data.db?mode=ro&cache=private <td>
 **          Open file "data.db" in the current directory for read-only access.
 **          Regardless of whether or not shared-cache mode is enabled by
 **          default, use a private cache.
 ** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
 **          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
-** <tr><td> file:data.db?mode=readonly <td> 
+** <tr><td> file:data.db?mode=readonly <td>
 **          An error. "readonly" is not a valid option for the "mode" parameter.
 ** </table>
 **
 ** ^URI hexadecimal escape sequences (%HH) are supported within the path and
 ** query components of a URI. A hexadecimal escape sequence consists of a
-** percent sign - "%" - followed by exactly two hexadecimal digits 
+** percent sign - "%" - followed by exactly two hexadecimal digits
 ** specifying an octet value. ^Before the path or query components of a
-** URI filename are interpreted, they are encoded using UTF-8 and all 
+** URI filename are interpreted, they are encoded using UTF-8 and all
 ** hexadecimal escape sequences replaced by a single byte containing the
 ** corresponding octet. If this process generates an invalid UTF-8 encoding,
 ** the results are undefined.
@@ -2782,33 +2786,33 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** See also: [sqlite3_temp_directory]
 */
 SQLITE_API int sqlite3_open(
-  const char *filename,   /* Database filename (UTF-8) */
-  sqlite3 **ppDb          /* OUT: SQLite db handle */
+    const char *filename,   /* Database filename (UTF-8) */
+    sqlite3 **ppDb          /* OUT: SQLite db handle */
 );
 SQLITE_API int sqlite3_open16(
-  const void *filename,   /* Database filename (UTF-16) */
-  sqlite3 **ppDb          /* OUT: SQLite db handle */
+    const void *filename,   /* Database filename (UTF-16) */
+    sqlite3 **ppDb          /* OUT: SQLite db handle */
 );
 SQLITE_API int sqlite3_open_v2(
-  const char *filename,   /* Database filename (UTF-8) */
-  sqlite3 **ppDb,         /* OUT: SQLite db handle */
-  int flags,              /* Flags */
-  const char *zVfs        /* Name of VFS module to use */
+    const char *filename,   /* Database filename (UTF-8) */
+    sqlite3 **ppDb,         /* OUT: SQLite db handle */
+    int flags,              /* Flags */
+    const char *zVfs        /* Name of VFS module to use */
 );
 
 /*
 ** CAPI3REF: Obtain Values For URI Parameters
 **
 ** These are utility routines, useful to VFS implementations, that check
-** to see if a database file was a URI that contained a specific query 
+** to see if a database file was a URI that contained a specific query
 ** parameter, and if so obtains the value of that query parameter.
 **
-** If F is the database filename pointer passed into the xOpen() method of 
-** a VFS implementation when the flags parameter to xOpen() has one or 
+** If F is the database filename pointer passed into the xOpen() method of
+** a VFS implementation when the flags parameter to xOpen() has one or
 ** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
 ** P is the name of the query parameter, then
 ** sqlite3_uri_parameter(F,P) returns the value of the P
-** parameter if it exists or a NULL pointer if P does not appear as a 
+** parameter if it exists or a NULL pointer if P does not appear as a
 ** query parameter on F.  If P is a query parameter of F
 ** has no explicit value, then sqlite3_uri_parameter(F,P) returns
 ** a pointer to an empty string.
@@ -2817,7 +2821,7 @@ SQLITE_API int sqlite3_open_v2(
 ** parameter and returns true (1) or false (0) according to the value
 ** of P.  The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
 ** value of query parameter P is one of "yes", "true", or "on" in any
-** case or if the value begins with a non-zero number.  The 
+** case or if the value begins with a non-zero number.  The
 ** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
 ** query parameter P is one of "no", "false", or "off" in any case or
 ** if the value begins with a numeric zero.  If P is not a query
@@ -2828,7 +2832,7 @@ SQLITE_API int sqlite3_open_v2(
 ** 64-bit signed integer and returns that integer, or D if P does not
 ** exist.  If the value of P is something other than an integer, then
 ** zero is returned.
-** 
+**
 ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
 ** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
 ** is not a database file pathname pointer that SQLite passed into the xOpen
@@ -2837,7 +2841,7 @@ SQLITE_API int sqlite3_open_v2(
 */
 SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
 SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char *, const char *, sqlite3_int64);
 
 
 /*
@@ -2848,7 +2852,7 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
 ** associated with a [database connection]. If a prior API call failed
 ** but the most recent API call succeeded, the return value from
 ** sqlite3_errcode() is undefined.  ^The sqlite3_extended_errcode()
-** interface is the same except that it always returns the 
+** interface is the same except that it always returns the
 ** [extended result code] even when extended result codes are
 ** disabled.
 **
@@ -2880,8 +2884,8 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
 */
 SQLITE_API int sqlite3_errcode(sqlite3 *db);
 SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
-SQLITE_API const char *sqlite3_errmsg(sqlite3*);
-SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errmsg(sqlite3 *);
+SQLITE_API const void *sqlite3_errmsg16(sqlite3 *);
 SQLITE_API const char *sqlite3_errstr(int);
 
 /*
@@ -2921,7 +2925,7 @@ typedef struct sqlite3_stmt sqlite3_stmt;
 ** new limit for that construct.)^
 **
 ** ^If the new limit is a negative number, the limit is unchanged.
-** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a 
+** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
 ** [limits | hard upper bound]
 ** set at compile-time by a C preprocessor macro called
 ** [limits | SQLITE_MAX_<i>NAME</i>].
@@ -2929,7 +2933,7 @@ typedef struct sqlite3_stmt sqlite3_stmt;
 ** ^Attempts to increase a limit above its hard upper bound are
 ** silently truncated to the hard upper bound.
 **
-** ^Regardless of whether or not the limit was changed, the 
+** ^Regardless of whether or not the limit was changed, the
 ** [sqlite3_limit()] interface returns the prior value of the limit.
 ** ^Hence, to find the current value of a limit without changing it,
 ** simply invoke this interface with the third parameter set to -1.
@@ -2949,7 +2953,7 @@ typedef struct sqlite3_stmt sqlite3_stmt;
 **
 ** New run-time limit categories may be added in future releases.
 */
-SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+SQLITE_API int sqlite3_limit(sqlite3 *, int id, int newVal);
 
 /*
 ** CAPI3REF: Run-Time Limit Categories
@@ -3084,46 +3088,46 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** </li>
 **
 ** <li>
-** ^If the specific value bound to [parameter | host parameter] in the 
+** ^If the specific value bound to [parameter | host parameter] in the
 ** WHERE clause might influence the choice of query plan for a statement,
-** then the statement will be automatically recompiled, as if there had been 
+** then the statement will be automatically recompiled, as if there had been
 ** a schema change, on the first  [sqlite3_step()] call following any change
-** to the [sqlite3_bind_text | bindings] of that [parameter]. 
-** ^The specific value of WHERE-clause [parameter] might influence the 
+** to the [sqlite3_bind_text | bindings] of that [parameter].
+** ^The specific value of WHERE-clause [parameter] might influence the
 ** choice of query plan if the parameter is the left-hand side of a [LIKE]
 ** or [GLOB] operator or if the parameter is compared to an indexed column
 ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
-** the 
+** the
 ** </li>
 ** </ol>
 */
 SQLITE_API int sqlite3_prepare(
-  sqlite3 *db,            /* Database handle */
-  const char *zSql,       /* SQL statement, UTF-8 encoded */
-  int nByte,              /* Maximum length of zSql in bytes. */
-  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
-  const char **pzTail     /* OUT: Pointer to unused portion of zSql */
+    sqlite3 *db,            /* Database handle */
+    const char *zSql,       /* SQL statement, UTF-8 encoded */
+    int nByte,              /* Maximum length of zSql in bytes. */
+    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
+    const char **pzTail     /* OUT: Pointer to unused portion of zSql */
 );
 SQLITE_API int sqlite3_prepare_v2(
-  sqlite3 *db,            /* Database handle */
-  const char *zSql,       /* SQL statement, UTF-8 encoded */
-  int nByte,              /* Maximum length of zSql in bytes. */
-  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
-  const char **pzTail     /* OUT: Pointer to unused portion of zSql */
+    sqlite3 *db,            /* Database handle */
+    const char *zSql,       /* SQL statement, UTF-8 encoded */
+    int nByte,              /* Maximum length of zSql in bytes. */
+    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
+    const char **pzTail     /* OUT: Pointer to unused portion of zSql */
 );
 SQLITE_API int sqlite3_prepare16(
-  sqlite3 *db,            /* Database handle */
-  const void *zSql,       /* SQL statement, UTF-16 encoded */
-  int nByte,              /* Maximum length of zSql in bytes. */
-  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
-  const void **pzTail     /* OUT: Pointer to unused portion of zSql */
+    sqlite3 *db,            /* Database handle */
+    const void *zSql,       /* SQL statement, UTF-16 encoded */
+    int nByte,              /* Maximum length of zSql in bytes. */
+    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
+    const void **pzTail     /* OUT: Pointer to unused portion of zSql */
 );
 SQLITE_API int sqlite3_prepare16_v2(
-  sqlite3 *db,            /* Database handle */
-  const void *zSql,       /* SQL statement, UTF-16 encoded */
-  int nByte,              /* Maximum length of zSql in bytes. */
-  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
-  const void **pzTail     /* OUT: Pointer to unused portion of zSql */
+    sqlite3 *db,            /* Database handle */
+    const void *zSql,       /* SQL statement, UTF-16 encoded */
+    int nByte,              /* Maximum length of zSql in bytes. */
+    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
+    const void **pzTail     /* OUT: Pointer to unused portion of zSql */
 );
 
 /*
@@ -3143,8 +3147,8 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
 ** the content of the database file.
 **
 ** Note that [application-defined SQL functions] or
-** [virtual tables] might change the database indirectly as a side effect.  
-** ^(For example, if an application defines a function "eval()" that 
+** [virtual tables] might change the database indirectly as a side effect.
+** ^(For example, if an application defines a function "eval()" that
 ** calls [sqlite3_exec()], then the following SQL statement would
 ** change the database file through side-effects:
 **
@@ -3158,10 +3162,10 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
 ** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
 ** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
 ** since the statements themselves do not actually modify the database but
-** rather they control the timing of when other statements modify the 
+** rather they control the timing of when other statements modify the
 ** database.  ^The [ATTACH] and [DETACH] statements also cause
 ** sqlite3_stmt_readonly() to return true since, while those statements
-** change the configuration of a database connection, they do not make 
+** change the configuration of a database connection, they do not make
 ** changes to the content of the database files on disk.
 */
 SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -3170,20 +3174,20 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
 ** CAPI3REF: Determine If A Prepared Statement Has Been Reset
 **
 ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
-** [prepared statement] S has been stepped at least once using 
-** [sqlite3_step(S)] but has not run to completion and/or has not 
+** [prepared statement] S has been stepped at least once using
+** [sqlite3_step(S)] but has not run to completion and/or has not
 ** been reset using [sqlite3_reset(S)].  ^The sqlite3_stmt_busy(S)
-** interface returns false if S is a NULL pointer.  If S is not a 
+** interface returns false if S is a NULL pointer.  If S is not a
 ** NULL pointer and is not a pointer to a valid [prepared statement]
 ** object, then the behavior is undefined and probably undesirable.
 **
 ** This interface can be used in combination [sqlite3_next_stmt()]
-** to locate all prepared statements associated with a database 
+** to locate all prepared statements associated with a database
 ** connection that are in need of being reset.  This can be used,
-** for example, in diagnostic routines to search for prepared 
+** for example, in diagnostic routines to search for prepared
 ** statements that are holding a transaction open.
 */
-SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
+SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *);
 
 /*
 ** CAPI3REF: Dynamically Typed Value Object
@@ -3205,7 +3209,7 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
 ** sqlite3_value object but no mutex is held for an unprotected
 ** sqlite3_value object.  If SQLite is compiled to be single-threaded
 ** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
-** or if SQLite is run in one of reduced mutex modes 
+** or if SQLite is run in one of reduced mutex modes
 ** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
 ** then there is no distinction between protected and unprotected
 ** sqlite3_value objects and they can be used interchangeably.  However,
@@ -3290,7 +3294,7 @@ typedef struct sqlite3_context sqlite3_context;
 ** If a non-negative fourth parameter is provided to sqlite3_bind_text()
 ** or sqlite3_bind_text16() then that parameter must be the byte offset
 ** where the NUL terminator would occur assuming the string were NUL
-** terminated.  If any NUL characters occur at byte offsets less than 
+** terminated.  If any NUL characters occur at byte offsets less than
 ** the value of the fourth parameter then the resulting string value will
 ** contain embedded NULs.  The result of expressions involving strings
 ** with embedded NULs is undefined.
@@ -3299,7 +3303,7 @@ typedef struct sqlite3_context sqlite3_context;
 ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
 ** string after SQLite has finished with it.  ^The destructor is called
 ** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
-** sqlite3_bind_text(), or sqlite3_bind_text16() fails.  
+** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
 ** ^If the fifth argument is
 ** the special value [SQLITE_STATIC], then SQLite assumes that the
 ** information is in static, unmanaged space and does not need to be freed.
@@ -3333,15 +3337,15 @@ typedef struct sqlite3_context sqlite3_context;
 ** See also: [sqlite3_bind_parameter_count()],
 ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
 */
-SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
-SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
-SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
-SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
-SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
-SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
-SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+SQLITE_API int sqlite3_bind_blob(sqlite3_stmt *, int, const void *, int n, void(*)(void *));
+SQLITE_API int sqlite3_bind_double(sqlite3_stmt *, int, double);
+SQLITE_API int sqlite3_bind_int(sqlite3_stmt *, int, int);
+SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *, int, sqlite3_int64);
+SQLITE_API int sqlite3_bind_null(sqlite3_stmt *, int);
+SQLITE_API int sqlite3_bind_text(sqlite3_stmt *, int, const char *, int n, void(*)(void *));
+SQLITE_API int sqlite3_bind_text16(sqlite3_stmt *, int, const void *, int, void(*)(void *));
+SQLITE_API int sqlite3_bind_value(sqlite3_stmt *, int, const sqlite3_value *);
+SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *, int, int n);
 
 /*
 ** CAPI3REF: Number Of SQL Parameters
@@ -3361,7 +3365,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
 ** [sqlite3_bind_parameter_name()], and
 ** [sqlite3_bind_parameter_index()].
 */
-SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
+SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *);
 
 /*
 ** CAPI3REF: Name Of A Host Parameter
@@ -3388,7 +3392,7 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
 ** [sqlite3_bind_parameter_count()], and
 ** [sqlite3_bind_parameter_index()].
 */
-SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *, int);
 
 /*
 ** CAPI3REF: Index Of A Parameter With A Given Name
@@ -3404,7 +3408,7 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
 ** [sqlite3_bind_parameter_count()], and
 ** [sqlite3_bind_parameter_index()].
 */
-SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *, const char *zName);
 
 /*
 ** CAPI3REF: Reset All Bindings On A Prepared Statement
@@ -3413,7 +3417,7 @@ SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
 ** the [sqlite3_bind_blob | bindings] on a [prepared statement].
 ** ^Use this routine to reset all host parameters to NULL.
 */
-SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
+SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *);
 
 /*
 ** CAPI3REF: Number Of Columns In A Result Set
@@ -3452,8 +3456,8 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
 ** then the name of the column is unspecified and may change from
 ** one release of SQLite to the next.
 */
-SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
-SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *, int N);
+SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *, int N);
 
 /*
 ** CAPI3REF: Source Of Data In A Query Result
@@ -3500,12 +3504,12 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
 ** for the same [prepared statement] and result column
 ** at the same time then the results are undefined.
 */
-SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *, int);
+SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *, int);
+SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *, int);
 
 /*
 ** CAPI3REF: Declared Datatype Of A Query Result
@@ -3536,8 +3540,8 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
 ** is associated with individual values, not with the containers
 ** used to hold those values.
 */
-SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *, int);
 
 /*
 ** CAPI3REF: Evaluate An SQL Statement
@@ -3595,7 +3599,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
 ** For all versions of SQLite up to and including 3.6.23.1, a call to
 ** [sqlite3_reset()] was required after sqlite3_step() returned anything
 ** other than [SQLITE_ROW] before any subsequent invocation of
-** sqlite3_step().  Failure to reset the prepared statement using 
+** sqlite3_step().  Failure to reset the prepared statement using
 ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
 ** sqlite3_step().  But after version 3.6.23.1, sqlite3_step() began
 ** calling [sqlite3_reset()] automatically in this circumstance rather
@@ -3616,7 +3620,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
 ** then the more specific [error codes] are returned directly
 ** by sqlite3_step().  The use of the "v2" interface is recommended.
 */
-SQLITE_API int sqlite3_step(sqlite3_stmt*);
+SQLITE_API int sqlite3_step(sqlite3_stmt *);
 
 /*
 ** CAPI3REF: Number of columns in a result set
@@ -3725,7 +3729,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 ** the number of bytes in that string.
 ** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
 **
-** ^The values returned by [sqlite3_column_bytes()] and 
+** ^The values returned by [sqlite3_column_bytes()] and
 ** [sqlite3_column_bytes16()] do not include the zero terminators at the end
 ** of the string.  ^For clarity: the values returned by
 ** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
@@ -3832,16 +3836,16 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 ** pointer.  Subsequent calls to [sqlite3_errcode()] will return
 ** [SQLITE_NOMEM].)^
 */
-SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
-SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *, int iCol);
+SQLITE_API double sqlite3_column_double(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_int(sqlite3_stmt *, int iCol);
+SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt *, int iCol);
+SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *, int iCol);
+SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_type(sqlite3_stmt *, int iCol);
+SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *, int iCol);
 
 /*
 ** CAPI3REF: Destroy A Prepared Statement Object
@@ -3918,7 +3922,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 ** ^The second parameter is the name of the SQL function to be created or
 ** redefined.  ^The length of the name is limited to 255 bytes in a UTF-8
 ** representation, exclusive of the zero-terminator.  ^Note that the name
-** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.  
+** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
 ** ^Any attempt to create a function with a longer name
 ** will result in [SQLITE_MISUSE] being returned.
 **
@@ -3955,13 +3959,13 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 ** callbacks.
 **
 ** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
-** then it is destructor for the application data pointer. 
+** then it is destructor for the application data pointer.
 ** The destructor is invoked when the function is deleted, either by being
 ** overloaded or when the database connection closes.)^
 ** ^The destructor is also invoked if the call to
 ** sqlite3_create_function_v2() fails.
 ** ^When the destructor callback of the tenth parameter is invoked, it
-** is passed a single argument which is a copy of the application data 
+** is passed a single argument which is a copy of the application data
 ** pointer which was the fifth parameter to sqlite3_create_function_v2().
 **
 ** ^It is permitted to register multiple implementations of the same
@@ -3972,7 +3976,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 ** nArg parameter is a better match than a function implementation with
 ** a negative nArg.  ^A function where the preferred text encoding
 ** matches the database encoding is a better
-** match than a function where the encoding is different.  
+** match than a function where the encoding is different.
 ** ^A function where the encoding difference is between UTF16le and UTF16be
 ** is a closer match than a function where the encoding difference is
 ** between UTF8 and UTF16.
@@ -3985,35 +3989,35 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 ** statement in which the function is running.
 */
 SQLITE_API int sqlite3_create_function(
-  sqlite3 *db,
-  const char *zFunctionName,
-  int nArg,
-  int eTextRep,
-  void *pApp,
-  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
-  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
-  void (*xFinal)(sqlite3_context*)
+    sqlite3 *db,
+    const char *zFunctionName,
+    int nArg,
+    int eTextRep,
+    void *pApp,
+    void (*xFunc)(sqlite3_context *, int, sqlite3_value **),
+    void (*xStep)(sqlite3_context *, int, sqlite3_value **),
+    void (*xFinal)(sqlite3_context *)
 );
 SQLITE_API int sqlite3_create_function16(
-  sqlite3 *db,
-  const void *zFunctionName,
-  int nArg,
-  int eTextRep,
-  void *pApp,
-  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
-  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
-  void (*xFinal)(sqlite3_context*)
+    sqlite3 *db,
+    const void *zFunctionName,
+    int nArg,
+    int eTextRep,
+    void *pApp,
+    void (*xFunc)(sqlite3_context *, int, sqlite3_value **),
+    void (*xStep)(sqlite3_context *, int, sqlite3_value **),
+    void (*xFinal)(sqlite3_context *)
 );
 SQLITE_API int sqlite3_create_function_v2(
-  sqlite3 *db,
-  const char *zFunctionName,
-  int nArg,
-  int eTextRep,
-  void *pApp,
-  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
-  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
-  void (*xFinal)(sqlite3_context*),
-  void(*xDestroy)(void*)
+    sqlite3 *db,
+    const char *zFunctionName,
+    int nArg,
+    int eTextRep,
+    void *pApp,
+    void (*xFunc)(sqlite3_context *, int, sqlite3_value **),
+    void (*xStep)(sqlite3_context *, int, sqlite3_value **),
+    void (*xFinal)(sqlite3_context *),
+    void(*xDestroy)(void *)
 );
 
 /*
@@ -4034,19 +4038,19 @@ SQLITE_API int sqlite3_create_function_v2(
 ** DEPRECATED
 **
 ** These functions are [deprecated].  In order to maintain
-** backwards compatibility with older code, these functions continue 
+** backwards compatibility with older code, these functions continue
 ** to be supported.  However, new applications should avoid
 ** the use of these functions.  To help encourage people to avoid
 ** using these functions, we are not going to tell you what they do.
 */
 #ifndef SQLITE_OMIT_DEPRECATED
-SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context *);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt *);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt *, sqlite3_stmt *);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
 SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
-                      void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void *, sqlite3_int64, int),
+        void *, sqlite3_int64);
 #endif
 
 /*
@@ -4094,18 +4098,18 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
 ** These routines must be called from the same thread as
 ** the SQL function that supplied the [sqlite3_value*] parameters.
 */
-SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
-SQLITE_API double sqlite3_value_double(sqlite3_value*);
-SQLITE_API int sqlite3_value_int(sqlite3_value*);
-SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
-SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
-SQLITE_API int sqlite3_value_type(sqlite3_value*);
-SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_blob(sqlite3_value *);
+SQLITE_API int sqlite3_value_bytes(sqlite3_value *);
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value *);
+SQLITE_API double sqlite3_value_double(sqlite3_value *);
+SQLITE_API int sqlite3_value_int(sqlite3_value *);
+SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value *);
+SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *);
+SQLITE_API const void *sqlite3_value_text16(sqlite3_value *);
+SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *);
+SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *);
+SQLITE_API int sqlite3_value_type(sqlite3_value *);
+SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *);
 
 /*
 ** CAPI3REF: Obtain Aggregate Function Context
@@ -4113,7 +4117,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** Implementations of aggregate SQL functions use this
 ** routine to allocate memory for storing their state.
 **
-** ^The first time the sqlite3_aggregate_context(C,N) routine is called 
+** ^The first time the sqlite3_aggregate_context(C,N) routine is called
 ** for a particular aggregate function, SQLite
 ** allocates N of memory, zeroes out that memory, and returns a pointer
 ** to the new memory. ^On second and subsequent calls to
@@ -4126,7 +4130,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** In those cases, sqlite3_aggregate_context() might be called for the
 ** first time from within xFinal().)^
 **
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
 ** when first called if N is less than or equal to zero or if a memory
 ** allocate error occurs.
 **
@@ -4135,10 +4139,10 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** value of N in subsequent call to sqlite3_aggregate_context() within
 ** the same aggregate function instance will not resize the memory
 ** allocation.)^  Within the xFinal callback, it is customary to set
-** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
 ** pointless memory allocations occur.
 **
-** ^SQLite automatically frees the memory allocated by 
+** ^SQLite automatically frees the memory allocated by
 ** sqlite3_aggregate_context() when the aggregate query concludes.
 **
 ** The first parameter must be a copy of the
@@ -4149,7 +4153,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** This routine must be called from the same thread in which
 ** the aggregate SQL function is running.
 */
-SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *, int nBytes);
 
 /*
 ** CAPI3REF: User Data For Functions
@@ -4163,7 +4167,7 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
 ** This routine must be called from the same thread in which
 ** the application-defined function is running.
 */
-SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+SQLITE_API void *sqlite3_user_data(sqlite3_context *);
 
 /*
 ** CAPI3REF: Database Connection For Functions
@@ -4174,7 +4178,7 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context*);
 ** and [sqlite3_create_function16()] routines that originally
 ** registered the application defined function.
 */
-SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *);
 
 /*
 ** CAPI3REF: Function Auxiliary Data
@@ -4218,8 +4222,8 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
 ** These routines must be called from the same thread in which
 ** the SQL function is running.
 */
-SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
-SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *, int N);
+SQLITE_API void sqlite3_set_auxdata(sqlite3_context *, int N, void *, void (*)(void *));
 
 
 /*
@@ -4236,7 +4240,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
 ** The typedef is necessary to work around problems in certain
 ** C++ compilers.
 */
-typedef void (*sqlite3_destructor_type)(void*);
+typedef void (*sqlite3_destructor_type)(void *);
 #define SQLITE_STATIC      ((sqlite3_destructor_type)0)
 #define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)
 
@@ -4350,22 +4354,22 @@ typedef void (*sqlite3_destructor_type)(void*);
 ** than the one containing the application-defined function that received
 ** the [sqlite3_context] pointer, the results are undefined.
 */
-SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
-SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
-SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
-SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
-SQLITE_API void sqlite3_result_null(sqlite3_context*);
-SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
+SQLITE_API void sqlite3_result_blob(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_double(sqlite3_context *, double);
+SQLITE_API void sqlite3_result_error(sqlite3_context *, const char *, int);
+SQLITE_API void sqlite3_result_error16(sqlite3_context *, const void *, int);
+SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *);
+SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *);
+SQLITE_API void sqlite3_result_error_code(sqlite3_context *, int);
+SQLITE_API void sqlite3_result_int(sqlite3_context *, int);
+SQLITE_API void sqlite3_result_int64(sqlite3_context *, sqlite3_int64);
+SQLITE_API void sqlite3_result_null(sqlite3_context *);
+SQLITE_API void sqlite3_result_text(sqlite3_context *, const char *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_text16(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_text16le(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_text16be(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_value(sqlite3_context *, sqlite3_value *);
+SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *, int n);
 
 /*
 ** CAPI3REF: Define New Collating Sequences
@@ -4405,7 +4409,7 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
 ** deleted.  ^When all collating functions having the same name are deleted,
 ** that collation is no longer usable.
 **
-** ^The collating function callback is invoked with a copy of the pArg 
+** ^The collating function callback is invoked with a copy of the pArg
 ** application data pointer and with two strings in the encoding specified
 ** by the eTextRep argument.  The collating function must return an
 ** integer that is negative, zero, or positive
@@ -4435,38 +4439,38 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
 ** calls to the collation creation functions or when the
 ** [database connection] is closed using [sqlite3_close()].
 **
-** ^The xDestroy callback is <u>not</u> called if the 
+** ^The xDestroy callback is <u>not</u> called if the
 ** sqlite3_create_collation_v2() function fails.  Applications that invoke
-** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should 
+** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
 ** check the return code and dispose of the application data pointer
 ** themselves rather than expecting SQLite to deal with it for them.
-** This is different from every other SQLite interface.  The inconsistency 
-** is unfortunate but cannot be changed without breaking backwards 
+** This is different from every other SQLite interface.  The inconsistency
+** is unfortunate but cannot be changed without breaking backwards
 ** compatibility.
 **
 ** See also:  [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
 */
 SQLITE_API int sqlite3_create_collation(
-  sqlite3*, 
-  const char *zName, 
-  int eTextRep, 
-  void *pArg,
-  int(*xCompare)(void*,int,const void*,int,const void*)
+    sqlite3 *,
+    const char *zName,
+    int eTextRep,
+    void *pArg,
+    int(*xCompare)(void *, int, const void *, int, const void *)
 );
 SQLITE_API int sqlite3_create_collation_v2(
-  sqlite3*, 
-  const char *zName, 
-  int eTextRep, 
-  void *pArg,
-  int(*xCompare)(void*,int,const void*,int,const void*),
-  void(*xDestroy)(void*)
+    sqlite3 *,
+    const char *zName,
+    int eTextRep,
+    void *pArg,
+    int(*xCompare)(void *, int, const void *, int, const void *),
+    void(*xDestroy)(void *)
 );
 SQLITE_API int sqlite3_create_collation16(
-  sqlite3*, 
-  const void *zName,
-  int eTextRep, 
-  void *pArg,
-  int(*xCompare)(void*,int,const void*,int,const void*)
+    sqlite3 *,
+    const void *zName,
+    int eTextRep,
+    void *pArg,
+    int(*xCompare)(void *, int, const void *, int, const void *)
 );
 
 /*
@@ -4496,14 +4500,14 @@ SQLITE_API int sqlite3_create_collation16(
 ** [sqlite3_create_collation_v2()].
 */
 SQLITE_API int sqlite3_collation_needed(
-  sqlite3*, 
-  void*, 
-  void(*)(void*,sqlite3*,int eTextRep,const char*)
+    sqlite3 *,
+    void *,
+    void(*)(void *, sqlite3 *, int eTextRep, const char *)
 );
 SQLITE_API int sqlite3_collation_needed16(
-  sqlite3*, 
-  void*,
-  void(*)(void*,sqlite3*,int eTextRep,const void*)
+    sqlite3 *,
+    void *,
+    void(*)(void *, sqlite3 *, int eTextRep, const void *)
 );
 
 #ifdef SQLITE_HAS_CODEC
@@ -4515,8 +4519,8 @@ SQLITE_API int sqlite3_collation_needed16(
 ** of SQLite.
 */
 SQLITE_API int sqlite3_key(
-  sqlite3 *db,                   /* Database to be rekeyed */
-  const void *pKey, int nKey     /* The key */
+    sqlite3 *db,                   /* Database to be rekeyed */
+    const void *pKey, int nKey     /* The key */
 );
 
 /*
@@ -4528,26 +4532,26 @@ SQLITE_API int sqlite3_key(
 ** of SQLite.
 */
 SQLITE_API int sqlite3_rekey(
-  sqlite3 *db,                   /* Database to be rekeyed */
-  const void *pKey, int nKey     /* The new key */
+    sqlite3 *db,                   /* Database to be rekeyed */
+    const void *pKey, int nKey     /* The new key */
 );
 
 /*
-** Specify the activation key for a SEE database.  Unless 
+** Specify the activation key for a SEE database.  Unless
 ** activated, none of the SEE routines will work.
 */
 SQLITE_API void sqlite3_activate_see(
-  const char *zPassPhrase        /* Activation phrase */
+    const char *zPassPhrase        /* Activation phrase */
 );
 #endif
 
 #ifdef SQLITE_ENABLE_CEROD
 /*
-** Specify the activation key for a CEROD database.  Unless 
+** Specify the activation key for a CEROD database.  Unless
 ** activated, none of the CEROD routines will work.
 */
 SQLITE_API void sqlite3_activate_cerod(
-  const char *zPassPhrase        /* Activation phrase */
+    const char *zPassPhrase        /* Activation phrase */
 );
 #endif
 
@@ -4592,7 +4596,7 @@ SQLITE_API int sqlite3_sleep(int);
 ** ^The [temp_store_directory pragma] may modify this variable and cause
 ** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
 ** the [temp_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from 
+** that this variable points to is held in memory obtained from
 ** [sqlite3_malloc] and the pragma may attempt to free that memory
 ** using [sqlite3_free].
 ** Hence, if this variable is modified directly, either it should be
@@ -4644,7 +4648,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory;
 ** ^The [data_store_directory pragma] may modify this variable and cause
 ** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
 ** the [data_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from 
+** that this variable points to is held in memory obtained from
 ** [sqlite3_malloc] and the pragma may attempt to free that memory
 ** using [sqlite3_free].
 ** Hence, if this variable is modified directly, either it should be
@@ -4674,7 +4678,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
 ** connection while this routine is running, then the return value
 ** is undefined.
 */
-SQLITE_API int sqlite3_get_autocommit(sqlite3*);
+SQLITE_API int sqlite3_get_autocommit(sqlite3 *);
 
 /*
 ** CAPI3REF: Find The Database Handle Of A Prepared Statement
@@ -4686,7 +4690,7 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*);
 ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
 ** create the statement in the first place.
 */
-SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *);
 
 /*
 ** CAPI3REF: Return The Filename For A Database Connection
@@ -4774,8 +4778,8 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
 **
 ** See also the [sqlite3_update_hook()] interface.
 */
-SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
-SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+SQLITE_API void *sqlite3_commit_hook(sqlite3 *, int(*)(void *), void *);
+SQLITE_API void *sqlite3_rollback_hook(sqlite3 *, void(*)(void *), void *);
 
 /*
 ** CAPI3REF: Data Change Notification Callbacks
@@ -4824,9 +4828,9 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 ** interfaces.
 */
 SQLITE_API void *sqlite3_update_hook(
-  sqlite3*, 
-  void(*)(void *,int ,char const *,char const *,sqlite3_int64),
-  void*
+    sqlite3 *,
+    void(*)(void *, int , char const *, char const *, sqlite3_int64),
+    void *
 );
 
 /*
@@ -4887,7 +4891,7 @@ SQLITE_API int sqlite3_release_memory(int);
 **
 ** See also: [sqlite3_release_memory()]
 */
-SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+SQLITE_API int sqlite3_db_release_memory(sqlite3 *);
 
 /*
 ** CAPI3REF: Impose A Limit On Heap Size
@@ -4899,7 +4903,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
 ** as heap memory usages approaches the limit.
 ** ^The soft heap limit is "soft" because even though SQLite strives to stay
 ** below the limit, it will exceed the limit rather than generate
-** an [SQLITE_NOMEM] error.  In other words, the soft heap limit 
+** an [SQLITE_NOMEM] error.  In other words, the soft heap limit
 ** is advisory only.
 **
 ** ^The return value from sqlite3_soft_heap_limit64() is the size of
@@ -5016,15 +5020,15 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
 ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
 */
 SQLITE_API int sqlite3_table_column_metadata(
-  sqlite3 *db,                /* Connection handle */
-  const char *zDbName,        /* Database name or NULL */
-  const char *zTableName,     /* Table name */
-  const char *zColumnName,    /* Column name */
-  char const **pzDataType,    /* OUTPUT: Declared data type */
-  char const **pzCollSeq,     /* OUTPUT: Collation sequence name */
-  int *pNotNull,              /* OUTPUT: True if NOT NULL constraint exists */
-  int *pPrimaryKey,           /* OUTPUT: True if column part of PK */
-  int *pAutoinc               /* OUTPUT: True if column is auto-increment */
+    sqlite3 *db,                /* Connection handle */
+    const char *zDbName,        /* Database name or NULL */
+    const char *zTableName,     /* Table name */
+    const char *zColumnName,    /* Column name */
+    char const **pzDataType,    /* OUTPUT: Declared data type */
+    char const **pzCollSeq,     /* OUTPUT: Collation sequence name */
+    int *pNotNull,              /* OUTPUT: True if NOT NULL constraint exists */
+    int *pPrimaryKey,           /* OUTPUT: True if column part of PK */
+    int *pAutoinc               /* OUTPUT: True if column is auto-increment */
 );
 
 /*
@@ -5062,10 +5066,10 @@ SQLITE_API int sqlite3_table_column_metadata(
 ** See also the [load_extension() SQL function].
 */
 SQLITE_API int sqlite3_load_extension(
-  sqlite3 *db,          /* Load the extension into this database connection */
-  const char *zFile,    /* Name of the shared library containing extension */
-  const char *zProc,    /* Entry point.  Derived from zFile if 0 */
-  char **pzErrMsg       /* Put error message here if not 0 */
+    sqlite3 *db,          /* Load the extension into this database connection */
+    const char *zFile,    /* Name of the shared library containing extension */
+    const char *zProc,    /* Entry point.  Derived from zFile if 0 */
+    char **pzErrMsg       /* Put error message here if not 0 */
 );
 
 /*
@@ -5149,8 +5153,8 @@ typedef struct sqlite3_module sqlite3_module;
 ** CAPI3REF: Virtual Table Object
 ** KEYWORDS: sqlite3_module {virtual table module}
 **
-** This structure, sometimes called a "virtual table module", 
-** defines the implementation of a [virtual tables].  
+** This structure, sometimes called a "virtual table module",
+** defines the implementation of a [virtual tables].
 ** This structure consists mostly of methods for the module.
 **
 ** ^A virtual table module is created by filling in a persistent
@@ -5161,39 +5165,40 @@ typedef struct sqlite3_module sqlite3_module;
 ** of this structure must not change while it is registered with
 ** any database connection.
 */
-struct sqlite3_module {
-  int iVersion;
-  int (*xCreate)(sqlite3*, void *pAux,
-               int argc, const char *const*argv,
-               sqlite3_vtab **ppVTab, char**);
-  int (*xConnect)(sqlite3*, void *pAux,
-               int argc, const char *const*argv,
-               sqlite3_vtab **ppVTab, char**);
-  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
-  int (*xDisconnect)(sqlite3_vtab *pVTab);
-  int (*xDestroy)(sqlite3_vtab *pVTab);
-  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
-  int (*xClose)(sqlite3_vtab_cursor*);
-  int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
-                int argc, sqlite3_value **argv);
-  int (*xNext)(sqlite3_vtab_cursor*);
-  int (*xEof)(sqlite3_vtab_cursor*);
-  int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
-  int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
-  int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
-  int (*xBegin)(sqlite3_vtab *pVTab);
-  int (*xSync)(sqlite3_vtab *pVTab);
-  int (*xCommit)(sqlite3_vtab *pVTab);
-  int (*xRollback)(sqlite3_vtab *pVTab);
-  int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
-                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
-                       void **ppArg);
-  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
-  /* The methods above are in version 1 of the sqlite_module object. Those 
-  ** below are for version 2 and greater. */
-  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
-  int (*xRelease)(sqlite3_vtab *pVTab, int);
-  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+struct sqlite3_module
+{
+    int iVersion;
+    int (*xCreate)(sqlite3 *, void *pAux,
+                   int argc, const char *const *argv,
+                   sqlite3_vtab **ppVTab, char **);
+    int (*xConnect)(sqlite3 *, void *pAux,
+                    int argc, const char *const *argv,
+                    sqlite3_vtab **ppVTab, char **);
+    int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info *);
+    int (*xDisconnect)(sqlite3_vtab *pVTab);
+    int (*xDestroy)(sqlite3_vtab *pVTab);
+    int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+    int (*xClose)(sqlite3_vtab_cursor *);
+    int (*xFilter)(sqlite3_vtab_cursor *, int idxNum, const char *idxStr,
+                   int argc, sqlite3_value **argv);
+    int (*xNext)(sqlite3_vtab_cursor *);
+    int (*xEof)(sqlite3_vtab_cursor *);
+    int (*xColumn)(sqlite3_vtab_cursor *, sqlite3_context *, int);
+    int (*xRowid)(sqlite3_vtab_cursor *, sqlite3_int64 *pRowid);
+    int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
+    int (*xBegin)(sqlite3_vtab *pVTab);
+    int (*xSync)(sqlite3_vtab *pVTab);
+    int (*xCommit)(sqlite3_vtab *pVTab);
+    int (*xRollback)(sqlite3_vtab *pVTab);
+    int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+                         void (**pxFunc)(sqlite3_context *, int, sqlite3_value **),
+                         void **ppArg);
+    int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+    /* The methods above are in version 1 of the sqlite_module object. Those
+    ** below are for version 2 and greater. */
+    int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+    int (*xRelease)(sqlite3_vtab *pVTab, int);
+    int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
 };
 
 /*
@@ -5249,30 +5254,34 @@ struct sqlite3_module {
 ** a cost of N.  A binary search of a table of N entries should have a
 ** cost of approximately log(N).
 */
-struct sqlite3_index_info {
-  /* Inputs */
-  int nConstraint;           /* Number of entries in aConstraint */
-  struct sqlite3_index_constraint {
-     int iColumn;              /* Column on left-hand side of constraint */
-     unsigned char op;         /* Constraint operator */
-     unsigned char usable;     /* True if this constraint is usable */
-     int iTermOffset;          /* Used internally - xBestIndex should ignore */
-  } *aConstraint;            /* Table of WHERE clause constraints */
-  int nOrderBy;              /* Number of terms in the ORDER BY clause */
-  struct sqlite3_index_orderby {
-     int iColumn;              /* Column number */
-     unsigned char desc;       /* True for DESC.  False for ASC. */
-  } *aOrderBy;               /* The ORDER BY clause */
-  /* Outputs */
-  struct sqlite3_index_constraint_usage {
-    int argvIndex;           /* if >0, constraint is part of argv to xFilter */
-    unsigned char omit;      /* Do not code a test for this constraint */
-  } *aConstraintUsage;
-  int idxNum;                /* Number used to identify the index */
-  char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
-  int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
-  int orderByConsumed;       /* True if output is already ordered */
-  double estimatedCost;      /* Estimated cost of using this index */
+struct sqlite3_index_info
+{
+    /* Inputs */
+    int nConstraint;           /* Number of entries in aConstraint */
+    struct sqlite3_index_constraint
+    {
+        int iColumn;              /* Column on left-hand side of constraint */
+        unsigned char op;         /* Constraint operator */
+        unsigned char usable;     /* True if this constraint is usable */
+        int iTermOffset;          /* Used internally - xBestIndex should ignore */
+    } *aConstraint;            /* Table of WHERE clause constraints */
+    int nOrderBy;              /* Number of terms in the ORDER BY clause */
+    struct sqlite3_index_orderby
+    {
+        int iColumn;              /* Column number */
+        unsigned char desc;       /* True for DESC.  False for ASC. */
+    } *aOrderBy;               /* The ORDER BY clause */
+    /* Outputs */
+    struct sqlite3_index_constraint_usage
+    {
+        int argvIndex;           /* if >0, constraint is part of argv to xFilter */
+        unsigned char omit;      /* Do not code a test for this constraint */
+    } *aConstraintUsage;
+    int idxNum;                /* Number used to identify the index */
+    char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
+    int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
+    int orderByConsumed;       /* True if output is already ordered */
+    double estimatedCost;      /* Estimated cost of using this index */
 };
 
 /*
@@ -5299,7 +5308,7 @@ struct sqlite3_index_info {
 ** preexisting [virtual table] for the module.
 **
 ** ^The module name is registered on the [database connection] specified
-** by the first parameter.  ^The name of the module is given by the 
+** by the first parameter.  ^The name of the module is given by the
 ** second parameter.  ^The third parameter is a pointer to
 ** the implementation of the [virtual table module].   ^The fourth
 ** parameter is an arbitrary client data pointer that is passed through
@@ -5316,17 +5325,17 @@ struct sqlite3_index_info {
 ** destructor.
 */
 SQLITE_API int sqlite3_create_module(
-  sqlite3 *db,               /* SQLite connection to register module with */
-  const char *zName,         /* Name of the module */
-  const sqlite3_module *p,   /* Methods for the module */
-  void *pClientData          /* Client data for xCreate/xConnect */
+    sqlite3 *db,               /* SQLite connection to register module with */
+    const char *zName,         /* Name of the module */
+    const sqlite3_module *p,   /* Methods for the module */
+    void *pClientData          /* Client data for xCreate/xConnect */
 );
 SQLITE_API int sqlite3_create_module_v2(
-  sqlite3 *db,               /* SQLite connection to register module with */
-  const char *zName,         /* Name of the module */
-  const sqlite3_module *p,   /* Methods for the module */
-  void *pClientData,         /* Client data for xCreate/xConnect */
-  void(*xDestroy)(void*)     /* Module destructor function */
+    sqlite3 *db,               /* SQLite connection to register module with */
+    const char *zName,         /* Name of the module */
+    const sqlite3_module *p,   /* Methods for the module */
+    void *pClientData,         /* Client data for xCreate/xConnect */
+    void(*xDestroy)(void *)    /* Module destructor function */
 );
 
 /*
@@ -5347,11 +5356,12 @@ SQLITE_API int sqlite3_create_module_v2(
 ** is delivered up to the client application, the string will be automatically
 ** freed by sqlite3_free() and the zErrMsg field will be zeroed.
 */
-struct sqlite3_vtab {
-  const sqlite3_module *pModule;  /* The module for this virtual table */
-  int nRef;                       /* NO LONGER USED */
-  char *zErrMsg;                  /* Error message from sqlite3_mprintf() */
-  /* Virtual table implementations will typically add additional fields */
+struct sqlite3_vtab
+{
+    const sqlite3_module *pModule;  /* The module for this virtual table */
+    int nRef;                       /* NO LONGER USED */
+    char *zErrMsg;                  /* Error message from sqlite3_mprintf() */
+    /* Virtual table implementations will typically add additional fields */
 };
 
 /*
@@ -5371,9 +5381,10 @@ struct sqlite3_vtab {
 ** This superclass exists in order to define fields of the cursor that
 ** are common to all implementations.
 */
-struct sqlite3_vtab_cursor {
-  sqlite3_vtab *pVtab;      /* Virtual table of this cursor */
-  /* Virtual table implementations will typically add additional fields */
+struct sqlite3_vtab_cursor
+{
+    sqlite3_vtab *pVtab;      /* Virtual table of this cursor */
+    /* Virtual table implementations will typically add additional fields */
 };
 
 /*
@@ -5384,13 +5395,13 @@ struct sqlite3_vtab_cursor {
 ** to declare the format (the names and datatypes of the columns) of
 ** the virtual tables they implement.
 */
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+SQLITE_API int sqlite3_declare_vtab(sqlite3 *, const char *zSQL);
 
 /*
 ** CAPI3REF: Overload A Function For A Virtual Table
 **
 ** ^(Virtual tables can provide alternative implementations of functions
-** using the [xFindFunction] method of the [virtual table module].  
+** using the [xFindFunction] method of the [virtual table module].
 ** But global versions of those functions
 ** must exist in order to be overloaded.)^
 **
@@ -5402,7 +5413,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
 ** purpose is to be a placeholder function that can be overloaded
 ** by a [virtual table].
 */
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API int sqlite3_overload_function(sqlite3 *, const char *zFuncName, int nArg);
 
 /*
 ** The interface to the virtual-table mechanism defined above (back up
@@ -5441,8 +5452,8 @@ typedef struct sqlite3_blob sqlite3_blob;
 **
 ** ^If the flags parameter is non-zero, then the BLOB is opened for read
 ** and write access. ^If it is zero, the BLOB is opened for read access.
-** ^It is not possible to open a column that is part of an index or primary 
-** key for writing. ^If [foreign key constraints] are enabled, it is 
+** ^It is not possible to open a column that is part of an index or primary
+** key for writing. ^If [foreign key constraints] are enabled, it is
 ** not possible to open a column that is part of a [child key] for writing.
 **
 ** ^Note that the database name is not the filename that contains
@@ -5485,13 +5496,13 @@ typedef struct sqlite3_blob sqlite3_blob;
 ** be released by a call to [sqlite3_blob_close()].
 */
 SQLITE_API int sqlite3_blob_open(
-  sqlite3*,
-  const char *zDb,
-  const char *zTable,
-  const char *zColumn,
-  sqlite3_int64 iRow,
-  int flags,
-  sqlite3_blob **ppBlob
+    sqlite3 *,
+    const char *zDb,
+    const char *zTable,
+    const char *zColumn,
+    sqlite3_int64 iRow,
+    int flags,
+    sqlite3_blob **ppBlob
 );
 
 /*
@@ -5545,7 +5556,7 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
 /*
 ** CAPI3REF: Return The Size Of An Open BLOB
 **
-** ^Returns the size in bytes of the BLOB accessible via the 
+** ^Returns the size in bytes of the BLOB accessible via the
 ** successfully opened [BLOB handle] in its only argument.  ^The
 ** incremental blob I/O routines can only read or overwriting existing
 ** blob content; they cannot change the size of a blob.
@@ -5653,8 +5664,8 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOff
 ** the default.  The choice for the new VFS is arbitrary.)^
 */
 SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
-SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
-SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
+SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *, int makeDflt);
+SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *);
 
 /*
 ** CAPI3REF: Mutexes
@@ -5770,10 +5781,10 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
 */
 SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
-SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
+SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *);
+SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *);
+SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *);
+SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *);
 
 /*
 ** CAPI3REF: Mutex Methods Object
@@ -5841,16 +5852,17 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
 ** prior to returning.
 */
 typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
-struct sqlite3_mutex_methods {
-  int (*xMutexInit)(void);
-  int (*xMutexEnd)(void);
-  sqlite3_mutex *(*xMutexAlloc)(int);
-  void (*xMutexFree)(sqlite3_mutex *);
-  void (*xMutexEnter)(sqlite3_mutex *);
-  int (*xMutexTry)(sqlite3_mutex *);
-  void (*xMutexLeave)(sqlite3_mutex *);
-  int (*xMutexHeld)(sqlite3_mutex *);
-  int (*xMutexNotheld)(sqlite3_mutex *);
+struct sqlite3_mutex_methods
+{
+    int (*xMutexInit)(void);
+    int (*xMutexEnd)(void);
+    sqlite3_mutex *(*xMutexAlloc)(int);
+    void (*xMutexFree)(sqlite3_mutex *);
+    void (*xMutexEnter)(sqlite3_mutex *);
+    int (*xMutexTry)(sqlite3_mutex *);
+    void (*xMutexLeave)(sqlite3_mutex *);
+    int (*xMutexHeld)(sqlite3_mutex *);
+    int (*xMutexNotheld)(sqlite3_mutex *);
 };
 
 /*
@@ -5883,8 +5895,8 @@ struct sqlite3_mutex_methods {
 ** interface should also return 1 when given a NULL pointer.
 */
 #ifndef NDEBUG
-SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *);
+SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *);
 #endif
 
 /*
@@ -5911,13 +5923,13 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
 /*
 ** CAPI3REF: Retrieve the mutex for a database connection
 **
-** ^This interface returns a pointer the [sqlite3_mutex] object that 
+** ^This interface returns a pointer the [sqlite3_mutex] object that
 ** serializes access to the [database connection] given in the argument
 ** when the [threading mode] is Serialized.
 ** ^If the [threading mode] is Single-thread or Multi-thread then this
 ** routine returns a NULL pointer.
 */
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *);
 
 /*
 ** CAPI3REF: Low-Level Control Of Database Files
@@ -5951,7 +5963,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
 **
 ** See also: [SQLITE_FCNTL_LOCKSTATE]
 */
-SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+SQLITE_API int sqlite3_file_control(sqlite3 *, const char *zDbName, int op, void *);
 
 /*
 ** CAPI3REF: Testing Interface
@@ -6055,7 +6067,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
 ** <dd>This parameter records the largest memory allocation request
 ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
 ** internal equivalents).  Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.  
+** *pHighwater parameter to [sqlite3_status()] is of interest.
 ** The value written into the *pCurrent parameter is undefined.</dd>)^
 **
 ** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
@@ -6064,11 +6076,11 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
 **
 ** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
 ** <dd>This parameter returns the number of pages used out of the
-** [pagecache memory allocator] that was configured using 
+** [pagecache memory allocator] that was configured using
 ** [SQLITE_CONFIG_PAGECACHE].  The
 ** value returned is in pages, not in bytes.</dd>)^
 **
-** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] 
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
 ** <dd>This parameter returns the number of bytes of page cache
 ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
@@ -6081,7 +6093,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
 ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
 ** <dd>This parameter records the largest memory allocation request
 ** handed to [pagecache memory allocator].  Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.  
+** *pHighwater parameter to [sqlite3_status()] is of interest.
 ** The value written into the *pCurrent parameter is undefined.</dd>)^
 **
 ** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
@@ -6105,7 +6117,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
 ** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
 ** <dd>This parameter records the largest memory allocation request
 ** handed to [scratch memory allocator].  Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.  
+** *pHighwater parameter to [sqlite3_status()] is of interest.
 ** The value written into the *pCurrent parameter is undefined.</dd>)^
 **
 ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
@@ -6129,12 +6141,12 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
 /*
 ** CAPI3REF: Database Connection Status
 **
-** ^This interface is used to retrieve runtime status information 
+** ^This interface is used to retrieve runtime status information
 ** about a single [database connection].  ^The first argument is the
 ** database connection object to be interrogated.  ^The second argument
 ** is an integer constant, taken from the set of
 ** [SQLITE_DBSTATUS options], that
-** determines the parameter to interrogate.  The set of 
+** determines the parameter to interrogate.  The set of
 ** [SQLITE_DBSTATUS options] is likely
 ** to grow in future releases of SQLite.
 **
@@ -6148,7 +6160,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
 **
 ** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
 */
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API int sqlite3_db_status(sqlite3 *, int op, int *pCur, int *pHiwtr, int resetFlg);
 
 /*
 ** CAPI3REF: Status Parameters for database connections
@@ -6169,7 +6181,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 ** checked out.</dd>)^
 **
 ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
-** <dd>This parameter returns the number malloc attempts that were 
+** <dd>This parameter returns the number malloc attempts that were
 ** satisfied using lookaside memory. Only the high-water value is meaningful;
 ** the current value is always zero.)^
 **
@@ -6197,7 +6209,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
 ** <dd>This parameter returns the approximate number of of bytes of heap
 ** memory used to store the schema for all databases associated
-** with the connection - main, temp, and any [ATTACH]-ed databases.)^ 
+** with the connection - main, temp, and any [ATTACH]-ed databases.)^
 ** ^The full amount of memory used by the schemas is reported, even if the
 ** schema memory is shared with other database connections due to
 ** [shared cache mode] being enabled.
@@ -6212,13 +6224,13 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 **
 ** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
 ** <dd>This parameter returns the number of pager cache hits that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT 
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
 ** is always 0.
 ** </dd>
 **
 ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
 ** <dd>This parameter returns the number of pager cache misses that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS 
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
 ** is always 0.
 ** </dd>
 **
@@ -6257,7 +6269,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 ** statements.  For example, if the number of table steps greatly exceeds
 ** the number of table searches or result rows, that would tend to indicate
 ** that the prepared statement is using a full table scan rather than
-** an index.  
+** an index.
 **
 ** ^(This interface is used to retrieve and reset counter values from
 ** a [prepared statement].  The first argument is the prepared statement
@@ -6270,7 +6282,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 **
 ** See also: [sqlite3_status()] and [sqlite3_db_status()].
 */
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *, int op, int resetFlg);
 
 /*
 ** CAPI3REF: Status Parameters for prepared statements
@@ -6284,7 +6296,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 ** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
 ** <dd>^This is the number of times that SQLite has stepped forward in
 ** a table as part of a full table scan.  Large numbers for this counter
-** may indicate opportunities for performance improvement through 
+** may indicate opportunities for performance improvement through
 ** careful use of indices.</dd>
 **
 ** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
@@ -6328,9 +6340,10 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** See [sqlite3_pcache_methods2] for additional information.
 */
 typedef struct sqlite3_pcache_page sqlite3_pcache_page;
-struct sqlite3_pcache_page {
-  void *pBuf;        /* The content of the page */
-  void *pExtra;      /* Extra information associated with the page */
+struct sqlite3_pcache_page
+{
+    void *pBuf;        /* The content of the page */
+    void *pExtra;      /* Extra information associated with the page */
 };
 
 /*
@@ -6338,15 +6351,15 @@ struct sqlite3_pcache_page {
 ** KEYWORDS: {page cache}
 **
 ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
-** register an alternative page cache implementation by passing in an 
+** register an alternative page cache implementation by passing in an
 ** instance of the sqlite3_pcache_methods2 structure.)^
-** In many applications, most of the heap memory allocated by 
+** In many applications, most of the heap memory allocated by
 ** SQLite is used for the page cache.
-** By implementing a 
+** By implementing a
 ** custom page cache using this API, an application can better control
-** the amount of memory consumed by SQLite, the way in which 
-** that memory is allocated and released, and the policies used to 
-** determine exactly which parts of a database file are cached and for 
+** the amount of memory consumed by SQLite, the way in which
+** that memory is allocated and released, and the policies used to
+** determine exactly which parts of a database file are cached and for
 ** how long.
 **
 ** The alternative page cache mechanism is an
@@ -6359,19 +6372,19 @@ struct sqlite3_pcache_page {
 ** [sqlite3_config()] returns.)^
 **
 ** [[the xInit() page cache method]]
-** ^(The xInit() method is called once for each effective 
+** ^(The xInit() method is called once for each effective
 ** call to [sqlite3_initialize()])^
 ** (usually only once during the lifetime of the process). ^(The xInit()
 ** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
-** The intent of the xInit() method is to set up global data structures 
-** required by the custom page cache implementation. 
-** ^(If the xInit() method is NULL, then the 
+** The intent of the xInit() method is to set up global data structures
+** required by the custom page cache implementation.
+** ^(If the xInit() method is NULL, then the
 ** built-in default page cache is used instead of the application defined
 ** page cache.)^
 **
 ** [[the xShutdown() page cache method]]
 ** ^The xShutdown() method is called by [sqlite3_shutdown()].
-** It can be used to clean up 
+** It can be used to clean up
 ** any outstanding resources before process shutdown, if required.
 ** ^The xShutdown() method may be NULL.
 **
@@ -6390,7 +6403,7 @@ struct sqlite3_pcache_page {
 ** though this is not guaranteed. ^The
 ** first parameter, szPage, is the size in bytes of the pages that must
 ** be allocated by the cache.  ^szPage will always a power of two.  ^The
-** second parameter szExtra is a number of bytes of extra storage 
+** second parameter szExtra is a number of bytes of extra storage
 ** associated with each page cache entry.  ^The szExtra parameter will
 ** a number less than 250.  SQLite will use the
 ** extra szExtra bytes on each page to store metadata about the underlying
@@ -6403,7 +6416,7 @@ struct sqlite3_pcache_page {
 ** it is purely advisory.  ^On a cache where bPurgeable is false, SQLite will
 ** never invoke xUnpin() except to deliberately delete a page.
 ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
-** false will always have the "discard" flag set to true.  
+** false will always have the "discard" flag set to true.
 ** ^Hence, a cache created with bPurgeable false will
 ** never contain any unpinned pages.
 **
@@ -6418,12 +6431,12 @@ struct sqlite3_pcache_page {
 ** [[the xPagecount() page cache methods]]
 ** The xPagecount() method must return the number of pages currently
 ** stored in the cache, both pinned and unpinned.
-** 
+**
 ** [[the xFetch() page cache methods]]
-** The xFetch() method locates a page in the cache and returns a pointer to 
+** The xFetch() method locates a page in the cache and returns a pointer to
 ** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
 ** The pBuf element of the returned sqlite3_pcache_page object will be a
-** pointer to a buffer of szPage bytes used to store the content of a 
+** pointer to a buffer of szPage bytes used to store the content of a
 ** single database page.  The pExtra element of sqlite3_pcache_page will be
 ** a pointer to the szExtra bytes of extra storage that SQLite has requested
 ** for each entry in the page cache.
@@ -6462,8 +6475,8 @@ struct sqlite3_pcache_page {
 ** page cache implementation. ^The page cache implementation
 ** may choose to evict unpinned pages at any time.
 **
-** The cache must not perform any reference counting. A single 
-** call to xUnpin() unpins the page regardless of the number of prior calls 
+** The cache must not perform any reference counting. A single
+** call to xUnpin() unpins the page regardless of the number of prior calls
 ** to xFetch().
 **
 ** [[the xRekey() page cache methods]]
@@ -6493,21 +6506,22 @@ struct sqlite3_pcache_page {
 ** do their best.
 */
 typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
-struct sqlite3_pcache_methods2 {
-  int iVersion;
-  void *pArg;
-  int (*xInit)(void*);
-  void (*xShutdown)(void*);
-  sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
-  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
-  int (*xPagecount)(sqlite3_pcache*);
-  sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
-  void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
-  void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, 
-      unsigned oldKey, unsigned newKey);
-  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
-  void (*xDestroy)(sqlite3_pcache*);
-  void (*xShrink)(sqlite3_pcache*);
+struct sqlite3_pcache_methods2
+{
+    int iVersion;
+    void *pArg;
+    int (*xInit)(void *);
+    void (*xShutdown)(void *);
+    sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
+    void (*xCachesize)(sqlite3_pcache *, int nCachesize);
+    int (*xPagecount)(sqlite3_pcache *);
+    sqlite3_pcache_page *(*xFetch)(sqlite3_pcache *, unsigned key, int createFlag);
+    void (*xUnpin)(sqlite3_pcache *, sqlite3_pcache_page *, int discard);
+    void (*xRekey)(sqlite3_pcache *, sqlite3_pcache_page *,
+                   unsigned oldKey, unsigned newKey);
+    void (*xTruncate)(sqlite3_pcache *, unsigned iLimit);
+    void (*xDestroy)(sqlite3_pcache *);
+    void (*xShrink)(sqlite3_pcache *);
 };
 
 /*
@@ -6516,18 +6530,19 @@ struct sqlite3_pcache_methods2 {
 ** retained in the header file for backwards compatibility only.
 */
 typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
-struct sqlite3_pcache_methods {
-  void *pArg;
-  int (*xInit)(void*);
-  void (*xShutdown)(void*);
-  sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
-  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
-  int (*xPagecount)(sqlite3_pcache*);
-  void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
-  void (*xUnpin)(sqlite3_pcache*, void*, int discard);
-  void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
-  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
-  void (*xDestroy)(sqlite3_pcache*);
+struct sqlite3_pcache_methods
+{
+    void *pArg;
+    int (*xInit)(void *);
+    void (*xShutdown)(void *);
+    sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
+    void (*xCachesize)(sqlite3_pcache *, int nCachesize);
+    int (*xPagecount)(sqlite3_pcache *);
+    void *(*xFetch)(sqlite3_pcache *, unsigned key, int createFlag);
+    void (*xUnpin)(sqlite3_pcache *, void *, int discard);
+    void (*xRekey)(sqlite3_pcache *, void *, unsigned oldKey, unsigned newKey);
+    void (*xTruncate)(sqlite3_pcache *, unsigned iLimit);
+    void (*xDestroy)(sqlite3_pcache *);
 };
 
 
@@ -6548,7 +6563,7 @@ typedef struct sqlite3_backup sqlite3_backup;
 **
 ** The backup API copies the content of one database into another.
 ** It is useful either for creating backups of databases or
-** for copying in-memory databases to or from persistent files. 
+** for copying in-memory databases to or from persistent files.
 **
 ** See Also: [Using the SQLite Online Backup API]
 **
@@ -6559,28 +6574,28 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** ^Thus, the backup may be performed on a live source database without
 ** preventing other database connections from
 ** reading or writing to the source database while the backup is underway.
-** 
-** ^(To perform a backup operation: 
+**
+** ^(To perform a backup operation:
 **   <ol>
 **     <li><b>sqlite3_backup_init()</b> is called once to initialize the
-**         backup, 
-**     <li><b>sqlite3_backup_step()</b> is called one or more times to transfer 
+**         backup,
+**     <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
 **         the data between the two databases, and finally
-**     <li><b>sqlite3_backup_finish()</b> is called to release all resources 
-**         associated with the backup operation. 
+**     <li><b>sqlite3_backup_finish()</b> is called to release all resources
+**         associated with the backup operation.
 **   </ol>)^
 ** There should be exactly one call to sqlite3_backup_finish() for each
 ** successful call to sqlite3_backup_init().
 **
 ** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
 **
-** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the 
-** [database connection] associated with the destination database 
+** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
+** [database connection] associated with the destination database
 ** and the database name, respectively.
 ** ^The database name is "main" for the main database, "temp" for the
 ** temporary database, or the name specified after the AS keyword in
 ** an [ATTACH] statement for an attached database.
-** ^The S and M arguments passed to 
+** ^The S and M arguments passed to
 ** sqlite3_backup_init(D,N,S,M) identify the [database connection]
 ** and database name of the source database, respectively.
 ** ^The source and destination [database connections] (parameters S and D)
@@ -6596,14 +6611,14 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** ^A successful call to sqlite3_backup_init() returns a pointer to an
 ** [sqlite3_backup] object.
 ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
-** sqlite3_backup_finish() functions to perform the specified backup 
+** sqlite3_backup_finish() functions to perform the specified backup
 ** operation.
 **
 ** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
 **
-** ^Function sqlite3_backup_step(B,N) will copy up to N pages between 
+** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
 ** the source and destination databases specified by [sqlite3_backup] object B.
-** ^If N is negative, all remaining source pages are copied. 
+** ^If N is negative, all remaining source pages are copied.
 ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
 ** are still more pages to be copied, then the function returns [SQLITE_OK].
 ** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
@@ -6625,8 +6640,8 @@ typedef struct sqlite3_backup sqlite3_backup;
 **
 ** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
 ** the [sqlite3_busy_handler | busy-handler function]
-** is invoked (if one is specified). ^If the 
-** busy-handler returns non-zero before the lock is available, then 
+** is invoked (if one is specified). ^If the
+** busy-handler returns non-zero before the lock is available, then
 ** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
 ** sqlite3_backup_step() can be retried later. ^If the source
 ** [database connection]
@@ -6634,15 +6649,15 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
 ** case the call to sqlite3_backup_step() can be retried later on. ^(If
 ** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
-** [SQLITE_READONLY] is returned, then 
-** there is no point in retrying the call to sqlite3_backup_step(). These 
-** errors are considered fatal.)^  The application must accept 
-** that the backup operation has failed and pass the backup operation handle 
+** [SQLITE_READONLY] is returned, then
+** there is no point in retrying the call to sqlite3_backup_step(). These
+** errors are considered fatal.)^  The application must accept
+** that the backup operation has failed and pass the backup operation handle
 ** to the sqlite3_backup_finish() to release associated resources.
 **
 ** ^The first call to sqlite3_backup_step() obtains an exclusive lock
-** on the destination file. ^The exclusive lock is not released until either 
-** sqlite3_backup_finish() is called or the backup operation is complete 
+** on the destination file. ^The exclusive lock is not released until either
+** sqlite3_backup_finish() is called or the backup operation is complete
 ** and sqlite3_backup_step() returns [SQLITE_DONE].  ^Every call to
 ** sqlite3_backup_step() obtains a [shared lock] on the source database that
 ** lasts for the duration of the sqlite3_backup_step() call.
@@ -6651,18 +6666,18 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** through the backup process.  ^If the source database is modified by an
 ** external process or via a database connection other than the one being
 ** used by the backup operation, then the backup will be automatically
-** restarted by the next call to sqlite3_backup_step(). ^If the source 
+** restarted by the next call to sqlite3_backup_step(). ^If the source
 ** database is modified by the using the same database connection as is used
 ** by the backup operation, then the backup database is automatically
 ** updated at the same time.
 **
 ** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
 **
-** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the 
+** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
 ** application wishes to abandon the backup operation, the application
 ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
 ** ^The sqlite3_backup_finish() interfaces releases all
-** resources associated with the [sqlite3_backup] object. 
+** resources associated with the [sqlite3_backup] object.
 ** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
 ** active write-transaction on the destination database is rolled back.
 ** The [sqlite3_backup] object is invalid
@@ -6702,8 +6717,8 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** connections, then the source database connection may be used concurrently
 ** from within other threads.
 **
-** However, the application must guarantee that the destination 
-** [database connection] is not passed to any other API (by any thread) after 
+** However, the application must guarantee that the destination
+** [database connection] is not passed to any other API (by any thread) after
 ** sqlite3_backup_init() is called and before the corresponding call to
 ** sqlite3_backup_finish().  SQLite does not currently check to see
 ** if the application incorrectly accesses the destination [database connection]
@@ -6714,11 +6729,11 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** If running in [shared cache mode], the application must
 ** guarantee that the shared cache used by the destination database
 ** is not accessed while the backup is running. In practice this means
-** that the application must guarantee that the disk file being 
+** that the application must guarantee that the disk file being
 ** backed up to is not accessed by any connection within the process,
 ** not just the specific connection that was passed to sqlite3_backup_init().
 **
-** The [sqlite3_backup] object itself is partially threadsafe. Multiple 
+** The [sqlite3_backup] object itself is partially threadsafe. Multiple
 ** threads may safely make multiple concurrent calls to sqlite3_backup_step().
 ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
 ** APIs are not strictly speaking threadsafe. If they are invoked at the
@@ -6726,10 +6741,10 @@ typedef struct sqlite3_backup sqlite3_backup;
 ** possible that they return invalid values.
 */
 SQLITE_API sqlite3_backup *sqlite3_backup_init(
-  sqlite3 *pDest,                        /* Destination database handle */
-  const char *zDestName,                 /* Destination database name */
-  sqlite3 *pSource,                      /* Source database handle */
-  const char *zSourceName                /* Source database name */
+    sqlite3 *pDest,                        /* Destination database handle */
+    const char *zDestName,                 /* Destination database name */
+    sqlite3 *pSource,                      /* Source database handle */
+    const char *zSourceName                /* Source database name */
 );
 SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
 SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
@@ -6742,8 +6757,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 ** ^When running in shared-cache mode, a database operation may fail with
 ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
 ** individual tables within the shared-cache cannot be obtained. See
-** [SQLite Shared-Cache Mode] for a description of shared-cache locking. 
-** ^This API may be used to register a callback that SQLite will invoke 
+** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
+** ^This API may be used to register a callback that SQLite will invoke
 ** when the connection currently holding the required lock relinquishes it.
 ** ^This API is only available if the library was compiled with the
 ** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
@@ -6751,14 +6766,14 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 ** See Also: [Using the SQLite Unlock Notification Feature].
 **
 ** ^Shared-cache locks are released when a database connection concludes
-** its current transaction, either by committing it or rolling it back. 
+** its current transaction, either by committing it or rolling it back.
 **
 ** ^When a connection (known as the blocked connection) fails to obtain a
 ** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
 ** identity of the database connection (the blocking connection) that
-** has locked the required resource is stored internally. ^After an 
+** has locked the required resource is stored internally. ^After an
 ** application receives an SQLITE_LOCKED error, it may call the
-** sqlite3_unlock_notify() method with the blocked connection handle as 
+** sqlite3_unlock_notify() method with the blocked connection handle as
 ** the first argument to register for a callback that will be invoked
 ** when the blocking connections current transaction is concluded. ^The
 ** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
@@ -6772,15 +6787,15 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 **
 ** ^If the blocked connection is attempting to obtain a write-lock on a
 ** shared-cache table, and more than one other connection currently holds
-** a read-lock on the same table, then SQLite arbitrarily selects one of 
+** a read-lock on the same table, then SQLite arbitrarily selects one of
 ** the other connections to use as the blocking connection.
 **
-** ^(There may be at most one unlock-notify callback registered by a 
+** ^(There may be at most one unlock-notify callback registered by a
 ** blocked connection. If sqlite3_unlock_notify() is called when the
 ** blocked connection already has a registered unlock-notify callback,
 ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
 ** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is canceled. ^The blocked connections 
+** unlock-notify callback is canceled. ^The blocked connections
 ** unlock-notify callback may also be canceled by closing the blocked
 ** connection using [sqlite3_close()].
 **
@@ -6793,7 +6808,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 **
 ** <b>Callback Invocation Details</b>
 **
-** When an unlock-notify callback is registered, the application provides a 
+** When an unlock-notify callback is registered, the application provides a
 ** single void* pointer that is passed to the callback when it is invoked.
 ** However, the signature of the callback function allows SQLite to pass
 ** it an array of void* context pointers. The first argument passed to
@@ -6806,12 +6821,12 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 ** same callback function, then instead of invoking the callback function
 ** multiple times, it is invoked once with the set of void* context pointers
 ** specified by the blocked connections bundled together into an array.
-** This gives the application an opportunity to prioritize any actions 
+** This gives the application an opportunity to prioritize any actions
 ** related to the set of unblocked database connections.
 **
 ** <b>Deadlock Detection</b>
 **
-** Assuming that after registering for an unlock-notify callback a 
+** Assuming that after registering for an unlock-notify callback a
 ** database waits for the callback to be issued before taking any further
 ** action (a reasonable assumption), then using this API may cause the
 ** application to deadlock. For example, if connection X is waiting for
@@ -6834,7 +6849,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 **
 ** <b>The "DROP TABLE" Exception</b>
 **
-** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost 
+** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
 ** always appropriate to call sqlite3_unlock_notify(). There is however,
 ** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
 ** SQLite checks if there are any currently executing SELECT statements
@@ -6847,13 +6862,13 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
 ** One way around this problem is to check the extended error code returned
 ** by an sqlite3_step() call. ^(If there is a blocking connection, then the
 ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
-** the special "DROP TABLE/INDEX" case, the extended error code is just 
+** the special "DROP TABLE/INDEX" case, the extended error code is just
 ** SQLITE_LOCKED.)^
 */
 SQLITE_API int sqlite3_unlock_notify(
-  sqlite3 *pBlocked,                          /* Waiting connection */
-  void (*xNotify)(void **apArg, int nArg),    /* Callback function to invoke */
-  void *pNotifyArg                            /* Argument to pass to xNotify */
+    sqlite3 *pBlocked,                          /* Waiting connection */
+    void (*xNotify)(void **apArg, int nArg),    /* Callback function to invoke */
+    void *pNotifyArg                            /* Argument to pass to xNotify */
 );
 
 
@@ -6912,10 +6927,10 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
 ** ^The [sqlite3_wal_hook()] function is used to register a callback that
 ** will be invoked each time a database connection commits data to a
 ** [write-ahead log] (i.e. whenever a transaction is committed in
-** [journal_mode | journal_mode=WAL mode]). 
+** [journal_mode | journal_mode=WAL mode]).
 **
-** ^The callback is invoked by SQLite after the commit has taken place and 
-** the associated write-lock on the database released, so the implementation 
+** ^The callback is invoked by SQLite after the commit has taken place and
+** the associated write-lock on the database released, so the implementation
 ** may read, write or [checkpoint] the database as required.
 **
 ** ^The first parameter passed to the callback function when it is invoked
@@ -6934,7 +6949,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
 ** that does not correspond to any valid SQLite error code, the results
 ** are undefined.
 **
-** A single database handle may have at most a single write-ahead log callback 
+** A single database handle may have at most a single write-ahead log callback
 ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
 ** previously registered write-ahead log callback. ^Note that the
 ** [sqlite3_wal_autocheckpoint()] interface and the
@@ -6942,9 +6957,9 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
 ** those overwrite any prior [sqlite3_wal_hook()] settings.
 */
 SQLITE_API void *sqlite3_wal_hook(
-  sqlite3*, 
-  int(*)(void *,sqlite3*,const char*,int),
-  void*
+    sqlite3 *,
+    int(*)(void *, sqlite3 *, const char *, int),
+    void *
 );
 
 /*
@@ -6954,7 +6969,7 @@ SQLITE_API void *sqlite3_wal_hook(
 ** [sqlite3_wal_hook()] that causes any database on [database connection] D
 ** to automatically [checkpoint]
 ** after committing a transaction if there are N or
-** more frames in the [write-ahead log] file.  ^Passing zero or 
+** more frames in the [write-ahead log] file.  ^Passing zero or
 ** a negative value as the nFrame parameter disables automatic
 ** checkpoints entirely.
 **
@@ -6995,15 +7010,15 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 /*
 ** CAPI3REF: Checkpoint a database
 **
-** Run a checkpoint operation on WAL database zDb attached to database 
-** handle db. The specific operation is determined by the value of the 
+** Run a checkpoint operation on WAL database zDb attached to database
+** handle db. The specific operation is determined by the value of the
 ** eMode parameter:
 **
 ** <dl>
 ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
-**   Checkpoint as many frames as possible without waiting for any database 
+**   Checkpoint as many frames as possible without waiting for any database
 **   readers or writers to finish. Sync the db file if all frames in the log
-**   are checkpointed. This mode is the same as calling 
+**   are checkpointed. This mode is the same as calling
 **   sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
 **
 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
@@ -7014,10 +7029,10 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **   but not database readers.
 **
 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
-**   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after 
+**   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
 **   checkpointing the log file it blocks (calls the busy-handler callback)
-**   until all readers are reading from the database file only. This ensures 
-**   that the next client to write to the database file restarts the log file 
+**   until all readers are reading from the database file only. This ensures
+**   that the next client to write to the database file restarts the log file
 **   from the beginning. This call blocks database writers while it is running,
 **   but not database readers.
 ** </dl>
@@ -7031,30 +7046,30 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 ** before returning to communicate this to the caller.
 **
 ** All calls obtain an exclusive "checkpoint" lock on the database file. If
-** any other process is running a checkpoint operation at the same time, the 
-** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a 
+** any other process is running a checkpoint operation at the same time, the
+** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a
 ** busy-handler configured, it will not be invoked in this case.
 **
-** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive 
+** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive
 ** "writer" lock on the database file. If the writer lock cannot be obtained
 ** immediately, and a busy-handler is configured, it is invoked and the writer
 ** lock retried until either the busy-handler returns 0 or the lock is
 ** successfully obtained. The busy-handler is also invoked while waiting for
 ** database readers as described above. If the busy-handler returns 0 before
 ** the writer lock is obtained or while waiting for database readers, the
-** checkpoint operation proceeds from that point in the same way as 
-** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible 
+** checkpoint operation proceeds from that point in the same way as
+** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
 ** without blocking any further. SQLITE_BUSY is returned in this case.
 **
 ** If parameter zDb is NULL or points to a zero length string, then the
 ** specified operation is attempted on all WAL databases. In this case the
-** values written to output parameters *pnLog and *pnCkpt are undefined. If 
-** an SQLITE_BUSY error is encountered when processing one or more of the 
-** attached WAL databases, the operation is still attempted on any remaining 
-** attached databases and SQLITE_BUSY is returned to the caller. If any other 
-** error occurs while processing an attached database, processing is abandoned 
-** and the error code returned to the caller immediately. If no error 
-** (SQLITE_BUSY or otherwise) is encountered while processing the attached 
+** values written to output parameters *pnLog and *pnCkpt are undefined. If
+** an SQLITE_BUSY error is encountered when processing one or more of the
+** attached WAL databases, the operation is still attempted on any remaining
+** attached databases and SQLITE_BUSY is returned to the caller. If any other
+** error occurs while processing an attached database, processing is abandoned
+** and the error code returned to the caller immediately. If no error
+** (SQLITE_BUSY or otherwise) is encountered while processing the attached
 ** databases, SQLITE_OK is returned.
 **
 ** If database zDb is the name of an attached database that is not in WAL
@@ -7063,11 +7078,11 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 ** attached database, SQLITE_ERROR is returned to the caller.
 */
 SQLITE_API int sqlite3_wal_checkpoint_v2(
-  sqlite3 *db,                    /* Database handle */
-  const char *zDb,                /* Name of attached database (or NULL) */
-  int eMode,                      /* SQLITE_CHECKPOINT_* value */
-  int *pnLog,                     /* OUT: Size of WAL log in frames */
-  int *pnCkpt                     /* OUT: Total number of frames checkpointed */
+    sqlite3 *db,                    /* Database handle */
+    const char *zDb,                /* Name of attached database (or NULL) */
+    int eMode,                      /* SQLITE_CHECKPOINT_* value */
+    int *pnLog,                     /* OUT: Size of WAL log in frames */
+    int *pnCkpt                     /* OUT: Total number of frames checkpointed */
 );
 
 /*
@@ -7096,7 +7111,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
 ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].)  Further options
 ** may be added in the future.
 */
-SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+SQLITE_API int sqlite3_vtab_config(sqlite3 *, int op, ...);
 
 /*
 ** CAPI3REF: Virtual Table Configuration Options
@@ -7120,20 +7135,20 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
 ** If X is non-zero, then the virtual table implementation guarantees
 ** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
 ** any modifications to internal or persistent data structures have been made.
-** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite 
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
 ** is able to roll back a statement or database transaction, and abandon
-** or continue processing the current SQL statement as appropriate. 
+** or continue processing the current SQL statement as appropriate.
 ** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
 ** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
 ** had been ABORT.
 **
 ** Virtual table implementations that are required to handle OR REPLACE
-** must do so within the [xUpdate] method. If a call to the 
-** [sqlite3_vtab_on_conflict()] function indicates that the current ON 
-** CONFLICT policy is REPLACE, the virtual table implementation should 
+** must do so within the [xUpdate] method. If a call to the
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
+** CONFLICT policy is REPLACE, the virtual table implementation should
 ** silently replace the appropriate rows within the xUpdate callback and
 ** return SQLITE_OK. Or, if this is not possible, it may return
-** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
 ** constraint handling.
 ** </dl>
 */
@@ -7213,14 +7228,14 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
 **   SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
 */
 SQLITE_API int sqlite3_rtree_geometry_callback(
-  sqlite3 *db,
-  const char *zGeom,
+    sqlite3 *db,
+    const char *zGeom,
 #ifdef SQLITE_RTREE_INT_ONLY
-  int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
+    int (*xGeom)(sqlite3_rtree_geometry *, int n, sqlite3_int64 *a, int *pRes),
 #else
-  int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
+    int (*xGeom)(sqlite3_rtree_geometry *, int n, double *a, int *pRes),
 #endif
-  void *pContext
+    void *pContext
 );
 
 
@@ -7228,12 +7243,13 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
 ** A pointer to a structure of the following type is passed as the first
 ** argument to callbacks registered using rtree_geometry_callback().
 */
-struct sqlite3_rtree_geometry {
-  void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
-  int nParam;                     /* Size of array aParam[] */
-  double *aParam;                 /* Parameters passed to SQL geom function */
-  void *pUser;                    /* Callback implementation user data */
-  void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
+struct sqlite3_rtree_geometry
+{
+    void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
+    int nParam;                     /* Size of array aParam[] */
+    double *aParam;                 /* Parameters passed to SQL geom function */
+    void *pUser;                    /* Callback implementation user data */
+    void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
 };
 
 
index bab1e7c..58d2df4 100644 (file)
@@ -36,7 +36,7 @@ SSMRESULT CPropagationEngine::finalConstruct()
 
     SSM_CLEANUP_ASSERT(m_pContextRepository->registerResourceFinderEvent(this));
 
-    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
+    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
 
     SSM_CLEANUP_ASSERT(initializeEngine());
 
@@ -148,7 +148,7 @@ SSMRESULT CPropagationEngine::addResourceFromGetList()
     std::vector<ISSMResource *>      contextModelList;
     std::stringstream               sstream;
 
-    m_pResponseReactor->getList(&contextModelList);
+    m_pSensingEngine->getList(&contextModelList);
     for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
          itor != contextModelList.end(); ++itor)
     {
@@ -288,12 +288,12 @@ CLEANUP:
     return res;
 }
 
-SSMRESULT CPropagationEngine::installResponseReactor(IN IResponseReactor *pResponseReactor)
+SSMRESULT CPropagationEngine::installCurrentSensors()
 {
     SSMRESULT res = SSM_E_FAIL;
     std::vector<ISSMResource *>      contextModelList;
 
-    pResponseReactor->getList(&contextModelList);
+    m_pSensingEngine->getList(&contextModelList);
 
     for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
          itor != contextModelList.end(); ++itor)
@@ -449,7 +449,7 @@ SSMRESULT CPropagationEngine::initializeEngine()
 
     SSM_CLEANUP_ASSERT(updateDeviceInfo(&ssmResource, NULL));
 
-    SSM_CLEANUP_ASSERT(installResponseReactor(m_pResponseReactor));
+    SSM_CLEANUP_ASSERT(installCurrentSensors());
 
 CLEANUP:
     SAFE_RELEASE(pRootModel);
@@ -525,11 +525,11 @@ SSMRESULT CPropagationEngine::onModelStatusChange(IN IContextModel::Status newSt
     {
         case IContextModel::STATUS_ACTIVATE:
             pModel->addRef();
-            m_pResponseReactor->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+            m_pSensingEngine->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
             break;
 
         case IContextModel::STATUS_DEACTIVATE:
-            m_pResponseReactor->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+            m_pSensingEngine->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
             //pModel->CleanUpModelData();
             pModel->release();
             break;
@@ -537,7 +537,7 @@ SSMRESULT CPropagationEngine::onModelStatusChange(IN IContextModel::Status newSt
         case IContextModel::STATUS_START_READ_VALUE:
             //Model must be released from OnEvent callType
             pModel->addRef();
-            m_pResponseReactor->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
+            m_pSensingEngine->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
             break;
 
         case IContextModel::STATUS_STOP_READ_VALUE:
index 45eca05..0b59a69 100644 (file)
@@ -56,7 +56,7 @@ class CPropagationEngine :
         CSimpleMutex                                m_mtxContextModelList;
         CSimpleMutex                                m_mtxLookUpList;
 
-        CObjectPtr<IResponseReactor>                m_pResponseReactor;
+        CObjectPtr<ISensingEngine>                  m_pSensingEngine;
 
         CObjectPtr<IContextModel>                   m_pDeviceModel;
 
@@ -75,9 +75,9 @@ class CPropagationEngine :
         SSMRESULT addResourceFromGetList();
 
         //TODO: Install Context model from SSMResource
-        SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
+        SSMRESULT installCurrentSensors();
 
-        SSMRESULT installResponseReactor(IN IResponseReactor *pResponseReactor);
+        SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
 
         SSMRESULT installContextModel(IN IContextModel *pParentModel,
                                       IN IContextModel::ConstructionType constructionType,
index f109cfb..1217284 100644 (file)
@@ -20,9 +20,7 @@
 #ifndef _SSMCore_H_
 #define _SSMCore_H_
 
-#include <string>
-#include <vector>
-
+#include "SSMInterface.h"
 #include "SSMModelDefinition.h"
 
 #define IN
 */
 #define INTERFACE_DECLSPEC
 
-enum SSMRESULT
-{
-    SSM_S_OK
-    , SSM_S_FALSE
-    , SSM_E_POINTER
-    , SSM_E_OUTOFMEMORY
-    , SSM_E_FAIL
-    , SSM_E_NOINTERFACE
-    , SSM_E_NOTIMPL
-};
-
-/**
-* @class    IModelData
-* @brief    IModelData Interface
-*            This class represents context model data package
-*
-* @see
-*/
-class IModelData
-{
-    public:
-        /**
-        * @fn     getDataId
-        * @brief Get affected DataId. ContextModel has plenty of data so \n
-        *         returned data is matched from given condition
-        *
-        * @param None
-        *
-        * @return int
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual int getDataId() = 0;
-
-        /**
-        * @fn     GetPropertyCount
-        * @brief ContextModel has at least one property that contains data \n
-        *         property is described from its specification.
-        *
-        * @param None
-        *
-        * @return int
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual int getPropertyCount() = 0;
-
-        /**
-        * @fn     getPropertyName
-        * @brief Retrieve propertyName
-        *
-        * @param [in] int propertyIndex - index of property to read
-        *
-        * @return std::string
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual std::string getPropertyName(IN int propertyIndex) = 0;
-
-        /**
-        * @fn     getPropertyValue
-        * @brief Retrieve propertyValue
-        *
-        * @param [in] int propertyIndex - index of property to read
-        *
-        * @return std::string
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual std::string getPropertyValue(IN int propertyIndex) = 0;
-
-        /**
-        * @fn     getPropertyValueByName
-        * @brief Retrieve propertyValue using given name
-        *
-        * @param [in] std::string propertyName - property name looking for
-        *
-        * @return std::string
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual std::string getPropertyValueByName(IN std::string propertyName) = 0;
-    protected:
-        virtual ~IModelData() {};
-};
-
-/**
-* @class    IDataReader
-* @brief    IDataReader Interface
-*            This class represents context model data package's reader
-*
-* @see
-*/
-class IDataReader
-{
-    public:
-        /**
-        * @fn     getAffectedModels
-        * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
-        *
-        * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT getAffectedModels(OUT std::vector<std::string> *pAffectedModels) = 0;
-
-        /**
-        * @fn     getModelDataCount
-        * @brief Get affected data count. There are multiple data can exist from given condition.
-        *
-        * @param [in] std::string modelName - affected ContextModel name
-        *
-        * @param [out] int *pDataCount - affected dataId count
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT getModelDataCount(IN std::string modelName, OUT int *pDataCount) = 0;
-
-        /**
-        * @fn     getModelData
-        * @brief Get actual Context Model data
-        *
-        * @param [in] std::string modelName - affected ContextModel name
-        *
-        *
-        * @param [in] int dataIndex - affected dataId index
-        *
-        *
-        * @param [out] IModelData **ppModelData - affected ContextModel data reader
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT getModelData(IN std::string modelName, IN int dataIndex,
-                                       OUT IModelData **ppModelData) = 0;
-    protected:
-        virtual ~IDataReader() {};
-};
-
-/**
-* @class    IQueryEngineEvent
-* @brief    IQueryEngineEvent Interface
-*            This class represents Query Engine's event that contains results
-*
-* @see
-*/
-class IQueryEngineEvent
-{
-    public:
-        /**
-        * @fn     onQueryEngineEvent
-        * @brief Transmit result of SSMCore to Application layer
-        *
-        * @param [in] int cqid - entered ContextQuery ID
-        *
-        * @param [in] IDataReader *pResult - result of SSMCore
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult) = 0;
-    protected:
-        virtual ~IQueryEngineEvent() {};
-};
-
 /**
 * @class    IQueryEngine
 * @brief    IQueryEngine Interface
index 23aabed..9dbb031 100644 (file)
@@ -17,6 +17,7 @@
 * limitations under the License.
 *
 ******************************************************************/
+#include "SSMCore.h"
 #include "SSMInterface/SSMCore_JNI.h"
 #include "Common/PlatformLayer.h"
 
index 51a13db..8fe3bb2 100644 (file)
@@ -24,7 +24,7 @@
 #include "Common/InternalInterface.h"
 using namespace OC;
 
-static std::vector< OC::AttributeMap > g_vecQueryEventResults;
+static std::vector< std::map<std::string, std::string> > g_vecQueryEventResults;
 
 class CQueryEngineEvent: public IQueryEngineEvent
 {
@@ -46,23 +46,23 @@ class CQueryEngineEvent: public IQueryEngineEvent
             IModelData *pModelData = NULL;
             std::vector < std::string > affectedModels;
 
-            AttributeMap queryEventResult;
+            std::map<std::string, std::string> queryEventResult;
 
             std::stringstream sstream;
 
             // QueryEngine Id
-            queryEventResult["queryEngineId"].push_back(m_queryEngineId);
+            queryEventResult["queryEngineId"] = m_queryEngineId;
 
             // CQID
             sstream << cqid;
-            queryEventResult["CQID"].push_back(sstream.str());
+            queryEventResult["CQID"] = sstream.str();
             sstream.str("");
 
             pResult->getAffectedModels(&affectedModels);
 
             // Affected Model Count
             sstream << affectedModels.size();
-            queryEventResult["modelCount"].push_back(sstream.str());
+            queryEventResult["modelCount"] = sstream.str();
             sstream.str("");
 
             //TODO: we assume that contains only one model at time
@@ -71,14 +71,14 @@ class CQueryEngineEvent: public IQueryEngineEvent
             {
                 // Model Name
                 sstream << (*itor);
-                queryEventResult["modelName"].push_back(sstream.str());
+                queryEventResult["modelName"] = sstream.str();
                 sstream.str("");
 
                 pResult->getModelDataCount(*itor, &dataCount);
 
                 // Data Count
                 sstream << dataCount;
-                queryEventResult["dataCount"].push_back(sstream.str());
+                queryEventResult["dataCount"] = sstream.str();
                 sstream.str("");
 
                 //FixME: we have to support multiple data count
@@ -88,26 +88,28 @@ class CQueryEngineEvent: public IQueryEngineEvent
 
                     // Data Id
                     sstream << pModelData->getDataId();
-                    queryEventResult["dataId"].push_back(sstream.str());
+                    queryEventResult["dataId"] = sstream.str();
                     sstream.str("");
 
                     // Property Count
                     sstream << pModelData->getPropertyCount();
-                    queryEventResult["propertyCount"].push_back(sstream.str());
+                    queryEventResult["propertyCount"] = sstream.str();
                     sstream.str("");
 
                     for (int j = 0; j < pModelData->getPropertyCount(); j++)
                     {
                         // Property Name & Value
                         sstream << pModelData->getPropertyValue(j).c_str();
-                        queryEventResult[pModelData->getPropertyName(j).c_str()].push_back(sstream.str());
+                        queryEventResult[pModelData->getPropertyName(j).c_str()] = sstream.str();
                         sstream.str("");
                     }
                 }
             }
 
             g_vecQueryEventResults.push_back(queryEventResult);
-            OCPlatform::notifyObservers(m_hSSMResource);
+
+            //TODO: need to modify for notifying proper clients
+            OCPlatform::notifyAllObservers(m_hSSMResource);
 
             return SSM_S_OK;
         }
@@ -115,7 +117,6 @@ class CQueryEngineEvent: public IQueryEngineEvent
 
 SSMResourceServer::SSMResourceServer()
 {
-    m_pPlatform = NULL;
     m_hSSMResource = NULL;
 }
 
@@ -126,16 +127,10 @@ SSMResourceServer::~SSMResourceServer()
 int SSMResourceServer::initializeManager(std::string &xmlDescription)
 {
     SSMRESULT res = SSM_E_FAIL;
-    CObjectPtr < IResourceConnectivity > pResourceConnectivity;
 
     SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
     SSM_CLEANUP_ASSERT(StartSSMCore());
 
-    SSM_CLEANUP_ASSERT(
-        CreateGlobalInstance(OID_IResourceConnectivity, (IBase **) &pResourceConnectivity));
-
-    m_pPlatform = (OC::OCPlatform *) pResourceConnectivity->getPlatform();
-
     if (createResource() != 0)
     {
         SSM_CLEANUP_ASSERT (SSM_E_FAIL);
@@ -165,18 +160,17 @@ CLEANUP:
 int SSMResourceServer::createResource()
 {
     std::string resourceURI = "/service/SoftSensorManager"; // URI of the resource
-    std::string resourceTypeName =
-        "core.SoftSensorManager"; // resource type name. In this case, it is light
+    std::string resourceTypeName = "core.SoftSensorManager"; // resource type name.
     std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
 
     // OCResourceProperty is defined ocstack.h
     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
     // This will internally create and register the resource.
-    OCStackResult result = m_pPlatform->registerResource(m_hSSMResource, resourceURI,
+    OCStackResult result = OCPlatform::registerResource(m_hSSMResource, resourceURI,
                            resourceTypeName, resourceInterface,
-                           std::bind(&SSMResourceServer::entityHandler, this, std::placeholders::_1,
-                                     std::placeholders::_2), resourceProperty);
+                           std::bind(&SSMResourceServer::entityHandler, this, std::placeholders::_1
+                                    ), resourceProperty);
 
     if (OC_STACK_OK != result)
     {
@@ -186,27 +180,34 @@ int SSMResourceServer::createResource()
     return 0;
 }
 
-void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request,
-                                      std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request)
 {
     SSMRESULT res = SSM_E_FAIL;
 
+    auto response = std::make_shared<OC::OCResourceResponse>();
+
     if (request)
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if (requestFlag == RequestHandlerFlag::InitFlag)
+        response->setRequestHandle(request->getRequestHandle());
+        response->setResourceHandle(request->getResourceHandle());
+
+        if (requestFlag & RequestHandlerFlag::InitFlag)
         {
             // entity handler to perform resource initialization operations
         }
-        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
         {
+            cout << "\t\trequestFlag : Request\n";
+
             // If the request type is GET
             if (requestType == "GET")
             {
-                AttributeMap responseAttributeMap;
+                std::map<std::string, std::string> responseAttributeMap;
 
                 OCRepresentation rep = request->getResourceRepresentation();
 
@@ -218,7 +219,12 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                 if (response)
                 {
-                    rep.setAttributeMap(responseAttributeMap);
+                    for (std::map<std::string, std::string>::iterator itor =
+                             responseAttributeMap.begin(); itor != responseAttributeMap.end();
+                         ++itor)
+                    {
+                        rep.setValue(itor->first, itor->second);
+                    }
 
                     response->setErrorCode(200);
                     response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
@@ -228,16 +234,12 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
             {
                 OCRepresentation rep = request->getResourceRepresentation();
 
-                AttributeMap requestAttributeMap = rep.getAttributeMap();
-
                 IQueryEngine *pQueryEngine = NULL;
 
                 std::stringstream sstream;
 
-                AttributeMap responseAttributeMap;
-
                 // Process query params and do required operations ..
-                if (requestAttributeMap["command"].back() == "CreateQueryEngine")
+                if (rep.getValue<std::string>("command") == "CreateQueryEngine")
                 {
                     CQueryEngineEvent *queryEngineEvent = NULL;
 
@@ -245,7 +247,7 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("CreateQueryEngine failed");
+                        rep.setValue("error", "CreateQueryEngine failed");
                         goto CLEANUP;
                     }
 
@@ -256,8 +258,7 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                     if (queryEngineEvent == NULL)
                     {
-                        responseAttributeMap["error"].push_back(
-                            "QueryEngineEvent create failed");
+                        rep.setValue("error", "QueryEngineEvent create failed");
                         goto CLEANUP;
                     }
 
@@ -265,49 +266,49 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("RegisterQueryEvent failed");
+                        rep.setValue("error", "RegisterQueryEvent failed");
                         goto CLEANUP;
                     }
 
-                    responseAttributeMap["queryEngineId"].push_back(sstream.str());
+                    rep.setValue("queryEngineId", sstream.str());
                 }
-                else if (requestAttributeMap["command"].back() == "ReleaseQueryEngine")
+                else if (rep.getValue<std::string>("command") == "ReleaseQueryEngine")
                 {
-                    pQueryEngine = (IQueryEngine *) stoi(
-                                       requestAttributeMap["queryEngineId"].back());
+                    pQueryEngine = (IQueryEngine *) std::stoi(
+                                       rep.getValue<std::string>("queryEngineId"));
 
                     ReleaseQueryEngine(pQueryEngine);
                 }
-                else if (requestAttributeMap["command"].back() == "ExecuteContextQuery")
+                else if (rep.getValue<std::string>("command") == "ExecuteContextQuery")
                 {
                     int CQID = 0;
 
-                    pQueryEngine = (IQueryEngine *) stoi(
-                                       requestAttributeMap["queryEngineId"].back());
+                    pQueryEngine = (IQueryEngine *) std::stoi(
+                                       rep.getValue<std::string>("queryEngineId"));
 
                     res = pQueryEngine->executeContextQuery(
-                              requestAttributeMap["contextQuery"].back(), &CQID);
+                              rep.getValue<std::string>("contextQuery"), &CQID);
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("ExecuteContextQuery failed");
+                        rep.setValue("error", "ExecuteContextQuery failed");
                         goto CLEANUP;
                     }
 
                     sstream << CQID;
 
-                    responseAttributeMap["CQID"].push_back(sstream.str());
+                    rep.setValue("CQID", sstream.str());
                 }
-                else if (requestAttributeMap["command"].back() == "KillContextQuery")
+                else if (rep.getValue<std::string>("command") == "KillContextQuery")
                 {
-                    pQueryEngine = (IQueryEngine *) stoi(
-                                       requestAttributeMap["queryEngineId"].back());
+                    pQueryEngine = (IQueryEngine *) std::stoi(
+                                       rep.getValue<std::string>("queryEngineId"));
 
-                    res = pQueryEngine->killContextQuery(stoi(requestAttributeMap["CQID"].back()));
+                    res = pQueryEngine->killContextQuery(std::stoi(rep.getValue<std::string>("CQID")));
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("KillContextQuery failed");
+                        rep.setValue("error", "KillContextQuery failed");
                         goto CLEANUP;
                     }
                 }
@@ -315,8 +316,6 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 CLEANUP:
                 if (response)
                 {
-                    rep.setAttributeMap(responseAttributeMap);
-
                     response->setErrorCode(200);
                     response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
                 }
@@ -330,12 +329,12 @@ CLEANUP:
                 // DELETE request operations
             }
         }
-        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
         {
             // perform observe related operations on the resource.
         }
     }
-    else
-    {
-    }
+
+    return OCPlatform::sendResponse(response) == OC_STACK_OK ? OC_EH_OK : OC_EH_ERROR;
 }
@@ -34,11 +34,9 @@ class SSMResourceServer
         int initializeManager(std::string &xmlDescription);
         int terminateManager();
 
-        void entityHandler(std::shared_ptr< OC::OCResourceRequest > request,
-                           std::shared_ptr< OC::OCResourceResponse > response);
+        OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest > request);
 
     private:
-        OC::OCPlatform *m_pPlatform;
         OCResourceHandle m_hSSMResource;
         int createResource();
 };
index 5eed956..0d0149e 100644 (file)
 #include "QueryProcessor/ConditionedModel.h"
 #include "QueryProcessor/EvaluationEngine.h"
 #include "QueryProcessor/PropagationEngine.h"
-#include "SensorProcessor/ResponseReactor.h"
+#include "SensorProcessor/SensingEngine.h"
 #include "SensorProcessor/ContextExecutor.h"
 #include "SensorProcessor/ContextDataReader.h"
 #include "SensorProcessor/ResourceFinder.h"
-#include "SensorProcessor/ResourceConnectivity.h"
 
 inline bool operator<( const OID &lhs, const OID &rhs )
 {
@@ -121,8 +120,9 @@ SSMRESULT CSoftSensorManager::initializeCore(IN std::string xmlDescription)
     }
 
     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IContextRepository, (IBase **)&m_pContextRepository));
-    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
-    m_pContextRepository->setCurrentDeviceInfo(name, type, pathSoftSensors, pathDescription);
+    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
+    SSM_CLEANUP_ASSERT(m_pContextRepository->initRepository(name, type, pathSoftSensors,
+                       pathDescription));
 
     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IPropagationEngine, (IBase **)&m_pPropagationEngine));
 
@@ -173,7 +173,7 @@ unsigned long CSoftSensorManager::releaseQueryEngine(IN IQueryEngine *pQueryEngi
 
 SSMRESULT CSoftSensorManager::getInstalledModelList(OUT std::vector<ISSMResource *> *pList)
 {
-    m_pResponseReactor->getList(pList);
+    m_pSensingEngine->getList(pList);
 
     return SSM_S_OK;
 }
@@ -238,18 +238,11 @@ SSMRESULT CreateGlobalInstance(IN const OID &objectID, OUT IBase **ppvObject)
             SSM_CLEANUP_ASSERT(CreateInstance(OID_IContextDataReader, ppvObject));
         }
     }
-    else if (IsEqualOID(OID_IResponseReactor, objectID))
+    else if (IsEqualOID(OID_ISensingEngine, objectID))
     {
-        if (g_globalInstance->find(OID_IResponseReactor) == g_globalInstance->end())
+        if (g_globalInstance->find(OID_ISensingEngine) == g_globalInstance->end())
         {
-            SSM_CLEANUP_ASSERT(CreateInstance(OID_IResponseReactor, ppvObject));
-        }
-    }
-    else if (IsEqualOID(OID_IResourceConnectivity, objectID))
-    {
-        if (g_globalInstance->find(OID_IResourceConnectivity) == g_globalInstance->end())
-        {
-            SSM_CLEANUP_ASSERT(CreateInstance(OID_IResourceConnectivity, ppvObject));
+            SSM_CLEANUP_ASSERT(CreateInstance(OID_ISensingEngine, ppvObject));
         }
     }
     else
@@ -313,9 +306,9 @@ SSMRESULT CreateInstance(IN const OID &objectID, OUT IBase **ppObject)
     {
         SSM_CLEANUP_ASSERT(CreateNewObject<CContextRepository>(objectID, ppObject));
     }
-    else if (IsEqualOID(OID_IResponseReactor, objectID))
+    else if (IsEqualOID(OID_ISensingEngine, objectID))
     {
-        SSM_CLEANUP_ASSERT(CreateNewObject<CResponseReactor>(objectID, ppObject));
+        SSM_CLEANUP_ASSERT(CreateNewObject<CSensingEngine>(objectID, ppObject));
     }
     else if (IsEqualOID(OID_IContextExecutor, objectID))
     {
@@ -353,10 +346,6 @@ SSMRESULT CreateInstance(IN const OID &objectID, OUT IBase **ppObject)
     {
         SSM_CLEANUP_ASSERT(CreateNewObject<CContextDataReader>(objectID, ppObject));
     }
-    else if (IsEqualOID(OID_IResourceConnectivity, objectID))
-    {
-        SSM_CLEANUP_ASSERT(CreateNewObject<CResourceConnectivity>(objectID, ppObject));
-    }
 
 CLEANUP:
     return res;
index 1718097..8baa123 100644 (file)
@@ -44,7 +44,7 @@ class CSoftSensorManager :
     private:
         CObjectPtr<IContextRepository>      m_pContextRepository;
         CObjectPtr<IPropagationEngine>      m_pPropagationEngine;
-        CObjectPtr<IResponseReactor>        m_pResponseReactor;
+        CObjectPtr<ISensingEngine>          m_pSensingEngine;
 
     public:
         SSMRESULT finalConstruct();
diff --git a/service/soft-sensor-manager/SSMCore/src/SSMResourceServerLauncher.cpp b/service/soft-sensor-manager/SSMCore/src/SSMResourceServerLauncher.cpp
deleted file mode 100644 (file)
index bf96c57..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed 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.
- *
- ******************************************************************/
-
-/*
- * SSMResourceServerLauncher.cpp
- */
-#include "SSMResourceServer.h"
-
-string xmlDescription = "<SSMCore>"
-                        "<Device>"
-                        "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
-                        "<Name>MyPC</Name>"
-                        "<Type>PC</Type>"
-                        "</Device>"
-                        "</SSMCore>";
-
-using namespace std;
-
-int main(int argc, char *argv[])
-{
-    int inputKey = 0;
-
-    try
-    {
-        SSMResourceServer ssmResourceServer;
-
-        cout << "Initializing Resource Server" << endl;
-
-        if (ssmResourceServer.initializeManager(xmlDescription) != 0)
-        {
-            cout << "SSM Resource Server init failed" << endl;
-            return -1;
-        }
-
-        cout << "SSM Resource Server is working, press anykey to terminate" << endl;
-
-        cin >> inputKey;
-
-        cout << "SSM Resource Server is terminating" << endl;
-
-        if (ssmResourceServer.terminateManager() != 0)
-        {
-            cout << "SSM Resource Server terminate failed" << endl;
-        }
-    }
-    catch (std::exception e)
-    {
-        cout << e.what() << endl;
-    }
-
-    cout << "bye bye" << endl;
-}
index 9f26e55..2fbcd84 100644 (file)
@@ -75,22 +75,6 @@ void CContextExecutor::getDataFromDatabase(std::string modelName, int startIndex
     m_pContextDataReader->getContextData(modelName, startIndex, count, data, pLastIndex);
 }
 
-std::string CContextExecutor::checkError(std::vector<ContextData> data)
-{
-    std::string errorMsg = "OK";
-
-    for (unsigned int i = 0 ; i < data.size() ; ++i)
-    {
-        if (data[i].outputProperty[0].find("error") != data[i].outputProperty[0].end())
-        {
-            errorMsg = data[i].outputProperty[0].find("error")->second ;
-            break;
-        }
-    }
-
-    return errorMsg;
-}
-
 void CContextExecutor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
                                        IEvent *pEvent)
 {
@@ -242,10 +226,12 @@ std::map<std::string, std::vector<ContextData> >  CContextExecutor::getPreparedC
     std::string primitiveSensor)
 {
     //check m_relatedSoftSensor / apply timestamp
-    std::map<std::string, std::vector<ContextData> > returnData;
 
     SSMRESULT ret = SSM_E_FAIL;
 
+    std::map<std::string, std::vector<ContextData> >    returnData;
+    std::vector<ContextData>                            contextDataList;
+
     for (unsigned int i = 0; i < m_relatedSoftSensor[primitiveSensor].size(); ++i)
     {
         std::string softSensorName = m_relatedSoftSensor[primitiveSensor][i];
@@ -253,24 +239,26 @@ std::map<std::string, std::vector<ContextData> >  CContextExecutor::getPreparedC
         {
             ret = SSM_S_OK;
             std::vector<std::string> inputList = m_registeredResources[softSensorName]->inputList;
-            std::vector<ContextData> contextDataList;
             for (unsigned int j = 0; j < inputList.size(); j++) //check all "inputlist" arrived or not
             {
                 if (m_storedPrimitiveSensorData.find(inputList[j]) == m_storedPrimitiveSensorData.end())
                 {
+                    //Still we have partial data
                     ret = SSM_E_FAIL;
                     break;
                 }
                 else
                 {
-                    std::vector<ContextData> primitiveSensorData = m_storedPrimitiveSensorData[inputList[j]];
-                    for (unsigned k = 0; k < primitiveSensorData.size(); k++)
+                    //Copy all properties of current primitiveSensor data to outputs
+                    for (std::vector<ContextData>::iterator itor = m_storedPrimitiveSensorData[inputList[j]].begin();
+                         itor != m_storedPrimitiveSensorData[inputList[j]].end(); ++itor)
                     {
-                        contextDataList.push_back(primitiveSensorData[k]);
+                        contextDataList.push_back(*itor);
                     }
                 }
             }
 
+            //We have all inputs
             if (ret == SSM_S_OK)
             {
                 returnData.insert(std::make_pair(softSensorName, contextDataList));
@@ -296,27 +284,14 @@ int CContextExecutor::onEvent(std::string type, TypeofEvent callType,
         //find soft sensor
         std::map<std::string, std::vector<ContextData> > readyContextList = getPreparedContextList(type);
 
-        if (readyContextList.size() > 0)
+        //Run SoftSensor!  readyContextList has all data for run
+        std::map<std::string, std::vector<ContextData> >::iterator iter;
+        for (iter = readyContextList.begin(); iter != readyContextList.end(); ++iter)
         {
-            //Run SoftSensor!  readyContextList has all data for run
-            std::map<std::string, std::vector<ContextData> >::iterator iter = readyContextList.begin();
-            for (; iter != readyContextList.end(); ++iter)
-            {
-                std::string softSensorName = iter->first;
-                std::vector<ContextData> inputData = iter->second;
-                std::string errorMsg = checkError(inputData);
+            std::string softSensorName = iter->first;
+            std::vector<ContextData> inputData = iter->second;
 
-                if (!errorMsg.compare("OK"))
-                {
-                    runLogic(inputData, softSensorName);
-                }
-                else
-                {
-                    inputData.clear();
-                    inputData.push_back(makeErrorContextData(softSensorName, errorMsg));
-                    addOutput(inputData);
-                }
-            }
+            runLogic(inputData, softSensorName);
         }
     }
     else //This data is primitive
@@ -421,18 +396,4 @@ void CContextExecutor::runLogic(std::vector<ContextData> inputData, std::string
         m_ctxEventList[softSensor]->onCtxEvent(SPF_START, inputData);
     }
     m_mtxLibraryIO.unlock();
-}
-
-ContextData CContextExecutor::makeErrorContextData(std::string rootName, std::string errMsg)
-{
-    std::map<std::string, std::string> errorMap;
-    ContextData errorContextData;
-
-    errorMap.insert(std::make_pair("error", errMsg));
-    errorMap.insert(std::make_pair("available", "false"));
-    errorContextData.rootName = rootName;
-    errorContextData.outputPropertyCount = 2;
-    errorContextData.outputProperty.push_back(errorMap);
-
-    return errorContextData;
 }
\ No newline at end of file
index c8f88a9..6b3a6c9 100644 (file)
@@ -214,9 +214,6 @@ class CContextExecutor :
         std::map<std::string, std::vector<ContextData> >  getPreparedContextList(
             IN std::string primitiveSensor);
         void runLogic(IN std::vector<ContextData> inputData, IN std::string softSensor);
-        ContextData makeErrorContextData(IN std::string rootName, IN std::string errMsg);
-        std::string checkError(IN std::vector<ContextData> data);
-
 };
 
 #endif
index f6c6423..c17f703 100644 (file)
@@ -65,23 +65,43 @@ void CContextRepository::finalRelease()
 {
 }
 
-void CContextRepository::setCurrentDeviceInfo(IN std::string name, IN std::string type,
+SSMRESULT CContextRepository::initRepository(IN std::string name, IN std::string type,
         IN std::string pathSoftSensors, IN std::string pathDescription)
 {
-    //TODO: Someone need to provides a way to generate permanent uuid function
-    /*
-    m_currentDeviceInfo.friendlyName = name;
-    //m_currentDeviceInfo.ID="2fac1234-31f8-11b4-a222-08002b34c003";
-    m_currentDeviceInfo.ID = udn;
-    m_currentDeviceInfo.IPAddress = "127.0.0.1";
-    m_currentDeviceInfo.tp = tp;
-    //m_currentDeviceInfo.type = SSM_DEVICE_MOBILE;
-    m_currentDeviceInfo.type = td;
-    */
+    SSMRESULT res = SSM_E_FAIL;
+
+    std::vector<DictionaryData> dict;
+
     m_name = name;
     m_type = type;
-    m_pathSoftSensors = pathSoftSensors;
-    m_pathSoftSensorsDescription = pathDescription;
+
+    if (pathSoftSensors.length() == 0)
+    {
+        SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
+        m_pathSoftSensors.append("/");
+    }
+    else
+    {
+        m_pathSoftSensors = pathSoftSensors;
+    }
+
+    if (pathDescription.length() == 0)
+    {
+        SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensorsDescription));
+        m_pathSoftSensorsDescription.append("/");
+        m_pathSoftSensorsDescription.append(DEFAULT_PATH_SOFT_SENSORS);
+    }
+    else
+    {
+        m_pathSoftSensorsDescription = pathDescription;
+    }
+
+
+    SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
+    SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, &m_lstSoftSensor));
+
+CLEANUP:
+    return res;
 }
 
 SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
@@ -118,7 +138,7 @@ SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
             keyStr = subItem->name();  // key
             valueStr = subItem->value();   // value
 
-            if (!keyStr.compare("root_name"))
+            if (!keyStr.compare("name"))
             {
                 dictionaryData.rootName = trim_both(valueStr);
             }
@@ -131,58 +151,29 @@ SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
                 keyStr = subItem2->name();  // key
                 valueStr = subItem2->value();   // value
 
-                if (!keyStr.compare("attribute_property_count"))
-                {
-                    dictionaryData.attributePropertyCount = trim_both(valueStr);
-                }
-                else if (!keyStr.compare("output_property_count"))
-                {
-                    dictionaryData.outputPropertyCount  = trim_both(valueStr);
-                }
-                if (!keyStr.compare("inputs_count"))
-                {
-                    dictionaryData.inputCount = trim_both(valueStr);
-                }
-                else if (!keyStr.compare("app_inputs_count"))
-                {
-                    dictionaryData.appInputCount  = trim_both(valueStr);
-                }
-                else if (!keyStr.compare("app_input"))
-                {
-                    dictionaryData.appInputs.push_back(trim_both(valueStr));
-                }
-                else if (!keyStr.compare("input"))
+                if (!keyStr.compare("input"))
                 {
                     dictionaryData.inputs.push_back(trim_both(valueStr));
                 }
                 ////std::cout<<name << " :: " << subItem2->value() <<std::endl<<std::endl;
                 for (subItem3 = subItem2->first_node(); subItem3 ; subItem3 = subItem3->next_sibling())
                 {
-
                     std::string newKeyStr = subItem3->name();  // key
                     valueStr = subItem3->value();   // value
 
-                    if (!keyStr.compare("attribute_property") || !keyStr.compare("output_property") )
-                    {
-                        propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr)))    ;
-                    }
-                    else if (!keyStr.compare("enter_condition"))
+                    if (!keyStr.compare("attribute") || !keyStr.compare("output") )
                     {
-                        enterconditionVector.push_back(trim_both(valueStr));
+                        propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr)));
                     }
                 }
-                if (!keyStr.compare("attribute_property"))
+                if (!keyStr.compare("attribute"))
                 {
                     dictionaryData.attributeProperty.push_back(propertyMap);
                 }
-                else if (!keyStr.compare("output_property"))
+                else if (!keyStr.compare("output"))
                 {
                     dictionaryData.outputProperty.push_back(propertyMap);
                 }
-                else if (!keyStr.compare("enter_condition"))
-                {
-                    dictionaryData.enterConditions.push_back(enterconditionVector);
-                }
             }
         }
         //for accurate data.
@@ -208,22 +199,6 @@ SSMRESULT CContextRepository::loadXMLFromFile(std::string descriptionFilePath,
     SSMRESULT res = SSM_E_FAIL;
     std::basic_ifstream< char > xmlFile(descriptionFilePath.c_str());
 
-    if (descriptionFilePath.length() > 0 && xmlFile.fail())
-    {
-        //error while opening given path, return error
-        SSM_CLEANUP_ASSERT(SSM_E_FAIL);
-    }
-
-    if (descriptionFilePath.length() == 0)
-    {
-        //No given path, try to open local Path
-        std::string path;
-        SSM_CLEANUP_ASSERT(GetCurrentPath(&path));
-        path.append("/");
-        path.append(DEFAULT_PATH_SOFT_SENSORS);
-        xmlFile.open(path);
-    }
-
     //path loaded
     if (!xmlFile.fail())
     {
@@ -250,23 +225,20 @@ CLEANUP:
 
 SSMRESULT CContextRepository::getSoftSensorList(OUT std::vector<ISSMResource *> *pSoftSensorList)
 {
-    SSMRESULT res = SSM_E_FAIL;
-    std::vector<DictionaryData> dict;
-
-    SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
-
-    SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, pSoftSensorList));
+    for (size_t i = 0; i < m_lstSoftSensor.size(); i++)
+    {
+        pSoftSensorList->push_back(m_lstSoftSensor.at(i));
+    }
 
-CLEANUP:
-    return res;
+    return SSM_S_OK;
 }
 
 SSMRESULT CContextRepository::getPrimitiveSensorList(OUT std::vector<ISSMResource *>
         *pPrimitiveSensorList)
 {
-    for (size_t i = 0; i < m_lstSensor.size(); i++)
+    for (size_t i = 0; i < m_lstPrimitiveSensor.size(); i++)
     {
-        pPrimitiveSensorList->push_back(m_lstSensor.at(i));
+        pPrimitiveSensorList->push_back(m_lstPrimitiveSensor.at(i));
     }
 
     return SSM_S_OK;
@@ -274,7 +246,7 @@ SSMRESULT CContextRepository::getPrimitiveSensorList(OUT std::vector<ISSMResourc
 
 SSMRESULT CContextRepository::onResourceFound(IN ISSMResource *pSensor)
 {
-    m_lstSensor.push_back(pSensor);
+    m_lstPrimitiveSensor.push_back(pSensor);
 
     for (size_t i = 0; i < m_resourceEvents.size(); i++)
     {
@@ -287,11 +259,11 @@ SSMRESULT CContextRepository::onResourceFound(IN ISSMResource *pSensor)
 SSMRESULT CContextRepository::onResourceLost(IN ISSMResource *pSensor)
 {
     std::vector<ISSMResource *>::iterator    itor;
-    itor = std::find(m_lstSensor.begin(), m_lstSensor.end(), pSensor);
+    itor = std::find(m_lstPrimitiveSensor.begin(), m_lstPrimitiveSensor.end(), pSensor);
 
-    if (itor != m_lstSensor.end())
+    if (itor != m_lstPrimitiveSensor.end())
     {
-        m_lstSensor.erase(itor);
+        m_lstPrimitiveSensor.erase(itor);
         return SSM_S_OK;
     }
 
@@ -349,13 +321,6 @@ SSMRESULT CContextRepository::loadSoftSensor(std::string softSensorName, ICtxDel
     typedef void(*InitContext)(IN ICtxDelegate *);
     InitContext InitializeContextFunction = NULL;
 
-    if (m_pathSoftSensors.length() == 0)
-    {
-        SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
-    }
-
-    m_pathSoftSensors.append("/");
-
     // load dll(so)
     res = SSM_E_FAIL;
     for (unsigned int i = 1; i <= SSM_MODEL_RETRY; ++i)
@@ -386,8 +351,10 @@ SSMRESULT CContextRepository::loadSoftSensor(std::string softSensorName, ICtxDel
 #endif
         if (hModule == NULL)
         {
-            InitializeContextFunction = NULL;
-            continue;
+            //load library failed. raise error
+            SSM_CLEANUP_ASSERT(SSM_E_FAIL);
+            //InitializeContextFunction = NULL;
+            //continue;
         }
 
         if (InitializeContextFunction != NULL)
index 314408f..d3e13e3 100644 (file)
@@ -42,7 +42,8 @@ class CContextRepository :
 {
     private:
         CSimpleMutex                 m_mtxFileIO;
-        std::vector<ISSMResource *>   m_lstSensor;
+        std::vector<ISSMResource *>   m_lstPrimitiveSensor;
+        std::vector<ISSMResource *>   m_lstSoftSensor;
         CObjectPtr<IResourceFinder>  m_resourceFinder;
         std::string                  m_name;
         std::string                  m_type;
@@ -72,21 +73,21 @@ class CContextRepository :
 
 
         /**
-        * @fn           setCurrentDeviceInfo
-        * @brief        set device information
+        * @fn           initRepository
+        * @brief        initialize repository using given info
         *
         * @param        [in] std::string name - Device name
         * @param        [in] std::string type - Device Type
         * @param        [in] std::string pathSoftSensors - SoftSensors Repository path
         * @param        [in] std::string pathDescription - SoftSensors Description path
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        void setCurrentDeviceInfo(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
-                                  IN std::string pathDescription);
+        SSMRESULT initRepository(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
+                                 IN std::string pathDescription);
 
         /**
         * @fn           getSoftSensorList
diff --git a/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.cpp b/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.cpp
deleted file mode 100644 (file)
index 67214c8..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed 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 "ResourceConnectivity.h"
-
-SSMRESULT CResourceConnectivity::finalConstruct()
-{
-    SSMRESULT res = SSM_E_FAIL;
-    OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
-                           "134.134.161.33", 56831, OC::QualityOfService::NonConfirmable);
-
-    m_pPlatform = new OC::OCPlatform(cfg);
-
-    SSM_CLEANUP_NULL_ASSERT(m_pPlatform);
-
-    res = SSM_S_OK;
-
-CLEANUP:
-    return res;
-}
-
-void CResourceConnectivity::finalRelease()
-{
-    SAFE_DELETE(m_pPlatform);
-}
-
-void *CResourceConnectivity::getPlatform()
-{
-    return m_pPlatform;
-}
diff --git a/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.h b/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.h
deleted file mode 100644 (file)
index ec28c81..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed 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 _ResourceConnectivity_H_
-#define _ResourceConnectivity_H_
-
-#include "SSMInterface/SSMCore.h"
-#include "Common/PlatformLayer.h"
-#include "Common/InternalInterface.h"
-#include "OCPlatform.h"
-
-class CResourceConnectivity :
-    public CObjectRoot<CObjectMultiThreadModel>
-    , public IResourceConnectivity
-{
-    public:
-        SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
-        {
-            if (ppObject == NULL)
-                return SSM_E_POINTER;
-
-            if (IsEqualOID(objectID, OID_IResourceConnectivity))
-            {
-                IBase *pBase = (IResourceConnectivity *)this;
-                pBase->addRef();
-                *ppObject = pBase;
-                return SSM_S_OK;
-            }
-
-            return SSM_E_NOINTERFACE;
-        }
-
-        SSMRESULT finalConstruct();
-        void finalRelease();
-
-        void *getPlatform();
-
-    private:
-        OC::OCPlatform      *m_pPlatform;
-};
-
-#endif
index dcf1f1c..1eaa069 100644 (file)
@@ -23,12 +23,14 @@ SSMRESULT CResourceFinder::finalConstruct()
 {
     SSMRESULT res = SSM_E_FAIL;
 
+    OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+                           "0.0.0.0", 0, OC::QualityOfService::LowQos);
+
     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ITasker, (IBase **)&m_pTasker));
-    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResourceConnectivity,
-                                            (IBase **)&m_pResourceConnectivity));
+
+    OC::OCPlatform::Configure(cfg);
 
     m_pResourceFinderEvent = NULL;
-    m_pPlatform = (OC::OCPlatform *)m_pResourceConnectivity->getPlatform();
 
 CLEANUP:
     return res;
@@ -58,9 +60,13 @@ void CResourceFinder::onResourceFound(std::shared_ptr<OC::OCResource> resource)
 
 SSMRESULT CResourceFinder::startResourceFinder()
 {
-    //m_pPlatform->findResource("", "oc/core/service/SoftSensorManager/SoftSensor",
-    m_pPlatform->findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
-                              std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+    OCStackResult res = OC_STACK_ERROR;
+
+    res = OC::OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
+                                       std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+
+    if (res != OC_STACK_OK)
+        return SSM_E_FAIL;
 
     return SSM_S_OK;
 }
@@ -91,7 +97,7 @@ void CResourceFinder::onExecute(IN void *pArg)
             SSM_CLEANUP_ASSERT(pResourceHandler->initHandler(*pResource, this));
             m_mapResourceHandler[pResource->get()->host() + pResource->get()->uri()] = pResourceHandler;
             pResource->get()->get(queryParams, std::bind(&OICResourceHandler::onGetResourceProfile,
-                                  pResourceHandler, std::placeholders::_1, std::placeholders::_2));
+                                  pResourceHandler, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
             break;
 
         case RESOURCE_DISCOVER_SETUP_RESOURCE:
index dc1b524..b070a77 100644 (file)
@@ -24,6 +24,7 @@
 #include "Common/PlatformLayer.h"
 #include "Common/InternalInterface.h"
 #include "OCPlatform.h"
+#include "OCApi.h"
 
 class CResourceFinder :
     public CObjectRoot<CObjectMultiThreadModel>
@@ -90,7 +91,7 @@ CLEANUP:
 
                     m_pResource.get()->observe(OC::ObserveType::Observe, queryParams,
                                                std::bind(&OICResourceHandler::onResourceDataReceived,
-                                                         this, std::placeholders::_1, std::placeholders::_2));
+                                                         this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
 
                     return SSM_S_OK;
                 }
@@ -102,28 +103,29 @@ CLEANUP:
                     return SSM_S_OK;
                 }
 
-                void onResourceDataReceived(const OC::OCRepresentation &representation, const int &eCode)
+                void onResourceDataReceived(const OC::HeaderOptions headerOptions,
+                                            const OC::OCRepresentation &representation,
+                                            const int &eCode, const int &sequenceNumber)
                 {
                     if (eCode == 0)
                     {
                         std::vector<ContextData>        lstCtxData;
                         ContextData             ctxData;
                         std::map<std::string, std::string>  outputProperty;
-                        OC::AttributeMap            attributeMap = representation.getAttributeMap();
 
                         //Bind data
                         ctxData.rootName = m_pResource->uri().substr(1);
 
                         //TODO: Temporally used for json parsing limitation
-                        ctxData.outputPropertyCount = attributeMap.size() / 3;
+                        ctxData.outputPropertyCount = representation.numberOfAttributes() / 3;
 
                         if (ctxData.outputPropertyCount > 0)
                         {
-                            for (size_t i = 0; i < attributeMap.size() / 3; i++)
+                            for (int i = 0; i < ctxData.outputPropertyCount; i++)
                             {
-                                outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
-                                outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
-                                outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+                                outputProperty["name"] = representation.getValue<std::string>(toString(i * 3));
+                                outputProperty["type"] = representation.getValue<std::string>(toString(i * 3 + 1));
+                                outputProperty["value"] = representation.getValue<std::string>(toString(i * 3 + 2));
                                 ctxData.outputProperty.push_back(outputProperty);
                             }
 
@@ -138,13 +140,13 @@ CLEANUP:
                     }
                 }
 
-                void onGetResourceProfile(const OC::OCRepresentation &representation, const int &eCode)
+                void onGetResourceProfile(const OC::HeaderOptions &headerOptions,
+                                          const OC::OCRepresentation &representation, const int &eCode)
                 {
                     //unpack attributeMap
 
                     //Create SSMResource using OCResource attributeMap
                     std::map<std::string, std::string>      outputProperty;
-                    OC::AttributeMap                    attributeMap = representation.getAttributeMap();
                     ISSMResource        *pSSMResource = new ISSMResource();
                     pSSMResource->location = SENSOR_LOCATION_REMOTE;
                     pSSMResource->name = m_pResource->host() + m_pResource->uri();
@@ -160,11 +162,11 @@ CLEANUP:
                     //bind default primitive sensor property, value to resource class for schema creating
 
                     //TODO: Temporally used for json parsing limitation
-                    for (size_t i = 0; i < attributeMap.size() / 3; i++)
+                    for (int i = 0; i < representation.numberOfAttributes() / 3; i++)
                     {
-                        outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
-                        outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
-                        outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+                        outputProperty["name"] = representation.getValue<std::string>(toString(i * 3));
+                        outputProperty["type"] = representation.getValue<std::string>(toString(i * 3 + 1));
+                        outputProperty["value"] = representation.getValue<std::string>(toString(i * 3 + 2));
                         pSSMResource->outputProperty.push_back(outputProperty);
                     }
                     /////////////////////////////////////////////////////
@@ -181,11 +183,16 @@ CLEANUP:
                 std::shared_ptr<OC::OCResource>     m_pResource;
                 IThreadClient                       *m_pResourceFinderClient;
                 IEvent                              *m_pEvent;
+
+                std::string toString(int t)
+                {
+                    std::ostringstream os;
+                    os << t;
+                    return os.str();
+                }
         };
 
         enum RESOURCE_DISCOVER_STATE {RESOURCE_DISCOVER_REQUESTPROFILE, RESOURCE_DISCOVER_SETUP_RESOURCE};
-        OC::OCPlatform                      *m_pPlatform;
-        CObjectPtr<IResourceConnectivity>   m_pResourceConnectivity;
         IResourceFinderEvent                *m_pResourceFinderEvent;
         CObjectPtr<ITasker>             m_pTasker;
         std::map<std::string , OICResourceHandler *> m_mapResourceHandler;
@@ -17,9 +17,9 @@
 * limitations under the License.
 *
 ******************************************************************/
-#include "ResponseReactor.h"
+#include "SensingEngine.h"
 
-SSMRESULT CResponseReactor::finalConstruct()
+SSMRESULT CSensingEngine::finalConstruct()
 {
     SSMRESULT res = SSM_S_OK;
 
@@ -31,12 +31,12 @@ CLEANUP:
     return res;
 }
 
-void CResponseReactor::finalRelease()
+void CSensingEngine::finalRelease()
 {
 }
 
-void CResponseReactor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
-                                       IEvent *pEvent)
+SSMRESULT CSensingEngine::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
+        IEvent *pEvent)
 {
     m_mtxRequestedContextData.lock();
     // if already exists
@@ -53,9 +53,11 @@ void CResponseReactor::registerContext(TypeofEvent callType, ISSMResource *pSSMR
     m_pContextExecutor->registerContext(callType, pSSMResource, this);
 
     m_mtxRequestedContextData.unlock();
+
+    return SSM_S_OK;
 }
 
-void CResponseReactor::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+SSMRESULT CSensingEngine::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
         IEvent *pEvent)
 {
     m_mtxUnregisterContext.lock();
@@ -70,20 +72,24 @@ void CResponseReactor::unregisterContext(TypeofEvent callType, ISSMResource *pSS
     }
 
     m_mtxUnregisterContext.unlock();
+
+    return SSM_S_OK;
 }
 
-void CResponseReactor::getList(std::vector<ISSMResource *> *pList)
+SSMRESULT CSensingEngine::getList(std::vector<ISSMResource *> *pList)
 {
     pList->clear();
 
     m_pContextRepository->getSoftSensorList(pList);
 
     m_pContextRepository->getPrimitiveSensorList(pList);
+
+    return SSM_S_OK;
 }
 
 //Dispatch to upper layer
-int CResponseReactor::onEvent(std::string type, TypeofEvent callType,
-                              std::vector<ContextData> ctxData)
+int CSensingEngine::onEvent(std::string type, TypeofEvent callType,
+                            std::vector<ContextData> ctxData)
 {
     std::map<std::string, CallbackData >::iterator  itor;
 
 
 #include "SSMInterface/SSMCore.h"
 #include "Common/PlatformLayer.h"
-
-//temp include
-#include "ContextRepository.h"
-#include "ContextExecutor.h"
+#include "Common/InternalInterface.h"
 
 /**
- * @class    CResponseReactor
- * @brief    Class for implement of reactor pattern
- *           Delegate requested context to context executor layer.
+ * @class    CSensingEngine
+ * @brief    Class for implementing main abstration of SensorProcessor
  *
  *
  * @see
  */
-class CResponseReactor :
+class CSensingEngine :
     public CObjectRoot<CObjectMultiThreadModel>
-    , public IResponseReactor
+    , public ISensingEngine
 {
     private:
         CObjectPtr<IContextRepository>  m_pContextRepository;
@@ -57,7 +53,6 @@ class CResponseReactor :
         CSimpleMutex                        m_mtxUnregisterContext;
 
     public:
-
         SSMRESULT finalConstruct();
         void finalRelease();
 
@@ -66,7 +61,7 @@ class CResponseReactor :
             if (ppObject == NULL)
                 return SSM_E_POINTER;
 
-            if (IsEqualOID(objectID, OID_IResponseReactor))
+            if (IsEqualOID(objectID, OID_ISensingEngine))
             {
                 IBase *pBase = this;
                 pBase->addRef();
@@ -85,13 +80,14 @@ class CResponseReactor :
         * @param        [in]  ISSMResource *pSSMResource -  Requested context model resource.
         * @param        [in]  IEvent *pEvent -  IEvent class for callback.
         *
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        void registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+        SSMRESULT registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+                                  IN IEvent *pEvent);
 
         /**
         * @fn           unregisterContext
@@ -101,13 +97,14 @@ class CResponseReactor :
         * @param        [in]  ISSMResource *pSSMResource -  Requested context model resource.
         * @param        [in]  IEvent *pEvent -  IEvent class for callback.
         *
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        void  unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+        SSMRESULT  unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+                                     IN IEvent *pEvent);
 
         /**
         * @fn           getList
@@ -115,13 +112,13 @@ class CResponseReactor :
         *
         * @param        [out]  std::vector<ISSMResource> *pList - ISSMResource vector of low level context models or high level context models.
         *
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        virtual void getList(OUT std::vector<ISSMResource *> *pList);
+        SSMRESULT getList(OUT std::vector<ISSMResource *> *pList);
 
         /**
         * @fn           onEvent
@@ -140,6 +137,4 @@ class CResponseReactor :
         */
         int onEvent(IN std::string name, IN TypeofEvent callType, IN std::vector<ContextData> ctxData);
 };
-
-
-#endif
+#endif
\ No newline at end of file
diff --git a/service/soft-sensor-manager/SampleApp/SConscript b/service/soft-sensor-manager/SampleApp/SConscript
new file mode 100644 (file)
index 0000000..545d993
--- /dev/null
@@ -0,0 +1,24 @@
+##
+# sampleapp build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+sample_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+
+######################################################################
+# Build flags
+######################################################################
+
+######################################################################
+# Source files and Targets
+######################################################################
+if target_os == 'linux' :
+       # Build linux sample app
+       SConscript('linux/SSMTesterApp/SConscript')
+       SConscript('linux/THSensorApp/SConscript')
+       SConscript('linux/THSensorApp1/SConscript')
index df3988f..0d7011d 100644 (file)
@@ -1,23 +1,39 @@
+# //******************************************************************
+# //
+# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+# //
+# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+# //
+# // Licensed 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 ../../../../build/arduino/environment.mk
-
 ARDUINO_DIR = /usr/share/arduino
-SRC_PATH=../src
 
+BUILD := release
+PLATFORM := arduinomega
+ARDUINO_PORT := ttyACM0
+
+SRC_PATH=../src
 # override with `make PLATFORM=arduinomega ARDUINOWIFI=1` to enable Arduino WiFi shield
 ARDUINOWIFI := 0
 
 APP_NAME := thserver
 
-BUILD := release
-#BUILD := debug
-PLATFORM := arduinomega
-ARDUINO_PORT := /dev/ttyACM0
-
-OBJ_DIR := ./bin
-
-TB_DIR = ${IOT_BASE}/csdk
-BUILD_DIR = $(TB_DIR)/build/arduino
+TB_DIR = ../../../../../../resource/csdk
 LOGGER_DIR = $(TB_DIR)/logger
+OC_LOG_DIR = $(TB_DIR)/../oc_logger
 TBSTACK_DIR = $(TB_DIR)/stack
 TBSOCKET_DIR = $(TB_DIR)/ocsocket
 
@@ -30,56 +46,81 @@ VPATH := $(SDIR_ARD_PLATFORM)
 OCSOCK_DIR = $(TB_DIR)/ocsocket
 LOGGER_DIR = $(TB_DIR)/logger
 STACK_DIR  = $(TB_DIR)/stack
-INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(STACK_DIR)/include
+INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(OC_LOG_DIR)/include -I$(LOGGER_DIR)/include -I$(STACK_DIR)/include
+
+CC_FLAGS.debug         := -O1 -g3 -Wall -c -fmessage-length=0 -pedantic -fpic
+CC_FLAGS.release       := -Os -Wall -c -fmessage-length=0 -fpic
 
-CFLAGS := -Os -Wall -c -DTB_LOG
+CFLAGS := $(CC_FLAGS.$(BUILD)) -DTB_LOG
 
 ifeq ($(ARDUINOWIFI),1)
        CFLAGS += -DARDUINOWIFI
+       ARDUINO_SHIELD_TYPE := "/wifi_shield"
+       TRANSPORT_OBJS = $(WIFI_COBJ)
+else
+       ARDUINO_SHIELD_TYPE := "/ethernet_shield"
+       TRANSPORT_OBJS = $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ)
 endif
 
-#all: prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex
-all: preclean prebuild precopy prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex
+OUT_DIR := $(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)
 
-precopy:
-#      @cd $(TB_DIR) && mkdir -p ${BUILD} && cp -Rdp release/liboctbstack.a ${BUILD}/
+OBJ_DIR := $(OUT_DIR)/bin
 
-preclean: 
-       @cd $(BUILD_DIR) && make deepclean 
-       
-prebuild:
-       @cd $(BUILD_DIR) && make PLATFORM=arduinomega ARDUINOWIFI=0
+all: prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex
 
 core.a: $(PLATFORM_OBJS)
-       @cd $(OBJ_DIR) && $(AR) -x $(TB_DIR)/build/arduino/$(BUILD)/liboctbstack.a
-       $(AR) rcs $@ $^ $(OBJ_DIR)/*.o
-       $(RANLIB) $@
+       @cd $(OBJ_DIR) && $(AR) -x ../../../../$(TB_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/liboctbstack.a
+       $(AR) rcs $(OBJ_DIR)/$@ $(foreach obj, $^, $(OBJ_DIR)/$(obj)) $(OBJ_DIR)/*.o
+       @cd $(OBJ_DIR) && $(RANLIB) $@
 
 prep_dirs:
+       -mkdir $(PLATFORM)
+       -mkdir $(PLATFORM)/$(ARDUINO_SHIELD_TYPE)
+       -mkdir $(OUT_DIR)
        -mkdir $(OBJ_DIR)
 
 %.o: %.c
-       $(CC) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@
-
+       $(CC) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@
 %.o: %.cpp
-       $(CCPLUS) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@
-
+       $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@ 
 %.o: ${SRC_PATH}/%.cpp
-       $(CCPLUS) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@
+       $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@
 
 $(APP_NAME).elf: $(APP_NAME).o core.a
-       $(CC) -Os -Wl,--gc-sections,--relax $(CFLAGS_PLATFORM) $^ -lm -o $@
+ifeq ($(PLATFORM),arduinomega)
+       $(CC) -Os -Wl,--gc-sections,--relax $(CFLAGS_PLATFORM) $(foreach obj, $^, $(OBJ_DIR)/$(obj)) -lm -o $(OBJ_DIR)/$@
+else ifeq ($(PLATFORM),arduinodue)
+       $(CXX) -Os -Wl,--gc-sections -mcpu=cortex-m3 -T/$(SDIR_ARD_CORE_3)/linker_scripts/gcc/flash.ld -Wl,-Map,$(APP_NAME).map -o $(OBJ_DIR)/$@ -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group $(foreach obj, $(APP_NAME).o $(SYSCALLS_SAM3_OBJ) $(SPI_OBJ) $(TRANSPORT_OBJS) $(VARIANT_OBJ) core.a, $(OBJ_DIR)/$(obj)) $(SDIR_ARD_CORE_3)/libsam_sam3x8e_gcc_rel.a -Wl,--end-group
+else
+       $(error Wrong value for PLATFORM !!)
+endif
 
 $(APP_NAME).hex: $(APP_NAME).elf
-       $(AVR_OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(APP_NAME).eep
-       $(AVR_OBJCOPY) -O ihex -R .eeprom $< $@
+ifeq ($(PLATFORM),arduinomega)
+       $(AVR_OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $(OBJ_DIR)/$< $(OBJ_DIR)/$(APP_NAME).eep
+       $(AVR_OBJCOPY) -O ihex -R .eeprom $(OBJ_DIR)/$< $(OUT_DIR)/$@
+else ifeq ($(PLATFORM),arduinodue)
+       $(ARDUINO_TOOLS_DIR)/arm-none-eabi-objcopy -O binary $(OBJ_DIR)/$< $(OUT_DIR)/$@
+else
+       $(error Wrong value for PLATFORM !!)
+endif
 
 install: all
-       $(AVR_PROGRAMMER) -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P$(ARDUINO_PORT) -b115200 -D -Uflash:w:$(APP_NAME).hex:i
+ifeq ($(PLATFORM),arduinomega)
+       $(AVR_PROGRAMMER) -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/$(ARDUINO_PORT) -b115200 -D -Uflash:w:$(OUT_DIR)/$(APP_NAME).hex:i
+else ifeq ($(PLATFORM),arduinodue)
+       stty -F /dev/$(ARDUINO_PORT) speed 1200 cs8 -cstopb -parenb
+       $(ARDUINO_DIR)/hardware/tools/bossac -i -d --port=$(ARDUINO_PORT) -U false -e -w -v -b $(OUT_DIR)/$(APP_NAME).hex -R
+else
+       $(error Wrong value for PLATFORM !!)
+endif
 
 .PHONY: clean
 
-clean:
-       @rm -f *.o *.d *.elf *.eep *.a *.hex *.bin *.map *-
-       @rm -rf $(OBJ_DIR)
+clean: legacy_clean
+       rm -rf arduinomega
+       rm -rf arduinodue
 
+legacy_clean:
+       @rm -rf bin
+       @rm -f *.o *.d *.elf *.eep *.a *.hex *.bin *.map *-
index 572d372..28cb319 100644 (file)
@@ -58,14 +58,38 @@ typedef struct THRESOURCE
 
 static THResource TH;
 
-String g_responsePayloadPut =
-    "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
-String g_responsePayloadGet =
-    "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
+//char* g_responsePayloadPut =    "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
+//char* g_responsePayloadGet =    "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
 
 /// This is the port which Arduino Server will use for all unicast communication with it's peers
 static uint16_t OC_WELL_KNOWN_PORT = 5683;
 
+#define JSON_BASE00 "{\"href\":\"\",\"rep\":{"
+#define JSON_BASE01 "\"0\":\"temperature\",\"1\":\"int\",\"2\":\""
+#define JSON_BASE02 "\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\""
+#define JSON_BASE03 "\"}}"
+
+char temp[100];
+
+#define LENGTH_VAR      100
+static int base_length = 0;
+
+bool JsonGenerator( THResource &th, char *jsonBuf, uint16_t buf_length )
+{
+    if ( (buf_length - base_length) < LENGTH_VAR )
+    {
+        OC_LOG_V(ERROR, TAG, "Error : length is very long.");
+        return false;
+    }
+
+    sprintf(jsonBuf, JSON_BASE00 JSON_BASE01"%d", th.m_temp);
+    sprintf(jsonBuf + strlen(jsonBuf), JSON_BASE02"%d"JSON_BASE03, th.m_humid);
+
+    Serial.println(jsonBuf);
+
+    return true;
+}
+
 byte read_dht11_dat()
 {
     byte i = 0;
@@ -93,6 +117,9 @@ static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0";
 char ssid[] = "SoftSensor_AP";
 char pass[] = "1234567890";
 
+//char ssid[] = "Iotivity-1";
+//char pass[] = "1234567890";
+
 int ConnectToNetwork()
 {
     char *fwVersion;
@@ -141,7 +168,8 @@ int ConnectToNetwork()
         OC_LOG_V(ERROR, TAG, "error is: %d", error);
         return -1;
     }
-    OC_LOG_V(INFO, TAG, "IPAddress : %s", Serial.print(Ethernet.localIP()));
+    IPAddress ip = Ethernet.localIP();
+    OC_LOG_V(INFO, TAG, "IP Address:  %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
     return 0;
 }
 #endif //ARDUINOWIFI
@@ -159,90 +187,63 @@ void PrintArduinoMemoryStats()
     extern char *__brkval;
     //address of tmp gives us the current stack boundry
     int tmp;
+    OC_LOG_V(INFO, TAG, "Stack: %u         Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
     OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
              ((unsigned int)&tmp - (unsigned int)__brkval));
 #endif
 }
 
+
 // This is the entity handler for the registered resource.
 // This is invoked by OCStack whenever it recevies a request for this resource.
 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
                                         OCEntityHandlerRequest *entityHandlerRequest )
 {
     OCEntityHandlerResult ehRet = OC_EH_OK;
-    const char *typeOfMessage;
 
-    switch (flag)
-    {
-        case OC_INIT_FLAG:
-            typeOfMessage = "OC_INIT_FLAG";
-            break;
-        case OC_REQUEST_FLAG:
-            typeOfMessage = "OC_REQUEST_FLAG";
-            break;
-        case OC_OBSERVE_FLAG:
-            typeOfMessage = "OC_OBSERVE_FLAG";
-            break;
-        default:
-            typeOfMessage = "UNKNOWN";
-    }
-    OC_LOG_V(INFO, TAG, "Receiving message type: %s", typeOfMessage);
-
-    if (entityHandlerRequest && flag == OC_REQUEST_FLAG)
+    if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
     {
+        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
         if (OC_REST_GET == entityHandlerRequest->method)
         {
-            int str_len = g_responsePayloadGet.length() + 1;
-            char charBuf[str_len + 1];
-
-            g_responsePayloadGet.toCharArray(charBuf, str_len);
-
-            if (strlen(charBuf) < entityHandlerRequest->resJSONPayloadLen)
+            if (JsonGenerator( TH, (char *)entityHandlerRequest->resJSONPayload, \
+                               entityHandlerRequest->resJSONPayloadLen))
             {
-                strncpy((char *)entityHandlerRequest->resJSONPayload, charBuf,
-                        entityHandlerRequest->resJSONPayloadLen);
             }
             else
+            {
                 ehRet = OC_EH_ERROR;
+            }
         }
         if (OC_REST_PUT == entityHandlerRequest->method)
         {
-
-            int str_len1 = g_responsePayloadPut.length() + 1;
-            char charBuf1[str_len1];
-
-            g_responsePayloadPut.toCharArray(charBuf1, str_len1);
-
-            if (strlen(charBuf1) < entityHandlerRequest->resJSONPayloadLen)
+            //Do something with the 'put' payload
+            if (JsonGenerator( TH, (char *)entityHandlerRequest->resJSONPayload, \
+                               entityHandlerRequest->resJSONPayloadLen))
             {
-                strncpy((char *)entityHandlerRequest->resJSONPayload, charBuf1,
-                        entityHandlerRequest->resJSONPayloadLen);
             }
             else
+            {
                 ehRet = OC_EH_ERROR;
+            }
         }
     }
-    else if (entityHandlerRequest && flag == OC_OBSERVE_FLAG)
+    if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
     {
-        g_THUnderObservation = 1;
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
+        {
+            OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+            g_THUnderObservation = 1;
+        }
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
+        {
+            OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+        }
     }
 
     return ehRet;
 }
 
-/* Json Generator */
-String JsonGenerator(THResource TH)
-{
-    String a = "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"";
-    String b = "\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"";
-    String c = "\"}}";
-
-    String ss;
-
-    ss = a + TH.m_temp + b + TH.m_humid + c;
-    return ss;
-}
-
 // This method is used to display 'Observe' functionality of OC Stack.
 static uint8_t modCounter = 0;
 void *ChangeTHRepresentation (void *param)
@@ -297,18 +298,15 @@ void *ChangeTHRepresentation (void *param)
         Serial.print(dht11_dat[2], DEC);
         Serial.println("C  ");
 
-// delay(2000); //fresh time
         TH.m_humid = dht11_dat[0];
         TH.m_temp = dht11_dat[2];
 
-        g_responsePayloadGet = JsonGenerator(TH);
-
         if (g_THUnderObservation)
         {
             OC_LOG_V(INFO, TAG, " =====> Notifying stack of new humid level %d\n", TH.m_humid);
             OC_LOG_V(INFO, TAG, " =====> Notifying stack of new temp level %d\n", TH.m_temp);
 
-            result = OCNotifyObservers (TH.m_handle);
+            result = OCNotifyAllObservers (TH.m_handle, OC_NA_QOS);
 
             if (OC_STACK_NO_OBSERVERS == result)
             {
index 52a3596..67a1609 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../build/linux/root_path.inc
 -include ../../build/linux/environment.mk
 
 MAKE=make
diff --git a/service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/SConscript b/service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/SConscript
new file mode 100644 (file)
index 0000000..f711552
--- /dev/null
@@ -0,0 +1,36 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+linux_sample_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include'])
+linux_sample_env.AppendUnique(CPPPATH = ['../../../SSMCore/include'])
+linux_sample_env.AppendUnique(CPPPATH = ['../../../SSMCore/src'])
+linux_sample_env.AppendUnique(CPPPATH = ['../../../SDK/include'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['libSSMSDK'])
+linux_sample_env.AppendUnique(LIBS = ['libSSMCORE'])
+linux_sample_env.AppendUnique(LIBS = ['oc'])
+linux_sample_env.AppendUnique(LIBS = ['octbstack'])
+linux_sample_env.AppendUnique(LIBS = ['libcoap'])
+linux_sample_env.AppendUnique(LIBS = ['liboc_logger'])
+linux_sample_env.AppendUnique(LIBS = ['dl'])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+ssmtesterapp = linux_sample_env.Program('SSMTesterApp', 'src/SSMTestApp.cpp')
+Alias("SSMTesterApp", ssmtesterapp)
+env.AppendTarget('SSMTesterApp')
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -7,15 +7,19 @@ INC_PATH=../include
 RST_NAME=release
 
 # Insert your project name.
-TARGET=ClientApp
+TARGET=SSMTesterApp
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+
 
+CXX_LIB+=${OUTPUTS_DIR}/${SSM_LIB} 
+CXX_LIB+=${OUTPUTS_DIR}/${SSMCORE_LIB} 
 CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
 CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} 
-CXX_LIB+=-lpthread
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
+CXX_LIB+=-lpthread -ldl
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
 OBJPATH=${SRCLIST:.cpp=.o}
@@ -28,11 +32,11 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "--------- ClientApp Build Begin. -----------" 
+       @echo "--------- ${TARGET} Build Begin. -----------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
-${TARGET}: ${OBJLIST} ${OUTPUTS_DIR}/SSMClient.o
+${TARGET}: ${OBJLIST}
        $(CXX) $(CXX_FLAGS) -o ./${RST_NAME}/$@ $^ ${CXX_LIB}
        @echo " "
 
@@ -43,7 +47,7 @@ ${TARGET}: ${OBJLIST} ${OUTPUTS_DIR}/SSMClient.o
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
-       @echo "----------- ClientApp Build Successful. ------------"
+       @echo "----------- ${TARGET} Build Successful. ------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
@@ -29,6 +29,7 @@
 
 #include "OCResource.h"
 #include "OCPlatform.h"
+#include "SSMInterface.h"
 #include "SSMClient.h"
 #include "ISSMClientListener.h"
 
@@ -47,9 +48,11 @@ typedef enum
 } DIResult;
 
 class SSMTestApp: public ISSMClientListener
+    , public IQueryEngineEvent
 {
     private:
-        SSMClient m_SSMClient;
+        //SSMClient m_SSMClient;
+        SSMInterface m_SSMClient;
 
     public:
 
@@ -60,8 +63,8 @@ class SSMTestApp: public ISSMClientListener
         void unregisterQuery();
 
         /* operations from listener interface */
-        void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode);
-
+        void onRegisterQuery(const std::string &jsonData, SSMReturn &eCode);
+        SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult);
 };
 
 #endif /* SSMTESTAPP_H_ */
@@ -23,7 +23,6 @@
 #include <iostream>
 
 #include "SSMTestApp.h"
-#include "SSMClient.h"
 
 SSMTestApp::SSMTestApp()
 {
@@ -45,8 +44,8 @@ void SSMTestApp::displayMenu()
 /* Register Query.*/
 void SSMTestApp::registerQuery(std::string queryString)
 {
-    std::string qid;
-    SSMReturn rtn = SSM_ERROR;
+    int qid;
+    SSMRESULT rtn = SSM_E_FAIL;
 
     if (queryString.size() == 0)
     {
@@ -57,10 +56,10 @@ void SSMTestApp::registerQuery(std::string queryString)
 
     rtn = m_SSMClient.registerQuery(queryString, this, qid);
 
-    if (rtn == SSM_SUCCESS)
+    if (rtn == SSM_S_OK)
     {
         printf("The query has been registered!\n");
-        printf("QID : %s\n", qid.c_str());
+        printf("QID : %d\n", qid);
     }
     else
         printf("Error occured(%d)", rtn);
@@ -70,73 +69,26 @@ void SSMTestApp::registerQuery(std::string queryString)
 void SSMTestApp::unregisterQuery(void)
 {
     std::string qid;
-    SSMReturn rtn = SSM_ERROR;
+    SSMRESULT rtn = SSM_E_FAIL;
 
     printf("   Please Enter query string: ");
     cin.ignore();
     getline(cin, qid);
 
-    rtn = m_SSMClient.unregisterQuery(qid);
+    rtn = m_SSMClient.unregisterQuery(atoi(qid.c_str()));
 
-    if (rtn == SSM_SUCCESS)
+    if (rtn == SSM_S_OK)
         printf("The query has been unregistered!\n");
     else
         printf("Error occured(%d)\n", (int) rtn);
 }
 
 /* APP. Level Callback Function for Observer of client. */
-void SSMTestApp::onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode)
+void SSMTestApp::onRegisterQuery(const std::string &jsonData, SSMReturn &eCode)
 {
     if (eCode == SSM_SUCCESS)
     {
-        printf("onListener!!!!\n");
-        printf("\n");
-        printf("T : dry bult temperature. (℃)\n");
-        printf("H : relative humidity. (%%)\n");
-        printf("Discomport level = 9/5 * T + 32 - 0.55*(1 - H/100)*(9/5 * T - 26) \n");
-        printf("\n");
-        printf("**************************************\n");
-        printf("* All    Discomport level : 80 over. *\n");
-        printf("* Half   Discomport level : 75 over. *\n");
-        printf("* Little Discomport level : 68 over. *\n");
-        printf("* All    Comport    level : 67 under.*\n");
-        printf("**************************************\n");
-        printf("\n");
-
-        for (AttributeMap::const_iterator itor = attributeMap.begin(); itor != attributeMap.end();
-             ++itor)
-        {
-            if (strcmp(itor->first.c_str(), "temperature") == 0)
-            {
-                std::cout << "* Temperature : " << itor->second.front().c_str() << "℃" << std::endl;
-            }
-            else if (strcmp(itor->first.c_str(), "humidity") == 0)
-            {
-                std::cout << "* Humidity : " << itor->second.front().c_str() << "%" << std::endl;
-            }
-            else if (strcmp(itor->first.c_str(), "discomfortIndex") == 0)
-            {
-                int DI = std::stoi(itor->second.front().c_str());
-
-                std::cout << "* DiscomfortIndex : " << DI << "%" << std::endl;
-
-                switch (DI)
-                {
-                    case ALL_DISCOMPORT:
-                        std::cout << "* [Result] All person Discomfort." << std::endl;
-                        break;
-                    case HALF_DISCOMPORT:
-                        std::cout << "* [Result] Half person Discomfort." << std::endl;
-                        break;
-                    case LITTLE_DISCOMPORT:
-                        std::cout << "* [Result] Little person Discomfort." << std::endl;
-                        break;
-                    case ALL_COMPORT:
-                        std::cout << "* [Result] All person Comfort." << std::endl;
-                        break;
-                }
-            }
-        }
+        std::cout << jsonData << std::endl;
     }
     else
     {
@@ -144,6 +96,36 @@ void SSMTestApp::onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eC
     }
 }
 
+SSMRESULT SSMTestApp::onQueryEngineEvent(int cqid, IDataReader *pResult)
+{
+    int     dataCount = 0;
+    IModelData      *pModelData = NULL;
+    std::vector<std::string>        affectedModels;
+
+    cout << "Event received! cqid = " << cqid << endl;
+
+    pResult->getAffectedModels(&affectedModels);
+
+    for (std::vector<std::string>::iterator itor = affectedModels.begin();
+         itor != affectedModels.end(); ++itor)
+    {
+        cout << "Printing " << *itor << " model" << endl;
+        pResult->getModelDataCount(*itor, &dataCount);
+        for (int i = 0; i < dataCount; i++)
+        {
+            pResult->getModelData(*itor, i, &pModelData);
+            cout << "dataId: " << pModelData->getDataId() << endl;
+            for (int j = 0; j < pModelData->getPropertyCount(); j++)
+            {
+                cout << "Type: " << pModelData->getPropertyName(j) << " Value: " << pModelData->getPropertyValue(
+                         j) << endl;
+            }
+        }
+    }
+
+    return SSM_S_OK;
+}
+
 /**
  * APP. Main Function.
  */
diff --git a/service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript b/service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript
new file mode 100644 (file)
index 0000000..9ea870c
--- /dev/null
@@ -0,0 +1,30 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+linux_sample_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc'])
+linux_sample_env.AppendUnique(LIBS = ['octbstack'])
+linux_sample_env.AppendUnique(LIBS = ['libcoap'])
+linux_sample_env.AppendUnique(LIBS = ['liboc_logger'])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+thsensorapp = linux_sample_env.Program('THSensorApp', 'src/ThingResourceServer.cpp')
+Alias("thsensorapp_sample", thsensorapp)
+env.AppendTarget('thsensorapp_sample')
index eaa5630..28802e8 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -11,10 +11,11 @@ TARGET=THSensorApp
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 
 CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
 CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} 
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
 CXX_LIB+=-lpthread
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@@ -28,7 +29,7 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "---------- THSensorApp Build Begin. ------------" 
+       @echo "---------- ${TARGET} Build Begin. ------------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
@@ -43,7 +44,7 @@ ${TARGET}: ${OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
-       @echo "----------- THSensorApp Build Successful. -------------"
+       @echo "----------- ${TARGET} Build Successful. -------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
index 8431ceb..d8b5dc8 100644 (file)
@@ -35,8 +35,8 @@ using namespace std;
 #include <string>
 #include <cstdlib>
 
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               56830
+#define COAP_IP                 "0.0.0.0"
+#define COAP_PORT               0
 #define COAP_MODE               ModeType::Server
 #define COAP_SRVTYPE        ServiceType::InProc
 
@@ -50,27 +50,39 @@ class TemphumidResource
         /// Access this property from a TB client
         int m_humid;
         int m_temp;
-        string m_resourceUri;
+        std::string m_resourceUri;
+        std::vector<std::string> m_resourceTypes;
+        std::vector<std::string> m_resourceInterfaces;
         OCResourceHandle m_resourceHandle;
+        OCRepresentation m_resourceRep;
+        ObservationIds m_interestedObservers;
 
     public:
         /// Constructor
         TemphumidResource() :
-            m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor"), m_resourceHandle(NULL)
+            m_humid(0), m_temp(0)
         {
+            m_resourceUri = "/Thing_TempHumSensor";
+            m_resourceTypes.push_back(COAP_TYPE_NAME);
+            m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+            printf("Running thing as %s\n", m_resourceUri.c_str());
+            m_resourceRep.setUri(m_resourceUri);
+            m_resourceRep.setResourceTypes(m_resourceTypes);
+            m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
         }
 
         ~TemphumidResource()
         {
         }
 
-        void registerResource(OC::OCPlatform &platform);
+        void registerResource();
 
         OCResourceHandle getHandle();
 
-        void setRepresentation(AttributeMap &attributeMap);
+        void setResourceRepresentation(OCRepresentation &rep);
 
-        void getRepresentation(AttributeMap &attributeMap);
+        OCRepresentation getResourceRepresentation();
 };
 
 #endif /* THINGRESOURCESERVER_H_ */
index 8c32639..39e0fff 100644 (file)
 
 int g_Observation = 0;
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request);
 
 /*
  * TempResourceFunctions
  */
 
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
 {
-    string resourceURI = m_resourceUri; // URI of the resource
-    string resourceTypeName = COAP_TYPE_NAME; // resource type name.
-    string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
     // This will internally create and register the resource.
-    OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
-                           resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+    OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+                           m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
 
     if (OC_STACK_OK != result)
     {
@@ -52,29 +47,37 @@ OCResourceHandle TemphumidResource::getHandle()
     return m_resourceHandle;
 }
 
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
 {
-    cout << "\t\t\t" << "Received representation: " << endl;
-    cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
-    cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+    int tempHumid;
+    int tempTemp;
+
+    rep.getValue("2", tempTemp);
+    rep.getValue("5", tempHumid);
+
+    m_humid = tempHumid;
+    m_temp = tempTemp;
 
-    m_temp = std::stoi(attributeMap["temp"][0]);
-    m_humid = std::stoi(attributeMap["humid"][0]);
+    cout << "\t\t\t" << "Received representation: " << endl;
+    cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+    cout << "\t\t\t\t" << "humid: " << m_temp << endl;
 }
 
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
 {
-    attributeMap["0"].push_back("temperature");
-    attributeMap["1"].push_back("int");
-
-    attributeMap["2"].push_back(to_string(m_temp));
 
-    attributeMap["3"].push_back("humidity");
-    attributeMap["4"].push_back("int");
+    // This representation is temporaily for soft-sensor-management - name, type, vale
+    m_resourceRep.setValue("0", std::string("temperature"));
+    m_resourceRep.setValue("1", std::string("int"));
+    m_resourceRep.setValue("2", std::to_string(m_temp));
+    m_resourceRep.setValue("3", std::string("humidity"));
+    m_resourceRep.setValue("4", std::string("int"));
+    m_resourceRep.setValue("5", std::to_string(m_humid));
 
-    attributeMap["5"].push_back(to_string(m_humid));
+    return m_resourceRep;
 }
 
+// Create the instance of the TemphumidResource class
 TemphumidResource g_myResource;
 
 void *TestSensorVal(void *param)
@@ -97,7 +100,7 @@ void *TestSensorVal(void *param)
             cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
                  << endl;
 
-            OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+            OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
 
             if (OC_STACK_NO_OBSERVERS == result)
             {
@@ -109,24 +112,29 @@ void *TestSensorVal(void *param)
     return NULL;
 }
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request)
 {
     cout << "\tIn Server CPP entity handler:\n";
 
+    auto response = std::make_shared<OC::OCResourceResponse>();
+
     if (request)
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if (requestFlag == RequestHandlerFlag::InitFlag)
+        response->setRequestHandle(request->getRequestHandle());
+        response->setResourceHandle(request->getResourceHandle());
+
+        if (requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
 
             // entity handler to perform resource initialization operations
         }
-        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
 
@@ -136,20 +144,14 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 cout << "\t\t\trequestType : GET\n";
 
                 // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
                 // Process query params and do required operations ..
 
                 // Get the representation of this resource at this point and send it as response
-                OCRepresentation rep = request->getResourceRepresentation();
-                AttributeMap attributeMap;
-
-                g_myResource.getRepresentation(attributeMap);
+                OCRepresentation rep = g_myResource.getResourceRepresentation();
 
                 if (response)
                 {
                     // TODO Error Code
-                    rep.setAttributeMap(attributeMap);
                     response->setErrorCode(200);
                     response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
                 }
@@ -167,7 +169,8 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 // DELETE request operations
             }
         }
-        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
         {
             pthread_t threadId;
 
@@ -187,18 +190,20 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
     {
         std::cout << "Request invalid" << std::endl;
     }
+
+    return OCPlatform::sendResponse(response) == OC_STACK_OK ? OC_EH_OK : OC_EH_ERROR;
 }
 
 int main()
 {
     // Create PlatformConfig object
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
 
     try
     {
-        OCPlatform platform(cfg);
+        OC::OCPlatform::Configure(cfg);
 
-        g_myResource.registerResource(platform);
+        g_myResource.registerResource();
 
         int input = 0;
         cout << "Type any key to terminate" << endl;
diff --git a/service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript b/service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript
new file mode 100644 (file)
index 0000000..f6c65fa
--- /dev/null
@@ -0,0 +1,30 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+linux_sample_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc'])
+linux_sample_env.AppendUnique(LIBS = ['octbstack'])
+linux_sample_env.AppendUnique(LIBS = ['libcoap'])
+linux_sample_env.AppendUnique(LIBS = ['liboc_logger'])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+thsensorapp1 = linux_sample_env.Program('THSensorApp', 'src/ThingResourceServer1.cpp')
+Alias("thsensorapp1_sample", thsensorapp1)
+env.AppendTarget('thsensorapp1_sample')
index 360f3ef..a195f01 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -11,10 +11,11 @@ TARGET=THSensorApp1
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 
 CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
 CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} 
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
 CXX_LIB+=-lpthread
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@@ -28,7 +29,7 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "---------- THSensorApp Build Begin. ------------" 
+       @echo "---------- ${TARGET} Build Begin. ------------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
@@ -43,7 +44,7 @@ ${TARGET}: ${OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
-       @echo "----------- THSensorApp Build Successful. -------------"
+       @echo "----------- ${TARGET} Build Successful. -------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
index eada4e6..b32b589 100644 (file)
@@ -35,8 +35,8 @@ using namespace std;
 #include <string>
 #include <cstdlib>
 
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               56838
+#define COAP_IP                 "0.0.0.0"
+#define COAP_PORT               0
 #define COAP_MODE               ModeType::Server
 #define COAP_SRVTYPE        ServiceType::InProc
 
@@ -50,27 +50,39 @@ class TemphumidResource
         /// Access this property from a TB client
         int m_humid;
         int m_temp;
-        string m_resourceUri;
+        std::string m_resourceUri;
+        std::vector<std::string> m_resourceTypes;
+        std::vector<std::string> m_resourceInterfaces;
         OCResourceHandle m_resourceHandle;
+        OCRepresentation m_resourceRep;
+        ObservationIds m_interestedObservers;
 
     public:
         /// Constructor
         TemphumidResource() :
-            m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor1"), m_resourceHandle(NULL)
+            m_humid(0), m_temp(0)
         {
+            m_resourceUri = "/Thing_TempHumSensor1";
+            m_resourceTypes.push_back(COAP_TYPE_NAME);
+            m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+            printf("Running thing as %s\n", m_resourceUri.c_str());
+            m_resourceRep.setUri(m_resourceUri);
+            m_resourceRep.setResourceTypes(m_resourceTypes);
+            m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
         }
 
         ~TemphumidResource()
         {
         }
 
-        void registerResource(OC::OCPlatform &platform);
+        void registerResource();
 
         OCResourceHandle getHandle();
 
-        void setRepresentation(AttributeMap &attributeMap);
+        void setResourceRepresentation(OCRepresentation &rep);
 
-        void getRepresentation(AttributeMap &attributeMap);
+        OCRepresentation getResourceRepresentation();
 };
 
 #endif /* THINGRESOURCESERVER_H_ */
index b1d3857..c52416b 100644 (file)
 
 int g_Observation = 0;
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request);
 
 /*
- * TempResourceFunctions
- */
+* TempResourceFunctions
+*/
 
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
 {
-    string resourceURI = m_resourceUri; // URI of the resource
-    string resourceTypeName = COAP_TYPE_NAME; // resource type name.
-    string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
     // This will internally create and register the resource.
-    OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
-                           resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+    OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+                           m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
 
     if (OC_STACK_OK != result)
     {
@@ -52,29 +47,37 @@ OCResourceHandle TemphumidResource::getHandle()
     return m_resourceHandle;
 }
 
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
 {
-    cout << "\t\t\t" << "Received representation: " << endl;
-    cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
-    cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+    int tempHumid;
+    int tempTemp;
+
+    rep.getValue("2", tempTemp);
+    rep.getValue("5", tempHumid);
+
+    m_humid = tempHumid;
+    m_temp = tempTemp;
 
-    m_temp = std::stoi(attributeMap["temp"][0]);
-    m_humid = std::stoi(attributeMap["humid"][0]);
+    cout << "\t\t\t" << "Received representation: " << endl;
+    cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+    cout << "\t\t\t\t" << "humid: " << m_temp << endl;
 }
 
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
 {
-    attributeMap["0"].push_back("temperature");
-    attributeMap["1"].push_back("int");
-
-    attributeMap["2"].push_back(to_string(m_temp));
 
-    attributeMap["3"].push_back("humidity");
-    attributeMap["4"].push_back("int");
+    // This representation is temporaily for soft-sensor-management - name, type, vale
+    m_resourceRep.setValue("0", std::string("temperature"));
+    m_resourceRep.setValue("1", std::string("int"));
+    m_resourceRep.setValue("2", std::to_string(m_temp));
+    m_resourceRep.setValue("3", std::string("humidity"));
+    m_resourceRep.setValue("4", std::string("int"));
+    m_resourceRep.setValue("5", std::to_string(m_humid));
 
-    attributeMap["5"].push_back(to_string(m_humid));
+    return m_resourceRep;
 }
 
+// Create the instance of the TemphumidResource class
 TemphumidResource g_myResource;
 
 void *TestSensorVal(void *param)
@@ -97,7 +100,7 @@ void *TestSensorVal(void *param)
             cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
                  << endl;
 
-            OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+            OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
 
             if (OC_STACK_NO_OBSERVERS == result)
             {
@@ -109,24 +112,29 @@ void *TestSensorVal(void *param)
     return NULL;
 }
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request)
 {
     cout << "\tIn Server CPP entity handler:\n";
 
+    auto response = std::make_shared<OC::OCResourceResponse>();
+
     if (request)
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if (requestFlag == RequestHandlerFlag::InitFlag)
+        response->setRequestHandle(request->getRequestHandle());
+        response->setResourceHandle(request->getResourceHandle());
+
+        if (requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
 
             // entity handler to perform resource initialization operations
         }
-        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
 
@@ -136,20 +144,14 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 cout << "\t\t\trequestType : GET\n";
 
                 // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
                 // Process query params and do required operations ..
 
                 // Get the representation of this resource at this point and send it as response
-                OCRepresentation rep = request->getResourceRepresentation();
-                AttributeMap attributeMap;
-
-                g_myResource.getRepresentation(attributeMap);
+                OCRepresentation rep = g_myResource.getResourceRepresentation();
 
                 if (response)
                 {
                     // TODO Error Code
-                    rep.setAttributeMap(attributeMap);
                     response->setErrorCode(200);
                     response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
                 }
@@ -167,7 +169,8 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 // DELETE request operations
             }
         }
-        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
         {
             pthread_t threadId;
 
@@ -178,7 +181,7 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
 
             if (!startedThread)
             {
-                pthread_create(&threadId, NULL, TestSensorVal, (void *) NULL);
+                pthread_create(&threadId, NULL, TestSensorVal, (void *)NULL);
                 startedThread = 1;
             }
         }
@@ -187,19 +190,20 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
     {
         std::cout << "Request invalid" << std::endl;
     }
+
+    return OCPlatform::sendResponse(response) == OC_STACK_OK ? OC_EH_OK : OC_EH_ERROR;
 }
 
 int main()
 {
     // Create PlatformConfig object
-
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
 
     try
     {
-        OCPlatform platform(cfg);
+        OC::OCPlatform::Configure(cfg);
 
-        g_myResource.registerResource(platform);
+        g_myResource.registerResource();
 
         int input = 0;
         cout << "Type any key to terminate" << endl;
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/CMakeLists.txt b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/CMakeLists.txt
deleted file mode 100644 (file)
index 95611d0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(oic)
-
-SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
-SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
-SET(EX_SERVER "simpleserver")
-SET(EX_CLIENT "simpleclient")
-SET(EX_CLIENTSERVER "simpleclientserver")
-SET(OCTBSTACK "octbstack")
-
-INCLUDE_DIRECTORIES(include)
-INCLUDE_DIRECTORIES(csdk/stack/include)
-INCLUDE_DIRECTORIES(csdk/ocsocket/include)
-INCLUDE_DIRECTORIES(csdk/ocrandom/include)
-INCLUDE_DIRECTORIES(csdk/logger/include)
-INCLUDE_DIRECTORIES(csdk/libcoap-4.1.1)
-INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
-LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
-
-#SET(EXTRA_CXXFLAGS "-std=c++11")
-SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
-
-SET(SRCS
-       OCLib/OCReflect.cpp
-       OCLib/OCPlatform.cpp
-       OCLib/OCResource.cpp
-       OCLib/OCUtilities.cpp
-       OCLib/InProcServerWrapper.cpp
-       OCLib/InProcClientWrapper.cpp)
-ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
-
-ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_SUBDIRECTORY(csdk)
-#ADD_SUBDIRECTORY(examples)
-ADD_SUBDIRECTORY(oic-sample)
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/build.sh b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/build.sh
deleted file mode 100644 (file)
index 7b56050..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-# Prevent Support Tool(Defect analysis and commit) Execution Batch File!!
-
-# variables
-SDBPATH=/home/iotivity/tizen-sdk/tools/sdb
-GBSRPMPATH=/home/iotivity/GBS-ROOT/rsa/local/repos/rsa/armv7l/RPMS
-PACKAGE=oic-0.0.1-0.armv7l.rpm
-
-gbs build -A armv7l --include-all --ccache
-
-$SDBPATH root on
-
-$SDBPATH push $GBSRPMPATH/$PACKAGE /root/
-
-$SDBPATH shell rpm -Uvh --force /root/oic-0.0.1-0.armv7l.rpm
-
-$SDBPATH shell /usr/apps/com.samsung.oicapp-test/bin/oicapp-test
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.rule b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.rule
deleted file mode 100644 (file)
index fad1929..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-com.samsung.oicapp-test system::use_internet r
-
-system::use_internet com.samsung.oicapp-test r
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.xml b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.xml
deleted file mode 100644 (file)
index 5a79f6e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.oicapp-test" version="0.1.0" install-location="internal-only">
-       <label>OIC tset</label>
-       <author email="email@samsung.com" href="www.samsung.com">Name</author>
-       <description>OIC test Application</description>
-       <ui-application appid="com.samsung.oicapp-test" exec="/usr/apps/com.samsung.oicapp-test/bin/oicapp-test" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
-               <icon>com.samsung.oicapp-test.png</icon>
-               <label>OIC test</label>
-       </ui-application>
-</manifest>
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/ISSMClientListener.h b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/ISSMClientListener.h
deleted file mode 100644 (file)
index f425b3d..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed 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.
- *
- ******************************************************************/
-
-/**
- * @file    ISSMClientListener.h
- * @brief   This file contains client listener interfaces.
- */
-
-#ifndef ISSMCLIENTLISTENER_H_
-#define ISSMCLIENTLISTENER_H_
-#include <string>
-#include "OCPlatform.h"
-
-/**
- * @brief This enum defines Soft Sensor return types
- */
-typedef enum
-{
-    SSM_SUCCESS, SSM_ERROR, SSM_ERROR_QUERY_PARSING, SSM_ERROR_NO_QUERY, SSM_ERROR_NETWORK
-} SSMReturn;
-
-using namespace OC;
-/**
- *  @brief  ISSMClientListener is a listener interface from which application is derived to get callback from SoftSensorManager service
- */
-class ISSMClientListener
-{
-    public:
-        /**
-         * @brief   onRegisterQuery is a pure virtual operation which should be implemented in applications to get callback messages.
-         * @param [in] attributeMap - A data map in which SoftSensorManager service sends sensor data with cqid.
-         * @param [in] eCode - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
-         *                          SSMClient can callback message to the appication.
-         * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
-         * @return  SSMReturn
-
-         */
-        virtual void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode) = 0;
-        virtual ~ISSMClientListener()
-        {
-        }
-};
-
-#endif /* ISSMCLIENTLISTENER_H_ */
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.cpp b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.cpp
deleted file mode 100644 (file)
index e3375f2..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed 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 <iostream>
-#include <string>
-
-#include "SSMClient.h"
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-const char *SSM_RESOURCE_URI = "/service/SoftSensorManager";
-
-#define SSM_RESOURCE_TYPE       = "core.SoftSensorManager"
-
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               5683
-#define COAP_MODE               ModeType::Client
-#define COAP_SRVTYPE            ServiceType::InProc
-
-#define COAP_SERVER_ADDR        "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
-
-SSMClient::SSMClient()
-{
-    m_sem.create(100000);
-    m_pPlatform = NULL;
-    m_appListener = NULL;
-    m_retResponse = SSM_ERROR;
-    _findResource();
-    _createQueryEngine();
-}
-
-SSMClient::~SSMClient()
-{
-    _releaseQueryEngine(m_queryEngineId);
-    if (m_pPlatform)
-    {
-        delete m_pPlatform;
-        m_pPlatform = NULL;
-    }
-}
-
-void SSMClient::_findResource()
-{
-    // Create PlatformConfig object
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::Confirmable);
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-    try
-    {
-        m_pPlatform = new OCPlatform(cfg);
-
-        // Find all resources
-        OCStackResult result;
-        if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
-                                                std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
-            != OC_STACK_OK)
-        {
-            delete m_pPlatform;
-            m_pPlatform = NULL;
-            return;
-        }
-
-        m_sem.wait();
-
-    }
-    catch (OCException e)
-    {
-        //log(e.what());
-    }
-}
-
-void SSMClient::_createQueryEngine(void)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("CreateQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    if (m_SSMResource->put(rep, queryParamsMap,
-                           std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
-    {
-        return;
-    }
-
-    m_sem.wait();
-}
-
-void SSMClient::_releaseQueryEngine(std::string queryEngineId)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("ReleaseQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    m_SSMResource->put(rep, queryParamsMap,
-                       std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
-                                 std::placeholders::_2));
-
-    m_sem.wait();
-}
-
-SSMReturn SSMClient::registerQuery(std::string queryString, ISSMClientListener *listener,
-                                   std::string &cqid)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues contextQueryValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("ExecuteContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    contextQueryValue.push_back(queryString);
-
-    requestAttributeMap["contextQuery"] = contextQueryValue;
-
-    m_appListener = listener;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    if (m_SSMResource->put(rep, queryParamsMap,
-                           std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
-        return SSM_ERROR_NETWORK;
-
-    m_sem.wait();
-
-    if (m_retResponse == SSM_SUCCESS)
-    {
-        cqid = m_responseAttributeMap["CQID"].back();
-    }
-
-    return m_retResponse;
-}
-
-SSMReturn SSMClient::unregisterQuery(std::string cqid)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues cqidValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("KillContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    cqidValue.push_back(cqid);
-
-    requestAttributeMap["CQID"] = cqidValue;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    if (m_SSMResource->put(rep, queryParamsMap,
-                           std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
-        return SSM_ERROR_NETWORK;
-
-    m_sem.wait();
-
-    return m_retResponse;
-}
-
-/**
- * Callback Function List.
- */
-// Callback to found resources
-void SSMClient::onFoundResource(std::shared_ptr< OCResource > resource)
-{
-    std::string resourceURI;
-    try
-    {
-        // Do some operations with resource object.
-        if (resource)
-        {
-            // Get the resource URI
-            resourceURI = resource->uri();
-
-            if (resourceURI.compare(SSM_RESOURCE_URI) == 0)
-            {
-                m_SSMResource = resource;
-            }
-        }
-    }
-    catch (std::exception &e)
-    {
-        //log(e.what());
-    }
-
-    m_sem.release();
-}
-
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
-{
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-    m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
-    m_responseAttributeMap["queryEngineId"].pop_back();
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
-{
-    QueryParamsMap queryParamsMap;
-
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
-    {
-        m_retResponse = SSM_ERROR_QUERY_PARSING;
-        goto CLEANUP;
-    }
-
-    m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
-                           std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
-
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
-{
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
-    {
-        m_retResponse = SSM_ERROR_NO_QUERY;
-        goto CLEANUP;
-    }
-
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
-{
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
-{
-    SSMReturn ret = SSM_SUCCESS;
-
-    if (eCode != 0)
-    {
-        ret = SSM_ERROR_NETWORK;
-    }
-
-    m_appListener->onRegisterQuery(rep.getAttributeMap(), ret);
-}
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.h b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.h
deleted file mode 100644 (file)
index 1ee47bd..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed 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.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/**
- * @file    SSMClient.h
- * @brief   This file contains the declaration of classes and its members related to SSMClient.
- */
-
-#ifndef RESOURCECLIENT_H_
-#define RESOURCECLIENT_H_
-
-#include <string>
-
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "ISSMClientListener.h"
-
-using namespace OC;
-
-#if defined(WIN32)
-class CSemaphore
-{
-    private:
-        HANDLE hSemaphore;
-        int m_MaxTimeOut;
-
-    public:
-        /**
-         * This is CSemaphore constructor.
-         */
-        CSemaphore()
-        {
-            m_MaxTimeOut = 0;
-        }
-        /**
-         *This is CSemaphore destructor.
-         */
-        ~CSemaphore()
-        {
-        }
-
-        /**
-         * This is a function to creat a semaphore
-         * This is syncronus call.
-         * @param maximumRequestTimeOut
-         *          [IN] Request Time out.
-         *
-         * @return  None
-         *
-         */
-        void create(int maximumRequestTimeOut)
-        {
-            hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
-            m_MaxTimeOut = maximumRequestTimeOut;
-        }
-
-        /**
-         * This is a function to wait for semaphore
-         *
-         * @return  None
-         *
-         */
-        void wait()
-        {
-            WaitForSingleObject(hSemaphore, m_MaxTimeOut);
-        }
-
-        /**
-         * This is a function to release  semaphore
-         *
-         * @return  None
-         *
-         */
-        void release()
-        {
-            ReleaseSemaphore(hSemaphore, 1, NULL);
-        }
-
-};
-
-#elif defined(LINUX)
-#include <semaphore.h>
-
-#define SEM_SUCCESS     0
-
-class CSemaphore
-{
-    private:
-        sem_t hSemaphore;
-        timespec m_MaxTimeOut;
-
-    public:
-        /**
-         * This is CSemaphore constructor.
-         */
-        CSemaphore()
-        {
-            m_MaxTimeOut.tv_sec = 0;
-            m_MaxTimeOut.tv_nsec = 0;
-        }
-        /**
-         *This is CSemaphore destructor.
-         */
-        ~CSemaphore()
-        {
-        }
-        /**
-         * This is a function to creat a semaphore
-         * This is syncronus call.
-         * @param maximumRequestTimeOut
-         *          [IN] Request Time out.
-         *
-         * @return  None
-         *
-         */
-        void create(int maximumRequestTimeOut)
-        {
-            if ( sem_init(&hSemaphore, 1, 0) < SEM_SUCCESS )
-            {
-                perror("Error : sem_init.");
-                exit(0);
-            }
-            m_MaxTimeOut.tv_sec = maximumRequestTimeOut;
-        }
-
-        void wait()
-        {
-            sem_wait( &hSemaphore );
-        }
-
-        /**
-         * This is a function to release  semaphore
-         *
-         * @return  None
-         *
-         */
-        void release()
-        {
-            sem_post(&hSemaphore);
-        }
-
-};
-#endif
-
-/**
- *  @brief  SSMClient is a wrapper class to provide SoftSensorManager functionality to Application.
- *          Basically, SoftSensorManager is developed in Resource model (i.e. messaging with basic functions of put, get, and post).
- *          SSMClient abstracts the resource based operations from client applications and provides c++ style functions.
- */
-class SSMClient
-{
-    private:
-        SSMReturn m_retResponse;
-        OCPlatform *m_pPlatform;
-        CSemaphore m_sem;
-        /**
-         * @brief SoftSensorManager Resource.
-         */
-        std::shared_ptr< OCResource > m_SSMResource;
-        /**
-         * @brief attribute map .
-         */
-        AttributeMap m_responseAttributeMap;
-        /**
-         * @brief query engine.
-         */
-        std::string m_queryEngineId;
-        /**
-         * @brief app listener
-         */
-        ISSMClientListener *m_appListener;
-
-        /**
-         * @brief internal find resource function
-         */
-        void _findResource(void);
-
-        /**
-         * @brief internal Query engine function
-         */
-        void _createQueryEngine(void);
-
-        /**
-         * @brief internal release query function
-         */
-        void _releaseQueryEngine(std::string queryEngineId);
-
-    public:
-        /**
-         * Constructor for SSMClient.
-         */
-        SSMClient();
-        ~SSMClient();
-
-        /**
-         * This API sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
-         *
-         * @param [in] queryString - A conditions query statement where the caller application specifies sensors for required data and conditions when the caller wants to get the data.
-         * @param [in] listener - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
-         *                          SSMClient can callback message to the application.
-         * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
-         * @return  SSMReturn
-
-         */
-        SSMReturn registerQuery(std::string queryString, ISSMClientListener *listener,
-                                std::string &cqid);
-        /**
-         * This API is to cancel the registered sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
-         *
-         * @param [in] listener - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
-         *                          SSMClient can callback message to the application.
-         * @param [in] cqid - A query id generated from SoftSensorManager service for the queryString request.
-         * @return  SSMReturn
-         */
-        SSMReturn unregisterQuery(std::string cqid);
-
-        // friend option. for callback from SSMResource
-        void onFoundResource(std::shared_ptr< OCResource > resource);
-        void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onRegisterQuery(const OCRepresentation &rep, const int eCode);
-        void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
-        void onObserve(const OCRepresentation &rep, const int &eCode);
-};
-
-#endif /* RESOURCECLIENT_H_ */
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.service b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.service
deleted file mode 100644 (file)
index e15779f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-Description=OIC
-After=deviced.service
-
-[Service]
-Type=simple
-ExecStart=/usr/bin/simpleserver
-TimeoutStopSec=1s
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
diff --git a/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt b/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7aa6d40
--- /dev/null
@@ -0,0 +1,45 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(ssm)
+
+SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
+SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
+#SET(EX_SERVER "simpleserver")
+#SET(EX_CLIENT "simpleclient")
+#SET(EX_CLIENTSERVER "simpleclientserver")
+#SET(OCTBSTACK "octbstack")
+
+#INCLUDE_DIRECTORIES(include)
+#INCLUDE_DIRECTORIES(csdk/stack/include)
+#INCLUDE_DIRECTORIES(csdk/ocsocket/include)
+#INCLUDE_DIRECTORIES(csdk/ocrandom/include)
+#INCLUDE_DIRECTORIES(csdk/logger/include)
+#INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
+#LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
+
+#SET(EXTRA_CXXFLAGS "-std=c++11")
+#SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
+
+#SET(SRCS
+#      OCLib/OCReflect.cpp
+#      OCLib/OCPlatform.cpp
+#      OCLib/OCResource.cpp
+#      OCLib/InProcServerWrapper.cpp
+#      OCLib/InProcClientWrapper.cpp)
+#ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
+
+#ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_SUBDIRECTORY(csdk)
+#ADD_SUBDIRECTORY(examples)
+ADD_SUBDIRECTORY(oic-sample)
@@ -1,11 +1,11 @@
-SET(TESTAPP "oicapp-test")
+SET(TESTAPP "ssmtester")
 
 FILE(GLOB SRCS src/*.c src/*.cpp)
 
 SET(VENDOR "samsung")
 SET(PACKAGE ${TESTAPP})
 SET(PKGNAME "com.${VENDOR}.${PACKAGE}")
-SET(PREFIX "/usr/apps/com.samsung.oicapp-test")
+SET(PREFIX "/usr/apps/com.samsung.ssmtester")
 SET(BINDIR "${PREFIX}/bin")
 SET(RESDIR "${PREFIX}/res")
 SET(DATADIR "${PREFIX}/data")
@@ -38,8 +38,10 @@ ADD_DEFINITIONS("-DEDJDIR=\"${EDJDIR}\"")
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 
+LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lib)
+
 ADD_EXECUTABLE(${TESTAPP} ${SRCS})
-TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ssmcore oc octbstack oc_logger pthread dl)
 
 INSTALL(TARGETS ${TESTAPP} DESTINATION ${BINDIR})
 
diff --git a/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule b/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule
new file mode 100644 (file)
index 0000000..701ef6f
--- /dev/null
@@ -0,0 +1,3 @@
+com.samsung.ssmtester system::use_internet r
+
+system::use_internet com.samsung.ssmtester r
diff --git a/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml b/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml
new file mode 100644 (file)
index 0000000..ea0671f
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.ssmtester" version="0.1.0" install-location="internal-only">
+       <label>OIC test</label>
+       <author email="email@samsung.com" href="www.samsung.com">Name</author>
+       <description>SSM test Application</description>
+       <ui-application appid="com.samsung.ssmtester" exec="/usr/apps/com.samsung.ssmtester/bin/ssmtester" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
+               <icon>com.samsung.oicapp-test.png</icon>
+               <label>SSM test</label>
+       </ui-application>
+</manifest>
 #include <efl_assist.h>
 
 #include <string>
+#include <sstream>
 
 #include "oicapp-test.h"
 #include "oicapp-utils.h"
 
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "SSMClient.h"
-#include "ISSMClientListener.h"
+#include "SSMInterface.h"
 
 static oicapp_data *g_ad = NULL;
 
-class CSSMClientListener: public ISSMClientListener
+int g_CQID = 9999;
+
+class CQueryEngineEvent : public IQueryEngineEvent
 {
     public:
-        void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn::SSMReturn &eCode)
-        {
-            //EFL UI printing
 
-            char *queryResult = "";
+        SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult)
+        {
             std::stringstream sstream;
 
-            for (AttributeMap::const_iterator itor = attributeMap.begin(); itor != attributeMap.end(); itor++)
+            int     dataCount = 0;
+            IModelData      *pModelData = NULL;
+            std::vector<std::string>        affectedModels;
+
+            pResult->getAffectedModels(&affectedModels);
+
+            for (std::vector<std::string>::iterator itor = affectedModels.begin();
+                 itor != affectedModels.end(); ++itor)
             {
-                //if (itor->first == "queryEngineId")
-                //{
-                //  sstream << itor->first.c_str() << " : " << std::hex << stoi(itor->second.front().c_str()) << "\n";
-                //}
-                //else
-                //{
-                sstream << itor->first.c_str() << " : " << itor->second.front().c_str() << "\n";
-                //}
+                printf("Printing %s\n", itor->c_str());
+                pResult->getModelDataCount(*itor, &dataCount);
+                for (int i = 0; i < dataCount; i++)
+                {
+                    pResult->getModelData(*itor, i, &pModelData);
+                    printf("dataId: %d\n", pModelData->getDataId());
+                    for (int j = 0; j < pModelData->getPropertyCount(); j++)
+                    {
+                        sstream << "Type: " << pModelData->getPropertyName(j).c_str() <<
+                                " Value: " << pModelData->getPropertyValue(j).c_str() << "<br>";
+                    }
+                }
             }
 
-//      queryResult = const_cast<char *>(sstream .str().c_str());
-            oicapp_util_put_msg (g_ad, g_ad->input_msg);
+            sstream << std::ends;
 
+            oicapp_util_put_msg(g_ad, sstream.str().c_str());
 
+            return SSM_S_OK;
         }
 };
 
-CSSMClientListener  *g_SSMClientListener = new CSSMClientListener();
-SSMClient           *g_SSMClient        = NULL;
+CQueryEngineEvent   *g_SSMClientListener = new CQueryEngineEvent();
+SSMInterface        *g_SSMClient = new SSMInterface();
 
 static Elm_Object_Item *oicapp_append_separator(Evas_Object *genlist,
         oicapp_data *ad)
@@ -64,7 +74,7 @@ static Elm_Object_Item *oicapp_append_separator(Evas_Object *genlist,
 
     item = elm_genlist_item_append(genlist, &ad->itc_seperator, NULL, NULL,
                                    ELM_GENLIST_ITEM_NONE, NULL, NULL);
-    elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
+    //elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
 
     return item;
 }
@@ -181,7 +191,7 @@ static Elm_Object_Item *_gl_append_item(oicapp_data *ad, Elm_Genlist_Item_Class
 static void oicapp_append_contents(oicapp_data *ad)
 {
     Elm_Object_Item *item;
-
+    /*
     oicapp_append_separator(ad->genlist, ad);
 
     _gl_append_item(ad, &ad->itc_edit);
@@ -196,6 +206,26 @@ static void oicapp_append_contents(oicapp_data *ad)
     ad->item_multiline = item;
 
     oicapp_append_separator(ad->genlist, ad);
+    */
+    oicapp_append_separator(ad->genlist, ad);
+
+    elm_genlist_item_append(ad->genlist, &ad->itc_edit, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    elm_genlist_item_append(ad->genlist, &ad->itc_btn, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    item = _gl_append_item(ad, &ad->itc_multiline);
+
+    ad->item_multiline = item;
+
+    oicapp_append_separator(ad->genlist, ad);
 }
 
 static Evas_Object *oicapp_create_conform(Evas_Object *win)
@@ -236,9 +266,33 @@ static void _btn_clicked(void *data, Evas_Object *obj, void *event_info)
 {
     oicapp_data *ad = (oicapp_data *)data;
 
-    std::string cqid;
+    std::string str = std::string(ad->input_msg);
+
+    std::string strGT = "&gt;";
+
+    std::string strLT = "&lt;";
+
+    std::size_t foundGT = str.find(strGT);
 
-    g_SSMClient->registerQuery(std::string(ad->input_msg), g_SSMClientListener, cqid);
+    std::size_t foundLT = str.find(strLT);
+
+    std::stringstream sstream;
+
+    if (foundGT != std::string::npos)
+    {
+        str.replace(foundGT, strGT.length(), ">");
+    }
+
+    if (foundLT != std::string::npos)
+    {
+        str.replace(foundLT, strLT.length(), "<");
+    }
+
+    g_SSMClient->registerQuery(str, g_SSMClientListener, g_CQID);
+
+    sstream << "Query executed! cqid = " << g_CQID << std::ends;
+
+    oicapp_util_put_msg(ad, sstream.str().c_str());
 
     ERR("button clicked(%s)", ad->input_msg);
 }
@@ -264,8 +318,6 @@ static void _edit_unfocused(void *data, Evas_Object *obj, void *event_info)
 
     ad->input_msg = strdup(elm_entry_entry_get(obj));
 
-//  oicapp_util_put_msg(ad, ad->input_msg);
-
     DBG("Clicked : %s", ad->input_msg);
 
 }
@@ -282,6 +334,14 @@ static Evas_Object *_gl_edit_content_get(void *data, Evas_Object *obj,
     return entry;
 }
 
+static char *_item_Text_get(void *data, Evas_Object *obj, const char *part)
+{
+    char *buf =
+        "subscribe Device.DiscomfortIndexSensor if Device.DiscomfortIndexSensor.discomfortIndex > 0";
+
+    return strdup(buf);
+}
+
 static inline void oicapp_init_itcs(oicapp_data *ad)
 {
     ad->itc_seperator.item_style = "dialogue/separator";
@@ -291,7 +351,7 @@ static inline void oicapp_init_itcs(oicapp_data *ad)
     ad->itc_seperator.func.del = NULL;
 
     ad->itc_edit.item_style = "dialogue/editfield";
-    ad->itc_edit.func.text_get = NULL;
+    ad->itc_edit.func.text_get = _item_Text_get;
     ad->itc_edit.func.content_get = _gl_edit_content_get;
     ad->itc_edit.func.state_get = NULL;
     ad->itc_edit.func.del = NULL;
@@ -304,7 +364,6 @@ static inline void oicapp_init_itcs(oicapp_data *ad)
 
     ad->itc_multiline.item_style = "multiline/1text";
     ad->itc_multiline.func.text_get = _gl_multiline_text_get;
-    //ad->itc_multiline.func.text_get = NULL;
     ad->itc_multiline.func.content_get = NULL;
     ad->itc_multiline.func.state_get = NULL;
     ad->itc_multiline.func.del = NULL;
@@ -344,7 +403,7 @@ static int oicapp_create(void *data)
 
     ad->genlist = oicapp_create_genlist(ad->navi);
 
-    it = elm_naviframe_item_push(ad->navi, "OIC Tester", NULL, NULL, ad->genlist, NULL);
+    it = elm_naviframe_item_push(ad->navi, "SSM Tester", NULL, NULL, ad->genlist, NULL);
     elm_naviframe_item_pop_cb_set(it, _back_cb, ad);
 
     ad->ip_addr = oicapp_util_wifi();
@@ -360,8 +419,6 @@ static int oicapp_create(void *data)
 
     oicapp_append_contents(ad);
 
-    g_SSMClient = new SSMClient();
-
     return 0;
 }
 
@@ -369,6 +426,9 @@ static int oicapp_terminate(void *data)
 {
     oicapp_data *ad = (oicapp_data *)data;
 
+    if (g_CQID != 9999)
+        g_SSMClient->unregisterQuery(g_CQID);
+
     if (ad->win)
         evas_object_del(ad->win);
 
@@ -63,6 +63,7 @@ void oicapp_util_put_msg(oicapp_data *ad, const char *msg)
        DBG("Output msg : %s", ad->output_msg);
 
        elm_genlist_item_update(ad->item_multiline);
+       elm_genlist_item_item_class_update(ad->item_multiline, &(ad->itc_multiline));
 }
 
 char* oicapp_util_wifi()
@@ -1,16 +1,17 @@
-Name:       oic
+Name:       ssm
 Summary:    Open Interconnect Consortium
 Version:       0.0.1
 Release:    0
 Group:      Network & Connectivity/Service
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
-Source1:    %{name}.service
+Source1:    libDiscomfortIndexSensor.so
+Source2:    SoftSensorDescription.xml
 Source1001:    %{name}.manifest
 BuildRequires: cmake
-BuildRequires: boost-devel
+#BuildRequires: boost-devel
 #BuildRequires: pkgconfig(glib-2.0)
-Buildrequires: gettext-tools
+#Buildrequires: gettext-tools
 BuildRequires: pkgconfig(appcore-efl)
 BuildRequires: pkgconfig(ecore-x)
 BuildRequires: pkgconfig(elementary)
@@ -32,8 +33,10 @@ cp %{SOURCE1001} .
 
 
 %install
-rm -rf %{buildroot}/BUILD/oic*
+rm -rf %{buildroot}/BUILD/ssm*
 #%make_install
+cp -af %{SOURCE1} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
+cp -af %{SOURCE2} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
 
 %post
 
@@ -44,8 +47,7 @@ rm -rf %{buildroot}/BUILD/oic*
 %files
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%{_bindir}/simple*
-/usr/apps/com.samsung.oicapp-test/*
+/usr/apps/com.samsung.ssmtester/*
 /usr/share/*
-/etc/smack/accesses2.d/com.samsung.oicapp-test.rule
+/etc/smack/accesses2.d/com.samsung.ssmtester.rule
 #%%license LICENSE.APLv2
diff --git a/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/SoftSensorDescription.xml b/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/SoftSensorDescription.xml
new file mode 100644 (file)
index 0000000..7910214
--- /dev/null
@@ -0,0 +1,41 @@
+<softsensors>
+       
+  <softsensor>
+    <name>DiscomfortIndexSensor</name>
+    <attributes>
+      <attribute>
+        <name>version</name>
+        <type>string</type>
+        <value>1.0</value>
+      </attribute>
+      <attribute>
+        <name>lifetime</name>
+        <type>int</type>
+        <value>60</value>
+      </attribute>
+    </attributes>
+    <outputs>
+      <output>
+        <name>timestamp</name>
+        <type>string</type>
+      </output>
+      <output>
+        <name>temperature</name>
+        <type>string</type>
+      </output>
+      <output>
+        <name>humidity</name>
+        <type>string</type>
+      </output>
+      <output>
+        <name>discomfortIndex</name>
+        <type>int</type>
+      </output>
+    </outputs>
+    <inputs>
+      <input>Thing_TempHumSensor</input>
+      <input>Thing_TempHumSensor1</input>
+    </inputs>
+  </softsensor>
+  
+</softsensors>
diff --git a/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/HighContextDictionary.xml b/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/HighContextDictionary.xml
deleted file mode 100644 (file)
index 4e5e413..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-<high_context_dictionary>
-       
-  <high_context>
-    <root_name>DiscomfortIndexSensor</root_name>
-    <attributes>
-      <attribute_property_count>2</attribute_property_count>
-      <attribute_property>
-        <name>version</name>
-        <type>string</type>
-        <value>1.0</value>
-      </attribute_property>
-      <attribute_property>
-        <name>lifetime</name>
-        <type>int</type>
-        <value>60</value>
-      </attribute_property>
-    </attributes>
-    <outputs>
-      <output_property_count>4</output_property_count>
-      <output_property>
-        <name>timestamp</name>
-        <type>string</type>
-        <value>&quot;&quot;</value>
-      </output_property>
-      <output_property>
-        <name>temperature</name>
-        <type>int</type>
-        <value>0</value>
-      </output_property>
-      <output_property>
-        <name>humidity</name>
-        <type>int</type>
-        <value>0</value>
-      </output_property>
-      <output_property>
-        <name>discomfortIndex</name>
-        <type>int</type>
-        <value>0</value>
-      </output_property>
-    </outputs>
-    <app_inputs>
-      <app_input_count>0</app_input_count>
-    </app_inputs>
-    <inputs>
-      <input_count>2</input_count>
-      <input>Thing_TempHumSensor</input>
-      <input>Thing_TempHumSensor1</input>
-    </inputs>
-    <enter_conditions>
-      <enter_condition>
-        <name>Thing_TempHumSensor</name>
-        <name>Thing_TempHumSensor1</name>
-      </enter_condition>
-    </enter_conditions>
-  </high_context>
-  
-</high_context_dictionary>
index 4fc2c18..4aae123 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 SRC_PATH=../../src
@@ -23,7 +23,7 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "---------- SoftSensor Build Begin. ------------" 
+       @echo "---------- ${TARGET} Build Begin. ------------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
@@ -38,8 +38,8 @@ ${TARGET}: ${OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/lib${TARGET}.so ${OUTPUTS_DIR}/
-       cp -Rdp ./HighContextDictionary.xml ${OUTPUTS_DIR}/
-       @echo "-------------- SoftSensor Build Successful. -------------"
+       cp -Rdp ../../${SSXML_NAME} ${OUTPUTS_DIR}/
+       @echo "-------------- ${TARGET} Build Successful. -------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
index aebbf9b..2dfe1a7 100644 (file)
@@ -180,6 +180,9 @@ DIResult DiscomfortIndexSensor::makeDiscomfortIndex(InValue *data)
     int discomfortIndex = (int) ERROR;
     double sumDI = 0.0;
 
+    m_result.m_temperature = "";
+    m_result.m_humidity = "";
+
     for (int i = 0; i < PHYSICAL_EA; i++)
     {
         if (i != 0)
@@ -256,14 +259,14 @@ ContextData DiscomfortIndexSensor::setOutput(int property_count, InValue *data)
 
     output_property.clear();
     output_property.insert(std::make_pair("name", "temperature"));
-    output_property.insert(std::make_pair("type", "int"));
+    output_property.insert(std::make_pair("type", "string"));
     output_property.insert(std::make_pair("value", m_result.m_temperature));
 
     out.outputProperty.push_back(output_property);
 
     output_property.clear();
     output_property.insert(std::make_pair("name", "humidity"));
-    output_property.insert(std::make_pair("type", "int"));
+    output_property.insert(std::make_pair("type", "string"));
     output_property.insert(std::make_pair("value", m_result.m_humidity));
 
     out.outputProperty.push_back(output_property);
index 82dba85..1c3ae15 100644 (file)
@@ -1,4 +1,7 @@
+IOTIVITY_DIR=${shell cd ../../../../ && pwd}
+${shell echo "ROOT_DIR=${IOTIVITY_DIR}" > ./root_path.inc}
 
+-include ./root_path.inc
 -include ./environment.mk
 
 MAKE=make
@@ -24,13 +27,12 @@ pre_job:
        @echo "*********************************************************" 
        @mkdir -p ${RST_NAME}
        @echo " "
-#      @cd ${IOT_BASE} &&      ${MAKE};
-#      @cd ${CUR_DIR};
+
        
 build:
        @for subdir in ${MAKE_LIST} ; do \
        echo ">>>>>>>>>>>> $${subdir}/Makefile run <<<<<<<<<<<<<" ; \
-       ${MAKE} -C $${subdir} ; \
+       cd $${subdir} && ${MAKE} ${OPTION} ; \
        echo " " ; \
        done
        @echo " "
@@ -46,11 +48,7 @@ post_job:
        @echo " " 
 
 clean:
-       
-#      @cd ${CUR_DIR}/../../../resource/ && make clean
-#      @cd ${CUR_DIR}/../../../resource/csdk && make deepclean
-#      @cd ${CUR_DIR}/9_Arduino_THSensorApp && make clean
-#      @cd ${CUR_DIR} 
+
        rm -rf ./${RST_NAME}
        @for subdir in ${MAKE_LIST} ; do \
        echo ">>>>>>>>>>>> $${subdir}/Makefile clean run <<<<<<<<<<<<<<" ; \
index 7e16a38..2d8949e 100644 (file)
@@ -1,23 +1,25 @@
-# root path of each PC.
-ROOT_DIR=/home/choi/tmp/test/upload/Iotivity-Candidate
 
-# service folder path.
-FD_SSM=${ROOT_DIR}/service/SoftSensorManager
+# ioc-resource folder path.
+IOT_BASE=${ROOT_DIR}/resource
+IOT_MAKE_PATH=${IOT_BASE}
+IOT_RELEASE=${IOT_BASE}/release/obj
+IOT_CSDK_LINUX_RELEASE=${IOT_BASE}/csdk/linux/release
+IOT_CSDK_ARDUINOMEGA_RELEASE=${IOT_BASE}/csdk/arduinomega/release
+
+# oic-service folder path.
+FD_SSM=${ROOT_DIR}/service/soft-sensor-manager
 FD_SAMPLEAPP=${FD_SSM}/SampleApp
 FD_BUILD=${FD_SSM}/build
 
 # outputs directory path.
 OUTPUTS_DIR=${FD_BUILD}/arduino/release
 
-# ioc-resource folder path.
-# IOT_BASE=${FD_SAMPLEAPP}/arduino/resource_a
-IOT_BASE=${ROOT_DIR}/resource
-IOT_MAKE_PATH=${IOT_BASE}
-IOT_RELEASE=${IOT_BASE}/release/obj
-IOT_CSDK_RELEASE=${IOT_BASE}/csdk/release
-
+#OPTION=PLATFORM=arduinomega ARDUINOWIFI=1
 # SoftSensorManager makefile path
+MAKE_00=${FD_SAMPLEAPP}/arduino
 MAKE_01=${FD_SAMPLEAPP}/arduino/THSensorApp/build
+MAKE_03=${FD_SAMPLEAPP}/arduino/Trackee_Thing/build
+MAKE_04=${FD_SAMPLEAPP}/arduino/Reference_Thing/build
 
-MAKE_LIST=${MAKE_01}
+MAKE_LIST=${MAKE_01} ${MAKE_03} ${MAKE_04}
 
index 39184bd..e0b44b8 100644 (file)
@@ -1,5 +1,4 @@
-#ARDUINO_DIR = /home/choi/devel/arduino-1.0.5
-ARDUINO_DIR = /home/choi/tmp/test/Arduino
+ARDUINO_DIR = /usr/share/arduino
 #ARDUINO_TOOLS_DIR = $(ARDUINO_DIR)/hardware/tools/avr/bin
 CC=avr-g++
 CCPLUS=avr-g++
index ee41b51..2b79304 100644 (file)
@@ -1,4 +1,7 @@
+IOTIVITY_DIR=${shell cd ../../../../ && pwd}
+${shell echo "ROOT_DIR=${IOTIVITY_DIR}" > ./root_path.inc}
 
+-include ./root_path.inc
 -include ./environment.mk
 
 MAKE=make
@@ -21,7 +24,6 @@ pre_job:
        @echo "*                                                       *"
        @echo "* It's build script for SoftSensorManagement system.    *"
        @echo "* Before build, Open the environment.mk file.           *"
-       @echo "* And, Modify ROOT_DIR path, which depend on your PC.   *"
        @echo "* And, Modify BOOST_BASE path, which depend on your PC. *"
        @echo "*                                                       *"
        @echo "*********************************************************" 
@@ -51,13 +53,10 @@ post_job:
 
 clean:
        
-#      @cd ${CUR_DIR}/../../../resource/ && make clean
-#      @cd ${CUR_DIR}/../../../resource/csdk && make deepclean
-#      @cd ${CUR_DIR}/9_Arduino_THSensorApp && make clean
-#      @cd ${CUR_DIR} 
        rm -rf ./${RST_NAME}
        @for subdir in ${MAKE_LIST} ; do \
        echo ">>>>>>>>>>>> $${subdir}/Makefile clean run <<<<<<<<<<<<<<" ; \
        ${MAKE} clean -C $${subdir} ; \
        echo " " ; \
        done
+       rm -rf ./root_path.inc
index c10c51f..d4def6d 100644 (file)
@@ -1,16 +1,15 @@
-# root path of each PC.
-ROOT_DIR=${PWD}/../../../..
-
 # boost folder path.
-BOOST_BASE=/home/iotivity/Desktop/boost_1_56_0
+BOOST_BASE=/usr/include
 
 # ioc-resource folder path.
 IOT_BASE=${ROOT_DIR}/resource
 IOT_MAKE_PATH=${IOT_BASE}
 IOT_RELEASE=${IOT_MAKE_PATH}/release/obj
-IOT_CSDK_RELEASE=${IOT_BASE}/csdk/release
+IOT_CSDK_RELEASE=${IOT_BASE}/csdk/linux/release
+IOT_LOG_DIR=${IOT_BASE}/oc_logger
 IOT_LIB=liboc.a
 IOT_CSDK_LIB=liboctbstack.a
+IOT_LOG_LIB=liboc_logger.a
 
 # service folder path.
 FD_SSM=${ROOT_DIR}/service/soft-sensor-manager
@@ -23,15 +22,17 @@ FD_BUILD=${FD_SSM}/build
 # outputs directory path.
 OUTPUTS_DIR=${FD_BUILD}/linux/release
 EXEC_DIR=${OUTPUTS_DIR}
-MODEL_DIR="\"${EXEC_DIR}/\""
-HIGH_LOCATION="\"${EXEC_DIR}/HighContextDictionary.xml\""
+SSXML_NAME="SoftSensorDescription.xml"
+SSM_LIB = libSSM.a
+SSMCORE_LIB=libSSMCore.a
 
 # SoftSensorManager makefile path
-MAKE_01=${FD_SDK}/build/linux
-MAKE_02=${FD_SSMCORE}/build/linux
+MAKE_01=${FD_SSMCORE}/build/linux
+MAKE_02=${FD_SDK}/build/linux
 MAKE_03=${FD_SAMPLEAPP}/linux
 MAKE_04=${FD_SAMPLEAPP}/arduino
 MAKE_05=${FD_SOFTSENSOR}/DiscomfortIndexSensor/build/linux
+MAKE_06=${FD_SOFTSENSOR}/IndoorTrajectorySensor/build/linux
 
-MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_03}
 
+MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_03} ${MAKE_05} ${MAKE_06}
\ No newline at end of file
diff --git a/service/things-manager/SConscript b/service/things-manager/SConscript
new file mode 100644 (file)
index 0000000..1fb3198
--- /dev/null
@@ -0,0 +1,36 @@
+##
+# things_manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', exports = 'lib_env')
+
+things_manager_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+things_manager_env.AppendUnique(CPPPATH = ['tgm/inc'])
+things_manager_env.AppendUnique(CPPPATH = ['sdk/inc'])
+
+if target_os not in ['windows', 'winrt']:
+       things_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
+       if target_os != 'android':
+               things_manager_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+if target_os == 'android':
+       things_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       things_manager_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+tgmsdk = things_manager_env.StaticLibrary('TGMSDKLibrary', 'sdk/src/TGMClient.cpp')
+
+things_manager_env.InstallTarget(tgmsdk, 'libTGMSDK')
+
+#Go to build sample apps
+SConscript('sampleapp/SConscript')
\ No newline at end of file
diff --git a/service/things-manager/sampleapp/SConscript b/service/things-manager/sampleapp/SConscript
new file mode 100644 (file)
index 0000000..bd1b631
--- /dev/null
@@ -0,0 +1,9 @@
+##
+# sampleapp build script
+##
+
+Import('env')
+
+if env.get('TARGET_OS') == 'linux':
+       # Build linux sample app
+       SConscript('linux/tgmclient/SConscript')
diff --git a/service/things-manager/sampleapp/linux/tgmclient/SConscript b/service/things-manager/sampleapp/linux/tgmclient/SConscript
new file mode 100644 (file)
index 0000000..2c347ff
--- /dev/null
@@ -0,0 +1,28 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+linux_sample_env = lib_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['../../../sdk/inc'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger', 'TGMSDKLibrary'])
+
+if env.get('TARGET_OS') not in ['windows', 'winrt']:
+       linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+tgmclient = linux_sample_env.Program('tgmclient', 'tgmsdkclient.cpp')
+
+Alias("tgmclient_sample", tgmclient)
+env.AppendTarget('tgmclient_sample')
\ No newline at end of file
diff --git a/service/third_party_libs.scons b/service/third_party_libs.scons
new file mode 100644 (file)
index 0000000..e9a140c
--- /dev/null
@@ -0,0 +1,99 @@
+######################################################################
+# This script manages third party libraries
+#
+#Note: The paths must keep consistent with oic-resource
+######################################################################
+import os
+import platform
+
+Import('env', 'lib_env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
+
+if target_os not in ['linux', 'darwin']:
+       utils_path = env.get('OIC_UTILS')
+
+resource_path = src_dir + '/resource'
+
+######################################################################
+# Check dependent packages (Linux only)
+######################################################################
+if target_os == 'linux':
+       if not env.GetOption('help'):
+               if not target_arch == platform.machine():
+                       print '''
+*********************************** Warning ***********************************
+* You are trying cross build, please make sure (%s) version libraries are
+* installed!                                                                 *
+*******************************************************************************
+''' % target_arch
+
+               conf = Configure(lib_env)
+
+               if not conf.CheckLib('boost_thread'):
+                       print 'Did not find boost_thread, exiting!'
+                       Exit(1)
+
+               if not conf.CheckLib('boost_system'):
+                       print 'Did not find boost_system, exiting!'
+                       Exit(1)
+
+               conf.Finish()
+
+######################################################################
+# The 'include' path of external libraries
+######################################################################
+lib_env.AppendUnique(CPPPATH = [
+               resource_path ,
+               resource_path + '/include' ,
+               resource_path + '/oc_logger/include',
+               resource_path + '/csdk/stack/include',
+               resource_path + '/csdk/ocsocket/include',
+               resource_path + '/csdk/ocrandom/include',
+               resource_path + '/csdk/logger/include'
+               ])
+
+######################################################################
+# The 'include' path of third party libraries
+######################################################################
+if target_os == 'android':
+       lib_env.AppendUnique(CPPPATH = [
+                                       utils_path + '/android/boost/include',
+                                       utils_path + '/android/expat/include/expat/',
+                                       utils_path + '/android/openssl/include',
+                               ])
+
+######################################################################
+# The path of third party libraries binary
+######################################################################
+if target_os == 'android':
+       if target_arch == 'armeabi-v7a-hard':
+               target_arch = 'armeabi-v7a'
+
+       if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+               if not env.GetOption('help') and not env.GetOption('clean'):
+                       print '''
+*********************************** Warning ***********************************
+* current only x86, armeabi, armeabi-v7a libraries are provided!              *
+*******************************************************************************
+'''
+       else:
+               lib_env.AppendUnique(LIBPATH = [
+                                                               utils_path + '/android/boost/libs/' + target_arch,
+                                                               utils_path + '/android/expat/lib/' + target_arch,
+                                                               utils_path + '/android/openssl/lib/' + target_arch,
+                                                       ])
+               # Too much boost warning, suppress the warning
+               lib_env.AppendUnique(CCFLAGS = ['-w'])
+
+elif target_os == 'ios':
+       lib_env.AppendUnique(FRAMEWORKPATH = [utils_path + '/ios/frameworks/'])
+       lib_env.AppendUnique(FRAMEWORKS = ['boost', 'expat', 'openssl'])
+elif target_os == 'darwin':
+       lib_env.AppendUnique(CPPPATH = ['/usr/local/include'])
+       lib_env.AppendUnique(LIBPATH = ['/usr/local/lib'])
+
+Import('env')
+lib_env.AppendUnique(LIBPATH = env.get('BUILD_DIR'))