CBOR rebase onto master for merge/review
authorOmkar Hegde <omkar.m.hegde@intel.com>
Fri, 10 Jul 2015 21:41:46 +0000 (14:41 -0700)
committerErich Keane <erich.keane@intel.com>
Tue, 14 Jul 2015 20:03:42 +0000 (20:03 +0000)
The CA layer has been converted to use binary data, rather
than string data to support CBOR as a transport.  The CSDK has
been changed to use the OCPlatform object model instead of json
strings.  Underneath this, the JSON encoding has been replaced
with CBOR.

Also, some of the previous blockwise transfer functionality has
been removed, since the blockwise-transfer functionality has been
pushed ot the CA stack.

Change-Id: I6423a5180643cea3d311ec7497b246117f7c02b0
Signed-off-by: Erich Keane <erich.keane@intel.com>
Signed-off-by: Omkar Hegde <omkar.m.hegde@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1613
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
88 files changed:
.gitignore
NOTICE.md
Readme.scons.txt
android/android_api/base/jni/JniOcRepresentation.cpp
android/android_api/base/jni/JniOcRepresentation.h
build_common/external_libs.scons
examples/OICMiddle/LineInput.cpp
examples/OICMiddle/WrapResource.cpp
extlibs/buildDependencies.sh
extlibs/cereal/SConscript [deleted file]
extlibs/tinycbor/SConscript [new file with mode: 0644]
extra_options.scons
gbsbuild.sh
resource/c_common/oic_malloc/include/oic_malloc.h
resource/c_common/oic_malloc/src/oic_malloc.c
resource/csdk/SConscript
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/common/src/caremotehandler.c
resource/csdk/connectivity/inc/caprotocolmessage.h
resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.c
resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.h
resource/csdk/connectivity/samples/arduino/casample.cpp
resource/csdk/connectivity/src/camessagehandler.c
resource/csdk/connectivity/src/caprotocolmessage.c
resource/csdk/connectivity/test/ca_api_unittest.cpp
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/src/provisioningmanager.c
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/pstatresource.c
resource/csdk/security/src/resourcemanager.c
resource/csdk/security/unittest/aclresourcetest.cpp
resource/csdk/security/unittest/pstatresource.cpp
resource/csdk/stack/include/internal/ocobserve.h
resource/csdk/stack/include/internal/ocpayloadcbor.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocresourcehandler.h
resource/csdk/stack/include/internal/ocserverrequest.h
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocpayload.h [new file with mode: 0644]
resource/csdk/stack/include/ocpresence.h [new file with mode: 0644]
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/include/ocstackconfig.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h
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
resource/csdk/stack/samples/linux/secure/SConscript
resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp
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/ocpayload.c [new file with mode: 0644]
resource/csdk/stack/src/ocpayloadconvert.c [new file with mode: 0644]
resource/csdk/stack/src/ocpayloadparse.c [new file with mode: 0644]
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/src/oicgroup.c
resource/csdk/stack/test/stacktests.cpp
resource/include/InProcClientWrapper.h
resource/include/OCApi.h
resource/include/OCRepresentation.h
resource/include/OCResourceRequest.h
resource/include/OCResourceResponse.h
resource/include/OCSerialization.h
resource/include/OicJsonSerializer.hpp [deleted file]
resource/patches/cereal_gcc46.patch [deleted file]
resource/src/InProcClientWrapper.cpp
resource/src/InProcServerWrapper.cpp
resource/src/OCPlatform_impl.cpp
resource/src/OCRepresentation.cpp
resource/src/OCResourceRequest.cpp
resource/src/SConscript
service/notification-manager/NotificationManager/src/hosting.c
tools/vagrant/iotivity-setup.sh

index 6adba9d..c891e5c 100644 (file)
@@ -96,6 +96,7 @@ extlibs/android/gradle/gradle-2.2.1
 extlibs/android/ndk/android-ndk-r10d
 extlibs/android/sdk/android-sdk_r24.2
 extlibs/boost/boost_1_58_0
+extlibs/tinycbor/tinycbor
 *.tgz
 *.zip
 extlibs/arduino/arduino-1.5.8
index 6d243f8..027511d 100644 (file)
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -40,20 +40,13 @@ license can be found at
 The original software is available from
   http://sourceforge.net/projects/boost/files/boost
 
-JSON serialization is provided by the cereal package,
-which is open source software, written by Philip Hazel, and copyright
-by the University of Cambridge, England. The original software is
-available from
-  ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
-
+CBOR serialization is provided by the tinycbor package,
+which is open source software, written by Thiago Macieira and is
+copyright by the Intel Corporation.  The original software is available
+from
+  https://github.com/01org/tinycbor/
 JSON serialization is provided by the cjson package,
 which is open source software, written and copyright by Dave Gamble
 with an MIT license. The original software is available from
   http://sourceforge.net/projects/cjson/
 
-JSON serialization is provided by the rapidjson package,
-which is open source software, written and copyright by Milo Yip
-with an MIT license. The original software is available from
-  http://code.google.com/p/rapidjson/
-
-
index 4ea28b1..a66dbb4 100644 (file)
@@ -9,8 +9,8 @@ command in this directory)
 
     Build release binaries:
       $ scons
-(Note: C++ sdk requires cereal. Please follow the instruction in the build
-message to install cereal)
+(Note: C sdk requires tiny-cbor. Please follow the instruction in the build
+message to install tiny-cbor)
 
     Build debug binaries:
       $scons RELEASE=false
@@ -116,13 +116,10 @@ so you don't need to add it in command line each time. The build script will
 guide you to do that.)
 
 Tizen:
-To build for tizen platform cereal library is needed.
-Please download cereal if it is not present in extlibs/cereal folder
-and apply the patch as following:
-       $ git clone https://github.com/USCiLab/cereal.git extlibs/cereal/cereal
-       $ cd  extlibs/cereal/cereal
-       $ git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245
-       $ git apply ../../../resource/patches/cereal_gcc46.patch
+To build for tizen platform tiny-cbor library is needed.
+Please download tiny-cbor if it is not present in extlibs/tiny-cbor folder
+by doing the following:
+       $ git clone https://github.com/01org/tinycbor.git extlibs/tinycbor/tinycbor
 
 
 * 3. External libraries
index e2c2cd0..c143069 100644 (file)
@@ -722,22 +722,6 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcRepresentation_setValueRepresent
 \r
 /*\r
 * Class:     org_iotivity_base_OcRepresentation\r
-* Method:    getJSONRepresentation\r
-* Signature: ()Ljava/lang/String;\r
-*/\r
-JNIEXPORT jstring JNICALL Java_org_iotivity_base_OcRepresentation_getJSONRepresentation\r
-(JNIEnv *env, jobject thiz)\r
-{\r
-    LOGD("OcRepresentation_getJSONRepresentation");\r
-    OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);\r
-    if (!rep) return nullptr;\r
-\r
-    std::string jsonStr = rep->getJSONRepresentation();\r
-    return env->NewStringUTF(jsonStr.c_str());\r
-}\r
-\r
-/*\r
-* Class:     org_iotivity_base_OcRepresentation\r
 * Method:    addChild\r
 * Signature: (Lorg/iotivity/base/OcRepresentation;)V\r
 */\r
@@ -1037,4 +1021,4 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcRepresentation_dispose
     {\r
         delete rep;\r
     }\r
-}
\ No newline at end of file
+}\r
index 3f25c29..fbf3131 100644 (file)
@@ -621,14 +621,6 @@ extern "C" {
 \r
     /*\r
     * Class:     org_iotivity_base_OcRepresentation\r
-    * Method:    getJSONRepresentation\r
-    * Signature: ()Ljava/lang/String;\r
-    */\r
-    JNIEXPORT jstring JNICALL Java_org_iotivity_base_OcRepresentation_getJSONRepresentation\r
-        (JNIEnv *, jobject);\r
-\r
-    /*\r
-    * Class:     org_iotivity_base_OcRepresentation\r
     * Method:    addChild\r
     * Signature: (Lorg/iotivity/base/OcRepresentation;)V\r
     */\r
@@ -766,4 +758,4 @@ extern "C" {
 #ifdef __cplusplus\r
 }\r
 #endif\r
-#endif
\ No newline at end of file
+#endif
index 432bbe5..cc60e2d 100644 (file)
@@ -121,6 +121,9 @@ def __install_lib(ienv, lib):
 
 SConscript('tools/UnpackAll.py')
 
+# tinycbor build/fetch
+SConscript(os.path.join(env.get('SRC_DIR'), 'extlibs', 'tinycbor', 'SConscript'))
+
 env.AddMethod(__prepare_lib, "PrepareLib")
 env.AddMethod(__configure, "Configure")
 env.AddMethod(__download, "Download")
index 685d33a..5fac3ed 100644 (file)
@@ -235,7 +235,7 @@ LineResult LineInput::processGet(elements_t& elems, stringstream& ss)
         return LR_Timeout;
     }
 
-    std::string jsonRep = wreq->m_rep.getJSONRepresentation();
+    std::string jsonRep ;//= wreq->m_rep.getJSONRepresentation();
     //ss << jsonRep << endl;
     printJSONAsTable(jsonRep);
         return LR_OK;
@@ -356,7 +356,7 @@ void LineInput::obsCB(token_t token, const HeaderOptions& headerOptions, const O
     if (!m_observer)
         return;
     cout << "cb " << eCode << " " << sequenceNumber << '\n';
-    cout << rep.getJSONRepresentation() << "\n";
+    //cout << rep.getJSONRepresentation() << "\n";
 }
 
 ParseState LineInput::finishElem(char*& e, elements_t& elems)
index 3cadb7d..a064d28 100644 (file)
@@ -164,7 +164,7 @@ void WrapResource::parseJSON(WrapRequest *wreq)
 {
     string sep = "\":";
     string anchor = "\"rep\":{";
-    string json = wreq->m_rep.getJSONRepresentation();
+    string json;// = wreq->m_rep.getJSONRepresentation();
     string name, type, value, next;
     size_t r, e, e1, s, c;
 
index 4ebe318..acd236e 100755 (executable)
@@ -7,15 +7,6 @@ cd "$(dirname "$0")"
 
 EXTDIR=$(pwd)
 
-# Check for cereal existence
-if [ ! -d "cereal" ]; then
-    git clone https://github.com/USCiLab/cereal.git cereal
-    pushd cereal
-    git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245
-    git apply ../../resource/patches/cereal_gcc46.patch
-    popd
-fi
-
 # Pick the preferred version of boost to use
 BOOST_MAJOR=1
 BOOST_MINOR=57
@@ -44,8 +35,8 @@ function buildBoost {
     if [ ! -d "boost" ]; then
         cloneBoost
     fi
-    
-    # Determine the 
+
+    # Determine the
     TOOLCHAIN=${ANDROID_NDK}/toolchains/${TOOLSET}-${VERSION}/prebuilt/${HOST_ARCH}/bin
 
     OLDPATH=$PATH
diff --git a/extlibs/cereal/SConscript b/extlibs/cereal/SConscript
deleted file mode 100644 (file)
index 946a483..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-######################################################################
-# Cereal library build script
-#
-# Only 'hpp' is used by Iotivity, it's unnecessary to build it
-######################################################################
-import os
-
-Import('env')
-
-src_dir = env.get('SRC_DIR')
-
-# In the pass, cereal library is in extlibs/cereal, according to external
-# library management rule, cereal should be put in extlibs/cereal/cereal.
-# jenkins of gerrit server, still follow the old, to avoid jenkins fail
-# both places are handled.
-old = os.path.join(src_dir, 'extlibs', 'cereal', 'include')
-cur = os.path.join(src_dir, 'extlibs', 'cereal', 'cereal', 'include')
-
-# check 'cereal' library, if it doesn't exits, ask user to download it
-if not os.path.exists(old) and not os.path.exists(cur):
-       cereal_env = Environment(ENV = os.environ)
-       c = cereal_env.Action(['git clone https://github.com/USCiLab/cereal.git cereal',
-               'cd cereal && git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245 && git apply ../../../resource/patches/cereal_gcc46.patch',
-               ])
-
-       print 'Downloading cereal library ...'
-       if cereal_env.Execute(c):
-               print '''
-*********************************** Error: ************************************
-* Please download cereal and apply the patch as following:                    *
-*     $ git clone https://github.com/USCiLab/cereal.git extlibs/cereal/cereal *
-*     $ cd  extlibs/cereal/cereal                                             *
-*     $ git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245             *
-*     $ git apply ../../../resource/patches/cereal_gcc46.patch                *
-*******************************************************************************
-'''
-               Exit(1)
-       else:
-               print 'Download cereal library complete'
-
-env.AppendUnique(CPPPATH = [old, cur])
diff --git a/extlibs/tinycbor/SConscript b/extlibs/tinycbor/SConscript
new file mode 100644 (file)
index 0000000..fc12833
--- /dev/null
@@ -0,0 +1,46 @@
+#******************************************************************
+#
+# Copyright 2015 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+import os
+
+Import('env')
+
+src_dir = env.get('SRC_DIR')
+
+cborDir = os.path.join(src_dir, 'extlibs','tinycbor','tinycbor')
+
+if not os.path.exists(cborDir):
+    print '''
+*********************************** Error: ****************************************
+* Please download cbor using the following command:                               *
+*     $ git clone https://github.com/01org/tinycbor.git extlibs/tinycbor/tinycbor *
+***********************************************************************************
+'''
+    Exit(1)
+
+cbor_src = [
+    os.path.join(cborDir,'src/cborparser.c'),
+    os.path.join(cborDir,'src/cborencoder.c')
+    ]
+
+env['cbor_files'] = cbor_src
+env.AppendUnique(CPPPATH  = [os.path.join(cborDir, 'src')])
+
+
index 6cd51b7..4403138 100644 (file)
@@ -30,5 +30,3 @@ Import('env')
 target_os = env.get('TARGET_OS')
 target_arch = env.get('TARGET_ARCH')
 src_dir = env.get('SRC_DIR')
-
-env.SConscript('extlibs/cereal/SConscript')
index d4542f0..749da0a 100644 (file)
@@ -20,7 +20,7 @@ mkdir ./tmp/extlibs/
 mkdir ./tmp/packaging
 cp -R ./build_common $sourcedir/tmp
 cp -R ./examples $sourcedir/tmp
-cp -R ./extlibs/cereal $sourcedir/tmp/extlibs
+cp -R ./extlibs/tinycbor $sourcedir/tmp/extlibs
 cp -R ./extlibs/cjson $sourcedir/tmp/extlibs
 cp -R ./extlibs/tinydtls $sourcedir/tmp/extlibs
 cp -R ./extlibs/timer $sourcedir/tmp/extlibs
@@ -35,7 +35,7 @@ cp ./tools/tizen/.gbs.conf ./tmp
 cd $sourcedir/tmp
 
 echo `pwd`
-rm -rf ./extlibs/cereal/cereal/.git*
+rm -rf ./extlibs/tinycbor/tinycbor/.git*
 
 # Initialize Git repository
 if [ ! -d .git ]; then
index df0b7b2..dc7ae45 100644 (file)
@@ -68,6 +68,26 @@ extern "C"
 void *OICMalloc(size_t size);
 
 /**
+ * Re-allocates a block of memory, pointed to by ptr to the size specified
+ * in size.  The returned value contains a pointer to the new location, with
+ * all data copied into it.  If the new size of the memory-object require movement,
+ * the previous space is freed.  If the new size is larger, the newly allocated
+ * area has non-deterministic content. If the space cannot be allocated, the value
+ * ptr is left unchanged.
+ *
+ * @param ptr - Pointer to a block of memory previously allocated by OICCalloc,
+ *              OICMalloc, or a previous call to this function.  If this value is
+ *              NULL, this function will work identically to a call to OICMalloc.
+ *
+ * @param size - Size of the new memory block in bytes, where size > 0
+ *
+ * @return
+ *      on success, a pointer to the newly sized memory block
+ *      on failure, a null pointer is returned, and the memory pointed to by *ptr is untouched
+ */
+void *OICRealloc(void *ptr, size_t size);
+
+/**
  * Allocates a block of memory for an array of num elements, each of them
  * size bytes long and initializes all its bits to zero.
  *
@@ -86,7 +106,7 @@ void *OICCalloc(size_t num, size_t size);
  * NOTE: This function is intended to be used internally by the TB Stack.
  *       It is not intended to be used by applications.
  *
- * @param ptr - Pointer to block of memory previously allocated by OCMalloc.
+ * @param ptr - Pointer to block of memory previously allocated by OICMalloc.
  *              If ptr is a null pointer, the function does nothing.
  */
 void OICFree(void *ptr);
index 40b7363..99df106 100644 (file)
@@ -98,6 +98,29 @@ void *OICCalloc(size_t num, size_t size)
 #endif
 }
 
+void *OICRealloc(void* ptr, size_t size)
+{
+    if(size == 0)
+    {
+        OICFree(ptr);
+        return NULL;
+    }
+
+#ifdef ENABLE_MALLOC_DEBUG
+    if(ptr == NULL)
+    {
+        return OICMalloc(size);
+    }
+
+    void* newptr = NULL;
+    newptr = realloc(ptr, size);
+    OIC_LOG_V(INFO, TAG, "realloc: ptr=%p, newptr=%p, size=%u", ptr, newptr, size);
+    return ptr;
+#else
+    return realloc(ptr, size);
+#endif
+}
+
 void OICFree(void *ptr)
 {
 #ifdef ENABLE_MALLOC_DEBUG
index 14bfd03..9519797 100644 (file)
@@ -102,6 +102,9 @@ liboctbstack_src = [
        '../../extlibs/cjson/cJSON.c',
        '../../extlibs/timer/timer.c',
        OCTBSTACK_SRC + 'ocstack.c',
+       OCTBSTACK_SRC + 'ocpayload.c',
+       OCTBSTACK_SRC + 'ocpayloadparse.c',
+       OCTBSTACK_SRC + 'ocpayloadconvert.c',
        OCTBSTACK_SRC + 'occlientcb.c',
        OCTBSTACK_SRC + 'ocresource.c',
        OCTBSTACK_SRC + 'ocobserve.c',
@@ -112,6 +115,8 @@ liboctbstack_src = [
        'ocrandom/src/ocrandom.c'
        ]
 
+liboctbstack_src.extend(env['cbor_files'])
+
 if target_os in ['arduino','darwin','ios'] :
        static_liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
        liboctbstack_env.InstallTarget(static_liboctbstack, 'liboctbstack')
index f821fba..3970fc5 100644 (file)
@@ -98,7 +98,7 @@ extern "C"
 /**
  * @brief Payload information from resource model
  */
-typedef char *CAPayload_t;
+typedef uint8_t *CAPayload_t;
 
 /**
  * @brief URI for the OIC base.CA considers relative URI as the URI.
@@ -303,6 +303,7 @@ typedef struct
     CAHeaderOption_t *options;  /** Header Options for the request */
     uint8_t numOptions;         /**< Number of Header options */
     CAPayload_t payload;        /**< payload of the request  */
+    size_t payloadSize;         /**< size in bytes of the payload */
     CAURI_t resourceUri;        /**< Resource URI information **/
 } CAInfo_t;
 
index eaa9ff0..49eb444 100644 (file)
@@ -115,7 +115,7 @@ CARequestInfo_t *CACloneRequestInfo(const CARequestInfo_t *rep)
     if (NULL != rep->info.payload)
     {
         // allocate payload field
-        char *temp = OICStrdup(rep->info.payload);
+        uint8_t *temp = OICMalloc(rep->info.payloadSize);
         if (NULL == temp)
         {
             OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory");
@@ -124,6 +124,7 @@ CARequestInfo_t *CACloneRequestInfo(const CARequestInfo_t *rep)
 
             return NULL;
         }
+        memcpy(temp, rep->info.payload, rep->info.payloadSize);
 
         // save the payload
         clone->info.payload = temp;
@@ -242,7 +243,7 @@ CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *rep)
     if (NULL != rep->info.payload)
     {
         // allocate payload field
-        char *temp = OICStrdup(rep->info.payload);
+        uint8_t *temp = (uint8_t *) OICMalloc(rep->info.payloadSize);
         if (NULL == temp)
         {
             OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
@@ -251,6 +252,7 @@ CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *rep)
 
             return NULL;
         }
+        memcpy(temp, rep->info.payload, rep->info.payloadSize);
 
         // save the payload
         clone->info.payload = temp;
index b71c9b9..591aac1 100644 (file)
@@ -94,7 +94,7 @@ CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, CAErrorInfo_t *errorInfo
  * @return  generated pdu
  */
 coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
-                              const char *payload, size_t payloadSize);
+                              const uint8_t *payload, size_t payloadSize);
 
 /**
  * @brief   parse the URI and creates the options
index 5762007..d246654 100644 (file)
@@ -276,7 +276,7 @@ int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data)
     return 1;
 }
 
-int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data)
+int coap_get_data(const coap_pdu_t *pdu, size_t *len, unsigned char **data)
 {
     assert(pdu);
     assert(len);
index c469b24..f45831a 100644 (file)
@@ -346,6 +346,6 @@ int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data);
  * or 1 if *len and *data have correct values. Note that these values are
  * destroyed with the pdu.
  */
-int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data);
+int coap_get_data(const coap_pdu_t *pdu, size_t *len, unsigned char **data);
 
 #endif /* _PDU_H_ */
index 52040c2..a254ec4 100644 (file)
@@ -432,7 +432,7 @@ void SendRequestAll()
     CAInfo_t requestData = {CA_MSG_RESET};
     requestData.token = token;
     requestData.tokenLength = tokenLength;
-    requestData.payload = "Temp Json Payload";
+    requestData.payload = (CAPayload_t)"Temp Json Payload";
     requestData.type = CA_MSG_NONCONFIRM;
     requestData.resourceUri = (char *)OICMalloc(strlen(resourceUri) + 1);
     strcpy(requestData.resourceUri, resourceUri);
@@ -704,7 +704,7 @@ void RequestHandler(const CAEndpoint_t *object, const CARequestInfo_t *requestIn
     Serial.print("uri: ");
     Serial.println(requestInfo->info.resourceUri);
     Serial.print("data: ");
-    Serial.println(requestInfo->info.payload);
+    Serial.println((char*)requestInfo->info.payload);
     Serial.print("Type: ");
     Serial.println(requestInfo->info.type);
 
@@ -739,7 +739,7 @@ void ResponseHandler(const CAEndpoint_t *object, const CAResponseInfo_t *respons
         Serial.print("uri: ");
         Serial.println(responseInfo->info.resourceUri);
         Serial.print("data: ");
-        Serial.println(responseInfo->info.payload);
+        Serial.println((char*)responseInfo->info.payload);
         Serial.print("Type: ");
         Serial.println(responseInfo->info.type);
         Serial.print("res result=");
@@ -765,7 +765,7 @@ void ErrorHandler(const CAEndpoint_t *rep, const CAErrorInfo_t* errorInfo)
         Serial.print("resourceUri: ");
         Serial.println(info->resourceUri);
         Serial.print("payload: ");
-        Serial.println(info->payload);
+        Serial.println((char*)info->payload);
     }
 
     return;
@@ -838,7 +838,7 @@ void SendResponse(CAEndpoint_t *endpoint, const CAInfo_t* info)
     {
         responseData.token = (info != NULL) ? info->token : NULL;
         responseData.tokenLength = (info != NULL) ? info->tokenLength : 0;
-        responseData.payload = static_cast<CAPayload_t>("response payload");
+        responseData.payload = reinterpret_cast<CAPayload_t>(const_cast<char*>("response payload"));
     }
     CAResponseInfo_t responseInfo = {CA_BAD_REQ, {CA_MSG_RESET}};
     responseInfo.result = static_cast<CAResponseResult_t>(respCode);
index d839c95..a4e37c3 100644 (file)
@@ -368,10 +368,6 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, u
             }
         }
 
-        if (NULL != ReqInfo->info.payload)
-        {
-            OIC_LOG_V(DEBUG, TAG, "Request- payload: %s", ReqInfo->info.payload);
-        }
         OIC_LOG_V(DEBUG, TAG, "Request- code: %d", ReqInfo->method);
         if (NULL != ReqInfo->info.token)
         {
@@ -379,6 +375,7 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, u
             OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) ReqInfo->info.token,
                            ReqInfo->info.tokenLength);
         }
+
         OIC_LOG_V(DEBUG, TAG, "Request- msgID : %d", ReqInfo->info.messageId);
         // store the data at queue.
         CAData_t *cadata = NULL;
@@ -429,7 +426,8 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, u
 
         if (NULL != ResInfo->info.payload)
         {
-            OIC_LOG_V(DEBUG, TAG, "Response- payload: %s", ResInfo->info.payload);
+            OIC_LOG_V(DEBUG, TAG, "Response- payload: %p(%u) from %s", ResInfo->info.payload,
+                    ResInfo->info.payloadSize, endpoint->addr);
         }
         OIC_LOG_V(DEBUG, TAG, "Response- code: %d", ResInfo->result);
         if (NULL != ResInfo->info.token)
index 7c7fefc..3883c82 100644 (file)
@@ -188,8 +188,7 @@ coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info)
             coap_delete_list(optlist);
             return NULL;
         }
-        size_t lenPayload = info->payload ? strlen(info->payload) : 0;
-        pdu = CAGeneratePDUImpl((code_t)code, optlist, info, info->payload, lenPayload);
+        pdu = CAGeneratePDUImpl((code_t)code, optlist, info, info->payload, info->payloadSize);
         if (NULL == pdu)
         {
             OIC_LOG(ERROR, TAG, "pdu NULL");
@@ -240,7 +239,7 @@ coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
 }
 
 coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
-                              const char *payload, size_t payloadSize)
+                              const uint8_t *payload, size_t payloadSize)
 {
     OIC_LOG(DEBUG, TAG, "IN");
     VERIFY_NON_NULL_RET(info, TAG, "info is NULL", NULL);
@@ -300,7 +299,6 @@ coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t
 
     if (NULL != payload)
     {
-        OIC_LOG_V(DEBUG, TAG, "add data, payload:%s", payload);
         coap_add_data(pdu, payloadSize, (const unsigned char *) payload);
     }
 
@@ -716,11 +714,12 @@ CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *
     outInfo->tokenLength = pdu->hdr->token_length;
 
     // set payload data
-    if (NULL != pdu->data)
+    size_t dataSize;
+    uint8_t *data;
+    if (coap_get_data(pdu, &dataSize, &data))
     {
-        uint32_t payloadLength = strlen((char*) pdu->data);
         OIC_LOG(DEBUG, TAG, "inside pdu->data");
-        outInfo->payload = (char *) OICMalloc(payloadLength + 1);
+        outInfo->payload = (uint8_t *) OICMalloc(dataSize);
         if (NULL == outInfo->payload)
         {
             OIC_LOG(ERROR, TAG, "Out of memory");
@@ -728,8 +727,8 @@ CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *
             OICFree(outInfo->token);
             return CA_MEMORY_ALLOC_FAILED;
         }
-        memcpy(outInfo->payload, pdu->data, payloadLength);
-        outInfo->payload[payloadLength] = '\0';
+        memcpy(outInfo->payload, pdu->data, dataSize);
+        outInfo->payloadSize = dataSize;
     }
 
     uint32_t length = strlen(optionResult);
index 1a4a20b..3449647 100644 (file)
@@ -265,7 +265,8 @@ TEST(SendRequestTest, DISABLED_TC_16_Positive_01)
         CADestroyToken(tempToken);
         FAIL() << "requestData.payload allocation failed";
     }
-    snprintf(requestData.payload, length, NORMAL_INFO_DATA, "a/light");
+    snprintf((char*)requestData.payload, length, NORMAL_INFO_DATA, "a/light");
+    requestData.payloadSize = length + 1;
     requestData.type = CA_MSG_NONCONFIRM;
 
     memset(&requestInfo, 0, sizeof(CARequestInfo_t));
@@ -308,7 +309,9 @@ TEST(SendResponseTest, DISABLED_TC_19_Positive_01)
     memset(&responseData, 0, sizeof(CAInfo_t));
     responseData.type = CA_MSG_NONCONFIRM;
     responseData.messageId = 1;
-    responseData.payload = (char *) "response payload";
+    responseData.payload = (CAPayload_t)malloc(sizeof("response payload"));
+    memcpy(responseData.payload, "response payload", sizeof("response payload"));
+    responseData.payloadSize = sizeof("response payload");
 
     CAGenerateToken(&tempToken, tokenLength);
     requestData.token = tempToken;
@@ -322,6 +325,7 @@ TEST(SendResponseTest, DISABLED_TC_19_Positive_01)
 
     CADestroyToken(tempToken);
     CADestroyEndpoint(tempRep);
+    free(responseData.payload);
     tempRep = NULL;
 }
 
@@ -334,7 +338,9 @@ TEST(SendResponseTest, DISABLED_TC_20_Negative_01)
     memset(&responseData, 0, sizeof(CAInfo_t));
     responseData.type = CA_MSG_NONCONFIRM;
     responseData.messageId = 1;
-    responseData.payload = (char *) "response payload";
+    responseData.payload = (CAPayload_t)malloc(sizeof("response payload"));
+    memcpy(responseData.payload, "response payload", sizeof("response payload"));
+    responseData.payloadSize = sizeof("response payload");
 
     CAGenerateToken(&tempToken, tokenLength);
     requestData.token = tempToken;
@@ -352,6 +358,7 @@ TEST(SendResponseTest, DISABLED_TC_20_Negative_01)
         CADestroyEndpoint(tempRep);
         tempRep = NULL;
     }
+    free (responseData.payload);
 }
 
 // check return value NULL is passed instead of a valid CAResponseInfo_t address
@@ -378,7 +385,9 @@ TEST(SendNotificationTest, DISABLED_TC_22_Positive_01)
 
     memset(&responseData, 0, sizeof(CAInfo_t));
     responseData.type = CA_MSG_NONCONFIRM;
-    responseData.payload = (char *) "Temp Notification Data";
+    responseData.payload = (CAPayload_t)malloc(sizeof("Temp Notification Data"));
+    memcpy(responseData.payload, "Temp Notification Data", sizeof("Temp Notification Data"));
+    responseData.payloadSize = sizeof("Temp Notification Data");
 
     CAGenerateToken(&tempToken, tokenLength);
     requestData.token = tempToken;
@@ -396,6 +405,7 @@ TEST(SendNotificationTest, DISABLED_TC_22_Positive_01)
         CADestroyEndpoint(tempRep);
         tempRep = NULL;
     }
+    free(responseData.payload);
 }
 
 // CASelectNewwork TC
index a58e868..d093b12 100644 (file)
@@ -28,6 +28,7 @@ provisioning_env = env.Clone()
 ######################################################################
 provisioning_env.AppendUnique(CPPPATH = [
                '../../stack/include',
+               '../../stack/include/internal',
                '../../ocrandom/include',
                '../../logger/include',
                '../../../oc_logger/include',
index 47b0657..14eed5f 100644 (file)
 #include <stdbool.h>
 
 #include "cJSON.h"
+#include "ocpayload.h"
+#include "ocpayloadcbor.h"
 #include "oic_malloc.h"
 #include "logger.h"
 #include "cacommon.h"
+#include "ocpayload.h"
 #include "cainterface.h"
 #include "provisioningmanager.h"
 #include "credentialgenerator.h"
@@ -313,7 +316,6 @@ static CAResult_t sendCARequest(CAMethod_t method,
         OC_LOG(ERROR, TAG, "Error while generating token");
         return CA_MEMORY_ALLOC_FAILED;
     }
-
     CAEndpoint_t *endpoint = NULL;
     if (CA_STATUS_OK != CACreateEndpoint((CATransportFlags_t)secure,
                                          devAddr->adapter, devAddr->addr,
@@ -324,20 +326,25 @@ static CAResult_t sendCARequest(CAMethod_t method,
         return CA_STATUS_FAILED;
     }
     CAMessageType_t msgType = CA_MSG_CONFIRM;
-    CAInfo_t requestData = { 0 };
-    requestData.token = gToken;
-    requestData.tokenLength  = CA_MAX_TOKEN_LEN;
     if (payload && '\0' != (*(payload + payloadLen)))
     {
         OC_LOG(ERROR, TAG, "Payload not properly terminated.");
         CADestroyEndpoint(endpoint);
         return CA_STATUS_INVALID_PARAM;
     }
-    requestData.payload = payload;
-    requestData.type = msgType;
+    OCSecurityPayload secPayload;
+    secPayload.securityData = payload;
+    secPayload.base.type = PAYLOAD_TYPE_SECURITY;
     CARequestInfo_t requestInfo = { 0 };
     requestInfo.method = method;
-    requestInfo.info = requestData;
+    requestInfo.isMulticast = false;
+    OCConvertPayload((OCPayload*)(&secPayload), &requestInfo.info.payload,
+            &requestInfo.info.payloadSize);
+    requestInfo.info.type = msgType;
+    requestInfo.info.token = gToken;
+    requestInfo.info.tokenLength  = CA_MAX_TOKEN_LEN;
+    requestInfo.info.resourceUri  = resourceUri;
+
     requestInfo.isMulticast = false;
     CAResult_t caResult = CA_STATUS_OK;
     caResult = CASendRequest(endpoint, &requestInfo);
@@ -421,6 +428,7 @@ static SPResult selectProvisioningMethod(OicSecOxm_t *supportedMethods, size_t n
     return SP_RESULT_SUCCESS;
 }
 
+OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize);
 /**
  * Response handler for discovery.
  *
@@ -442,22 +450,17 @@ static void ProvisionDiscoveryHandler(const CAEndpoint_t *object,
             }
             else
             {
-                // temp logic for trimming oc attribute from the json.
-                // JSONToBin should handle oc attribute.
-                char *pTempPayload = (char *)OICMalloc(strlen(responseInfo->info.payload));
-                if (NULL == pTempPayload)
+                OCPayload* payload;
+                OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
+                        responseInfo->info.payloadSize);
+
+                OicSecDoxm_t *ptrDoxm = NULL;
+
+                if(result == OC_STACK_OK && payload->type == PAYLOAD_TYPE_SECURITY)
                 {
-                    OC_LOG(ERROR, TAG, "Error while Memory allocation.");
-                    gStateManager = gStateManager | SP_DISCOVERY_ERROR;
-                    return;
+                    ptrDoxm = JSONToDoxmBin(((OCSecurityPayload*)payload)->securityData);
                 }
 
-                strcpy(pTempPayload, responseInfo->info.payload + 8);
-                pTempPayload[strlen(pTempPayload) - 2] = '\0';
-                OC_LOG_V(DEBUG, TAG, "Trimmed payload: %s", pTempPayload);
-                OicSecDoxm_t *ptrDoxm = JSONToDoxmBin(pTempPayload);
-                OICFree(pTempPayload);
-
                 if (NULL == ptrDoxm)
                 {
                     OC_LOG(INFO, TAG, "Ignoring malformed JSON");
@@ -539,26 +542,23 @@ static void ListMethodsHandler(const CAEndpoint_t *object,
                     return;
                 }
 
-                char *pTempPayload = (char *)OICMalloc(strlen(responseInfo->info.payload));
-                if (NULL == pTempPayload)
+                OCPayload* payload;
+                OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
+                        responseInfo->info.payloadSize);
+
+                OicSecPstat_t *pstat = NULL;
+
+                if(result == OC_STACK_OK && payload->type == PAYLOAD_TYPE_SECURITY)
                 {
-                    OC_LOG(ERROR, TAG, "Error in memory allocation.");
-                    gStateManager |= SP_LIST_METHODS_ERROR;
-                    return;
+                    pstat =  JSONToPstatBin(((OCSecurityPayload*)payload)->securityData);
                 }
 
-                strcpy(pTempPayload, responseInfo->info.payload + 8);
-                pTempPayload[strlen(pTempPayload) - 2] = '\0';
-
-                OicSecPstat_t *pstat =  JSONToPstatBin(pTempPayload);
                 if (NULL == pstat)
                 {
                     OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
-                    OICFree(pTempPayload);
                     gStateManager |= SP_LIST_METHODS_ERROR;
                     return;
                 }
-                OICFree(pTempPayload);
                 DeletePstatBinData(gPstat);
 
                 gPstat = pstat;
@@ -781,6 +781,7 @@ static SPResult findResource(unsigned short timeout)
     requestData.token = gToken;
     requestData.tokenLength  = CA_MAX_TOKEN_LEN;
     requestData.payload = NULL;
+    requestData.payloadSize = 0;
     requestData.type = msgType;
     requestData.resourceUri = DOXM_OWNED_FALSE_MULTICAST_QUERY;
     CARequestInfo_t requestInfo = { 0 };
@@ -958,7 +959,7 @@ static SPResult updateOperationMode(unsigned short timeout,
  * @param[in]  deviceInfo  Provisioning context
  * @return SP_SUCCESS on success
  */
-static SPResult initiateDtlsHandshake(const SPTargetDeviceInfo_t *deviceInfo)
+static SPResult initiateDtlsHandshake(SPTargetDeviceInfo_t *deviceInfo)
 {
     CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
 
@@ -976,6 +977,8 @@ static SPResult initiateDtlsHandshake(const SPTargetDeviceInfo_t *deviceInfo)
     }
     OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
 
+    //TODO: It is a temporary fix. Revisit it.
+    deviceInfo->endpoint.port = CA_SECURE_PORT;
     caresult = CAInitiateHandshake((CAEndpoint_t *)&deviceInfo->endpoint);
     if (CA_STATUS_OK != caresult)
     {
@@ -1322,7 +1325,7 @@ SPResult SPProvisionACL(unsigned short timeout, const SPTargetDeviceInfo_t *sele
     CAResult_t result = sendCARequest(CA_POST,
                                       &selectedDeviceInfo->endpoint,
                                       OC_SECURE,
-                                      OIC_RSRC_DOXM_URI,
+                                      OIC_RSRC_ACL_URI,
                                       aclString, payloadLen);
     OICFree(aclString);
     if (CA_STATUS_OK != result)
index 8e6e7c0..7921b0b 100644 (file)
@@ -305,7 +305,7 @@ static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest
     OCEntityHandlerResult ehRet = OC_EH_ERROR;
 
     // Convert JSON ACL data into binary. This will also validate the ACL data received.
-    OicSecAcl_t* newAcl = JSONToAclBin((char *)(ehRequest->reqJSONPayload));
+    OicSecAcl_t* newAcl = JSONToAclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
 
     if (newAcl)
     {
index 1ceb2d9..af21b26 100755 (executable)
@@ -506,7 +506,7 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
     OCEntityHandlerResult ret = OC_EH_ERROR;
 
     //Get binary representation of json
-    OicSecCred_t * cred  = JSONToCredBin((char *)ehRequest->reqJSONPayload);
+    OicSecCred_t * cred  = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
 
     if(cred)
     {
index a9a9696..310ffe5 100755 (executable)
@@ -419,7 +419,7 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
      * Convert JSON Doxm data into binary. This will also validate
      * the Doxm data received.
      */
-    OicSecDoxm_t* newDoxm = JSONToDoxmBin((char *)(ehRequest->reqJSONPayload));
+    OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
 
     if (newDoxm)
     {
index b0b0a58..aa798e0 100644 (file)
@@ -220,7 +220,7 @@ static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest
 
     if (ehRequest->resource)
     {
-        postJson = cJSON_Parse((char *) ehRequest->reqJSONPayload);
+        postJson = cJSON_Parse(((OCSecurityPayload*)ehRequest->payload)->securityData);
         VERIFY_NON_NULL(TAG, postJson, INFO);
         cJSON *jsonPstat = cJSON_GetObjectItem(postJson, OIC_JSON_PSTAT_NAME);
         VERIFY_NON_NULL(TAG, jsonPstat, INFO);
index 64725cc..f167855 100644 (file)
@@ -25,6 +25,7 @@
 #include "doxmresource.h"
 #include "credresource.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 #include "logger.h"
 #include "utlist.h"
 #include <string.h>
@@ -50,8 +51,9 @@ OCStackResult SendSRMResponse(const OCEntityHandlerRequest *ehRequest,
         response.requestHandle = ehRequest->requestHandle;
         response.resourceHandle = ehRequest->resource;
         response.ehResult = ehRet;
-        response.payload = (char *)rspPayload;
-        response.payloadSize = (rspPayload ? strlen(rspPayload) : 0);
+        response.payload = (OCPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+        response.payload->type = PAYLOAD_TYPE_SECURITY;
+        ((OCSecurityPayload*)response.payload)->securityData = OICStrdup(rspPayload);
         response.persistentBufferFlag = 0;
 
         return OCDoResponse(&response);
index 5608e16..2cdb0f8 100644 (file)
@@ -192,7 +192,9 @@ TEST(ACLResourceTest, ACLPostTest)
 
         // Create Entity Handler POST request payload
         ehReq.method = OC_REST_POST;
-        ehReq.reqJSONPayload = jsonStr;
+        ehReq.payload = (OCPayload*)calloc(1, sizeof(OCSecurityPayload));
+        ehReq.payload->type = PAYLOAD_TYPE_SECURITY;
+        ((OCSecurityPayload*)ehReq.payload)->securityData = jsonStr;
 
         OCEntityHandlerResult ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
         EXPECT_TRUE(OC_EH_ERROR == ehRet);
index 4ccdb86..10398c5 100644 (file)
@@ -73,7 +73,10 @@ TEST(PstatEntityHandlerTest, PstatEntityHandlerWithPostRequest)
 {
     OCEntityHandlerRequest req;
     req.method = OC_REST_POST;
-    req.reqJSONPayload = (char*)"{ \"pstat\": { \"tm\": 0, \"om\": 3 }}";
+    req.payload = (OCPayload*)calloc(1, sizeof(OCSecurityPayload));
+    req.payload->type = PAYLOAD_TYPE_SECURITY;
+    ((OCSecurityPayload*)req.payload)->securityData =
+        (char*)"{ \"pstat\": { \"tm\": 0, \"om\": 3 }}";
     EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
 }
 
index 7a5749a..37c8c09 100644 (file)
@@ -92,14 +92,14 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
  * @param resource Observed resource
  * @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 payload - OCRepresentationPayload object representing the message
  * @param maxAge Time To Live (in seconds) of observation.
  * @param qos Desired quality of service of the observation notifications.
  * @return ::OC_STACK_OK on success, some other value upon failure.
  */
 OCStackResult SendListObserverNotification (OCResource * resource,
         OCObservationId  *obsIdList, uint8_t numberOfIds,
-        const char *notificationJSONPayload, uint32_t maxAge,
+        const OCRepPayload *payload, uint32_t maxAge,
         OCQualityOfService qos);
 
 /**
diff --git a/resource/csdk/stack/include/internal/ocpayloadcbor.h b/resource/csdk/stack/include/internal/ocpayloadcbor.h
new file mode 100644 (file)
index 0000000..5d3c16e
--- /dev/null
@@ -0,0 +1,29 @@
+//******************************************************************
+//
+// 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_PAYLOAD_CBOR_H
+#define OC_PAYLOAD_CBOR_H
+
+#include "octypes.h"
+
+OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize);
+
+OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size);
+#endif
index e38806a..6fe298e 100644 (file)
@@ -126,8 +126,8 @@ typedef struct resourceinterface_t {
     /*** Future placeholder for access control and policy ***/
 } OCResourceInterface;
 
-typedef struct rsrc_t {
-    struct rsrc_t *next; // Points to next resource in list
+typedef struct OCResource {
+    struct OCResource *next; // Points to next resource in list
     // Relative path on the device; will be combined with base url to create fully qualified path
     char *uri;
     OCResourceType *rsrcType; // Resource type(s); linked list
@@ -135,7 +135,7 @@ typedef struct rsrc_t {
     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 OCResource *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
index b0776b3..4b8efcd 100644 (file)
@@ -138,8 +138,7 @@ void DeleteDeviceInfo();
  * Prepares a JSON string for response.
  */
 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
-                                           char * out,
-                                           uint16_t *remaining,
+                                           OCDiscoveryPayload* payload,
                                            CATransportAdapter_t adapter);
 
 /**
index fce897a..16f8dc6 100644 (file)
@@ -63,16 +63,16 @@ typedef struct OCServerRequest
     // Flag indicating slow response
     uint8_t slowFlag;
     uint8_t notificationFlag;
-    // reqJSON is retrieved from the payload of the received request PDU
-    char reqJSONPayload[1];
+    size_t payloadSize;
+    // payload is retrieved from the payload of the received request PDU
+    uint8_t payload[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
-    char *payload;
-    uint16_t remainingPayloadSize;
+    OCPayload* payload;
     OCRequestHandle requestHandle;
 } OCServerResponse;
 
@@ -159,7 +159,7 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
         uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
         OCQualityOfService qos, char * query,
         OCHeaderOption * rcvdVendorSpecificHeaderOptions,
-        char * reqJSONPayload, CAToken_t requestToken,
+        uint8_t * payload, CAToken_t requestToken,
         uint8_t tokenLength,
         char * resourceUrl, size_t reqTotalSize,
         const OCDevAddr *devAddr);
@@ -172,7 +172,8 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
  * @param method           - RESTful method
  * @param resource         - resource handle
  * @param queryBuf         - resource query of request
- * @param bufReqPayload    - JSON payload of request
+ * @param payload          - payload of request
+ * @param payloadSize      - size of the payload request
  * @param numVendorOptions - number of vendor options
  * @param vendorOptions    - vendor options
  * @param observeAction    - observe action flag
@@ -181,8 +182,10 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
  * @return
  *     OCStackResult
  */
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
-        OCMethod method, OCResourceHandle resource, char * queryBuf, char * bufReqPayload,
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest,
+        OCRequestHandle request,
+        OCMethod method, OCResourceHandle resource, char * queryBuf,
+        uint8_t * payload, size_t payloadSize,
         uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
         OCObservationId observeID);
 
index 1fd936b..709a4b0 100644 (file)
@@ -69,7 +69,7 @@ typedef struct
     // resource query send by client
     char query[MAX_QUERY_LENGTH];
     // reqJSON is retrieved from the payload of the received request PDU
-    char reqJSONPayload[MAX_REQUEST_LENGTH];
+    uint8_t payload[MAX_REQUEST_LENGTH];
     // qos is indicating if the request is CON or NON
     OCQualityOfService qos;
     // An array of the received vendor specific header options
@@ -136,26 +136,6 @@ OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16
         CAToken_t token, uint8_t tokenLength);
 
 #ifdef WITH_PRESENCE
-/**
- * The OCPresenceTrigger enum delineates the three spec-compliant modes for
- * "Trigger." These enum values are then mapped to JSON strings
- * "create", "change", "delete", respectively, before getting encoded into
- * the JSON payload.
- *
- * @enum OC_PRESENCE_TRIGGER_CREATE The creation of a resource is associated with
- *                            this invocation of @ref SendPresenceNotification.
- * @enum OC_PRESENCE_TRIGGER_CHANGE The change/update of a resource is associated
- *                            this invocation of @ref SendPresenceNotification.
- * @enum OC_PRESENCE_TRIGGER_DELETE The deletion of a resource is associated with
- *                            this invocation of @ref SendPresenceNotification.
- *
- */
-typedef enum
-{
-    OC_PRESENCE_TRIGGER_CREATE = 0,
-    OC_PRESENCE_TRIGGER_CHANGE = 1,
-    OC_PRESENCE_TRIGGER_DELETE = 2
-} OCPresenceTrigger;
 
 /**
  * Notify Presence subscribers that a resource has been modified.
diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h
new file mode 100644 (file)
index 0000000..91776c4
--- /dev/null
@@ -0,0 +1,384 @@
+//******************************************************************
+//
+// Copyright 2015 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 OCPAYLOAD_H_
+#define OCPAYLOAD_H_
+
+#include <stdbool.h>
+#include <inttypes.h>
+#include "logger.h"
+#include "octypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct OCResource OCResource;
+
+#ifdef TB_LOG
+    #define OC_LOG_PAYLOAD(level, tag, payload) OCPayloadLog((level),(tag),(payload))
+    #define UUID_SIZE (16)
+    #define UUID_LENGTH (37)
+const char *convertTriggerEnumToString(OCPresenceTrigger trigger);
+OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr);
+
+static inline void OCPayloadLogRep(LogLevel level, const char* tag, OCRepPayload* payload)
+{
+    OC_LOG(level, tag, PCF("Payload Type: Representation"));
+    OCRepPayload* rep = payload;
+    int i = 1;
+    while(rep)
+    {
+        OC_LOG_V(level, tag, "\tResource #%d", i);
+        OC_LOG_V(level, tag, "\tURL:%s", rep->uri);
+        OC_LOG(level, tag, PCF("\tResource Types:"));
+        OCStringLL* strll =  rep->types;
+        while(strll)
+        {
+            OC_LOG_V(level, tag, "\t\t%s", strll->value);
+            strll = strll->next;
+        }
+        OC_LOG(level, tag, PCF("\tInterfaces:"));
+        strll =  rep->interfaces;
+        while(strll)
+        {
+            OC_LOG_V(level, tag, "\t\t%s", strll->value);
+            strll = strll->next;
+        }
+
+        // TODO Finish Logging: Values
+        OCRepPayloadValue* val = rep->values;
+
+        OC_LOG(level, tag, PCF("\tValues:"));
+
+        while(val)
+        {
+            switch(val->type)
+            {
+                case OCREP_PROP_NULL:
+                    OC_LOG_V(level, tag, "\t\t%s: NULL", val->name);
+                    break;
+                case OCREP_PROP_INT:
+                    OC_LOG_V(level, tag, "\t\t%s(int):%lld", val->name, val->i);
+                    break;
+                case OCREP_PROP_DOUBLE:
+                    OC_LOG_V(level, tag, "\t\t%s(double):%f", val->name, val->d);
+                    break;
+                case OCREP_PROP_BOOL:
+                    OC_LOG_V(level, tag, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");
+                    break;
+                case OCREP_PROP_STRING:
+                    OC_LOG_V(level, tag, "\t\t%s(string):%s", val->name, val->str);
+                    break;
+                case OCREP_PROP_OBJECT:
+                    // Note: Only prints the URI (if available), to print further, you'll
+                    // need to dig into the object better!
+                    OC_LOG_V(level, tag, "\t\t%s(OCRep):%s", val->name, val->obj->uri);
+                    break;
+                case OCREP_PROP_ARRAY:
+                    switch(val->arr.type)
+                    {
+                        case OCREP_PROP_INT:
+                            OC_LOG_V(level, tag, "\t\t%s(int array):%lld x %lld x %lld",
+                                    val->name,
+                                    val->arr.dimensions[0], val->arr.dimensions[1],
+                                    val->arr.dimensions[2]);
+                            break;
+                        case OCREP_PROP_DOUBLE:
+                            OC_LOG_V(level, tag, "\t\t%s(double array):%lld x %lld x %lld",
+                                    val->name,
+                                    val->arr.dimensions[0], val->arr.dimensions[1],
+                                    val->arr.dimensions[2]);
+                            break;
+                        case OCREP_PROP_BOOL:
+                            OC_LOG_V(level, tag, "\t\t%s(bool array):%lld x %lld x %lld",
+                                    val->name,
+                                    val->arr.dimensions[0], val->arr.dimensions[1],
+                                    val->arr.dimensions[2]);
+                            break;
+                        case OCREP_PROP_STRING:
+                            OC_LOG_V(level, tag, "\t\t%s(string array):%lld x %lld x %lld",
+                                    val->name,
+                                    val->arr.dimensions[0], val->arr.dimensions[1],
+                                    val->arr.dimensions[2]);
+                            break;
+                        case OCREP_PROP_OBJECT:
+                            OC_LOG_V(level, tag, "\t\t%s(OCRep array):%lld x %lld x %lld",
+                                    val->name,
+                                    val->arr.dimensions[0], val->arr.dimensions[1],
+                                    val->arr.dimensions[2]);
+                            break;
+                        default:
+                            OC_LOG_V(ERROR, tag, "\t\t%s <-- Unknown/unsupported array type!",
+                                    val->name);
+                            break;
+                    }
+                    break;
+                default:
+                    OC_LOG_V(ERROR, tag, "\t\t%s <-- Unknown type!", val->name);
+                    break;
+            }
+            val = val -> next;
+        }
+
+        ++i;
+        rep = rep->next;
+    }
+
+}
+
+static inline void OCPayloadLogDiscovery(LogLevel level, const char* tag,
+        OCDiscoveryPayload* payload)
+{
+    OC_LOG(level, tag, PCF("Payload Type: Discovery"));
+    int i = 1;
+
+    if(!payload->resources)
+    {
+        OC_LOG(level, tag, PCF("\tNO Resources"));
+        return;
+    }
+
+    OCResourcePayload* res = payload->resources;
+
+    while(res)
+    {
+        OC_LOG_V(level, tag, "\tResource #%d", i);
+        OC_LOG_V(level, tag, "\tURI:%s", res->uri);
+        OC_LOG(level, tag, PCF("\tSID:"));
+        OC_LOG_BUFFER(level, tag, res->sid, UUID_SIZE);
+        OC_LOG(level, tag, PCF("\tResource Types:"));
+        OCStringLL* strll =  res->types;
+        while(strll)
+        {
+            OC_LOG_V(level, tag, "\t\t%s", strll->value);
+            strll = strll->next;
+        }
+        OC_LOG(level, tag, PCF("\tInterfaces:"));
+        strll =  res->interfaces;
+        while(strll)
+        {
+            OC_LOG_V(level, tag, "\t\t%s", strll->value);
+            strll = strll->next;
+        }
+
+        OC_LOG_V(level, tag, "\tBitmap: %u", res->bitmap);
+        OC_LOG_V(level, tag, "\tSecure?: %s", res->secure ? "true" : "false");
+        OC_LOG_V(level, tag, "\tPort: %u", res->port);
+        OC_LOG(level, tag, PCF(""));
+        res = res->next;
+        ++i;
+    }
+}
+
+static inline void OCPayloadLogDevice(LogLevel level, const char* tag, OCDevicePayload* payload)
+{
+    OC_LOG(level, tag, PCF("Payload Type: Device"));
+    OC_LOG_V(level, tag, "\tURI:%s", payload->uri);
+    OC_LOG(level, tag, PCF("\tSID:"));
+    OC_LOG_BUFFER(level, tag, payload->sid, UUID_SIZE);
+    OC_LOG_V(level, tag, "\tDevice Name:%s", payload->deviceName);
+    OC_LOG_V(level, tag, "\tSpec Version%s", payload->specVersion);
+    OC_LOG_V(level, tag, "\tData Model Version:%s", payload->dataModelVersion);
+}
+
+static inline void OCPayloadLogPlatform(LogLevel level, const char* tag, OCPlatformPayload* payload)
+{
+    OC_LOG(level, tag, PCF("Payload Type: Platform"));
+    OC_LOG_V(level, tag, "\tURI:%s", payload->uri);
+    OC_LOG_V(level, tag, "\tPlatform ID:%s", payload->info.platformID);
+    OC_LOG_V(level, tag, "\tMfg Name:%s", payload->info.manufacturerName);
+    OC_LOG_V(level, tag, "\tMfg URL:%s", payload->info.manufacturerUrl);
+    OC_LOG_V(level, tag, "\tModel Number:%s", payload->info.modelNumber);
+    OC_LOG_V(level, tag, "\tDate of Mfg:%s", payload->info.dateOfManufacture);
+    OC_LOG_V(level, tag, "\tPlatform Version:%s", payload->info.platformVersion);
+    OC_LOG_V(level, tag, "\tOS Version:%s", payload->info.operatingSystemVersion);
+    OC_LOG_V(level, tag, "\tHardware Version:%s", payload->info.hardwareVersion);
+    OC_LOG_V(level, tag, "\tFirmware Version:%s", payload->info.firmwareVersion);
+    OC_LOG_V(level, tag, "\tSupport URL:%s", payload->info.supportUrl);
+    OC_LOG_V(level, tag, "\tSystem Time:%s", payload->info.systemTime);
+}
+
+static inline void OCPayloadLogPresence(LogLevel level, const char* tag, OCPresencePayload* payload)
+{
+    OC_LOG(level, tag, PCF("Payload Type: Presence"));
+    OC_LOG_V(level, tag, "\tSequence Number:%u", payload->sequenceNumber);
+    OC_LOG_V(level, tag, "\tMax Age:%d", payload->maxAge);
+    OC_LOG_V(level, tag, "\tTrigger:%s", convertTriggerEnumToString(payload->trigger));
+    OC_LOG_V(level, tag, "\tResource Type:%s", payload->resourceType);
+}
+
+static inline void OCPayloadLogSecurity(LogLevel level, const char* tag,
+                                        OCSecurityPayload* payload)
+{
+    OC_LOG(level, tag, PCF("Payload Type: Security"));
+    OC_LOG_V(level, tag, "\tSecurity Data: %s", payload->securityData);
+}
+
+static inline void OCPayloadLog(LogLevel level, const char* tag, OCPayload* payload)
+{
+    if(!payload)
+    {
+        OC_LOG(level, tag, PCF("NULL Payload"));
+        return;
+    }
+    switch(payload->type)
+    {
+        case PAYLOAD_TYPE_REPRESENTATION:
+            OCPayloadLogRep(level, tag, (OCRepPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_DISCOVERY:
+            OCPayloadLogDiscovery(level, tag, (OCDiscoveryPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_DEVICE:
+            OCPayloadLogDevice(level, tag, (OCDevicePayload*)payload);
+            break;
+        case PAYLOAD_TYPE_PLATFORM:
+            OCPayloadLogPlatform(level, tag, (OCPlatformPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_PRESENCE:
+            OCPayloadLogPresence(level, tag, (OCPresencePayload*)payload);
+            break;
+        case PAYLOAD_TYPE_SECURITY:
+            OCPayloadLogSecurity(level, tag, (OCSecurityPayload*)payload);
+            break;
+        default:
+            OC_LOG_V(level, tag, "Unknown Payload Type: %d", payload->type);
+            break;
+    }
+}
+#else
+    #define OC_LOG_PAYLOAD(level, tag, payload)
+#endif
+
+void OCPayloadDestroy(OCPayload* payload);
+
+// Representation Payload
+OCRepPayload* OCRepPayloadCreate();
+
+size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+
+OCRepPayload* OCRepPayloadClone(const OCRepPayload* payload);
+
+void OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child);
+
+bool OCRepPayloadSetUri(OCRepPayload* payload, const char* uri);
+
+bool OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType);
+bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* interface);
+
+bool OCRepPayloadAddResourceTypeAsOwner(OCRepPayload* payload, char* resourceType);
+bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface);
+
+bool OCRepPayloadIsNull(const OCRepPayload* payload, const char* name);
+bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name);
+
+bool OCRepPayloadSetPropInt(OCRepPayload* payload, const char* name, int64_t value);
+bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value);
+
+bool OCRepPayloadSetPropDouble(OCRepPayload* payload, const char* name, double value);
+bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value);
+
+bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value);
+bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value);
+bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value);
+
+bool OCRepPayloadSetPropBool(OCRepPayload* payload, const char* name, bool value);
+bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value);
+
+bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value);
+bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name,
+        OCRepPayload* value);
+bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value);
+
+bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name,
+        int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name,
+        const int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadGetIntArray(const OCRepPayload* payload, const char* name,
+        int64_t** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+
+bool OCRepPayloadSetDoubleArrayAsOwner(OCRepPayload* payload, const char* name,
+        double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadSetDoubleArray(OCRepPayload* payload, const char* name,
+        const double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
+        double** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+
+bool OCRepPayloadSetStringArrayAsOwner(OCRepPayload* payload, const char* name,
+        char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadSetStringArray(OCRepPayload* payload, const char* name,
+        const char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadGetStringArray(const OCRepPayload* payload, const char* name,
+        char*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+
+bool OCRepPayloadSetBoolArrayAsOwner(OCRepPayload* payload, const char* name,
+        bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadSetBoolArray(OCRepPayload* payload, const char* name,
+        const bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadGetBoolArray(const OCRepPayload* payload, const char* name,
+        bool** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+
+bool OCRepPayloadSetPropObjectArrayAsOwner(OCRepPayload* payload, const char* name,
+        OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadSetPropObjectArray(OCRepPayload* payload, const char* name,
+        const OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+bool OCRepPayloadGetPropObjectArray(const OCRepPayload* payload, const char* name,
+        OCRepPayload*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]);
+
+void OCRepPayloadDestroy(OCRepPayload* payload);
+
+// Discovery Payload
+OCDiscoveryPayload* OCDiscoveryPayloadCreate();
+
+OCSecurityPayload* OCSecurityPayloadCreate(char* securityData);
+void OCSecurityPayloadDestroy(OCSecurityPayload* payload);
+
+void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
+        uint16_t port);
+void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res);
+size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload);
+OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, size_t index);
+
+void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload);
+
+// Device Payload
+OCDevicePayload* OCDevicePayloadCreate(const char* uri, const uint8_t* sid, const char* dname,
+        const char* specVer, const char* dmVer);
+void OCDevicePayloadDestroy(OCDevicePayload* payload);
+
+// Platform Payload
+OCPlatformPayload* OCPlatformPayloadCreate(const char* uri, const OCPlatformInfo* platformInfo);
+OCPlatformPayload* OCPlatformPayloadCreateAsOwner(char* uri, OCPlatformInfo* platformInfo);
+
+void OCPlatformPayloadDestroy(OCPlatformPayload* payload);
+
+// Presence Payload
+OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge,
+        OCPresenceTrigger trigger, const char* resourceType);
+void OCPresencePayloadDestroy(OCPresencePayload* payload);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/resource/csdk/stack/include/ocpresence.h b/resource/csdk/stack/include/ocpresence.h
new file mode 100644 (file)
index 0000000..688b7d9
--- /dev/null
@@ -0,0 +1,47 @@
+//******************************************************************
+//
+// Copyright 2015 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 OCPRESENCE_H_
+#define OCPRESENCE_H_
+
+#ifdef WITH_PRESENCE
+/**
+ * The OCPresenceTrigger enum delineates the three spec-compliant modes for
+ * "Trigger." These enum values are then mapped to strings
+ * "create", "change", "delete", respectively, before getting encoded into
+ * the payload payload.
+ *
+ * @enum OC_PRESENCE_TRIGGER_CREATE The creation of a resource is associated with
+ *                            this invocation of @ref SendPresenceNotification.
+ * @enum OC_PRESENCE_TRIGGER_CHANGE The change/update of a resource is associated
+ *                            this invocation of @ref SendPresenceNotification.
+ * @enum OC_PRESENCE_TRIGGER_DELETE The deletion of a resource is associated with
+ *                            this invocation of @ref SendPresenceNotification.
+ *
+ */
+typedef enum
+{
+    OC_PRESENCE_TRIGGER_CREATE = 0,
+    OC_PRESENCE_TRIGGER_CHANGE = 1,
+    OC_PRESENCE_TRIGGER_DELETE = 2
+} OCPresenceTrigger;
+#endif
+
+#endif
index fa10079..86ec2b9 100644 (file)
@@ -118,7 +118,7 @@ OCStackResult OCDoResource(OCDoHandle *handle,
                             OCMethod method,
                             const char *requestUri,
                             const OCDevAddr *destination,
-                            const char *request,
+                            OCPayload* payload,
                             OCConnectivityType connectivityType,
                             OCQualityOfService qos,
                             OCCallbackData *cbData,
@@ -438,7 +438,7 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
  * @param handle Handle of resource.
  * @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 payload OCRepresentationPayload object representing the 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
@@ -450,7 +450,7 @@ OCStackResult
 OCNotifyListOfObservers (OCResourceHandle handle,
                             OCObservationId  *obsIdList,
                             uint8_t          numberOfIds,
-                            const char    *notificationJSONPayload,
+                            const OCRepPayload *payload,
                             OCQualityOfService qos);
 
 
index eb7e565..d1463eb 100644 (file)
@@ -38,9 +38,9 @@
  * They have a combined size of 10 bytes.
  */
 #ifdef WITH_ARDUINO
-#define MAX_RESPONSE_LENGTH (246)
+#define MAX_RESPONSE_LENGTH (256)
 #else
-#define MAX_RESPONSE_LENGTH (1014)
+#define MAX_RESPONSE_LENGTH (1024)
 #endif
 
 /**
index 1ee5146..58bb476 100644 (file)
 #define OCTYPES_H_
 
 #include "ocstackconfig.h"
-
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
 #ifdef __cplusplus
 #include <string.h>
 
 extern "C" {
 #endif // __cplusplus
 #define WITH_PRESENCE
+#include "ocpresence.h"
 //-----------------------------------------------------------------------------
 // Defines
 //-----------------------------------------------------------------------------
@@ -50,7 +53,7 @@ extern "C" {
 /**
  * Attributes used to form a proper OIC conforming JSON message.
  */
-#define OC_RSRVD_OC                     "oic"
+//#define OC_RSRVD_OC                     "oic"
 #define OC_RSRVD_PAYLOAD                "payload"
 #define OC_RSRVD_HREF                   "href"
 #define OC_RSRVD_PROPERTY               "prop"
@@ -499,6 +502,168 @@ typedef struct OCHeaderOption
 } OCHeaderOption;
 
 /**
+ * This structure describes the platform properties. All non-Null properties will be included
+ * in a platform discovery request.
+ */
+typedef struct
+{
+    char *platformID;
+    char *manufacturerName;
+    char *manufacturerUrl;
+    char *modelNumber;
+    char *dateOfManufacture;
+    char *platformVersion;
+    char *operatingSystemVersion;
+    char *hardwareVersion;
+    char *firmwareVersion;
+    char *supportUrl;
+    char *systemTime;
+
+} OCPlatformInfo;
+
+/**
+ * This structure is expected as input for device properties.
+ * device name is mandatory and expected from the application.
+ * device id of type UUID will be generated by the stack.
+ */
+typedef struct
+{
+    char *deviceName;
+
+} OCDeviceInfo;
+
+// Enum to describe the type of object held by the OCPayload object
+typedef enum
+{
+    PAYLOAD_TYPE_INVALID,
+    PAYLOAD_TYPE_DISCOVERY,
+    PAYLOAD_TYPE_DEVICE,
+    PAYLOAD_TYPE_PLATFORM,
+    PAYLOAD_TYPE_REPRESENTATION,
+    PAYLOAD_TYPE_SECURITY,
+    PAYLOAD_TYPE_PRESENCE
+} OCPayloadType;
+
+typedef struct
+{
+    // The type of message that was received
+    OCPayloadType type;
+} OCPayload;
+
+typedef enum
+{
+    OCREP_PROP_NULL,
+    OCREP_PROP_INT,
+    OCREP_PROP_DOUBLE,
+    OCREP_PROP_BOOL,
+    OCREP_PROP_STRING,
+    OCREP_PROP_OBJECT,
+    OCREP_PROP_ARRAY
+}OCRepPayloadPropType;
+
+#define MAX_REP_ARRAY_DEPTH 3
+typedef struct
+{
+    OCRepPayloadPropType type;
+    size_t dimensions[MAX_REP_ARRAY_DEPTH];
+
+    union
+    {
+        int64_t* iArray;
+        double* dArray;
+        bool* bArray;
+        char** strArray;
+        struct OCRepPayload** objArray;
+    };
+} OCRepPayloadValueArray;
+
+typedef struct OCRepPayloadValue
+{
+    char* name;
+    OCRepPayloadPropType type;
+    union
+    {
+        int64_t i;
+        double d;
+        bool b;
+        char* str;
+        struct OCRepPayload* obj;
+        OCRepPayloadValueArray arr;
+    };
+    struct OCRepPayloadValue* next;
+
+} OCRepPayloadValue;
+
+typedef struct OCStringLL
+{
+    struct OCStringLL *next;
+    char* value;
+} OCStringLL;
+
+// used for get/set/put/observe/etc representations
+typedef struct OCRepPayload
+{
+    OCPayload base;
+    char* uri;
+    OCStringLL* types;
+    OCStringLL* interfaces;
+    OCRepPayloadValue* values;
+    struct OCRepPayload* next;
+} OCRepPayload;
+
+// used inside a discovery payload
+typedef struct OCResourcePayload
+{
+    char* uri;
+    uint8_t* sid;
+    OCStringLL* types;
+    OCStringLL* interfaces;
+    uint8_t bitmap;
+    bool secure;
+    uint16_t port;
+    struct OCResourcePayload* next;
+} OCResourcePayload;
+
+typedef struct
+{
+    OCPayload base;
+    OCResourcePayload* resources;
+} OCDiscoveryPayload;
+
+typedef struct
+{
+    OCPayload base;
+    char* uri;
+    uint8_t* sid;
+    char* deviceName;
+    char* specVersion;
+    char* dataModelVersion;
+} OCDevicePayload;
+
+typedef struct
+{
+    OCPayload base;
+    char* uri;
+    OCPlatformInfo info;
+} OCPlatformPayload;
+
+typedef struct
+{
+    OCPayload base;
+    char* securityData;
+} OCSecurityPayload;
+#ifdef WITH_PRESENCE
+typedef struct
+{
+    OCPayload base;
+    uint32_t sequenceNumber;
+    uint32_t maxAge;
+    OCPresenceTrigger trigger;
+    char* resourceType;
+} OCPresencePayload;
+#endif
+
+/**
  * Incoming requests handled by the server. Requests are passed in as a parameter to the
  * @ref OCEntityHandler callback API.
  * @brief The @ref OCEntityHandler callback API must be implemented in the application in order
@@ -519,8 +684,8 @@ typedef struct
     // An array of the received vendor specific header options
     uint8_t numRcvdVendorSpecificHeaderOptions;
     OCHeaderOption * rcvdVendorSpecificHeaderOptions;
-    // reqJSON is retrieved from the payload of the received request PDU
-    char * reqJSONPayload;
+    // the payload from the request PDU
+    OCPayload *payload;
 } OCEntityHandlerRequest;
 
 /**
@@ -538,44 +703,13 @@ typedef struct
     uint32_t sequenceNumber;
     /// resourceURI
     const char * resourceUri;
-    /// resJSONPayload is retrieved from the payload of the received request PDU
-    const char * resJSONPayload;
+    // the payload for the response PDU
+    OCPayload *payload;
     /// An array of the received vendor specific header options
     uint8_t numRcvdVendorSpecificHeaderOptions;
     OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
 } OCClientResponse;
 
-/**
- * This structure describes the platform properties. All non-Null properties will be included
- * in a platform discovery request.
- */
-typedef struct
-{
-    char *platformID;
-    char *manufacturerName;
-    char *manufacturerUrl;
-    char *modelNumber;
-    char *dateOfManufacture;
-    char *platformVersion;
-    char *operatingSystemVersion;
-    char *hardwareVersion;
-    char *firmwareVersion;
-    char *supportUrl;
-    char *systemTime;
-
-} OCPlatformInfo;
-
-/**
- * This structure is expected as input for device properties.
- * device name is mandatory and expected from the application.
- * device id of type UUID will be generated by the stack.
- */
-typedef struct
-{
-    char *deviceName;
-
-} OCDeviceInfo;
-
 typedef struct
 {
     // Request handle is passed to server via the entity handler for each incoming request.
@@ -586,9 +720,7 @@ typedef struct
     // Allow the entity handler to pass a result with the response
     OCEntityHandlerResult  ehResult;
     // this is the pointer to server payload data to be transferred
-    char *payload;
-    // size of server payload data.  I don't think we should rely on null terminated data for size
-    uint16_t payloadSize;
+    OCPayload* payload;
     // An array of the vendor specific header options the entity handler wishes to use in response
     uint8_t numSendVendorSpecificHeaderOptions;
     OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
index 4da7bb6..ebde612 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "logger.h"
 #include "ocstack.h"
+#include "ocpayload.h"
 #include <string.h>
 
 #ifdef ARDUINOWIFI
@@ -57,9 +58,6 @@ typedef struct LIGHTRESOURCE{
 
 static LightResource Light;
 
-static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":true,\"power\":10}}";
-static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":false,\"power\":0}}";
-
 #ifdef ARDUINOWIFI
 // Arduino WiFi Shield
 // Note : Arduino WiFi Shield currently does NOT support multicast and therefore
@@ -154,7 +152,12 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
 {
     OCEntityHandlerResult ehRet = OC_EH_OK;
     OCEntityHandlerResponse response = {0};
-    char payload[MAX_RESPONSE_LENGTH] = {0};
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return OC_EH_ERROR;
+    }
 
     if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
     {
@@ -162,28 +165,16 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
 
         if(OC_REST_GET == entityHandlerRequest->method)
         {
-            size_t responsePayloadGetLength = strlen(responsePayloadGet);
-            if (responsePayloadGetLength < (sizeof(payload) - 1))
-            {
-                strncpy(payload, responsePayloadGet, responsePayloadGetLength);
-            }
-            else
-            {
-                ehRet = OC_EH_ERROR;
-            }
+            OCRepPayloadSetUri(payload, "/a/light");
+            OCRepPayloadSetPropBool(payload, "state", true);
+            OCRepPayloadSetPropInt(payload, "power", 10);
         }
         else if(OC_REST_PUT == entityHandlerRequest->method)
         {
             //Do something with the 'put' payload
-            size_t responsePayloadPutLength = strlen(responsePayloadPut);
-            if (responsePayloadPutLength < (sizeof(payload) - 1))
-            {
-                strncpy((char *)payload, responsePayloadPut, responsePayloadPutLength);
-            }
-            else
-            {
-                ehRet = OC_EH_ERROR;
-            }
+            OCRepPayloadSetUri(payload, "/a/light");
+            OCRepPayloadSetPropBool(payload, "state", false);
+            OCRepPayloadSetPropInt(payload, "power", 0);
         }
 
         if (ehRet == OC_EH_OK)
@@ -192,8 +183,7 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
             response.requestHandle = entityHandlerRequest->requestHandle;
             response.resourceHandle = entityHandlerRequest->resource;
             response.ehResult = ehRet;
-            response.payload = payload;
-            response.payloadSize = strlen(payload);
+            response.payload = (OCPayload*) payload;
             response.numSendVendorSpecificHeaderOptions = 0;
             memset(response.sendVendorSpecificHeaderOptions, 0,
                     sizeof response.sendVendorSpecificHeaderOptions);
index d3f4b2a..c5f84c7 100644 (file)
@@ -28,6 +28,7 @@
 #include "ocstack.h"
 #include "logger.h"
 #include "occlient.h"
+#include "ocpayload.h"
 
 // Tracking user input
 static int UNICAST_DISCOVERY = 0;
@@ -44,7 +45,6 @@ static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
 //The following variable determines the interface protocol (IPv4, IPv6, etc)
 //to be used for sending unicast messages. Default set to IPv4.
 static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
-static std::string putPayload = "{\"oic\":[{\"rep\":{\"power\":15,\"state\":true}}]}";
 static std::string coapServerIP = "255.255.255.255";
 static std::string coapServerPort = "5683";
 static std::string coapServerResource = "/a/light";
@@ -77,6 +77,22 @@ void handleSigInt(int signum)
     }
 }
 
+OCPayload* putPayload()
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+
+    if(!payload)
+    {
+        std::cout << "Failed to create put payload object"<<std::endl;
+        std::exit(1);
+    }
+
+    OCRepPayloadSetPropInt(payload, "power", 15);
+    OCRepPayloadSetPropBool(payload, "state", true);
+
+    return (OCPayload*) payload;
+}
+
 static void PrintUsage()
 {
     OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1..17> -c <0|1>");
@@ -132,7 +148,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, method, query.str().c_str(), 0,
-                       (method == OC_REST_PUT) ? putPayload.c_str() : NULL,
+                       (method == OC_REST_PUT) ? putPayload() : NULL,
                        (OC_CONNTYPE), qos, &cbData, options, numOptions);
 
     if (ret != OC_STACK_OK)
@@ -163,8 +179,8 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
     if(clientResponse)
     {
         OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Put Response",
-                clientResponse->resJSONPayload);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Put Response"));
     }
     else
     {
@@ -183,8 +199,8 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
     if(clientResponse)
     {
         OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response",
-                clientResponse->resJSONPayload);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Post Response"));
     }
     else
     {
@@ -204,8 +220,8 @@ OCStackApplicationResult deleteReqCB(void *ctx,
     if(clientResponse)
     {
         OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Delete Response",
-                clientResponse->resJSONPayload);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Delete Response"));
     }
     else
     {
@@ -229,7 +245,8 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
     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_PAYLOAD(INFO, TAG, clientResponse->payload);
+    OC_LOG(INFO, TAG, PCF("=============> Get Response"));
 
     if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
     {
@@ -264,8 +281,8 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse
         OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
         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);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Obs Response"));
         gNumObserveNotifies++;
         if (gNumObserveNotifies == 15) //large number to test observing in DELETE case.
         {
@@ -320,8 +337,8 @@ OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientRespon
         OC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber);
         OC_LOG_V(INFO, TAG, "Callback Context for Presence notification recvd successfully %d",
                 gNumPresenceNotifies);
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Presence Response",
-                clientResponse->resJSONPayload);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Presence Response"));
         gNumPresenceNotifies++;
         if (gNumPresenceNotifies == 20)
         {
@@ -356,8 +373,10 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
         std::string connectionType = getConnectivityType (clientResponse->connType);
         OC_LOG_V(INFO, TAG, "Discovered on %s", connectionType.c_str());
         OC_LOG_V(INFO, TAG,
-                "Device =============> Discovered %s @ %s:%d",
-                clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+                "Device =============> Discovered @ %s:%d",
+                clientResponse->devAddr.addr,
+                clientResponse->devAddr.port);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
 
         parseClientResponse(clientResponse);
 
@@ -436,9 +455,8 @@ OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx, OCDoHandle handle,
 
     if(clientResponse)
     {
-        //OC_LOG truncates the response as it is too long.
-        fprintf(stderr, "Discovery response: \n %s\n", clientResponse->resJSONPayload);
-        fflush(stderr);
+        OC_LOG(INFO, TAG, PCF("Discovery Response:"));
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
     }
     else
     {
@@ -458,9 +476,8 @@ OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle,
 
     if(clientResponse)
     {
-        //OC_LOG truncates the response as it is too long.
-        fprintf(stderr, "Discovery response: \n %s\n", clientResponse->resJSONPayload);
-        fflush(stderr);
+        OC_LOG(INFO, TAG, PCF("Discovery Response:"));
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
     }
     else
     {
index 8f1eb62..70c69a1 100644 (file)
 #include <unistd.h>
 #include <stdint.h>
 #include <sstream>
+#include <iostream>
 
 #include "ocstack.h"
 #include "logger.h"
 #include "occlientbasicops.h"
-#include "cJSON.h"
+#include "ocpayload.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 
@@ -41,7 +42,6 @@ static int TEST_CASE = 0;
 static int CONNECTIVITY = 0;
 
 static const char UNICAST_DISCOVERY_QUERY[] = "coap://%s/oic/res";
-static std::string putPayload = "{\"oic\":[{\"rep\":{\"power\":15,\"state\":true}}]}";
 
 //The following variable determines the interface protocol (IP, etc)
 //to be used for sending unicast messages. Default set to IP.
@@ -62,6 +62,22 @@ void handleSigInt(int signum)
     }
 }
 
+OCPayload* putPayload()
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+
+    if(!payload)
+    {
+        std::cout << "Failed to create put payload object"<<std::endl;
+        std::exit(1);
+    }
+
+    OCRepPayloadSetPropInt(payload, "power", 15);
+    OCRepPayloadSetPropBool(payload, "state", true);
+
+    return (OCPayload*) payload;
+}
+
 static void PrintUsage()
 {
     OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3> -c <0|1>");
@@ -95,7 +111,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, OCMethod method,
     cbData.cd = NULL;
 
     ret = OCDoResource(NULL, method, query.str().c_str(), 0,
-        (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload.c_str() : NULL,
+        (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL,
          connType, qos, &cbData, options, numOptions);
 
     if (ret != OC_STACK_OK)
@@ -121,8 +137,8 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle,
 
     if(clientResponse)
     {
-        OC_LOG_V(INFO, TAG,"PUT Response: %s \nFrom %s:%d\n",
-                 clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Put Response"));
     }
     else
     {
@@ -145,8 +161,8 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle,
 
     if(clientResponse)
     {
-        OC_LOG_V(INFO, TAG,"POST Response: %s \nFrom %s:%d\n",
-                    clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Post Response"));
     }
     else
     {
@@ -170,8 +186,10 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle,
 
     if (clientResponse)
     {
-        OC_LOG_V(INFO, TAG,"Get Response: %s \nFrom %s:%d\n",
-                clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Get Response"));
 
         if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0 )
         {
@@ -217,8 +235,10 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     if (clientResponse)
     {
         OC_LOG_V(INFO, TAG,
-                "Device Discovered %s \n @ %s:%d\n",
-                clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+                "Device =============> Discovered @ %s:%d",
+                clientResponse->devAddr.addr,
+                clientResponse->devAddr.port);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
 
         collectUniqueResource(clientResponse);
     }
@@ -396,99 +416,6 @@ const char *getPort(const OCClientResponse *clientResponse)
     return port;
 }
 
-int parseJSON(const char * resJSONPayload, char ** sid_c,
-              char *** uri_c, int * totalRes)
-{
-    cJSON * root = NULL;
-    cJSON * oc = NULL;
-
-    root = cJSON_Parse((char *)(resJSONPayload));
-
-    if (!root)
-    {
-        OC_LOG(ERROR, TAG, "JSON Parsing Error");
-        return OC_STACK_INVALID_JSON;
-    }
-
-    oc = cJSON_GetObjectItem(root,"oic");
-    if (!oc)
-    {
-        OC_LOG(ERROR, TAG, "Invalid JSON : Missing oc object");
-        return OC_STACK_INVALID_JSON;
-    }
-
-    * totalRes = cJSON_GetArraySize(oc);
-
-    if(oc->type == cJSON_Array)
-    {
-        cJSON * resource = cJSON_GetArrayItem(oc, 0);
-
-        if(!resource)
-        {
-            return OC_STACK_INVALID_JSON;
-        }
-
-        if (cJSON_GetObjectItem(resource, "sid"))
-        {
-            char * sid = cJSON_GetObjectItem(resource, "sid")->valuestring;
-            if((* sid_c = (char *)OICCalloc(1, strlen (sid) + 1)))
-            {
-                memcpy(* sid_c, sid, strlen(sid) + 1);
-            }
-            else
-            {
-                OC_LOG(ERROR, TAG, "Memory not allocated to sid");
-                return OC_STACK_NO_MEMORY;
-            }
-        }
-        else
-        {
-            OC_LOG(ERROR, TAG, "Invalid JSON : Missing sid object");
-            return OC_STACK_INVALID_JSON;
-        }
-
-        if(!(* uri_c =  (char ** )OICMalloc ((* totalRes) * sizeof(char *))))
-        {
-            OC_LOG(ERROR, TAG, "Memory not allocated to uri_c array");
-            return OC_STACK_NO_MEMORY;
-        }
-
-        int i = 0;
-
-        while(true)
-        {
-            if (cJSON_GetObjectItem(resource, "href"))
-            {
-                char *uri= cJSON_GetObjectItem(resource, "href")->valuestring;
-                if(((*uri_c)[i] = (char *)OICCalloc(1, strlen (uri) + 1)))
-                {
-                    memcpy((*uri_c)[i], uri, strlen(uri) + 1);
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, "Memory not allocated to uri");
-                    return OC_STACK_NO_MEMORY;
-                }
-                i++;
-                if(i >= (* totalRes))
-                    break;
-                resource = cJSON_GetArrayItem(oc, i);
-            }
-            else
-            {
-               OC_LOG(ERROR, TAG, "Invalid JSON : Missing uri object");
-               return OC_STACK_INVALID_JSON;
-           }
-        }
-    }
-    else
-    {
-        return OC_STACK_INVALID_JSON;
-        OC_LOG(ERROR, TAG, "Invalid JSON : oc object type is not an array");
-    }
-    return OC_STACK_OK;
-}
-
 void queryResource()
 {
     switch(TEST_CASE)
@@ -514,46 +441,38 @@ void queryResource()
 
 void collectUniqueResource(const OCClientResponse * clientResponse)
 {
-    char * sid = NULL;
-    char ** uri = NULL;
-    int totalRes = 0;
-    int i;
+    OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+    char sidStr[UUID_LENGTH];
 
-    if(parseJSON(clientResponse->resJSONPayload, & sid, & uri, &totalRes)
-            != OC_STACK_OK)
-    {
-        OC_LOG(ERROR, TAG, "Error while parsing JSON payload in OCClientResponse");
+    while(res) {
 
-        OICFree(sid);
-        for (i = 0; i < totalRes; i++)
-        {
-            OICFree(uri[i]);
-        }
-        OICFree(uri);
+        int ret = snprintf(sidStr, UUID_LENGTH,
+                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                res->sid[0], res->sid[1], res->sid[2], res->sid[3],
+                res->sid[4], res->sid[5], res->sid[6], res->sid[7],
+                res->sid[8], res->sid[9], res->sid[10], res->sid[11],
+                res->sid[12], res->sid[13], res->sid[14], res->sid[15]
+                );
 
-       return;
-    }
-
-    for(i = 0; i < totalRes; i++)
-    {
-        if(insertResource(sid, uri[i], clientResponse) == 1)
+        if (ret == UUID_LENGTH - 1)
         {
-            printf("%s%s%s%s\n",sid, ":", uri[i], " is new");
-            printResourceList();
-            queryResource();
+            if(insertResource(sidStr, res->uri, clientResponse) == 1)
+            {
+                OC_LOG_V(INFO,TAG,"%s%s%s%s\n",sidStr, ":", res->uri, " is new");
+                printResourceList();
+                queryResource();
+            }
+            else {
+                OC_LOG_V(INFO,TAG,"%s%s%s%s\n",sidStr, ":", res->uri, " is old");
+            }
         }
         else
         {
-            printf("%s%s%s%s\n\n",sid, ":", uri[i], " has been seen before");
+            OC_LOG(ERROR, TAG, "Could Not Retrieve the Server ID");
         }
-    }
 
-    OICFree(sid);
-    for (i = 0; i < totalRes; i++)
-    {
-        OICFree(uri[i]);
+        res = res->next;
     }
-    OICFree(uri);
 }
 
 /* This function searches for the resource(sid:uri) in the ResourceList.
index 1180b43..8c4ce40 100644 (file)
 #include <ocstack.h>
 #include <iostream>
 #include <sstream>
+#include "ocpayload.h"
 #include "logger.h"
 const char *getResult(OCStackResult result);
 std::string getIPAddrTBServer(OCClientResponse * clientResponse);
 std::string getPortTBServer(OCClientResponse * clientResponse);
-std::string getQueryStrForGetPut(const char * responsePayload);
+std::string getQueryStrForGetPut();
 
 #define TAG PCF("occlient")
 #define DEFAULT_CONTEXT_VALUE 0x99
@@ -85,7 +86,6 @@ testToTextMap queryInterface[] = {
         {"?if=oic.if.ll", TEST_PUT_LINK_LIST},
 };
 
-static std::string putPayload = "{\"state\":\"off\",\"power\":\"0\"}";
 
 //The following variable determines the interface protocol (IP, etc)
 //to be used for sending unicast messages. Default set to IP.
@@ -115,6 +115,22 @@ int InitPutRequest(OCClientResponse * clientResponse);
 int InitGetRequest(OCClientResponse * clientResponse);
 int InitDiscovery();
 
+OCPayload* putPayload()
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+
+    if(!payload)
+    {
+        std::cout << "Failed to create put payload object"<<std::endl;
+        std::exit(1);
+    }
+
+    OCRepPayloadSetPropInt(payload, "power", 15);
+    OCRepPayloadSetPropBool(payload, "state", true);
+
+    return (OCPayload*) payload;
+}
+
 void PrintUsage()
 {
     OC_LOG(INFO, TAG, "Usage : occlientcoll -t <Test Case> -c <CA connectivity Type>");
@@ -150,7 +166,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
     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);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
     }
 
     return OC_STACK_KEEP_TRANSACTION;
@@ -166,13 +182,13 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
         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);
+            OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
         }
         else
         {
             OC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d",
                     gNumObserveNotifies);
-            OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
+            OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);;
             gNumObserveNotifies++;
             if (gNumObserveNotifies == 3)
             {
@@ -206,8 +222,10 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     }
 
     OC_LOG_V(INFO, TAG,
-            "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
-            clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+            "Device =============> Discovered @ %s:%d",
+            clientResponse->devAddr.addr,
+            clientResponse->devAddr.port);
+    OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
 
     if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
             TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
@@ -251,11 +269,12 @@ int InitObserveRequest(OCClientResponse * clientResponse)
     std::ostringstream obsReg;
     obsReg << "coap://" << clientResponse->devAddr.addr << ":" <<
             clientResponse->devAddr.addr <<
-            getQueryStrForGetPut(clientResponse->resJSONPayload);
+            getQueryStrForGetPut();
     cbData.cb = getReqCB;
     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    OC_LOG_V(INFO, TAG, "OBSERVE payload from client = %s ", putPayload.c_str());
+    OC_LOG_V(INFO, TAG, "OBSERVE payload from client =");
+    OC_LOG_PAYLOAD(INFO, TAG, putPayload());
 
     ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_CONNTYPE,
             OC_LOW_QOS, &cbData, NULL, 0);
@@ -283,9 +302,10 @@ int InitPutRequest(OCClientResponse * clientResponse)
     cbData.cb = putReqCB;
     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
+    OC_LOG_V(INFO, TAG, "PUT payload from client = ");
+    OC_LOG_PAYLOAD(INFO, TAG, putPayload());
 
-    ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(),
+    ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload(),
                         OC_CONNTYPE, OC_LOW_QOS, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
@@ -411,11 +431,8 @@ int main(int argc, char* argv[])
     return 0;
 }
 
-std::string getQueryStrForGetPut(const char * responsePayload)
+std::string getQueryStrForGetPut()
 {
-
-    std::string jsonPayload(responsePayload);
-
     return "/a/room";
 }
 
index 29b22c3..e875cf2 100644 (file)
@@ -28,6 +28,7 @@
 #include "ocstack.h"
 #include "logger.h"
 #include "occlientslow.h"
+#include "ocpayload.h"
 
 // Tracking user input
 static int UNICAST_DISCOVERY = 0;
@@ -35,9 +36,8 @@ static int TEST_CASE = 0;
 static int CONNECTIVITY = 0;
 
 static const char * UNICAST_DISCOVERY_QUERY = "coap://%s/oic/res";
-static std::string putPayload = "{\"state\":\"off\",\"power\":10}";
 static std::string coapServerIP = "255.255.255.255";
-static std::string coapServerPort = "5683";
+static uint16_t coapServerPort = 5683;
 static std::string coapServerResource = "/a/led";
 
 //The following variable determines the interface protocol (IP, etc)
@@ -67,6 +67,24 @@ static void PrintUsage()
     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");
+    OC_LOG(INFO, TAG, "-t 4 : Discover Resources and Initiate NonConfirmable Put Request");
+    OC_LOG(INFO, TAG, "-t 5 : Discover Resources and Initiate Confirmable Put Request");
+}
+
+OCPayload* putPayload()
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+
+    if(!payload)
+    {
+        std::cout << "Failed to create put payload object"<<std::endl;
+        std::exit(1);
+    }
+
+    OCRepPayloadSetPropInt(payload, "power", 15);
+    OCRepPayloadSetPropBool(payload, "state", true);
+
+    return (OCPayload*) payload;
 }
 
 OCStackResult InvokeOCDoResource(std::ostringstream &query,
@@ -81,7 +99,8 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     cbData.cd = NULL;
 
     ret = OCDoResource(NULL, method, query.str().c_str(), 0,
-            NULL, OC_CONNTYPE, qos, &cbData, options, numOptions);
+            (method == OC_REST_PUT) ? putPayload() : NULL,
+            OC_CONNTYPE, qos, &cbData, options, numOptions);
 
     if (ret != OC_STACK_OK)
     {
@@ -105,8 +124,8 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
     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, "Get Response =============> ");
+    OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
 
     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
             clientResponse->numRcvdVendorSpecificHeaderOptions)
@@ -142,9 +161,9 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     {
         OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
 
-        OC_LOG_V(INFO, TAG,
-                "Device =============> Discovered %s @ %s:%d",
-                clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+        OC_LOG_V(INFO, TAG, "Discovered @ %s:%u =============> ",
+            clientResponse->devAddr.addr, clientResponse->devAddr.port);
+        OC_LOG_PAYLOAD (INFO, TAG, clientResponse->payload);
 
         parseClientResponse(clientResponse);
 
@@ -156,6 +175,12 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
             case TEST_CON_OP:
                 InitGetRequest(OC_HIGH_QOS);
                 break;
+            case TEST_NON_CON_PUT:
+                InitPutRequest(OC_LOW_QOS);
+                break;
+            case TEST_CON_PUT:
+                InitPutRequest(OC_HIGH_QOS);
+                break;
             default:
                 PrintUsage();
                 break;
@@ -171,11 +196,21 @@ int InitGetRequest(OCQualityOfService qos)
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
     std::ostringstream query;
     query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
-
+    OC_LOG_V (INFO, TAG, "Performing GET with query : %s", query.str().c_str());
     return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
             OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
 }
 
+int InitPutRequest(OCQualityOfService qos)
+{
+    OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+    std::ostringstream query;
+    query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+    OC_LOG_V (INFO, TAG, "Performing PUT with query : %s", query.str().c_str());
+    return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)?
+            OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+}
+
 int InitDiscovery()
 {
     OCStackResult ret;
index 3c91393..c6e9486 100644 (file)
@@ -44,6 +44,8 @@ typedef enum
     TEST_DISCOVER_REQ = 1,
     TEST_NON_CON_OP,
     TEST_CON_OP,
+    TEST_NON_CON_PUT,
+    TEST_CON_PUT,
     MAX_TESTS
 } CLIENT_TEST;
 
@@ -77,6 +79,7 @@ std::string getQueryStrForGetPut(OCClientResponse * clientResponse);
  * POST & Discovery operations
  */
 int InitGetRequest(OCQualityOfService qos);
+int InitPutRequest(OCQualityOfService qos);
 int InitDiscovery();
 
 /* Function to retrieve ip address, port no. of the server
index 68a15fa..b0acb2c 100644 (file)
@@ -29,7 +29,7 @@
 #include <array>
 #include "ocstack.h"
 #include "logger.h"
-#include "cJSON.h"
+#include "ocpayload.h"
 #include "ocserver.h"
 
 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
@@ -55,17 +55,6 @@ static int stopPresenceCount = 10;
 #define numPresenceResources (2)
 #endif
 
-//TODO: Follow the pattern used in constructJsonResponse() when the payload is decided.
-const char responsePayloadDeleteOk[] =
-        "{App determines payload: Delete Resource operation succeeded.}";
-const char responsePayloadDeleteNotOK[] =
-        "{App determines payload: Delete Resource operation failed.}";
-const char responsePayloadResourceDoesNotExist[] =
-        "{App determines payload: The resource does not exist.}";
-const char responsePayloadDeleteResourceNotSupported[] =
-        "{App determines payload: The request is received for a non-support resource.}";
-
-
 char *gResourceUri= (char *)"/a/light";
 const char *dateOfManufacture = "myDateOfManufacture";
 const char *deviceName = "myDeviceName";
@@ -90,13 +79,33 @@ const char *resourceInterface = OC_RSRVD_INTERFACE_DEFAULT;
 OCPlatformInfo platformInfo;
 OCDeviceInfo deviceInfo;
 
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return nullptr;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
 //This function takes the request as an input and returns the response
-//in JSON format.
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
 {
-    cJSON *json = cJSON_CreateObject();
-    cJSON *format;
-    char *jsonResponse;
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return nullptr;
+    }
+
+    OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
+
     LightResource *currLightResource = &Light;
 
     if (ehRequest->resource == gLightInstance[0].handle)
@@ -112,51 +121,21 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
 
     if(OC_REST_PUT == ehRequest->method)
     {
-        // Get cJSON pointer to query
-        cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload);
-
-        if(!putJson)
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
         {
-            OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
-            return NULL;
+            currLightResource->power =pow;
         }
 
-        // Get root of JSON payload, then the 1st resource.
-        cJSON* carrier = cJSON_GetObjectItem(putJson, "oic");
-        if (carrier)
-        {
-            carrier = cJSON_GetArrayItem(carrier, 0);
-            carrier = cJSON_GetObjectItem(carrier, "rep");
-
-            cJSON* prop = cJSON_GetObjectItem(carrier,"power");
-            if (prop)
-            {
-                currLightResource->power =prop->valueint;
-            }
-
-            prop = cJSON_GetObjectItem(carrier,"state");
-            if (prop)
-            {
-                currLightResource->state = prop->valueint;
-            }
-        }
-        else
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
         {
-            OC_LOG_V(WARNING, TAG, "Failed to find oic node");
+            currLightResource->state = state;
         }
-
-        cJSON_Delete(putJson);
     }
 
-    cJSON_AddStringToObject(json,"href",gResourceUri);
-    cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
-    cJSON_AddBoolToObject(format, "state", currLightResource->state);
-    cJSON_AddNumberToObject(format, "power", currLightResource->power);
-
-    jsonResponse = cJSON_Print(json);
-    cJSON_Delete(json);
-
-    return jsonResponse;
+    return getPayload(gResourceUri, currLightResource->power, currLightResource->state);
 }
 
 /*
@@ -200,7 +179,7 @@ OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandler
 }
 
 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
-        char *payload, uint16_t maxPayloadSize)
+        OCRepPayload **payload)
 {
     OCEntityHandlerResult ehResult;
     bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
@@ -208,26 +187,15 @@ OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
     // Empty payload if the query has no match.
     if (queryPassed)
     {
-        char *getResp = constructJsonResponse(ehRequest);
+        OCRepPayload *getResp = constructResponse(ehRequest);
         if(!getResp)
         {
-            OC_LOG(ERROR, TAG, "constructJsonResponse failed");
+            OC_LOG(ERROR, TAG, "constructResponse failed");
             return OC_EH_ERROR;
         }
 
-        if (maxPayloadSize > strlen (getResp))
-        {
-            strncpy(payload, getResp, strlen(getResp));
-            ehResult = OC_EH_OK;
-        }
-        else
-        {
-            OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                    maxPayloadSize);
-            ehResult = OC_EH_ERROR;
-        }
-
-        free(getResp);
+        *payload = getResp;
+        ehResult = OC_EH_OK;
     }
     else
     {
@@ -238,10 +206,10 @@ OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
 }
 
 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
-        char *payload, uint16_t maxPayloadSize)
+        OCRepPayload** payload)
 {
     OCEntityHandlerResult ehResult;
-    char *putResp = constructJsonResponse(ehRequest);
+    OCRepPayload *putResp = constructResponse(ehRequest);
 
     if(!putResp)
     {
@@ -249,30 +217,17 @@ OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
         return OC_EH_ERROR;
     }
 
-    if (maxPayloadSize > 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",
-                maxPayloadSize);
-        ehResult = OC_EH_ERROR;
-    }
-
-    free(putResp);
+    *payload = putResp;
+    ehResult = OC_EH_OK;
 
     return ehResult;
 }
 
 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
-        OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
+        OCEntityHandlerResponse *response, OCRepPayload** payload)
 {
     OCEntityHandlerResult ehResult = OC_EH_OK;
-    char *respPLPost_light = NULL;
-    cJSON *json;
-    cJSON *format;
+    OCRepPayload *respPLPost_light = nullptr;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -293,10 +248,9 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
             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());
-            cJSON_AddStringToObject(format, "createduri", (char *) newLightUri);
+            respPLPost_light = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_light, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_light, "createduri", newLightUri);
 
             if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
             {
@@ -304,19 +258,16 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
                 gLightInstance[gCurrLightInstance].state = 0;
                 gLightInstance[gCurrLightInstance].power = 0;
                 gCurrLightInstance++;
-                respPLPost_light = cJSON_Print(json);
                 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
                 ehResult = OC_EH_RESOURCE_CREATED;
             }
-
-            cJSON_Delete(json);
         }
         else
         {
             // Update repesentation of /a/light
             Light.state = true;
             Light.power = 11;
-            respPLPost_light = constructJsonResponse(ehRequest);
+            respPLPost_light = constructResponse(ehRequest);
         }
     }
     else
@@ -329,34 +280,31 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
                 gLightInstance[i].power = 22;
                 if (i == 0)
                 {
-                    respPLPost_light = constructJsonResponse(ehRequest);
+                    respPLPost_light = constructResponse(ehRequest);
                     break;
                 }
                 else if (i == 1)
                 {
-                    respPLPost_light = constructJsonResponse(ehRequest);
+                    respPLPost_light = constructResponse(ehRequest);
                 }
             }
         }
     }
 
-    if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
+    if ((respPLPost_light != NULL))
     {
-        strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
+        *payload = respPLPost_light;
     }
     else
     {
-        OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                maxPayloadSize);
+        OC_LOG(INFO, TAG, "Payload was NULL");
         ehResult = OC_EH_ERROR;
     }
 
-    free(respPLPost_light);
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
-        char *payload, uint16_t maxPayloadSize)
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
 {
     if(ehRequest == NULL)
     {
@@ -376,8 +324,6 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
      * 2. optionally, app removes observers out of its array 'interestedObservers'
      */
 
-    const char* deleteResponse = NULL;
-
     if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
     {
         //Step 1: Ask stack to do the work.
@@ -387,7 +333,6 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
         {
             OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
             ehResult = OC_EH_OK;
-            deleteResponse = responsePayloadDeleteOk;
 
             //Step 2: clear observers who wanted to observe this resource at the app level.
             for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
@@ -403,13 +348,11 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
         else if (result == OC_STACK_NO_RESOURCE)
         {
             OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
-            deleteResponse = responsePayloadResourceDoesNotExist;
             ehResult = OC_EH_RESOURCE_DELETED;
         }
         else
         {
             OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
-            deleteResponse = responsePayloadDeleteNotOK;
             ehResult = OC_EH_ERROR;
         }
     }
@@ -418,43 +361,16 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
         //Let's this app not supporting DELETE on some resources so
         //consider the DELETE request is received for a non-support resource.
         OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
-        deleteResponse = responsePayloadDeleteResourceNotSupported;
         ehResult = OC_EH_FORBIDDEN;
     }
 
-    if (maxPayloadSize > strlen ((char *)deleteResponse))
-    {
-        strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
-    }
-    else
-    {
-        OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                maxPayloadSize);
-        ehResult = OC_EH_ERROR;
-    }
-
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest,
-        char *payload, uint16_t maxPayloadSize)
+OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
 {
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
 
-    const char* response = NULL;
-    response = responsePayloadResourceDoesNotExist;
-
-    if ( (ehRequest != NULL) &&
-         (maxPayloadSize > strlen ((char *)response)) )
-    {
-        strncpy((char *)payload, response, strlen((char *)response));
-    }
-    else
-    {
-        OC_LOG_V (ERROR, TAG, "Response buffer: %d bytes is too small",
-                maxPayloadSize);
-    }
-
     return OC_EH_RESOURCE_NOT_FOUND;
 }
 
@@ -504,7 +420,6 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
 
     OCEntityHandlerResult ehResult = OC_EH_OK;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     // Validate pointer
     if (!entityHandlerRequest)
@@ -517,6 +432,7 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
     memset(response.sendVendorSpecificHeaderOptions, 0,
             sizeof response.sendVendorSpecificHeaderOptions);
     memset(response.resourceUri, 0, sizeof response.resourceUri);
+    OCRepPayload* payload = nullptr;
 
 
     if (flag & OC_REQUEST_FLAG)
@@ -526,23 +442,22 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
         if (entityHandlerRequest->resource == NULL)
         {
             OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
-            ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest,
-                           payload, sizeof(payload) - 1);
+            ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
         }
         else if (OC_REST_GET == entityHandlerRequest->method)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-            ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+            ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
         }
         else if (OC_REST_PUT == entityHandlerRequest->method)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-            ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+            ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
         }
         else if (OC_REST_DELETE == entityHandlerRequest->method)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
-            ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+            ehResult = ProcessDeleteRequest (entityHandlerRequest);
         }
         else
         {
@@ -557,8 +472,7 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
             response.requestHandle = entityHandlerRequest->requestHandle;
             response.resourceHandle = entityHandlerRequest->resource;
             response.ehResult = ehResult;
-            response.payload = payload;
-            response.payloadSize = strlen(payload);
+            response.payload = reinterpret_cast<OCPayload*>(payload);
             // Indicate that response is NOT in a persistent buffer
             response.persistentBufferFlag = 0;
 
@@ -603,7 +517,6 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
 
     OCEntityHandlerResult ehResult = OC_EH_OK;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     // Validate pointer
     if (!entityHandlerRequest)
@@ -617,6 +530,7 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
     memset(response.sendVendorSpecificHeaderOptions,
             0, sizeof response.sendVendorSpecificHeaderOptions);
     memset(response.resourceUri, 0, sizeof response.resourceUri);
+    OCRepPayload* payload = nullptr;
 
     if (flag & OC_REQUEST_FLAG)
     {
@@ -625,22 +539,22 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         if (OC_REST_GET == entityHandlerRequest->method)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-            ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+            ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
         }
         else if (OC_REST_PUT == entityHandlerRequest->method)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-            ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+            ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
         }
         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);
+            ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
         }
         else if (OC_REST_DELETE == entityHandlerRequest->method)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
-            ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+            ehResult = ProcessDeleteRequest (entityHandlerRequest);
         }
         else
         {
@@ -655,8 +569,7 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             response.requestHandle = entityHandlerRequest->requestHandle;
             response.resourceHandle = entityHandlerRequest->resource;
             response.ehResult = ehResult;
-            response.payload = payload;
-            response.payloadSize = strlen(payload);
+            response.payload = reinterpret_cast<OCPayload*>(payload);
             // Indicate that response is NOT in a persistent buffer
             response.persistentBufferFlag = 0;
 
@@ -717,6 +630,7 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         }
     }
 
+    OCPayloadDestroy(response.payload);
     return ehResult;
 }
 
@@ -758,18 +672,10 @@ void *ChangeLightRepresentation (void *param)
                     }
                 }
 
-                cJSON *json = cJSON_CreateObject();
-                cJSON *format;
-                cJSON_AddStringToObject(json,"href",gResourceUri);
-                cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
-                cJSON_AddBoolToObject(format, "state", Light.state);
-                cJSON_AddNumberToObject(format, "power", Light.power);
-
-                char * obsResp = cJSON_Print(json);
-                cJSON_Delete(json);
+                OCRepPayload* payload = getPayload(gResourceUri, Light.power, Light.state);
                 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
-                        obsResp, OC_NA_QOS);
-                free(obsResp);
+                        payload, OC_NA_QOS);
+                OCRepPayloadDestroy(payload);
             }
             else if (gObserveNotifyType == 0)
             {
index e6d123e..8c87326 100644 (file)
@@ -62,8 +62,8 @@ const char *getResult(OCStackResult result);
  */
 int createLightResource (char *uri, LightResource *lightResource);
 
-/* This method converts the payload to JSON format */
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+/* This method constructs a response from the request */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
 
 /* This method changes the Light power using an independent thread
  * and notifies the observers of new state of the resource.
@@ -78,22 +78,15 @@ OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandler
 /* Following methods process the PUT, GET, POST, Delete,
  * & Observe requests */
 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
-                                         char *payload,
-                                         uint16_t maxPayloadSize);
+                                         OCRepPayload **payload);
 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
-                                         char *payload,
-                                         uint16_t maxPayloadSize);
+                                         OCRepPayload **payload);
 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);
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest);
+
+OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest);
 
 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest);
 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest);
index ead663c..e389865 100644 (file)
@@ -26,8 +26,8 @@
 #include <pthread.h>
 #include "ocstack.h"
 #include "logger.h"
-#include "cJSON.h"
 #include "ocserverbasicops.h"
+#include "ocpayload.h"
 
 //string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
 // 7 + 9 + 1 = 17
@@ -44,21 +44,33 @@ static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
 
 char *gResourceUri= (char *)"/a/led";
 
-//This function takes the request as an input and returns the response
-//in JSON format.
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
 {
-    cJSON *json = cJSON_CreateObject();
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return nullptr;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
 
-    if(!json)
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
     {
-        OC_LOG (ERROR, TAG, "json object not created properly");
-        return NULL;
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return nullptr;
     }
 
-    cJSON *format;
-    cJSON *putJson = NULL;
-    char *jsonResponse = NULL;
+    OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
+
     LEDResource *currLEDResource = &LED;
 
     if (ehRequest->resource == gLedInstance[0].handle)
@@ -74,82 +86,34 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
 
     if(OC_REST_PUT == ehRequest->method)
     {
-        cJSON* jsonObj = NULL;
-        putJson = cJSON_Parse(ehRequest->reqJSONPayload);
-        if(putJson)
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
         {
-            jsonObj = cJSON_GetObjectItem(putJson,"oic");
-            if (jsonObj)
-            {
-                jsonObj = cJSON_GetArrayItem(jsonObj, 0);
-                if (jsonObj)
-                {
-                    jsonObj = cJSON_GetObjectItem(jsonObj, "rep");
-                }
-            }
-        }
-        if (NULL == jsonObj)
-        {
-            OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
-            goto exit;
-        }
-
-        cJSON* prop = cJSON_GetObjectItem(jsonObj,"power");
-        if (prop)
-        {
-            currLEDResource->power =prop->valueint;
+            currLEDResource->power =pow;
         }
 
-        prop = cJSON_GetObjectItem(jsonObj,"state");
-        if (prop)
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
         {
-            currLEDResource->state = prop->valueint;
+            currLEDResource->state = state;
         }
     }
 
-    cJSON_AddStringToObject(json,"href",gResourceUri);
-    format = cJSON_CreateObject();
-
-    if(!format)
-    {
-        OC_LOG (ERROR, TAG, "format object not created properly");
-        goto exit;
-    }
-
-    cJSON_AddItemToObject(json, "rep", format);
-    cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off"));
-    cJSON_AddNumberToObject(format, "power", currLEDResource->power);
-
-    jsonResponse = cJSON_Print(json);
-
-exit:
-    cJSON_Delete(putJson);
-    cJSON_Delete(json);
-    return jsonResponse;
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
 }
 
-OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload,
-        uint16_t maxPayloadSize)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
 {
     OCEntityHandlerResult ehResult;
-    char *getResp = constructJsonResponse(ehRequest);
+    OCRepPayload *getResp = constructResponse(ehRequest);
 
     if(getResp)
     {
-        if (maxPayloadSize > 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",
-                    maxPayloadSize);
-            ehResult = OC_EH_ERROR;
-        }
-
-        free(getResp);
-    }
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+     }
     else
     {
         ehResult = OC_EH_ERROR;
@@ -158,27 +122,16 @@ OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload,
-        uint16_t maxPayloadSize)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
 {
     OCEntityHandlerResult ehResult;
-    char *putResp = constructJsonResponse(ehRequest);
+    OCRepPayload *putResp = constructResponse(ehRequest);
 
     if(putResp)
     {
-        if (maxPayloadSize > 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",
-                    maxPayloadSize);
-            ehResult = OC_EH_ERROR;
-        }
-
-        free(putResp);
+        *payload = putResp;
+        ehResult = OC_EH_OK;
     }
     else
     {
@@ -188,13 +141,11 @@ OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, char *payload,
-        uint16_t maxPayloadSize)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
 {
-    char *respPLPost_led = NULL;
-    cJSON *json;
-    cJSON *format;
-    OCEntityHandlerResult ehResult;
+    OCRepPayload *respPLPost_led = nullptr;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -215,22 +166,9 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, cha
             char newLedUri[URI_MAXSIZE ];
             snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
 
-            json = cJSON_CreateObject();
-            if(!json)
-            {
-                return OC_EH_ERROR;
-            }
-
-            cJSON_AddStringToObject(json,"href",gResourceUri);
-            format = cJSON_CreateObject();
-
-            if(!format)
-            {
-                return OC_EH_ERROR;
-            }
-
-            cJSON_AddItemToObject(json, "rep", format);
-            cJSON_AddStringToObject(format, "createduri", (char *) newLedUri);
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
 
             if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
             {
@@ -238,14 +176,13 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, cha
                 gLedInstance[gCurrLedInstance].state = 0;
                 gLedInstance[gCurrLedInstance].power = 0;
                 gCurrLedInstance++;
-                respPLPost_led = cJSON_Print(json);
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
             }
-
-            cJSON_Delete(json);
         }
         else
         {
-            respPLPost_led = constructJsonResponse(ehRequest);
+            respPLPost_led = constructResponse(ehRequest);
         }
     }
     else
@@ -256,31 +193,28 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, cha
             {
                 if (i == 0)
                 {
-                    respPLPost_led = constructJsonResponse(ehRequest);
+                    respPLPost_led = constructResponse(ehRequest);
                     break;
                 }
                 else if (i == 1)
                 {
-                    respPLPost_led = constructJsonResponse(ehRequest);
+                    respPLPost_led = constructResponse(ehRequest);
                 }
             }
         }
     }
 
-    if ((respPLPost_led != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_led)))
+    if ((respPLPost_led != NULL))
     {
-        strncpy(payload, respPLPost_led, strlen((char *)respPLPost_led));
+        *payload = respPLPost_led;
         ehResult = OC_EH_OK;
     }
     else
     {
-        OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                maxPayloadSize);
+        OC_LOG_V (INFO, TAG, "Payload was NULL");
         ehResult = OC_EH_ERROR;
     }
 
-    free(respPLPost_led);
-
     return ehResult;
 }
 
@@ -292,7 +226,15 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
 
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = nullptr;
 
     if (flag & OC_REQUEST_FLAG)
     {
@@ -302,17 +244,17 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             if (OC_REST_GET == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
             }
             else if (OC_REST_PUT == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
             }
             else if (OC_REST_POST == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
             }
             else
             {
@@ -320,14 +262,13 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
                         entityHandlerRequest->method);
             }
 
-            if (ehResult == OC_EH_OK)
+            if (ehResult == OC_EH_OK && 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 = payload;
-                response.payloadSize = strlen(payload);
+                response.payload = reinterpret_cast<OCPayload*>(payload);
                 response.numSendVendorSpecificHeaderOptions = 0;
                 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
                 memset(response.resourceUri, 0, sizeof(response.resourceUri));
@@ -343,6 +284,8 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             }
         }
     }
+
+    OCPayloadDestroy(response.payload);
     return ehResult;
 }
 
index aec3923..bd223cf 100644 (file)
@@ -48,21 +48,19 @@ typedef struct LEDRESOURCE{
  */
 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
 
-/* This method converts the payload to JSON format */
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+/* This method constructs a response from the request */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
 
 /* Following methods process the PUT, GET, POST
  * requests
  */
 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
-                                         char *payload,
-                                         uint16_t maxPayloadSize);
+                                        OCRepPayload **payload);
 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
-                                         char *payload,
-                                         uint16_t maxPayloadSize);
+                                        OCRepPayload **payload);
 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
-                                          char *payload,
-                                          uint16_t maxPayloadSize);
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
 
 /* call getResult in common.cpp to get the result in string format. */
 const char *getResult(OCStackResult result);
index feec1f8..d58b256 100644 (file)
@@ -28,6 +28,7 @@
 #include <pthread.h>
 #include <ocstack.h>
 #include <logger.h>
+#include "ocpayload.h"
 
 const char *getResult(OCStackResult result);
 
@@ -44,32 +45,9 @@ typedef struct LIGHTRESOURCE{
 
 static LightResource light;
 
-// TODO : hard coded for now, change after Sprint10
-const char rspGetRoomDefault[] = "{\"href\":\"/a/room\",\"rep\":{\"name\":\"John's Room\"}}";
-const char rspGetRoomCollection[] = "{\"href\":\"/a/room\"}";
-// TODO : Needs to be changed to retrieve current status of room and return that in response
-const char rspPutRoomDefault[] = "{\"href\":\"/a/room\",\"rep\":{\"name\":\"John's Room\"}}";
-const char rspPutRoomCollection[] = "{\"href\":\"/a/room\"}";
-const char rspFailureRoom[] = "{\"href\":\"/a/room\",\"rep\":{\"error\":\"ROOM_OP_FAIL\"}}";
-
-// TODO : hard coded for now, change after Sprint4
-const char rspGetLightDefault[] =
-        "{\"href\":\"/a/light\",\"rep\":{\"state\":\"false\",\"color\":\"0\"}}";
-const char rspGetLightCollection[] = "{\"href\":\"/a/light\"}";
-// TODO : Needs to be changed to retrieve current status of light and return that in response
-const char rspPutLightDefault[] =
-        "{\"href\":\"/a/light\",\"rep\":{\"state\":\"true\",\"color\":\"0\"}}";
-const char rspPutLightCollection[] = "{\"href\":\"/a/light\"}";
-const char rspFailureLight[] = "{\"href\":\"/a/light\",\"rep\":{\"error\":\"LIGHT_OP_FAIL\"}}";
-
-
-// TODO : hard coded for now, change after Sprint4
-const char rspGetFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"true\",\"speed\":10}}";
-const char rspGetFanCollection[] = "{\"href\":\"/a/fan\"}";
-// TODO : Needs to be changed to retrieve current status of fan and return that in response
-const char rspPutFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"false\",\"speed\":0}}";
-const char rspPutFanCollection[] = "{\"href\":\"/a/fan\"}";
-const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}";
+char *gLightResourceUri= (char *)"/a/light";
+char *gRoomResourceUri= (char *)"/a/room";
+char *gFanResourceUri= (char *)"/a/fan";
 
 typedef enum
 {
@@ -90,34 +68,6 @@ void PrintUsage()
 
 unsigned static int TEST = TEST_INVALID;
 
-static OCEntityHandlerResult
-HandleCallback(OCEntityHandlerRequest * ehRequest,
-               const char* opStr,
-               const char* errStr,
-               char *payload,
-               uint16_t maxPayloadSize)
-{
-    OCEntityHandlerResult ret = OC_EH_OK;
-
-    // Append opStr or errStr, after making sure there is
-    // enough room in the payload
-    if (strlen(opStr) < (maxPayloadSize - strlen(payload)))
-    {
-        strncat((char*)payload, opStr, strlen(opStr));
-    }
-    else if (strlen(errStr) < (maxPayloadSize - strlen(payload)))
-    {
-        strncat((char*)payload, errStr, strlen(errStr));
-        ret = OC_EH_ERROR;
-    }
-    else
-    {
-        ret = OC_EH_ERROR;
-    }
-
-    return ret;
-}
-
 static void
 PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
 {
@@ -159,7 +109,7 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
 {
     OCEntityHandlerResult ret = OC_EH_OK;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
+    OCRepPayload* payload = OCRepPayloadCreate();
 
     OC_LOG_V(INFO, TAG, "Callback for Room");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -172,54 +122,45 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
         {
             if(query.find(OC_RSRVD_INTERFACE_DEFAULT) != std::string::npos)
             {
-                ret = HandleCallback(ehRequest,
-                        rspGetRoomDefault, rspFailureRoom, payload, sizeof(payload));
-                if(ret != OC_EH_ERROR)
-                {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
-                }
-                if(ret != OC_EH_ERROR)
-                {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
-                }
+                OCRepPayloadSetUri(payload, gRoomResourceUri);
+                OCRepPayloadSetPropString(payload, "name", "John's Room");
+
+                OCRepPayload *tempPayload = OCRepPayloadCreate();
+                OCRepPayloadSetUri(tempPayload, gLightResourceUri);
+                OCRepPayloadAppend(payload, tempPayload);
+
+                OCRepPayload *tempPayload2 = OCRepPayloadCreate();
+                OCRepPayloadSetUri(tempPayload2, gFanResourceUri);
+                OCRepPayloadAppend(payload, tempPayload2);
             }
             else if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
             {
-                ret = HandleCallback(ehRequest,
-                        rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
-                if(ret != OC_EH_ERROR)
-                {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
-                }
-                if(ret != OC_EH_ERROR)
-                {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
-                }
+                OCRepPayloadSetUri(payload, gRoomResourceUri);
+
+                OCRepPayload *tempPayload = OCRepPayloadCreate();
+                OCRepPayloadSetUri(tempPayload, gLightResourceUri);
+                OCRepPayloadAppend(payload, tempPayload);
+
+                OCRepPayload *tempPayload2 = OCRepPayloadCreate();
+                OCRepPayloadSetUri(tempPayload2, gFanResourceUri);
+                OCRepPayloadAppend(payload, tempPayload2);
             }
             else if(query.find(OC_RSRVD_INTERFACE_BATCH) != std::string::npos)
             {
-                ret = HandleCallback(ehRequest,
-                        rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
-                if(ret != OC_EH_ERROR)
-                {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
-                }
-                if(ret != OC_EH_ERROR)
-                {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
-                }
+
+                OCRepPayloadSetUri(payload, gRoomResourceUri);
+
+                OCRepPayload *tempPayload = OCRepPayloadCreate();
+                OCRepPayloadSetUri(tempPayload, gLightResourceUri);
+                OCRepPayloadSetPropBool(tempPayload, "state", false);
+                OCRepPayloadSetPropInt(tempPayload, "color", 0);
+                OCRepPayloadAppend(payload, tempPayload);
+
+                OCRepPayload *tempPayload2 = OCRepPayloadCreate();
+                OCRepPayloadSetUri(tempPayload2, gFanResourceUri);
+                OCRepPayloadSetPropBool(tempPayload, "state", true);
+                OCRepPayloadSetPropInt(tempPayload, "speed", 10);
+                OCRepPayloadAppend(payload, tempPayload2);
             }
             if (ret == OC_EH_OK)
             {
@@ -227,8 +168,7 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
                 response.requestHandle = ehRequest->requestHandle;
                 response.resourceHandle = ehRequest->resource;
                 response.ehResult = ret;
-                response.payload = payload;
-                response.payloadSize = strlen(payload);
+                response.payload = reinterpret_cast<OCPayload*>(payload);
                 response.numSendVendorSpecificHeaderOptions = 0;
                 memset(response.sendVendorSpecificHeaderOptions,
                         0, sizeof response.sendVendorSpecificHeaderOptions);
@@ -249,48 +189,50 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest,
-                            rspPutRoomDefault, rspFailureRoom, payload, sizeof(payload));
+                    OCRepPayloadSetUri(payload, gRoomResourceUri);
+                    OCRepPayloadSetPropString(payload, "name", "John's Room");
                 }
             }
             if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest,
-                            rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
+                    OCRepPayloadSetUri(payload, gRoomResourceUri);
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspPutLightCollection, rspFailureLight, payload, sizeof(payload));
+                    OCRepPayload *tempPayload = OCRepPayloadCreate();
+                    OCRepPayloadSetUri(tempPayload, gLightResourceUri);
+                    OCRepPayloadAppend(payload, tempPayload);
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspPutFanCollection, rspFailureFan, payload, sizeof(payload));
+                    OCRepPayload *tempPayload = OCRepPayloadCreate();
+                    OCRepPayloadSetUri(tempPayload, gFanResourceUri);
+                    OCRepPayloadAppend(payload, tempPayload);
                 }
             }
             if(query.find(OC_RSRVD_INTERFACE_BATCH ) != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest,
-                            rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
+                    OCRepPayloadSetUri(payload, gRoomResourceUri);
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
+                    OCRepPayload *tempPayload = OCRepPayloadCreate();
+                    OCRepPayloadSetUri(tempPayload, gLightResourceUri);
+                    OCRepPayloadSetPropBool(tempPayload, "state", true);
+                    OCRepPayloadSetPropInt(tempPayload, "color", 0);
+                    OCRepPayloadAppend(payload, tempPayload);
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
-                    ret = HandleCallback(ehRequest,
-                            rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
+                    OCRepPayload *tempPayload = OCRepPayloadCreate();
+                    OCRepPayloadSetUri(tempPayload, gFanResourceUri);
+                    OCRepPayloadSetPropBool(tempPayload, "state", false);
+                    OCRepPayloadSetPropInt(tempPayload, "speed", 0);
+                    OCRepPayloadAppend(payload, tempPayload);
                 }
             }
             if (ret == OC_EH_OK)
@@ -299,8 +241,7 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
                 response.requestHandle = ehRequest->requestHandle;
                 response.resourceHandle = ehRequest->resource;
                 response.ehResult = ret;
-                response.payload = payload;
-                response.payloadSize = strlen(payload);
+                response.payload = reinterpret_cast<OCPayload*>(payload);
                 response.numSendVendorSpecificHeaderOptions = 0;
                 memset(response.sendVendorSpecificHeaderOptions,
                         0, sizeof response.sendVendorSpecificHeaderOptions);
@@ -334,7 +275,7 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
 {
     OCEntityHandlerResult ret = OC_EH_OK;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
+    OCRepPayload* payload = OCRepPayloadCreate();
 
     OC_LOG_V(INFO, TAG, "Callback for Light");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -343,13 +284,15 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
     {
         if(OC_REST_GET == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest,
-                    rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
+            OCRepPayloadSetUri(payload, gLightResourceUri);
+            OCRepPayloadSetPropBool(payload, "state", false);
+            OCRepPayloadSetPropInt(payload, "color", 0);
         }
         else if(OC_REST_PUT == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest,
-                    rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
+            OCRepPayloadSetUri(payload, gLightResourceUri);
+            OCRepPayloadSetPropBool(payload, "state", true);
+            OCRepPayloadSetPropInt(payload, "color", 0);
         }
         else
         {
@@ -364,8 +307,7 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
             response.requestHandle = ehRequest->requestHandle;
             response.resourceHandle = ehRequest->resource;
             response.ehResult = ret;
-            response.payload = payload;
-            response.payloadSize = strlen(payload);
+            response.payload = reinterpret_cast<OCPayload*>(payload);
             response.numSendVendorSpecificHeaderOptions = 0;
             memset(response.sendVendorSpecificHeaderOptions,
                     0, sizeof response.sendVendorSpecificHeaderOptions);
@@ -394,7 +336,7 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
 {
     OCEntityHandlerResult ret = OC_EH_OK;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
+    OCRepPayload* payload = OCRepPayloadCreate();
 
     OC_LOG_V(INFO, TAG, "Callback for Fan");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -403,13 +345,15 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
     {
         if(OC_REST_GET == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest, rspGetFanDefault,
-                    rspFailureFan, payload, sizeof(payload));
+            OCRepPayloadSetUri(payload, gFanResourceUri);
+            OCRepPayloadSetPropBool(payload, "state", true);
+            OCRepPayloadSetPropInt(payload, "speed", 10);
         }
         else if(OC_REST_PUT == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest, rspPutFanDefault,
-                    rspFailureFan, payload, sizeof(payload));
+            OCRepPayloadSetUri(payload, gFanResourceUri);
+            OCRepPayloadSetPropBool(payload, "state", false);
+            OCRepPayloadSetPropInt(payload, "speed", 0);
         }
         else
         {
@@ -424,8 +368,7 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
             response.requestHandle = ehRequest->requestHandle;
             response.resourceHandle = ehRequest->resource;
             response.ehResult = ret;
-            response.payload = payload;
-            response.payloadSize = strlen(payload);
+            response.payload = reinterpret_cast<OCPayload*>(payload);
             response.numSendVendorSpecificHeaderOptions = 0;
             memset(response.sendVendorSpecificHeaderOptions,
                     0, sizeof response.sendVendorSpecificHeaderOptions);
@@ -551,6 +494,7 @@ int main(int argc, char* argv[])
 
     return 0;
 }
+
 void createResources()
 {
     light.state = false;
index 2c42f6f..99a0b52 100644 (file)
@@ -31,6 +31,7 @@
 #include "logger.h"
 #include "cJSON.h"
 #include "ocserverslow.h"
+#include "ocpayload.h"
 
 volatile sig_atomic_t gQuitFlag = 0;
 
@@ -47,21 +48,11 @@ char *gResourceUri= (char *)"/a/led";
 
 //This function takes the request as an input and returns the response
 //in JSON format.
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
 {
-    cJSON *json = cJSON_CreateObject();
-
-    if(!json)
-    {
-        OC_LOG(ERROR, TAG, "CreateObject result in null for json");
-        return NULL;
-    }
-
-    cJSON *format;
-    char *jsonResponse;
     LEDResource *currLEDResource = &LED;
 
-    OC_LOG(INFO, TAG, "Entering constructJsonResponse");
+    OC_LOG(INFO, TAG, "Entering constructResponse");
 
     if (ehRequest->resource == gLedInstance[0].handle)
     {
@@ -78,63 +69,60 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
 
     if(OC_REST_PUT == ehRequest->method)
     {
-        cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
-
-        if(!putJson)
+        if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
         {
-            OC_LOG(ERROR, TAG, "CreateObject result in null for putJson");
-            cJSON_Delete(json);
-            return NULL;
+            OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+            return nullptr;
         }
 
-        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
-                "on") ? true:false);
-        currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
-        cJSON_Delete(putJson);
+        OCRepPayload *putPayload = reinterpret_cast<OCRepPayload*> (ehRequest->payload);
+
+        int64_t power;
+        bool state;
+
+        if (OCRepPayloadGetPropBool(putPayload, "state", &state))
+        {
+            currLEDResource->state = state;
+        }
+        if (OCRepPayloadGetPropInt (putPayload, "power", &power))
+        {
+            currLEDResource->power = power;
+        }
     }
 
-    cJSON_AddStringToObject(json,"href",gResourceUri);
-    format = cJSON_CreateObject();
+    OCRepPayload *response = OCRepPayloadCreate();
 
-    if(!format)
+    if (!response)
     {
-        OC_LOG(ERROR, TAG, "CreateObject result in null for format");
-        cJSON_Delete(json);
-        return NULL;
+        OC_LOG_V(ERROR, TAG, "Memory allocation for response payload failed.");
     }
 
-    cJSON_AddItemToObject(json, "rep", format);
-    cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off"));
-    cJSON_AddNumberToObject(format, "power", currLEDResource->power);
+    OCRepPayloadSetUri (response, gResourceUri);
+    OCRepPayloadSetPropBool(response, "state", currLEDResource->state);
+    OCRepPayloadSetPropInt(response, "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;
+    return response;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+void ProcessGetPutRequest (OCEntityHandlerRequest *ehRequest)
 {
-    OC_LOG(INFO, TAG, "Entering ProcessGetRequest");
-    char *getResp = constructJsonResponse(ehRequest);
+    OC_LOG(INFO, TAG, "Entering ProcessGetPutRequest");
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
 
     if(!getResp)
     {
-        OC_LOG(ERROR, TAG, "Failed to constructJsonResponse");
+        OC_LOG(ERROR, TAG, "Failed to construct response");
         return;
     }
-    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 = getResp;
-    response.payloadSize = strlen(getResp) + 1;
+    response.payload = reinterpret_cast<OCPayload*> (getResp);
     response.numSendVendorSpecificHeaderOptions = 0;
     memset(response.sendVendorSpecificHeaderOptions,
             0, sizeof response.sendVendorSpecificHeaderOptions);
@@ -154,46 +142,37 @@ void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
 OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
 {
     OC_LOG(INFO, TAG, "Copying received request for slow response");
-    OCEntityHandlerRequest *request =
+
+    OCEntityHandlerRequest *copyOfRequest =
             (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest));
-    if (request)
+
+    if (copyOfRequest)
     {
         // Do shallow copy
-        memcpy(request, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
-        // Do deep copy of query
-        request->query =
-                (char * )OICMalloc(strlen((const char *)entityHandlerRequest->query) + 1);
-        if (request->query)
-        {
-            strcpy((char *)request->query, (const char *)entityHandlerRequest->query);
+        memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
 
-            // Copy the request payload
-            request->reqJSONPayload = (char * )OICMalloc(
-                            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
-            {
-                OICFree(request->query);
-                OICFree(request);
-                request = NULL;
-            }
+        if (copyOfRequest->query)
+        {
+            // Do deep copy of query
+            copyOfRequest->query = (char *) OICMalloc(
+                    strlen((const char *)entityHandlerRequest->query) + 1);
+
+            strcpy((char *)copyOfRequest->query, (const char *)entityHandlerRequest->query);
         }
-        else
+
+        if (entityHandlerRequest->payload)
         {
-            OICFree(request);
-            request = NULL;
+            copyOfRequest->payload = reinterpret_cast<OCPayload*>
+                    (OCRepPayloadClone ((OCRepPayload*) entityHandlerRequest->payload));
         }
+
+        // Ignore vendor specific header options for example
+        copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
+        copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
     }
 
-    if (request)
+    if (copyOfRequest)
     {
         OC_LOG(INFO, TAG, "Copied client request");
     }
@@ -201,17 +180,17 @@ OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest
     {
         OC_LOG(ERROR, TAG, "Error copying client request");
     }
-    return request;
+    return copyOfRequest;
 }
 
-OCEntityHandlerResult
-OCEntityHandlerCb (OCEntityHandlerFlag flag,
+OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
         OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
 {
     OCEntityHandlerResult result = OC_EH_ERROR;
     OCEntityHandlerRequest *request = NULL;
 
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
     if (flag & OC_REQUEST_FLAG)
     {
         OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
@@ -219,10 +198,11 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         {
             OC_LOG_V (INFO, TAG, "request query %s from client",
                                         entityHandlerRequest->query);
-            OC_LOG_V (INFO, TAG, "request payload %s from client",
-                                        entityHandlerRequest->reqJSONPayload);
+            OC_LOG_PAYLOAD (INFO, TAG, entityHandlerRequest->payload);
+
             // Make deep copy of received request and queue it for slow processing
             request = CopyRequest(entityHandlerRequest);
+
             if (request)
             {
 
@@ -277,7 +257,12 @@ void AlarmHandler(int sig)
         if (entityHandlerRequest->method == OC_REST_GET)
         {
             OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-            ProcessGetRequest (entityHandlerRequest);
+            ProcessGetPutRequest (entityHandlerRequest);
+        }
+        else if (entityHandlerRequest->method == OC_REST_PUT)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+            ProcessGetPutRequest (entityHandlerRequest);
         }
         else
         {
@@ -286,7 +271,7 @@ void AlarmHandler(int sig)
         }
         // Free the request
         OICFree(entityHandlerRequest->query);
-        OICFree(entityHandlerRequest->reqJSONPayload);
+        OCPayloadDestroy(entityHandlerRequest->payload);
         OICFree(entityHandlerRequest);
 
         // If there are more requests in list, re-arm the alarm signal
@@ -307,10 +292,8 @@ int main(int argc, char* argv[])
         return 0;
     }
 
-    /*
-     * Declare and create the example resource: LED
-     */
-    createLEDResource(gResourceUri, &LED, false, 0);
+    // Declare and create the example resource: LED
+    createLEDResource(gResourceUri, &LED, false, 42);
 
     // Initialize slow response alarm
     signal(SIGALRM, AlarmHandler);
@@ -326,7 +309,6 @@ int main(int argc, char* argv[])
             OC_LOG(ERROR, TAG, "OCStack process error");
             return 0;
         }
-
         sleep(2);
     }
 
@@ -338,7 +320,7 @@ int main(int argc, char* argv[])
         for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
         {
             OICFree((*iter)->query);
-            OICFree((*iter)->reqJSONPayload);
+            OCPayloadDestroy((*iter)->payload);
             OICFree(*iter);
         }
         gRequestList.clear();
index b6dd32c..12bc216 100644 (file)
@@ -63,6 +63,7 @@ samples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 ######################################################################
 # Source files and Targets
 ######################################################################
+
 ocserverbasicops = samples_env.Program('ocserverbasicops', ['common.cpp', 'ocserverbasicops.cpp'])
 occlientbasicops = samples_env.Program('occlientbasicops', ['common.cpp', 'occlientbasicops.cpp'])
 
@@ -74,8 +75,8 @@ src_dir = samples_env.get('SRC_DIR')
 sec_samples_src_dir = src_dir + '/resource/csdk/stack/samples/linux/secure/'
 sec_samples_build_dir = env.get('BUILD_DIR') +'/resource/csdk/stack/samples/linux/secure'
 
-samples_env.Alias("install", samples_env.Install( sec_samples_build_dir, 
+samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
     sec_samples_src_dir + 'oic_svr_db_server.json'))
-samples_env.Alias("install", samples_env.Install( sec_samples_build_dir, 
+samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
     sec_samples_src_dir + 'oic_svr_db_client.json'))
 
index 3dabe56..1cde32b 100644 (file)
@@ -28,7 +28,7 @@
 #include "ocstack.h"
 #include "logger.h"
 #include "occlientbasicops.h"
-#include "cJSON.h"
+#include "ocpayload.h"
 #include "common.h"
 
 #define TAG "occlientbasicops"
@@ -41,7 +41,6 @@ static char UNICAST_DISCOVERY_QUERY[] = "coap://%s/oic/res";
 static char MULTICAST_DISCOVERY_QUERY[] = "/oic/res";
 OCConnectivityType discoveryReqConnType = CT_ADAPTER_IP;
 
-static std::string putPayload = "{\"oic\":[{\"rep\":{\"state\":\"off\",\"power\":10}}]}";
 static std::string coapServerIP;
 static std::string coapServerPort;
 static std::string coapServerResource;
@@ -66,6 +65,22 @@ void handleSigInt(int signum)
     }
 }
 
+OCPayload* putPayload()
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+
+    if(!payload)
+    {
+        std::cout << "Failed to create put payload object"<<std::endl;
+        std::exit(1);
+    }
+
+    OCRepPayloadSetPropInt(payload, "power", 15);
+    OCRepPayloadSetPropBool(payload, "state", true);
+
+    return (OCPayload*) payload;
+}
+
 static void PrintUsage()
 {
     OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3> -c <0|1>");
@@ -90,7 +105,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     cbData.cd = NULL;
 
     ret = OCDoResource(NULL, method, query.str().c_str(), 0,
-            (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload.c_str() : NULL,
+            (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL,
             ocConnType, qos, &cbData, options, numOptions);
 
     if (ret != OC_STACK_OK)
@@ -107,8 +122,8 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
     if(clientResponse)
     {
-        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Put Response", clientResponse->resJSONPayload);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Put Response"));
     }
     return OC_STACK_DELETE_TRANSACTION;
 }
@@ -120,8 +135,8 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
     if(clientResponse)
     {
         OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response",
-                clientResponse->resJSONPayload);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Post Response"));
     }
     return OC_STACK_DELETE_TRANSACTION;
 }
@@ -134,8 +149,8 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
     {
         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_PAYLOAD(INFO, TAG, clientResponse->payload);
+        OC_LOG(INFO, TAG, PCF("=============> Get Response"));
     }
     return OC_STACK_DELETE_TRANSACTION;
 }
@@ -150,8 +165,10 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     {
         OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
         OC_LOG_V(INFO, TAG,
-                "Device =============> Discovered %s @ %s:%d",
-                clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
+                "Device =============> Discovered @ %s:%d",
+                clientResponse->devAddr.addr,
+                clientResponse->devAddr.port);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
 
         ocConnType = clientResponse->connType;
 
@@ -387,9 +404,7 @@ std::string getPortTBServer(OCClientResponse * clientResponse)
 
 int parseClientResponse(OCClientResponse * clientResponse)
 {
-    int port = -1;
-    cJSON * root = NULL;
-    cJSON * oc = NULL;
+    OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
 
     // Initialize all global variables
     coapServerResource.clear();
@@ -397,90 +412,40 @@ int parseClientResponse(OCClientResponse * clientResponse)
     coapServerIP.clear();
     coapSecureResource = 0;
 
-    root = cJSON_Parse((char *)(clientResponse->resJSONPayload));
-    if (!root)
+    while(res)
     {
-        return -1;
-    }
+        coapServerResource.assign(res->uri);
+        OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
 
-    oc = cJSON_GetObjectItem(root,"oic");
-    if (!oc || oc->type != cJSON_Array)
-    {
-        cJSON_Delete(root);
-        return -1;
-    }
+        if(res->secure)
+        {
+            coapSecureResource = 1;
+        }
 
-    cJSON * firstDevice = cJSON_GetArrayItem(oc, 0);
-    if (!firstDevice)
-    {
-        cJSON_Delete(root);
-        return -1;
-    }
+        OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
 
-    cJSON * links = cJSON_GetObjectItem(firstDevice,"links");
-    if (!links)
-    {
-        cJSON_Delete(root);
-        return -1;
-    }
+        std::ostringstream ss;
+        ss << res->port;
+        coapServerPort = ss.str();
+        std::cout<<"PORT: "<<coapServerPort;
 
-    if (links->type == cJSON_Array)
-    {
-        int numRsrcs =  cJSON_GetArraySize(links);
-        for(int i = 0; i < numRsrcs; i++)
+        // If we discovered a secure resource, exit from here
+        if (coapSecureResource)
         {
-            cJSON * resource = cJSON_GetArrayItem(links, i);
-            if (cJSON_GetObjectItem(resource, "href"))
-            {
-                coapServerResource.assign(cJSON_GetObjectItem(resource, "href")->valuestring);
-            }
-            else
-            {
-                coapServerResource = "";
-            }
-            OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
-
-            {
-                cJSON * policy = cJSON_GetObjectItem(resource,"p");
-                if (policy)
-                {
-                    // If this is a secure resource, the info about the port at which the
-                    // resource is hosted on server is embedded inside discovery JSON response
-                    if (cJSON_GetObjectItem(policy, "sec"))
-                    {
-                        if ((cJSON_GetObjectItem(policy, "sec")->valueint) == 1)
-                        {
-                            coapSecureResource = 1;
-                        }
-                    }
-                    OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
-                    if (cJSON_GetObjectItem(policy, "port"))
-                    {
-                        port = cJSON_GetObjectItem(policy, "port")->valueint;
-                        OC_LOG_V(INFO, TAG, "Hosting Server Port (embedded inside JSON) -- %u", port);
-
-                        std::ostringstream ss;
-                        ss << port;
-                        coapServerPort = ss.str();
-                    }
-                }
-            }
-
-            // If we discovered a secure resource, exit from here
-            if (coapSecureResource)
-            {
-                break;
-            }
+            break;
         }
+
+        res = res->next;
     }
-    cJSON_Delete(root);
 
     coapServerIP = clientResponse->devAddr.addr;
-    if (port == -1)
+
+    if(coapServerPort.length() == 0 || coapServerPort == "0")
     {
         coapServerPort = getPortTBServer(clientResponse);
         OC_LOG_V(INFO, TAG, "Hosting Server Port -- %s", coapServerPort.c_str());
     }
+
     return 0;
 }
 
index 4dba110..6e212fe 100644 (file)
@@ -26,7 +26,7 @@
 #include <pthread.h>
 #include "ocstack.h"
 #include "logger.h"
-#include "cJSON.h"
+#include "ocpayload.h"
 #include "ocserverbasicops.h"
 #include "common.h"
 
@@ -46,88 +46,76 @@ char *gResourceUri= (char *)"/a/led";
 //of other devices which the server trusts
 static char CRED_FILE[] = "oic_svr_db_server.json";
 
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return nullptr;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
 //This function takes the request as an input and returns the response
-//in JSON format.
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
 {
-    cJSON *json = cJSON_CreateObject();
-    cJSON *putJson = NULL;
-    cJSON *format;
-    char *jsonResponse = NULL;
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return nullptr;
+    }
+
+    OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
+
     LEDResource *currLEDResource = &LED;
 
     if (ehRequest->resource == gLedInstance[0].handle)
     {
         currLEDResource = &gLedInstance[0];
-        gResourceUri = (char *) "a/led/0";
+        gResourceUri = (char *) "/a/led/0";
     }
     else if (ehRequest->resource == gLedInstance[1].handle)
     {
         currLEDResource = &gLedInstance[1];
-        gResourceUri = (char *) "a/led/1";
+        gResourceUri = (char *) "/a/led/1";
     }
 
     if(OC_REST_PUT == ehRequest->method)
     {
-        cJSON* jsonObj = NULL;
-        putJson = cJSON_Parse(ehRequest->reqJSONPayload);
-        if(putJson)
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
         {
-            jsonObj = cJSON_GetObjectItem(putJson,"oic");
-            if (jsonObj)
-            {
-                jsonObj = cJSON_GetArrayItem(jsonObj, 0);
-                if (jsonObj)
-                {
-                    jsonObj = cJSON_GetObjectItem(jsonObj, "rep");
-                }
-            }
+            currLEDResource->power =pow;
         }
-        if (NULL == jsonObj)
+
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
         {
-            OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
-            goto exit;
+            currLEDResource->state = state;
         }
-
-        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(jsonObj,"state")->valuestring ,
-                    "on") ? true:false);
-        currLEDResource->power = cJSON_GetObjectItem(jsonObj,"power")->valuedouble;
     }
 
-    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);
-
-    jsonResponse = cJSON_Print(json);
-
-exit:
-    cJSON_Delete(putJson);
-    cJSON_Delete(json);
-    return jsonResponse;
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
 }
 
 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
-                        char *payload, size_t maxPayloadSize)
+        OCRepPayload **payload)
 {
     OCEntityHandlerResult ehResult;
 
-    char *getResp = constructJsonResponse(ehRequest);
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
     if(getResp)
     {
-        if (maxPayloadSize > strlen (getResp))
-        {
-            strcpy(payload, getResp);
-            ehResult = OC_EH_OK;
-        }
-        else
-        {
-            OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                    maxPayloadSize);
-            ehResult = OC_EH_ERROR;
-        }
-
-        free(getResp);
+        *payload = getResp;
+        ehResult = OC_EH_OK;
     }
     else
     {
@@ -138,27 +126,16 @@ OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
 }
 
 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
-                        char *payload, size_t maxPayloadSize)
+        OCRepPayload **payload)
 {
     OCEntityHandlerResult ehResult;
 
-    char *putResp = constructJsonResponse(ehRequest);
+    OCRepPayload *putResp = constructResponse(ehRequest);
 
     if(putResp)
     {
-        if (maxPayloadSize > strlen (putResp))
-        {
-            strcpy(payload, putResp);
-            ehResult = OC_EH_OK;
-        }
-        else
-        {
-            OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                    maxPayloadSize);
-            ehResult = OC_EH_ERROR;
-        }
-
-        free(putResp);
+        *payload = putResp;
+        ehResult = OC_EH_OK;
     }
     else
     {
@@ -169,12 +146,10 @@ OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
 }
 
 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
-                        char *payload, size_t maxPayloadSize)
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
 {
-    char *respPLPost_led = NULL;
-    cJSON *json;
-    cJSON *format;
-    OCEntityHandlerResult ehResult;
+    OCRepPayload *respPLPost_led = nullptr;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -196,11 +171,9 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
             int newLedUriLength = strlen(newLedUri);
             snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
 
-            json = cJSON_CreateObject();
-
-            cJSON_AddStringToObject(json,"href",gResourceUri);
-            cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
-            cJSON_AddStringToObject(format, "createduri", (char *) newLedUri);
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
 
             if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
             {
@@ -208,14 +181,13 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
                 gLedInstance[gCurrLedInstance].state = 0;
                 gLedInstance[gCurrLedInstance].power = 0;
                 gCurrLedInstance++;
-                respPLPost_led = cJSON_Print(json);
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
             }
-
-            cJSON_Delete(json);
         }
         else
         {
-            respPLPost_led = constructJsonResponse(ehRequest);
+            respPLPost_led = constructResponse(ehRequest);
         }
     }
     else
@@ -226,31 +198,28 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
             {
                 if (i == 0)
                 {
-                    respPLPost_led = constructJsonResponse(ehRequest);
+                    respPLPost_led = constructResponse(ehRequest);
                     break;
                 }
                 else if (i == 1)
                 {
-                    respPLPost_led = constructJsonResponse(ehRequest);
+                    respPLPost_led = constructResponse(ehRequest);
                 }
             }
         }
     }
 
-    if ((respPLPost_led != NULL) && (maxPayloadSize > strlen (respPLPost_led)))
+    if (respPLPost_led != NULL)
     {
-        strcpy(payload, respPLPost_led);
+        *payload = respPLPost_led;
         ehResult = OC_EH_OK;
     }
     else
     {
-        OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                maxPayloadSize);
+        OC_LOG_V (INFO, TAG, "Payload was NULL");
         ehResult = OC_EH_ERROR;
     }
 
-    free(respPLPost_led);
-
     return ehResult;
 }
 
@@ -263,7 +232,15 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
 
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
     OCEntityHandlerResponse response;
-    char payload[MAX_RESPONSE_LENGTH] = {0};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = nullptr;
 
     if (flag & OC_REQUEST_FLAG)
     {
@@ -273,17 +250,17 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             if (OC_REST_GET == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload));
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
             }
             else if (OC_REST_PUT == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload));
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
             }
             else if (OC_REST_POST == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload));
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
             }
             else
             {
@@ -292,14 +269,13 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
                 ehResult = OC_EH_ERROR;
             }
 
-            if (ehResult == OC_EH_OK)
+            if (ehResult == OC_EH_OK && 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 = payload;
-                response.payloadSize = strlen(payload);
+                response.payload = reinterpret_cast<OCPayload*>(payload);
                 response.numSendVendorSpecificHeaderOptions = 0;
                 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
                 memset(response.resourceUri, 0, sizeof(response.resourceUri));
@@ -315,6 +291,8 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             }
         }
     }
+
+    OCPayloadDestroy(response.payload);
     return ehResult;
 }
 
index 4e1f7eb..f8b72db 100644 (file)
@@ -49,20 +49,18 @@ typedef struct LEDRESOURCE{
 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
 
 /* This method converts the payload to JSON format */
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
 
 /* Following methods process the PUT, GET, POST
  * requests
  */
 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
-                                         char *payload,
-                                         size_t maxPayloadSize);
+                                         OCRepPayload **payload);
 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
-                                         char *payload,
-                                         size_t maxPayloadSize);
+                                         OCRepPayload **payload);
 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
-                                          char *payload,
-                                          size_t maxPayloadSize);
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
 
 //-----------------------------------------------------------------------------
 // Callback functions
index 6e52718..4f89cd3 100644 (file)
@@ -150,6 +150,7 @@ void DeleteClientCB(ClientCB * cbNode)
         OC_LOG(INFO, TAG, PCF("deleting tokens"));
         OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)cbNode->token, cbNode->tokenLength);
         CADestroyToken (cbNode->token);
+        OICFree(cbNode->devAddr);
         OICFree(cbNode->handle);
         OICFree(cbNode->requestUri);
         if(cbNode->deleteCallback)
index 83bbfec..a851da3 100644 (file)
@@ -34,6 +34,7 @@
 #include "cJSON.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
+#include "ocpayload.h"
 
 /// Module Name
 #include <stdio.h>
@@ -219,54 +220,6 @@ ValidateQuery (const char *query, OCResourceHandle resource,
     return OC_STACK_OK;
 }
 
-
-static OCStackResult BuildRootResourceJSON(OCResource *resource,
-        char * bufferPtr, uint16_t *remaining)
-{
-    OCStackResult ret = OC_STACK_ERROR;
-    cJSON *resObj = NULL;
-    char *jsonStr = NULL;
-    uint16_t jsonLen;
-
-    OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON"));
-    resObj = cJSON_CreateObject();
-
-    if ( ! resObj)
-    {
-        ret = OC_STACK_NO_MEMORY;
-    }
-    else if (resource)
-    {
-        cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri));
-        jsonStr = cJSON_PrintUnformatted (resObj);
-
-        if(!jsonStr)
-        {
-            cJSON_Delete(resObj);
-            return OC_STACK_NO_MEMORY;
-        }
-
-        jsonLen = strlen(jsonStr);
-        if (jsonLen < *remaining)
-        {
-            OICStrcpy(bufferPtr, *remaining, jsonStr);
-            *remaining -= jsonLen;
-            bufferPtr += jsonLen;
-            ret = OC_STACK_OK;
-        }
-    }
-    else
-    {
-        ret = OC_STACK_INVALID_PARAM;
-    }
-
-    cJSON_Delete (resObj);
-    OICFree(jsonStr);
-
-    return ret;
-}
-
-
 static OCStackResult
 HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, char *filterValue)
 {
@@ -275,86 +228,47 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, c
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCStackResult ret = OC_STACK_ERROR;
-    char jsonbuffer[MAX_RESPONSE_LENGTH] = {};
-    size_t jsonbufferLength = 0;
-    uint16_t remaining = 0;
-    char *ptr = NULL;
+    OCStackResult ret = OC_STACK_OK;
     OCResource *collResource = (OCResource *)ehRequest->resource;
 
-    ptr = jsonbuffer;
-    remaining = MAX_RESPONSE_LENGTH;
-
-    ret = BuildRootResourceJSON(collResource, ptr, &remaining);
-
-    if (ret == OC_STACK_OK && remaining >= (sizeof (OC_JSON_SEPARATOR) + 1))
+    OCDiscoveryPayload* payload = OCDiscoveryPayloadCreate();
+    if(!payload)
     {
-        ptr += strlen((char*)ptr);
-        *ptr = OC_JSON_SEPARATOR;
-        ptr++;
-        remaining--;
+        ret = OC_STACK_NO_MEMORY;
     }
-    else
+
+    if(ret == OC_STACK_OK)
     {
-        ret = OC_STACK_ERROR;
+        ret = BuildVirtualResourceResponse(collResource, payload,
+                CA_ADAPTER_IP);
     }
 
     if (ret == OC_STACK_OK)
     {
-        for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        for  (int i = 0; i < MAX_CONTAINED_RESOURCES && ret == OC_STACK_OK; i++)
         {
             OCResource* temp = collResource->rsrcResources[i];
             if (temp)
             {
                 //TODO : Add resource type filtering once collections
                 // start supporting queries.
-                ret = BuildVirtualResourceResponse(temp,
-                         (char*)ptr, &remaining, CA_ADAPTER_IP);
-
-                if (ret != OC_STACK_OK)
-                {
-                    break;
-                }
-                ptr += strlen((char*)ptr);
-
-                // Check if we have added all resources.
-                if ((i + 1) == MAX_CONTAINED_RESOURCES)
-                {
-                    break;
-                }
-                // Add separator if more resources and enough space present.
-                if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
-                {
-                    *ptr = OC_JSON_SEPARATOR;
-                    ptr++;
-                    remaining--;
-                }
-                // No point continuing as no more space on buffer
-                // and/or no more resources.
-                else
-                {
-                    break;
-                }
-            }
-            else
-            {
-                break;
+                ret = BuildVirtualResourceResponse(temp, payload,
+                        CA_ADAPTER_IP);
             }
         }
     }
 
-    jsonbufferLength = strlen((const char *)jsonbuffer);
-    if(ret == OC_STACK_OK && jsonbufferLength)
+    if(ret == OC_STACK_OK)
     {
         OCEntityHandlerResponse response = {};
         response.ehResult = OC_EH_OK;
-        response.payload = jsonbuffer;
-        response.payloadSize = jsonbufferLength + 1;
+        response.payload = (OCPayload*)payload;
         response.persistentBufferFlag = 0;
         response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
         response.resourceHandle = (OCResourceHandle) collResource;
         ret = OCDoResponse(&response);
     }
+    OCDiscoveryPayloadDestroy(payload);
     return ret;
 }
 
@@ -363,30 +277,31 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 {
     OCStackResult stackRet = OC_STACK_ERROR;
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
-    char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
-    size_t jsonbufferLength = 0;
-    uint16_t remaining = 0;
-    char * ptr = NULL;
     OCResource * collResource = (OCResource *) ehRequest->resource;
 
-    ptr = jsonbuffer;
-    remaining = MAX_RESPONSE_LENGTH;
+    OCDiscoveryPayload* payload = OCDiscoveryPayloadCreate();
+    if(!payload)
+    {
+        stackRet = OC_STACK_NO_MEMORY;
+    }
 
-    stackRet = BuildRootResourceJSON(collResource, ptr, &remaining);
-    ptr += strlen((char*)ptr);
+    if(stackRet == OC_STACK_OK)
+    {
+        stackRet = BuildVirtualResourceResponse(collResource, payload,
+                CA_ADAPTER_IP);
+    }
 
-    jsonbufferLength = strlen((const char *)jsonbuffer);
-    if(jsonbufferLength)
+    if(stackRet == OC_STACK_OK)
     {
         OCEntityHandlerResponse response = {};
         response.ehResult = OC_EH_OK;
-        response.payload = jsonbuffer;
-        response.payloadSize = jsonbufferLength + 1;
+        response.payload = (OCPayload*)payload;
         response.persistentBufferFlag = 0;
         response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
         response.resourceHandle = (OCResourceHandle) collResource;
         stackRet = OCDoResponse(&response);
     }
+    OCDiscoveryPayloadDestroy(payload);
 
     if (stackRet == OC_STACK_OK)
     {
@@ -535,8 +450,8 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
 
             case STACK_IF_GROUP:
             {
-                OC_LOG_V(INFO, TAG, "IF_COLLECTION PUT with request ::\n%s\n ",
-                        ehRequest->reqJSONPayload);
+                OC_LOG(INFO, TAG, PCF("IF_COLLECTION PUT with request ::\n"));
+                OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
                 return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/,
                         (OCResource *) ehRequest->resource, ehRequest);
             }
@@ -551,8 +466,8 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
         {
             case STACK_IF_GROUP:
             {
-                OC_LOG_V(INFO, TAG, "IF_COLLECTION POST with request :: \n%s\n ",
-                        ehRequest->reqJSONPayload);
+                OC_LOG(INFO, TAG, PCF("IF_COLLECTION POST with request ::\n"));
+                OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
                 return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
                         (OCResource *) ehRequest->resource, ehRequest);
             }
@@ -565,8 +480,8 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
 
         if(ifQueryParam == STACK_IF_GROUP)
         {
-            OC_LOG_V(INFO, TAG, "IF_COLLECTION POST with request :: \n%s\n ",
-                    ehRequest->reqJSONPayload);
+            OC_LOG(INFO, TAG, PCF("IF_COLLECTION POST with request ::\n"));
+            OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
             return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
                     (OCResource *) ehRequest->resource, ehRequest);
         }
index 6ab5c58..c7d8a7d 100644 (file)
@@ -27,8 +27,8 @@
 #include "ocrandom.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
+#include "ocpayload.h"
 #include "ocserverrequest.h"
-#include "cJSON.h"
 
 #include "utlist.h"
 #include "pdu.h"
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
 
 static struct ResourceObserver * serverObsList = NULL;
-#ifdef WITH_PRESENCE
-static char* GetJSONStringForPresence(uint32_t ttl, uint32_t nonce,
-        OCPresenceTrigger trigger, OCResourceType *resourceType)
-{
-    char *jsonEncodedInfo = NULL;
-    const char * triggerStr = NULL;
-
-    cJSON *rootObj = cJSON_CreateObject();
-    VERIFY_NON_NULL (rootObj);
-
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_TTL, cJSON_CreateNumber(ttl));
-
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_NONCE, cJSON_CreateNumber(nonce));
-
-    triggerStr = convertTriggerEnumToString(trigger);
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_TRIGGER, cJSON_CreateString(triggerStr));
-
-    if(resourceType && resourceType->resourcetypename)
-    {
-        cJSON_AddItemToObject (rootObj, OC_RSRVD_RESOURCE_TYPE,
-                cJSON_CreateString(resourceType->resourcetypename));
-    }
-
-    jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
-
-exit:
-    cJSON_Delete(rootObj);
-
-    return jsonEncodedInfo;
-
-}
-
-static OCStackResult BuildPresenceResponse(char *out, uint16_t *remaining,
-        uint32_t ttl, uint32_t nonce, OCPresenceTrigger trigger,
-        OCResourceType *resourceType)
-{
-    if(!out || !remaining)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCStackResult ret = OC_STACK_ERROR;
-    char *jsonStr = NULL;
-    uint16_t jsonLen = 0;
-
-    jsonStr = GetJSONStringForPresence(ttl, nonce, trigger, resourceType);
-
-    if(jsonStr)
-    {
-        jsonLen = strlen(jsonStr);
-
-        if (jsonLen < *remaining)
-        {
-            OICStrcpy(out, *remaining, jsonStr);
-            *remaining = *remaining - jsonLen;
-            ret = OC_STACK_OK;
-        }
-        else
-        {
-            ret = OC_STACK_ERROR;
-        }
-
-        OICFree(jsonStr);
-    }
-    else
-    {
-        OC_LOG(ERROR, TAG, PCF("Error encoding presence payload."));
-        ret = OC_STACK_ERROR;
-    }
-    return ret;
-}
-#endif // WITH_PRESENCE
 /**
  * Determine observe QOS based on the QOS of the request.
  * The qos passed as a parameter overrides what the client requested.
@@ -215,7 +143,7 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
                     {
                         result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
                                     request->method, (OCResourceHandle) resPtr, request->query,
-                                    request->reqJSONPayload,
+                                    request->payload, request->payloadSize,
                                     request->numRcvdVendorSpecificHeaderOptions,
                                     request->rcvdVendorSpecificHeaderOptions,
                                     OC_OBSERVE_NO_OPTION, 0);
@@ -235,7 +163,6 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
             else
             {
                 OCEntityHandlerResponse ehResponse = {};
-                char presenceResBuf[MAX_RESPONSE_LENGTH] = {};
 
                 //This is effectively the implementation for the presence entity handler.
                 OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
@@ -248,17 +175,19 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
 
                 if(result == OC_STACK_OK)
                 {
-                    uint16_t remaining = MAX_RESPONSE_LENGTH;
-                    // create the payload here
-                    result = BuildPresenceResponse(presenceResBuf, &remaining,
-                            maxAge, resPtr->sequenceNum, trigger,
-                            resourceType);
+                    OCPresencePayload* presenceResBuf = OCPresencePayloadCreate(
+                            resPtr->sequenceNum, maxAge, trigger,
+                            resourceType ? resourceType->resourcetypename : NULL);
 
-                    if(result == OC_STACK_OK && remaining < MAX_RESPONSE_LENGTH)
+                    if(!presenceResBuf)
+                    {
+                        return OC_STACK_NO_MEMORY;
+                    }
+
+                    if(result == OC_STACK_OK)
                     {
                         ehResponse.ehResult = OC_EH_OK;
-                        ehResponse.payload = presenceResBuf;
-                        ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1;
+                        ehResponse.payload = (OCPayload*)presenceResBuf;
                         ehResponse.persistentBufferFlag = 0;
                         ehResponse.requestHandle = (OCRequestHandle) request;
                         ehResponse.resourceHandle = (OCResourceHandle) resPtr;
@@ -266,6 +195,8 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
                                 resourceObserver->resUri);
                         result = OCDoResponse(&ehResponse);
                     }
+
+                    OCPresencePayloadDestroy(presenceResBuf);
                 }
             }
             #endif
@@ -294,10 +225,11 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
 
 OCStackResult SendListObserverNotification (OCResource * resource,
         OCObservationId  *obsIdList, uint8_t numberOfIds,
-        const char *notificationJSONPayload, uint32_t maxAge,
+        const OCRepPayload *payload,
+        uint32_t maxAge,
         OCQualityOfService qos)
 {
-    if(!resource || !obsIdList || !notificationJSONPayload)
+    if(!resource || !obsIdList || !payload)
     {
         return OC_STACK_INVALID_PARAM;
     }
@@ -334,15 +266,13 @@ OCStackResult SendListObserverNotification (OCResource * resource,
                     {
                         OCEntityHandlerResponse ehResponse = {};
                         ehResponse.ehResult = OC_EH_OK;
-                        ehResponse.payload = (char *) OICMalloc(MAX_RESPONSE_LENGTH + 1);
+                        ehResponse.payload = (OCPayload*)OCRepPayloadCreate();
                         if(!ehResponse.payload)
                         {
                             FindAndDeleteServerRequest(request);
                             continue;
                         }
-                        OICStrcpy(ehResponse.payload, MAX_RESPONSE_LENGTH + 1,
-                                notificationJSONPayload);
-                        ehResponse.payloadSize = strlen(ehResponse.payload) + 1;
+                        memcpy(ehResponse.payload, payload, sizeof(*payload));
                         ehResponse.persistentBufferFlag = 0;
                         ehResponse.requestHandle = (OCRequestHandle) request;
                         ehResponse.resourceHandle = (OCResourceHandle) resource;
diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c
new file mode 100644 (file)
index 0000000..69cab70
--- /dev/null
@@ -0,0 +1,1401 @@
+//******************************************************************
+//
+// Copyright 2015 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 "ocpayload.h"
+#include "octypes.h"
+#include <string.h>
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "ocstackinternal.h"
+#include "ocresource.h"
+#include "logger.h"
+
+#define TAG "OCPayload"
+static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val);
+
+void OCPayloadDestroy(OCPayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+
+    switch(payload->type)
+    {
+        case PAYLOAD_TYPE_REPRESENTATION:
+            OCRepPayloadDestroy((OCRepPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_DISCOVERY:
+            OCDiscoveryPayloadDestroy((OCDiscoveryPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_DEVICE:
+            OCDevicePayloadDestroy((OCDevicePayload*)payload);
+            break;
+        case PAYLOAD_TYPE_PLATFORM:
+            OCPlatformPayloadDestroy((OCPlatformPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_PRESENCE:
+            OCPresencePayloadDestroy((OCPresencePayload*)payload);
+            break;
+        case PAYLOAD_TYPE_SECURITY:
+            OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
+            break;
+        default:
+            OC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
+            OICFree(payload);
+            break;
+    }
+}
+OCRepPayload* OCRepPayloadCreate()
+{
+    OCRepPayload* payload = (OCRepPayload*)OICCalloc(1, sizeof(OCRepPayload));
+
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
+
+    return payload;
+}
+
+void OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child)
+{
+    if(!parent)
+    {
+        return;
+    }
+
+    while(parent->next)
+    {
+        parent = parent->next;
+    }
+
+    parent->next= child;
+}
+
+static OCRepPayloadValue* OCRepPayloadFindValue(const OCRepPayload* payload, const char* name)
+{
+    if(!payload || !name)
+    {
+        return NULL;
+    }
+
+    OCRepPayloadValue* val = payload->values;
+    while(val)
+    {
+        if(0 == strcmp(val->name, name))
+        {
+            return val;
+        }
+        val = val->next;
+    }
+
+    return NULL;
+
+}
+
+static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source)
+{
+    size_t dimTotal = calcDimTotal(source->arr.dimensions);
+    switch(source->arr.type)
+    {
+        case OCREP_PROP_INT:
+            dest->arr.iArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
+            memcpy(dest->arr.iArray, source->arr.iArray, dimTotal * sizeof(int64_t));
+            break;
+        case OCREP_PROP_DOUBLE:
+            dest->arr.dArray = (double*)OICMalloc(dimTotal * sizeof(double));
+            memcpy(dest->arr.dArray, source->arr.dArray, dimTotal * sizeof(double));
+            break;
+        case OCREP_PROP_BOOL:
+            dest->arr.bArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
+            memcpy(dest->arr.bArray, source->arr.bArray, dimTotal * sizeof(bool));
+            break;
+        case OCREP_PROP_STRING:
+            dest->arr.strArray = (char**)OICMalloc(dimTotal * sizeof(char*));
+            for(size_t i = 0; i < dimTotal; ++i)
+            {
+                dest->arr.strArray[i] = OICStrdup(source->arr.strArray[i]);
+            }
+            break;
+        case OCREP_PROP_ARRAY:
+            dest->arr.objArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
+            for(size_t i = 0; i < dimTotal; ++i)
+            {
+                dest->arr.objArray[i] = OCRepPayloadClone(source->arr.objArray[i]);
+            }
+            break;
+        default:
+            OC_LOG(ERROR, TAG, PCF("CopyPropertyValueArray invalid type"));
+            break;
+    }
+}
+
+static void OCCopyPropertyValue (OCRepPayloadValue *dest, OCRepPayloadValue *source)
+{
+    if (!source || !dest)
+    {
+        return;
+    }
+
+    switch(source->type)
+    {
+        case OCREP_PROP_STRING:
+            dest->str = OICStrdup(source->str);
+            break;
+        case OCREP_PROP_OBJECT:
+            dest->obj = OCRepPayloadClone(source->obj);
+            break;
+        case OCREP_PROP_ARRAY:
+            OCCopyPropertyValueArray(dest, source);
+            break;
+        default:
+            // Nothing to do for the trivially copyable types.
+            break;
+    }
+}
+
+static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val)
+{
+    if(!val)
+    {
+        return;
+    }
+
+    if(val->type == OCREP_PROP_STRING)
+    {
+        OICFree(val->str);
+    }
+    else if (val->type == OCREP_PROP_OBJECT)
+    {
+        OCRepPayloadDestroy(val->obj);
+    }
+    else if (val->type == OCREP_PROP_ARRAY)
+    {
+        size_t dimTotal = calcDimTotal(val->arr.dimensions);
+        switch(val->arr.type)
+        {
+            case OCREP_PROP_INT:
+            case OCREP_PROP_DOUBLE:
+            case OCREP_PROP_BOOL:
+                // Since this is a union, iArray will
+                // point to all of the above
+                OICFree(val->arr.iArray);
+                break;
+            case OCREP_PROP_STRING:
+                for(size_t i = 0; i< dimTotal;++i)
+                {
+                    OICFree(val->arr.strArray[i]);
+                }
+                OICFree(val->arr.strArray);
+                break;
+            case OCREP_PROP_OBJECT:
+                for(size_t i = 0; i< dimTotal;++i)
+                {
+                    OCRepPayloadDestroy(val->arr.objArray[i]);
+                }
+                OICFree(val->arr.objArray);
+                break;
+            case OCREP_PROP_NULL:
+            case OCREP_PROP_ARRAY:
+                OC_LOG_V(ERROR, TAG, "FreeRepPayloadValueContents: Illegal type\
+                        inside an array: %d", val->arr.type);
+                break;
+        }
+    }
+}
+
+static void OCFreeRepPayloadValue(OCRepPayloadValue* val)
+{
+    if(!val)
+    {
+        return;
+    }
+
+    OICFree(val->name);
+    OCFreeRepPayloadValueContents(val);
+    OCFreeRepPayloadValue(val->next);
+    OICFree(val);
+}
+static OCRepPayloadValue* OCRepPayloadValueClone (OCRepPayloadValue* source)
+{
+    if (!source)
+    {
+        return NULL;
+    }
+
+    OCRepPayloadValue *sourceIter = source;
+    OCRepPayloadValue *destIter = (OCRepPayloadValue*) OICCalloc(1, sizeof(OCRepPayloadValue));
+    if (!destIter)
+    {
+        return NULL;
+    }
+
+    OCRepPayloadValue *headOfClone = destIter;
+
+    // Copy payload type and non pointer types in union.
+    *destIter = *sourceIter;
+    destIter->name = OICStrdup (sourceIter->name);
+    OCCopyPropertyValue (destIter, sourceIter);
+
+    sourceIter = sourceIter->next;
+
+    while (sourceIter)
+    {
+        destIter->next = (OCRepPayloadValue*) OICCalloc(1, sizeof(OCRepPayloadValue));
+        if (!destIter->next)
+        {
+            OCFreeRepPayloadValue (headOfClone);
+            return NULL;
+        }
+
+        *(destIter->next) = *sourceIter;
+        destIter->next->name = OICStrdup (sourceIter->name);
+        OCCopyPropertyValue (destIter->next, sourceIter);
+
+        sourceIter = sourceIter->next;
+        destIter = destIter->next;
+    }
+    return headOfClone;
+}
+
+static OCRepPayloadValue* OCRepPayloadFindAndSetValue(OCRepPayload* payload, const char* name,
+        OCRepPayloadPropType type)
+{
+    if(!payload || !name)
+    {
+        return NULL;
+    }
+
+    OCRepPayloadValue* val = payload->values;
+    if(val == NULL)
+    {
+        payload->values = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
+        payload->values->name = OICStrdup(name);
+        payload->values->type =type;
+        return payload->values;
+    }
+
+    while(val)
+    {
+        if(0 == strcmp(val->name, name))
+        {
+            OCFreeRepPayloadValueContents(val);
+            val->type = type;
+            return val;
+        }
+        else if(val->next == NULL)
+        {
+            val->next = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue));
+            val->next->name = OICStrdup(name);
+            val->next->type =type;
+            return val->next;
+        }
+
+        val = val->next;
+    }
+
+    OC_LOG(ERROR, TAG, PCF("FindAndSetValue reached point after while loop, pointer corruption?"));
+    return NULL;
+}
+
+bool OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType)
+{
+    return OCRepPayloadAddResourceTypeAsOwner(payload, OICStrdup(resourceType));
+}
+
+bool OCRepPayloadAddResourceTypeAsOwner(OCRepPayload* payload, char* resourceType)
+{
+    if(!payload || !resourceType)
+    {
+        return false;
+    }
+
+    if(payload->types)
+    {
+        OCStringLL* cur = payload->types;
+        while(cur->next)
+        {
+            cur = cur->next;
+        }
+        cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+
+        if(!cur->next)
+        {
+            return false;
+        }
+
+        cur->next->value = resourceType;
+        return true;
+    }
+    else
+    {
+        payload->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+        if(!payload->types)
+        {
+            return false;
+        }
+        payload->types->value = resourceType;
+        return true;
+    }
+}
+
+bool OCRepPayloadAddInterface(OCRepPayload* payload, const char* interface)
+{
+    return OCRepPayloadAddInterfaceAsOwner(payload, OICStrdup(interface));
+}
+
+bool OCRepPayloadAddInterfaceAsOwner(OCRepPayload* payload, char* interface)
+{
+    if(!payload || !interface)
+    {
+        return false;
+    }
+
+    if(payload->interfaces)
+    {
+        OCStringLL* cur = payload->interfaces;
+        while(cur->next)
+        {
+            cur = cur->next;
+        }
+        cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+
+        if(!cur->next)
+        {
+            return false;
+        }
+        cur->next->value = interface;
+        return true;
+    }
+    else
+    {
+        payload->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+        if(!payload->interfaces)
+        {
+            return false;
+        }
+        payload->interfaces->value = interface;
+        return true;
+    }
+}
+
+bool OCRepPayloadSetUri(OCRepPayload* payload, const char*  uri)
+{
+    if(!payload)
+    {
+        return false;
+    }
+
+    payload->uri = OICStrdup(uri);
+    return payload->uri != NULL;
+}
+
+bool OCRepPayloadIsNull(const OCRepPayload* payload, const char* name)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    return val->type == OCREP_PROP_NULL;
+}
+
+bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_NULL);
+    return val != NULL;
+}
+
+bool OCRepPayloadSetPropInt(OCRepPayload* payload,
+        const char* name, int64_t value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_INT);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->i = value;
+    return true;
+}
+
+bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_INT)
+    {
+        return false;
+    }
+
+    *value = val->i;
+    return true;
+}
+
+bool OCRepPayloadSetPropDouble(OCRepPayload* payload,
+        const char* name, double value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_DOUBLE);
+
+    if(!val )
+    {
+        return false;
+    }
+
+    val->d = value;
+    return true;
+}
+
+bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_DOUBLE)
+    {
+        return false;
+    }
+
+    *value = val->d;
+    return true;
+}
+
+bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value)
+{
+    char* temp = OICStrdup(value);
+    bool b = OCRepPayloadSetPropStringAsOwner(payload, name, temp);
+
+    if(!b)
+    {
+        OICFree(temp);
+    }
+    return b;
+}
+
+bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_STRING);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->str = value;
+    return val->str != NULL;
+}
+
+bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_STRING)
+    {
+        return false;
+    }
+
+    *value = OICStrdup(val->str);
+    return *value != NULL;
+}
+
+bool OCRepPayloadSetPropBool(OCRepPayload* payload,
+        const char* name, bool value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_BOOL);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->b = value;
+    return true;
+}
+
+bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_BOOL)
+    {
+        return false;
+    }
+
+    *value = val->b;
+    return true;
+}
+
+bool OCRepPayloadSetPropObject(OCRepPayload* payload, const char* name, const OCRepPayload* value)
+{
+    OCRepPayload* temp = OCRepPayloadClone(value);
+    bool b = OCRepPayloadSetPropObjectAsOwner(payload, name, temp);
+
+    if(!b)
+    {
+        OCRepPayloadDestroy(temp);
+    }
+    return b;
+}
+
+bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_OBJECT);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->obj = value;
+    return true;
+}
+
+bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value)
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_OBJECT)
+    {
+        return false;
+    }
+
+    *value = OCRepPayloadClone(val->obj);
+    return *value != NULL;
+}
+
+size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    if(dimensions[0] == 0)
+    {
+        return 0;
+    }
+
+    size_t total = 1;
+    for(uint8_t i = 0; i < MAX_REP_ARRAY_DEPTH && dimensions[i] != 0; ++i)
+    {
+        total *= dimensions[i];
+    }
+    return total;
+}
+
+bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name,
+        int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->arr.type = OCREP_PROP_INT;
+    memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    val->arr.iArray = array;
+
+    return true;
+}
+
+bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name,
+        const int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    size_t dimTotal = calcDimTotal(dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+
+    int64_t* newArray = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
+
+    if(!newArray)
+    {
+        return false;
+    }
+
+    memcpy(newArray, array, dimTotal * sizeof(int64_t));
+
+
+    bool b = OCRepPayloadSetIntArrayAsOwner(payload, name, newArray, dimensions);
+    if(!b)
+    {
+        OICFree(newArray);
+    }
+    return b;
+}
+
+bool OCRepPayloadGetIntArray(const OCRepPayload* payload, const char* name,
+        int64_t** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_INT
+            || !val->arr.iArray)
+    {
+        return false;
+    }
+
+    size_t dimTotal = calcDimTotal(val->arr.dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+    *array = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
+    if(!*array)
+    {
+        return false;
+    }
+
+    memcpy(*array, val->arr.iArray, dimTotal * sizeof(int64_t));
+    memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    return true;
+}
+
+bool OCRepPayloadSetDoubleArrayAsOwner(OCRepPayload* payload, const char* name,
+        double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->arr.type = OCREP_PROP_DOUBLE;
+    memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    val->arr.dArray = array;
+
+    return true;
+}
+bool OCRepPayloadSetDoubleArray(OCRepPayload* payload, const char* name,
+        const double* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    size_t dimTotal = calcDimTotal(dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+
+    double* newArray = (double*)OICMalloc(dimTotal * sizeof(double));
+
+    if(!newArray)
+    {
+        return false;
+    }
+
+    memcpy(newArray, array, dimTotal * sizeof(double));
+
+    bool b = OCRepPayloadSetDoubleArrayAsOwner(payload, name, newArray, dimensions);
+    if(!b)
+    {
+        OICFree(newArray);
+    }
+    return b;
+}
+
+bool OCRepPayloadGetDoubleArray(const OCRepPayload* payload, const char* name,
+        double** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_DOUBLE
+            || !val->arr.dArray)
+    {
+        return false;
+    }
+
+    size_t dimTotal = calcDimTotal(val->arr.dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+    *array = (double*)OICMalloc(dimTotal * sizeof(double));
+    if(!*array)
+    {
+        return false;
+    }
+
+    memcpy(*array, val->arr.dArray, dimTotal * sizeof(double));
+    memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    return true;
+}
+
+bool OCRepPayloadSetStringArrayAsOwner(OCRepPayload* payload, const char* name,
+        char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->arr.type = OCREP_PROP_STRING;
+    memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    val->arr.strArray = array;
+
+    return true;
+}
+bool OCRepPayloadSetStringArray(OCRepPayload* payload, const char* name,
+        const char** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    size_t dimTotal = calcDimTotal(dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+
+    char** newArray = (char**)OICMalloc(dimTotal * sizeof(char*));
+
+    if(!newArray)
+    {
+        return false;
+    }
+
+    for(size_t i = 0; i < dimTotal; ++i)
+    {
+        newArray[i] = OICStrdup(array[i]);
+    }
+
+    bool b = OCRepPayloadSetStringArrayAsOwner(payload, name, newArray, dimensions);
+
+    if(!b)
+    {
+        for(size_t i = 0; i < dimTotal; ++i)
+        {
+            OICFree(newArray[i]);
+        }
+        OICFree(newArray);
+    }
+    return b;
+}
+
+bool OCRepPayloadGetStringArray(const OCRepPayload* payload, const char* name,
+        char*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_STRING
+            || !val->arr.strArray)
+    {
+        return false;
+    }
+
+    size_t dimTotal = calcDimTotal(val->arr.dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+    *array = (char**)OICMalloc(dimTotal * sizeof(char*));
+    if(!*array)
+    {
+        return false;
+    }
+
+    memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+
+    for(size_t i = 0; i < dimTotal; ++i)
+    {
+        (*array)[i] = OICStrdup(val->arr.strArray[i]);
+    }
+
+    return true;
+
+}
+
+bool OCRepPayloadSetBoolArrayAsOwner(OCRepPayload* payload, const char* name,
+        bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->arr.type = OCREP_PROP_BOOL;
+    memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    val->arr.bArray = array;
+
+    return true;
+}
+bool OCRepPayloadSetBoolArray(OCRepPayload* payload, const char* name,
+        const bool* array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    size_t dimTotal = calcDimTotal(dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+
+    bool* newArray = (bool*)OICMalloc(dimTotal * sizeof(bool));
+
+    if(!newArray)
+    {
+        return false;
+    }
+
+    memcpy(newArray, array, dimTotal * sizeof(bool));
+
+
+    bool b = OCRepPayloadSetBoolArrayAsOwner(payload, name, newArray, dimensions);
+    if(!b)
+    {
+        OICFree(newArray);
+    }
+    return b;
+}
+
+bool OCRepPayloadGetBoolArray(const OCRepPayload* payload, const char* name,
+        bool** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BOOL
+            || !val->arr.bArray)
+    {
+        return false;
+    }
+
+    size_t dimTotal = calcDimTotal(val->arr.dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+    *array = (bool*)OICMalloc(dimTotal * sizeof(bool));
+    if(!*array)
+    {
+        return false;
+    }
+
+    memcpy(*array, val->arr.bArray, dimTotal * sizeof(bool));
+    memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    return true;
+}
+
+bool OCRepPayloadSetPropObjectArrayAsOwner(OCRepPayload* payload, const char* name,
+        OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY);
+
+    if(!val)
+    {
+        return false;
+    }
+
+    val->arr.type = OCREP_PROP_OBJECT;
+    memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+    val->arr.objArray = array;
+
+    return true;
+}
+
+bool OCRepPayloadSetPropObjectArray(OCRepPayload* payload, const char* name,
+        const OCRepPayload** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    size_t dimTotal = calcDimTotal(dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+
+    OCRepPayload** newArray = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
+
+    if(!newArray)
+    {
+        return false;
+    }
+
+    for(size_t i = 0; i < dimTotal; ++i)
+    {
+        newArray[i] = OCRepPayloadClone(array[i]);
+    }
+
+    bool b = OCRepPayloadSetPropObjectArrayAsOwner(payload, name, newArray, dimensions);
+
+    if(!b)
+    {
+        for(size_t i = 0; i < dimTotal; ++i)
+        {
+           OCRepPayloadDestroy(newArray[i]);
+        }
+        OICFree(newArray);
+    }
+    return b;
+}
+
+bool OCRepPayloadGetPropObjectArray(const OCRepPayload* payload, const char* name,
+        OCRepPayload*** array, size_t dimensions[MAX_REP_ARRAY_DEPTH])
+{
+    OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
+
+    if(!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_OBJECT
+            || !val->arr.objArray)
+    {
+        return false;
+    }
+
+    size_t dimTotal = calcDimTotal(val->arr.dimensions);
+    if(dimTotal == 0)
+    {
+        return false;
+    }
+    *array = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
+    if(!*array)
+    {
+        return false;
+    }
+
+    memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t));
+
+    for(size_t i = 0; i < dimTotal; ++i)
+    {
+        (*array)[i] = OCRepPayloadClone(val->arr.objArray[i]);
+    }
+
+    return true;
+}
+
+void OCFreeOCStringLL(OCStringLL* ll)
+{
+    if(!ll)
+    {
+        return;
+    }
+
+    OCFreeOCStringLL(ll->next);
+    OICFree(ll->value);
+    OICFree(ll);
+}
+
+OCStringLL* CloneOCStringLL (OCStringLL* ll)
+{
+    if (!ll)
+    {
+        return NULL;
+    }
+
+    OCStringLL *sourceIter = ll;
+
+    OCStringLL *destIter = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
+    if (!destIter)
+    {
+        return NULL;
+    }
+    destIter->value = OICStrdup (sourceIter->value);
+
+    OCStringLL *headOfClone = destIter;
+
+    sourceIter = sourceIter->next;
+
+    while (sourceIter)
+    {
+        destIter->next  = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
+        if (!destIter->next)
+        {
+            OCFreeOCStringLL (headOfClone);
+            return NULL;
+        }
+        destIter->next->value = OICStrdup (sourceIter->value);
+
+        destIter = destIter->next;
+        sourceIter = sourceIter->next;
+    }
+    return headOfClone;
+}
+
+OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
+{
+    if (!payload)
+    {
+        return NULL;
+    }
+
+    OCRepPayload *clone = OCRepPayloadCreate();
+
+    if (!clone)
+    {
+        return NULL;
+    }
+
+    clone->uri = OICStrdup (payload->uri);
+    clone->types = CloneOCStringLL (payload->types);
+    clone->interfaces = CloneOCStringLL (payload->interfaces);
+    clone->values = OCRepPayloadValueClone (payload->values);
+
+    return clone;
+}
+
+
+void OCRepPayloadDestroy(OCRepPayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+
+    OICFree(payload->uri);
+    OCFreeOCStringLL(payload->types);
+    OCFreeOCStringLL(payload->interfaces);
+    OCFreeRepPayloadValue(payload->values);
+    OCRepPayloadDestroy(payload->next);
+    OICFree(payload);
+}
+
+OCDiscoveryPayload* OCDiscoveryPayloadCreate()
+{
+    OCDiscoveryPayload* payload = (OCDiscoveryPayload*)OICCalloc(1, sizeof(OCDiscoveryPayload));
+
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_DISCOVERY;
+
+    return payload;
+}
+
+OCSecurityPayload* OCSecurityPayloadCreate(char* securityData)
+{
+    OCSecurityPayload* payload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_SECURITY;
+    payload->securityData = OICStrdup(securityData);
+
+    return payload;
+}
+
+void OCSecurityPayloadDestroy(OCSecurityPayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+
+    OICFree(payload->securityData);
+    OICFree(payload);
+}
+
+size_t OCDiscoveryPayloadGetResourceCount(OCDiscoveryPayload* payload)
+{
+    size_t i = 0;
+    OCResourcePayload* p = payload->resources;
+    while(p)
+    {
+        ++i;
+        p = p->next;
+    }
+    return i;
+}
+
+OCResourcePayload* OCDiscoveryPayloadGetResource(OCDiscoveryPayload* payload, size_t index)
+{
+    size_t i = 0;
+    OCResourcePayload* p = payload->resources;
+    while(p)
+    {
+        if(i == index)
+        {
+            return p;
+        }
+        ++i;
+        p = p->next;
+    }
+    return NULL;
+}
+
+static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t port)
+{
+    OCResourcePayload* pl = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
+    if(!pl)
+    {
+        return NULL;
+    }
+
+    pl->uri = OICStrdup(res->uri);
+    pl->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
+    memcpy(pl->sid, OCGetServerInstanceID(), UUID_SIZE);
+
+    // types
+    OCResourceType* typePtr = res->rsrcType;
+
+    if(typePtr != NULL)
+    {
+        pl->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+        pl->types->value = OICStrdup(typePtr->resourcetypename);
+
+        OCStringLL* cur = pl->types;
+        typePtr = typePtr->next;
+        while(typePtr)
+        {
+            cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+            cur->next->value = OICStrdup(typePtr->resourcetypename);
+            cur = cur->next;
+            typePtr = typePtr->next;
+        }
+    }
+
+    // interfaces
+    OCResourceInterface* ifPtr = res->rsrcInterface;
+    if(ifPtr != NULL)
+    {
+        pl->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+        pl->interfaces->value = OICStrdup(ifPtr->name);
+
+        OCStringLL* cur = pl->types;
+        ifPtr = ifPtr->next;
+        while(ifPtr)
+        {
+            cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+            cur->next->value = OICStrdup(ifPtr->name);
+            cur = cur->next;
+            ifPtr = ifPtr->next;
+        }
+    }
+
+    pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
+    pl->secure = (res->resourceProperties & OC_SECURE) != 0;
+    pl->port = port;
+
+    return pl;
+}
+
+void OCDiscoveryPayloadAddResource(OCDiscoveryPayload* payload, const OCResource* res,
+        uint16_t port)
+{
+    OCDiscoveryPayloadAddNewResource(payload, OCCopyResource(res, port));
+}
+
+void OCDiscoveryPayloadAddNewResource(OCDiscoveryPayload* payload, OCResourcePayload* res)
+{
+    if(!payload->resources)
+    {
+        payload->resources = res;
+    }
+    else
+    {
+        OCResourcePayload* p = payload->resources;
+        while(p->next)
+        {
+            p = p->next;
+        }
+        p->next = res;
+    }
+}
+
+void FreeOCDiscoveryResource(OCResourcePayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+
+    OICFree(payload->uri);
+    OICFree(payload->sid);
+    OCFreeOCStringLL(payload->types);
+    OCFreeOCStringLL(payload->interfaces);
+    FreeOCDiscoveryResource(payload->next);
+    OICFree(payload);
+
+}
+void OCDiscoveryPayloadDestroy(OCDiscoveryPayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+
+    FreeOCDiscoveryResource(payload->resources);
+    OICFree(payload);
+}
+
+OCDevicePayload* OCDevicePayloadCreate(const char* uri, const uint8_t* sid, const char* dname,
+        const char* specVer, const char* dmVer)
+{
+
+    OCDevicePayload* payload = (OCDevicePayload*)OICCalloc(1, sizeof(OCDevicePayload));
+
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_DEVICE;
+
+    payload->uri = OICStrdup(uri);
+    if(uri && !payload->uri)
+    {
+        goto exit;
+    }
+
+    if(sid)
+    {
+        payload->sid = (uint8_t*)OICMalloc(UUID_SIZE);
+        if(!payload->sid)
+        {
+            goto exit;
+        }
+        memcpy(payload->sid, sid, UUID_SIZE);
+    }
+
+    payload->deviceName = OICStrdup(dname);
+    if(dname && !payload->deviceName)
+    {
+        goto exit;
+    }
+
+    payload->specVersion = OICStrdup(specVer);
+    if(specVer && !payload->specVersion)
+    {
+        goto exit;
+    }
+
+    payload->dataModelVersion = OICStrdup(dmVer);
+    if(dmVer && !payload->dataModelVersion)
+    {
+        goto exit;
+    }
+
+    return payload;
+
+exit:
+    OCDevicePayloadDestroy((OCDevicePayload*)payload);
+    return NULL;
+}
+
+void OCDevicePayloadDestroy(OCDevicePayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+
+    OICFree(payload->uri);
+    OICFree(payload->sid);
+    OICFree(payload->deviceName);
+    OICFree(payload->specVersion);
+    OICFree(payload->dataModelVersion);
+    OICFree(payload);
+}
+
+static void OCCopyPlatformInfo(const OCPlatformInfo* platformInfo, OCPlatformPayload* target)
+{
+    target->info.platformID = OICStrdup(platformInfo->platformID);
+    target->info.manufacturerName = OICStrdup(platformInfo->manufacturerName);
+    target->info.manufacturerUrl = OICStrdup(platformInfo->manufacturerUrl);
+    target->info.modelNumber = OICStrdup(platformInfo->modelNumber);
+    target->info.dateOfManufacture = OICStrdup(platformInfo->dateOfManufacture);
+    target->info.platformVersion = OICStrdup(platformInfo->platformVersion);
+    target->info.operatingSystemVersion = OICStrdup(platformInfo->operatingSystemVersion);
+    target->info.hardwareVersion = OICStrdup(platformInfo->hardwareVersion);
+    target->info.firmwareVersion = OICStrdup(platformInfo->firmwareVersion);
+    target->info.supportUrl = OICStrdup(platformInfo->supportUrl);
+    target->info.systemTime = OICStrdup(platformInfo->systemTime);
+}
+
+OCPlatformPayload* OCPlatformPayloadCreateAsOwner(char* uri, OCPlatformInfo* platformInfo)
+{
+    OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_PLATFORM;
+    payload->uri = uri;
+    payload->info = *platformInfo;
+
+    return payload;
+}
+
+OCPlatformPayload* OCPlatformPayloadCreate(const char* uri, const OCPlatformInfo* platformInfo)
+{
+    OCPlatformPayload* payload = (OCPlatformPayload*)OICCalloc(1, sizeof(OCPlatformPayload));
+
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_PLATFORM;
+    payload->uri = OICStrdup(uri);
+    OCCopyPlatformInfo(platformInfo, payload);
+
+    return payload;
+}
+
+void OCPlatformPayloadDestroy(OCPlatformPayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+    OICFree(payload->uri);
+    OICFree(payload->info.platformID);
+    OICFree(payload->info.manufacturerName);
+    OICFree(payload->info.manufacturerUrl);
+    OICFree(payload->info.modelNumber);
+    OICFree(payload->info.dateOfManufacture);
+    OICFree(payload->info.platformVersion);
+    OICFree(payload->info.operatingSystemVersion);
+    OICFree(payload->info.hardwareVersion);
+    OICFree(payload->info.firmwareVersion);
+    OICFree(payload->info.supportUrl);
+    OICFree(payload->info.systemTime);
+    OICFree(payload);
+}
+
+OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge,
+        OCPresenceTrigger trigger, const char* resourceType)
+{
+    OCPresencePayload* payload = (OCPresencePayload*)OICCalloc(1, sizeof(OCPresencePayload));
+    if(!payload)
+    {
+        return NULL;
+    }
+
+    payload->base.type = PAYLOAD_TYPE_PRESENCE;
+    payload->sequenceNumber = seqNum;
+    payload->maxAge = maxAge;
+    payload->trigger = trigger;
+    payload->resourceType = OICStrdup(resourceType);
+    return payload;
+}
+
+void OCPresencePayloadDestroy(OCPresencePayload* payload)
+{
+    if(!payload)
+    {
+        return;
+    }
+    OICFree(payload->resourceType);
+    OICFree(payload);
+}
diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c
new file mode 100644 (file)
index 0000000..3b6bd02
--- /dev/null
@@ -0,0 +1,760 @@
+//******************************************************************
+//
+// Copyright 2015 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 "ocpayloadcbor.h"
+#include <stdlib.h>
+#include "oic_malloc.h"
+#include "logger.h"
+#include "ocpayload.h"
+#include "ocrandom.h"
+#include "ocresourcehandler.h"
+#include "cbor.h"
+
+#define TAG PCF("OCPayloadConvert")
+
+static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload,
+        size_t* size);
+static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload,
+        size_t* size);
+static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload,
+        size_t* size);
+static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size);
+static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload, uint8_t** outPayload,
+        size_t* size);
+static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload,
+        size_t* size);
+
+bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+        const char* value);
+
+bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+        const char* value);
+
+
+OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size)
+{
+    OC_LOG_V(INFO, TAG, "Converting payload of type %d", payload->type);
+    switch(payload->type)
+    {
+        case PAYLOAD_TYPE_DISCOVERY:
+            return OCConvertDiscoveryPayload((OCDiscoveryPayload*)payload, outPayload, size);
+        case PAYLOAD_TYPE_DEVICE:
+            return OCConvertDevicePayload((OCDevicePayload*)payload, outPayload, size);
+        case PAYLOAD_TYPE_PLATFORM:
+            return OCConvertPlatformPayload((OCPlatformPayload*)payload, outPayload, size);
+        case PAYLOAD_TYPE_REPRESENTATION:
+            return OCConvertRepPayload((OCRepPayload*)payload, outPayload, size);
+        case PAYLOAD_TYPE_PRESENCE:
+            return OCConvertPresencePayload((OCPresencePayload*)payload, outPayload, size);
+        case PAYLOAD_TYPE_SECURITY:
+            return OCConvertSecurityPayload((OCSecurityPayload*)payload, outPayload, size);
+        default:
+            OC_LOG_V(INFO,TAG, "ConvertPayload default %d", payload->type);
+            return OC_STACK_NOTIMPL;
+    }
+}
+
+static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload,
+        size_t* size)
+{
+    *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
+    *size = MAX_REQUEST_LENGTH;
+
+    if(!*outPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    CborEncoder encoder;
+    bool err = false;
+
+    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+
+    CborEncoder rootArray;
+    err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
+    err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY);
+
+    CborEncoder map;
+
+    err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+
+    if(payload->securityData)
+    {
+        err = err || AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION,
+                sizeof(OC_RSRVD_REPRESENTATION) - 1,
+                payload->securityData);
+    }
+
+    err = err || cbor_encoder_close_container(&rootArray, &map);
+
+    err = err || cbor_encoder_close_container(&encoder, &rootArray);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Convert Security Payload failed", err);
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+
+    if(!tempPayload)
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = tempPayload;
+    return OC_STACK_OK;
+}
+
+static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload,
+        size_t* size)
+{
+    *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
+    *size = MAX_REQUEST_LENGTH;
+
+    if(!*outPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    CborEncoder encoder = {};
+    bool err = false;
+    size_t resourceCount =  OCDiscoveryPayloadGetResourceCount(payload);
+
+    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+
+    CborEncoder rootArray;
+    err = err || cbor_encoder_create_array(&encoder, &rootArray, 1 + resourceCount);
+    err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY);
+
+    for(size_t i = 0; i < resourceCount; ++i)
+    {
+        CborEncoder map;
+        OCResourcePayload* resource = OCDiscoveryPayloadGetResource(payload, i);
+        err = err || cbor_encoder_create_map(&rootArray, &map, 3);
+        // Uri
+        err = err || AddTextStringToMap(&map, OC_RSRVD_HREF,
+                sizeof(OC_RSRVD_HREF) - 1,
+                resource->uri);
+
+        // Server ID
+        err = err || cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID,
+                sizeof(OC_RSRVD_SERVER_INSTANCE_ID) - 1);
+        err = err || cbor_encode_byte_string(&map, resource->sid, UUID_SIZE);
+        // Prop Tag
+        {
+            CborEncoder propMap;
+            err = err || cbor_encode_text_string(&map, OC_RSRVD_PROPERTY,
+                    sizeof(OC_RSRVD_PROPERTY) -1 );
+            err = err || cbor_encoder_create_map(&map, &propMap, 3);
+
+            // Resource Type
+            {
+                CborEncoder rtArray;
+                err = err || cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE,
+                    sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
+                err = err || cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength);
+
+                OCStringLL* rtPtr = resource->types;
+                while(rtPtr)
+                {
+                    err = err || cbor_encode_text_string(&rtArray, rtPtr->value,
+                            strlen(rtPtr->value));
+                    rtPtr = rtPtr->next;
+                }
+
+                err = err || cbor_encoder_close_container(&propMap, &rtArray);
+            }
+
+            // Interface Types
+            {
+                CborEncoder ifArray;
+                err = err || cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE,
+                        sizeof(OC_RSRVD_INTERFACE) - 1);
+                err = err || cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength);
+                OCStringLL* ifPtr = resource->interfaces;
+
+                while(ifPtr)
+                {
+                    err = err || cbor_encode_text_string(&ifArray, ifPtr->value,
+                        strlen(ifPtr->value));
+                    ifPtr= ifPtr->next;
+                }
+
+                err = err || cbor_encoder_close_container(&propMap, &ifArray);
+            }
+            // Policy
+            {
+                CborEncoder policyMap;
+                err = err || cbor_encode_text_string(&propMap, OC_RSRVD_POLICY,
+                        sizeof(OC_RSRVD_POLICY) - 1);
+                err = err || cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength);
+
+                // Bitmap
+                err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
+                        sizeof(OC_RSRVD_BITMAP) - 1);
+                err = err || cbor_encode_uint(&policyMap, resource->bitmap);
+
+                if(resource->secure)
+                {
+                    err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
+                            sizeof(OC_RSRVD_SECURE) - 1);
+                    err = err || cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE);
+
+                    if(resource->port != 0)
+                    {
+                        err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
+                                sizeof(OC_RSRVD_HOSTING_PORT) - 1);
+                        err = err || cbor_encode_uint(&policyMap, resource->port);
+                    }
+                }
+
+                err = err || cbor_encoder_close_container(&propMap, &policyMap);
+            }
+            // Close
+            err = err || cbor_encoder_close_container(&map, &propMap);
+        }
+        // Close Item
+        err = err || cbor_encoder_close_container(&rootArray, &map);
+    }
+    // Close main array
+    err = err || cbor_encoder_close_container(&encoder, &rootArray);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Convert Discovery Payload failed with : %d", err);
+        return OC_STACK_ERROR;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+
+    if(!tempPayload)
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = tempPayload;
+    return OC_STACK_OK;
+}
+
+static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload,
+        size_t* size)
+{
+    *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
+    *size = MAX_REQUEST_LENGTH;
+
+    if(!*outPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    CborEncoder encoder = {};
+    bool err = false;
+
+    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+    CborEncoder rootArray;
+    err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
+    err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE);
+
+    {
+        CborEncoder map;
+        err = err || cbor_encoder_create_map(&rootArray, &map, 2);
+
+        // uri
+        err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
+                payload->uri);
+
+        // Rep Map
+        {
+            CborEncoder repMap;
+            err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
+                    sizeof(OC_RSRVD_REPRESENTATION) - 1);
+            err = err || cbor_encoder_create_map(&map, &repMap, 4);
+
+            // Device ID
+            err = err || cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID,
+                    sizeof(OC_RSRVD_DEVICE_ID) - 1);
+            err = err || cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE);
+
+            // Device Name
+            err = err || AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME,
+                    sizeof(OC_RSRVD_DEVICE_NAME) - 1,
+                    payload->deviceName);
+
+            // Device Spec Version
+            err = err || AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION,
+                    sizeof(OC_RSRVD_SPEC_VERSION) - 1,
+                    payload->specVersion);
+
+            // Device data Model Version
+            err = err || AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION,
+                    sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1,
+                    payload->dataModelVersion);
+
+            err = err || cbor_encoder_close_container(&map, &repMap);
+        }
+
+        // Close Map
+        err = err || cbor_encoder_close_container(&rootArray, &map);
+    }
+
+    // Close main array
+    err = err || cbor_encoder_close_container(&encoder, &rootArray);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Convert Device Payload failed with : %d", err);
+        return OC_STACK_ERROR;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+
+    if(!tempPayload)
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = tempPayload;
+    return OC_STACK_OK;
+}
+
+static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload,
+        size_t* size)
+{
+    *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
+    *size = MAX_REQUEST_LENGTH;
+
+    if(!*outPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    CborEncoder encoder = {};
+    bool err = false;
+
+    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+    CborEncoder rootArray;
+    err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
+    err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM);
+    {
+        CborEncoder map;
+        err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+
+        // uri
+        err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
+                payload->uri);
+
+        // Rep Map
+        {
+            CborEncoder repMap;
+            err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
+                    sizeof(OC_RSRVD_REPRESENTATION) - 1);
+            err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
+
+            // Platform ID
+            err = err || AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID,
+                    sizeof(OC_RSRVD_PLATFORM_ID) - 1,
+                    payload->info.platformID);
+
+            // MFG Name
+            err = err || AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME,
+                    sizeof(OC_RSRVD_MFG_NAME) - 1,
+                    payload->info.manufacturerName);
+
+            // MFG Url
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL,
+                    sizeof(OC_RSRVD_MFG_URL) - 1,
+                    payload->info.manufacturerUrl);
+
+            // Model Num
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM,
+                    sizeof(OC_RSRVD_MODEL_NUM) - 1,
+                    payload->info.modelNumber);
+
+            // Date of Mfg
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE,
+                    sizeof(OC_RSRVD_MFG_DATE) - 1,
+                    payload->info.dateOfManufacture);
+
+            // Platform Version
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION,
+                    sizeof(OC_RSRVD_PLATFORM_VERSION) - 1,
+                    payload->info.platformVersion);
+
+            // OS Version
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION,
+                    sizeof(OC_RSRVD_OS_VERSION) - 1,
+                    payload->info.operatingSystemVersion);
+
+            // Hardware Version
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION,
+                    sizeof(OC_RSRVD_HARDWARE_VERSION) - 1,
+                    payload->info.hardwareVersion);
+
+            // Firmware Version
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION,
+                    sizeof(OC_RSRVD_FIRMWARE_VERSION) - 1,
+                    payload->info.firmwareVersion);
+
+            // Support URL
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL,
+                    sizeof(OC_RSRVD_SUPPORT_URL) - 1,
+                    payload->info.supportUrl);
+
+            // System Time
+            err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME,
+                    sizeof(OC_RSRVD_SYSTEM_TIME) - 1,
+                    payload->info.systemTime);
+            err = err || cbor_encoder_close_container(&map, &repMap);
+        }
+
+        // Close Map
+        err = err || cbor_encoder_close_container(&rootArray, &map);
+    }
+
+    // Close main array
+    err = err || cbor_encoder_close_container(&encoder, &rootArray);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Convert Platform Payload failed with : %d", err);
+        return OC_STACK_ERROR;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+
+    if(!tempPayload)
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = tempPayload;
+
+    return OC_STACK_OK;
+}
+
+static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload);
+
+static bool OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray)
+{
+    CborEncoder array;
+    bool err = false;
+
+    err = err || cbor_encoder_create_array(parent, &array, CborIndefiniteLength);
+    err = err || cbor_encode_uint(&array, valArray->type);
+    for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++i)
+    {
+        err = err || cbor_encode_uint(&array, valArray->dimensions[i]);
+    }
+
+    size_t dimTotal = calcDimTotal(valArray->dimensions);
+
+    for(size_t i = 0; i < dimTotal; ++i)
+    {
+        switch(valArray->type)
+        {
+            case OCREP_PROP_NULL:
+                OC_LOG(ERROR, TAG, PCF("ConvertArray Invalid NULL"));
+                err = CborUnknownError;
+                break;
+            case OCREP_PROP_INT:
+                err = err || cbor_encode_int(&array, valArray->iArray[i]);
+                break;
+            case OCREP_PROP_DOUBLE:
+                err = err || cbor_encode_double(&array, valArray->dArray[i]);
+                break;
+            case OCREP_PROP_BOOL:
+                err = err || cbor_encode_boolean(&array, valArray->bArray[i]);
+                break;
+            case OCREP_PROP_STRING:
+                err = err || cbor_encode_text_string(&array, valArray->strArray[i],
+                        strlen(valArray->strArray[i]));
+                break;
+            case OCREP_PROP_OBJECT:
+                err = OCConvertSingleRepPayload(&array, valArray->objArray[i]);
+                break;
+            case OCREP_PROP_ARRAY:
+                OC_LOG(ERROR, TAG, PCF("ConvertArray Invalid child array"));
+                err = CborUnknownError;
+                break;
+        }
+    }
+
+    err = err || cbor_encoder_close_container(parent, &array);
+    return err;
+}
+
+static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload)
+{
+    bool err = false;
+    CborEncoder map;
+    err = err || cbor_encoder_create_map(parent, &map, CborIndefiniteLength);
+
+    // Uri
+    err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF,
+            sizeof(OC_RSRVD_HREF) - 1,
+            payload->uri);
+
+    // Prop Map
+    // resource types, interfaces
+    if(payload->types || payload->interfaces)
+    {
+        OC_LOG_V(INFO, TAG, "Payload has types or interfaces");
+        err = err || cbor_encode_text_string(&map,
+                OC_RSRVD_PROPERTY,
+                sizeof(OC_RSRVD_PROPERTY) - 1);
+        CborEncoder propMap;
+        err = err || cbor_encoder_create_map(&map, &propMap, 2);
+
+        CborEncoder curArray;
+        if(payload->types)
+        {
+            err = err || cbor_encode_text_string(&propMap,
+                    OC_RSRVD_RESOURCE_TYPE,
+                    sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
+            err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
+            OCStringLL* val = payload->types;
+            while(val)
+            {
+                err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value));
+                val = val->next;
+            }
+            err = err || cbor_encoder_close_container(&propMap, &curArray);
+        }
+        if(payload->interfaces)
+        {
+            err = err || cbor_encode_text_string(&propMap,
+                    OC_RSRVD_INTERFACE,
+                    sizeof(OC_RSRVD_INTERFACE) - 1);
+            err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
+            OCStringLL* val = payload->interfaces;
+            while(val)
+            {
+                err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value));
+                val = val->next;
+            }
+            err = err || cbor_encoder_close_container(&propMap, &curArray);
+        }
+        err = err || cbor_encoder_close_container(&map, &propMap);
+    }
+
+    // Rep Map
+    {
+        CborEncoder repMap;
+        err = err || cbor_encode_text_string(&map,
+                OC_RSRVD_REPRESENTATION,
+                sizeof(OC_RSRVD_REPRESENTATION) - 1);
+        err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
+        OCRepPayloadValue* value = payload->values;
+        while(value)
+        {
+            err = err || cbor_encode_text_string(&repMap,
+                    value->name,
+                    strlen(value->name));
+            switch(value->type)
+            {
+                case OCREP_PROP_NULL:
+                    err = err || cbor_encode_null(&repMap);
+                    break;
+                case OCREP_PROP_INT:
+                    err = err || cbor_encode_int(&repMap,
+                            value->i);
+                    break;
+                case OCREP_PROP_DOUBLE:
+                    err = err || cbor_encode_double(&repMap,
+                            value->d);
+                    break;
+                case OCREP_PROP_BOOL:
+                    err = err || cbor_encode_boolean(&repMap,
+                            value->b);
+                    break;
+                case OCREP_PROP_STRING:
+                    err = err || cbor_encode_text_string(&repMap,
+                            value->str, strlen(value->str));
+                    break;
+                case OCREP_PROP_OBJECT:
+                    err = err || OCConvertSingleRepPayload(&repMap, value->obj);
+                    break;
+                case OCREP_PROP_ARRAY:
+                    err = err || OCConvertArray(&repMap, &value->arr);
+                    break;
+                default:
+                    OC_LOG_V(ERROR, TAG, "Invalid Prop type: %d",
+                            value->type);
+                    break;
+            }
+            value = value->next;
+        }
+
+        err = err || cbor_encoder_close_container(&map, &repMap);
+    }
+
+    // Close Map
+    err = err || cbor_encoder_close_container(parent, &map);
+
+    return err;
+}
+
+static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size)
+{
+    *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
+    *size = MAX_REQUEST_LENGTH;
+
+    if(!*outPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    CborEncoder encoder = {};
+    bool err = false;
+
+    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+    CborEncoder rootArray;
+    err = err || cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength);
+    err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION);
+
+    while(payload != NULL && !err)
+    {
+        err = err || OCConvertSingleRepPayload(&rootArray, payload);
+        payload = payload->next;
+    }
+
+    // Close main array
+    err = err || cbor_encoder_close_container(&encoder, &rootArray);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Convert Rep Payload failed with : %d", err);
+        return OC_STACK_ERROR;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+
+    if(!tempPayload)
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = tempPayload;
+
+    return OC_STACK_OK;
+}
+
+static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload,
+        uint8_t** outPayload, size_t* size)
+{
+    *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
+    *size = MAX_REQUEST_LENGTH;
+
+    if(!*outPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    CborEncoder encoder = {};
+    bool err = false;
+
+    cbor_encoder_init(&encoder, *outPayload, *size, 0);
+    CborEncoder rootArray;
+
+    err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
+    err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE);
+
+
+    CborEncoder map;
+    err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+
+    // Sequence Number
+    err = err || cbor_encode_text_string(&map,
+            OC_RSRVD_NONCE,
+            sizeof(OC_RSRVD_NONCE) - 1);
+    err = err || cbor_encode_uint(&map, payload->sequenceNumber);
+
+    // Max Age
+    err = err || cbor_encode_text_string(&map,
+            OC_RSRVD_TTL,
+            sizeof(OC_RSRVD_TTL) - 1);
+    err = err || cbor_encode_uint(&map, payload->maxAge);
+
+    // Trigger
+    const char* triggerStr = convertTriggerEnumToString(payload->trigger);
+    err = err || AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1,
+            triggerStr);
+
+    // Resource type name
+    if(payload->trigger != OC_PRESENCE_TRIGGER_DELETE)
+    {
+        err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE,
+                sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, payload->resourceType);
+    }
+
+    // Close Map
+    err = err || cbor_encoder_close_container(&rootArray, &map);
+    err = err || cbor_encoder_close_container(&encoder, &rootArray);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Convert Presence Payload failed with : %d", err);
+        return OC_STACK_ERROR;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+
+    if(!tempPayload)
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
+        OICFree(*outPayload);
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = tempPayload;
+
+    return OC_STACK_OK;
+}
+
+bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+        const char* value)
+{
+    return cbor_encode_text_string(map, key, keylen) ||
+           cbor_encode_text_string(map, value, strlen(value));
+}
+
+bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+        const char* value)
+{
+    return value ? AddTextStringToMap(map, key, keylen, value) : false;
+}
diff --git a/resource/csdk/stack/src/ocpayloadparse.c b/resource/csdk/stack/src/ocpayloadparse.c
new file mode 100644 (file)
index 0000000..2038d17
--- /dev/null
@@ -0,0 +1,868 @@
+//******************************************************************
+//
+// Copyright 2015 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 "ocpayloadcbor.h"
+#include <stdlib.h>
+#include "logger.h"
+#include "oic_malloc.h"
+#include "ocstackinternal.h"
+#include "ocpayload.h"
+#include "cbor.h"
+
+#define TAG PCF("OCPayloadParse")
+
+static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal);
+static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal);
+static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal);
+static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent);
+static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal);
+static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal);
+static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal);
+
+OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize)
+{
+    CborParser parser;
+    CborValue rootValue;
+    bool err = false;
+
+    OC_LOG_V(INFO, TAG, "CBOR Parsing size: %d", payloadSize, payload);
+    if((err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue)) != false)
+    {
+        OC_LOG_V(ERROR, TAG, "CBOR Parser init failed: %d", err);
+        return OC_STACK_ERROR;
+    }
+
+    if(!cbor_value_is_array(&rootValue))
+    {
+        OC_LOG_V(ERROR, TAG, "CBOR payload root object is not an array :%x", rootValue.type);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    CborValue arrayValue;
+    // enter the array
+    err = err || cbor_value_enter_container(&rootValue, &arrayValue);
+
+    int payloadType;
+    err = err || cbor_value_get_int(&arrayValue, &payloadType);
+    err = err || cbor_value_advance_fixed(&arrayValue);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "CBOR payload parse failed :%d", err);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    OCStackResult result = OC_STACK_ERROR;
+    switch(payloadType)
+    {
+        case PAYLOAD_TYPE_DISCOVERY:
+            result = OCParseDiscoveryPayload(outPayload, &arrayValue);
+            break;
+        case PAYLOAD_TYPE_DEVICE:
+            result = OCParseDevicePayload(outPayload, &arrayValue);
+            break;
+        case PAYLOAD_TYPE_PLATFORM:
+            result = OCParsePlatformPayload(outPayload, &arrayValue);
+            break;
+        case PAYLOAD_TYPE_REPRESENTATION:
+            result = OCParseRepPayload(outPayload, &arrayValue);
+            break;
+        case PAYLOAD_TYPE_PRESENCE:
+            result = OCParsePresencePayload(outPayload, &arrayValue);
+            break;
+        case PAYLOAD_TYPE_SECURITY:
+            result = OCParseSecurityPayload(outPayload, &arrayValue);
+            break;
+        default:
+            OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
+            result = OC_STACK_ERROR;
+            break;
+    }
+
+    if(result == OC_STACK_OK)
+    {
+        err = err || cbor_value_leave_container(&rootValue, &arrayValue);
+        if(err != CborNoError)
+        {
+            return OC_STACK_MALFORMED_RESPONSE;
+        }
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
+    }
+
+    return result;
+}
+
+void OCFreeOCStringLL(OCStringLL* ll);
+
+static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal)
+{
+    bool err = false;
+    char * securityData = NULL;
+
+    if(cbor_value_is_map(arrayVal))
+    {
+        CborValue curVal;
+        err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
+
+        if(cbor_value_is_valid(&curVal))
+        {
+            size_t len;
+            err = err || cbor_value_dup_text_string(&curVal, &securityData, &len, NULL);
+        }
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, PCF("Cbor main value not a map"));
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    err = err || cbor_value_advance(arrayVal);
+
+    if(err)
+    {
+        OC_LOG_V(ERROR, TAG, "Cbor in error condition");
+        OICFree(securityData);
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+    *outPayload = (OCPayload*)OCSecurityPayloadCreate(securityData);
+    OICFree(securityData);
+
+    return OC_STACK_OK;
+
+}
+
+static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal)
+{
+    bool err = false;
+
+    OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
+
+    if(!out)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    size_t resourceCount = 0;
+    while(!err &&
+            cbor_value_is_map(arrayVal))
+    {
+        OCResourcePayload* resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
+        if(!resource)
+        {
+            OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+            return OC_STACK_NO_MEMORY;
+        }
+        CborValue curVal;
+
+        // Uri
+        err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
+        size_t len;
+        err = err || cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
+
+        // SID
+        err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_SERVER_INSTANCE_ID, &curVal);
+        err = err || cbor_value_dup_byte_string(&curVal, &(resource->sid), &len, NULL);
+
+        // Prop Tag
+        {
+             err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_PROPERTY, &curVal);
+            // ResourceTypes
+            CborValue rtArray;
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE, &rtArray);
+
+            CborValue rtVal;
+             err = err || cbor_value_enter_container(&rtArray, &rtVal);
+
+            OCStringLL* llPtr = NULL;
+            while(!err && cbor_value_is_text_string(&rtVal))
+            {
+                if(resource->types == NULL)
+                {
+                    resource->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+                    llPtr = resource->types;
+                    if(!llPtr)
+                    {
+                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+                        OICFree(resource->uri);
+                        OICFree(resource->sid);
+                        OICFree(resource);
+                        return OC_STACK_NO_MEMORY;
+                    }
+                }
+                else
+                {
+                    llPtr->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+                    llPtr = llPtr->next;
+                    if(!llPtr)
+                    {
+                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+                        OICFree(resource->uri);
+                        OICFree(resource->sid);
+                        OCFreeOCStringLL(resource->types);
+                        OICFree(resource);
+                        return OC_STACK_NO_MEMORY;
+                    }
+
+                }
+
+                 err = err || cbor_value_dup_text_string(&rtVal, &(llPtr->value), &len, NULL);
+                 err = err || cbor_value_advance(&rtVal);
+            }
+
+             err = err || cbor_value_leave_container(&rtArray, &rtVal);
+            //
+            // Interface Types
+            CborValue ifArray;
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &ifArray);
+            CborValue ifVal;
+             err = err || cbor_value_enter_container(&ifArray, &ifVal);
+
+            llPtr = NULL;
+            while(!err && cbor_value_is_text_string(&ifVal))
+            {
+                if(resource->interfaces == NULL)
+                {
+                    resource->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+                    llPtr = resource->interfaces;
+                    if(!llPtr)
+                    {
+                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+                        OICFree(resource->uri);
+                        OICFree(resource->sid);
+                        OCFreeOCStringLL(resource->types);
+                        OICFree(resource);
+                        return OC_STACK_NO_MEMORY;
+                    }
+                }
+                else
+                {
+                    llPtr->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+                    llPtr = llPtr->next;
+                    if(!llPtr)
+                    {
+                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+                        OICFree(resource->uri);
+                        OICFree(resource->sid);
+                        OCFreeOCStringLL(resource->types);
+                        OCFreeOCStringLL(resource->interfaces);
+                        OICFree(resource);
+                        return OC_STACK_NO_MEMORY;
+                    }
+                }
+
+                 err = err || cbor_value_dup_text_string(&ifVal, &(llPtr->value), &len, NULL);
+                 err = err || cbor_value_advance(&ifVal);
+            }
+             err = err || cbor_value_leave_container(&ifArray, &ifVal);
+
+            // Policy
+            {
+                CborValue policyMap;
+                 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_POLICY, &policyMap);
+
+                // Bitmap
+                CborValue val;
+                err= err | cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &val);
+                uint64_t temp = 0;
+                 err = err || cbor_value_get_uint64(&val, &temp);
+                resource->bitmap = (uint8_t)temp;
+                // Secure Flag
+                err= err | cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
+                if(cbor_value_is_valid(&val))
+                {
+                     err = err || cbor_value_get_boolean(&val, &(resource->secure));
+                    // Port
+                     err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
+                    if(cbor_value_is_valid(&val) && cbor_value_is_map(&val))
+                    {
+                        CborValue port;
+                        cbor_value_map_find_value(&val, OC_RSRVD_HOSTING_PORT, &port);
+                        if(cbor_value_is_valid(&port))
+                        {
+                            err = err || cbor_value_get_uint64(&val, &temp);
+                            resource->port = (uint16_t)temp;
+                        }
+                    }
+                }
+            }
+        }
+
+         err = err || cbor_value_advance(arrayVal);
+        if(err)
+        {
+            OICFree(resource->uri);
+            OICFree(resource->sid);
+            OCFreeOCStringLL(resource->types);
+            OCFreeOCStringLL(resource->interfaces);
+            OICFree(resource);
+            OCDiscoveryPayloadDestroy(out);
+            OC_LOG_V(ERROR, TAG, "CBOR in error condition", err);
+            return OC_STACK_MALFORMED_RESPONSE;
+        }
+        ++resourceCount;
+        OCDiscoveryPayloadAddNewResource(out, resource);
+    }
+
+    *outPayload = (OCPayload*)out;
+
+    return OC_STACK_OK;
+}
+
+static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal)
+{
+    bool err = false;
+
+    if(cbor_value_is_map(arrayVal))
+    {
+        char* uri = NULL;
+        uint8_t* sid = NULL;
+        char* dname = NULL;
+        char* specVer = NULL;
+        char* dmVer = NULL;
+        CborValue curVal;
+         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
+        size_t len;
+         err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
+
+        // Representation
+        {
+             err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
+
+            CborValue repVal;
+            // Device ID
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_ID, &repVal);
+             err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
+            // Device Name
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_NAME, &repVal);
+             err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
+            // Device Spec Version
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SPEC_VERSION, &repVal);
+             err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
+            // Data Model Version
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
+             err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
+
+        }
+
+         err = err || cbor_value_advance(arrayVal);
+
+        if(err)
+        {
+            OICFree(uri);
+            OICFree(sid);
+            OICFree(dname);
+            OICFree(specVer);
+            OICFree(dmVer);
+            OC_LOG_V(ERROR, TAG, "CBOR in error condition %d", err);
+            return OC_STACK_MALFORMED_RESPONSE;
+        }
+
+        *outPayload = (OCPayload*)OCDevicePayloadCreate(uri, sid, dname, specVer, dmVer);
+
+        OICFree(uri);
+        OICFree(sid);
+        OICFree(dname);
+        OICFree(specVer);
+        OICFree(dmVer);
+        if(!*outPayload)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        return OC_STACK_OK;
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, PCF("Root device node was not a map"));
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+
+}
+
+static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal)
+{
+    bool err = false;
+
+    if(cbor_value_is_map(arrayVal))
+    {
+        char* uri = NULL;
+        OCPlatformInfo info = {};
+        CborValue curVal;
+         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
+        size_t len;
+         err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
+
+        // Representation
+        {
+             err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
+
+            CborValue repVal;
+            // Platform ID
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_PLATFORM_ID, &repVal);
+             err = err || cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
+
+            // MFG Name
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_NAME, &repVal);
+             err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
+
+            // MFG URL
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_URL, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
+            }
+
+            // Model Num
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MODEL_NUM, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
+            }
+
+            // Date of Mfg
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_DATE, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
+                        NULL);
+            }
+
+            // Platform Version
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_PLATFORM_VERSION, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len,
+                        NULL);
+            }
+
+            // OS Version
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_OS_VERSION, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
+                        &len, NULL);
+            }
+
+            // Hardware Version
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_HARDWARE_VERSION, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
+                        NULL);
+            }
+
+            // Firmware Version
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_FIRMWARE_VERSION, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
+                        NULL);
+            }
+
+            // Support URL
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SUPPORT_URL, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
+            }
+
+            // System Time
+             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SYSTEM_TIME, &repVal);
+            if(cbor_value_is_valid(&repVal))
+            {
+                 err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
+            }
+        }
+
+         err = err || cbor_value_advance(arrayVal);
+
+        if(err)
+        {
+            OICFree(info.dateOfManufacture);
+            OICFree(info.firmwareVersion);
+            OICFree(info.hardwareVersion);
+            OICFree(info.manufacturerName);
+            OICFree(info.manufacturerUrl);
+            OICFree(info.modelNumber);
+            OICFree(info.operatingSystemVersion);
+            OICFree(info.platformID);
+            OICFree(info.platformVersion);
+            OICFree(info.supportUrl);
+            OICFree(info.systemTime);
+            OC_LOG(ERROR, TAG, PCF("CBOR error In ParsePlatformPayload"));
+            return OC_STACK_MALFORMED_RESPONSE;
+        }
+
+        *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(uri, &info);
+
+        if(!*outPayload)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        return OC_STACK_OK;
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, PCF("Root device node was not a map"));
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+}
+
+static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+{
+    CborValue insideArray;
+    bool err = false;
+    uint64_t tempInt = 0;
+    OCRepPayloadPropType type;
+    size_t dimensions[MAX_REP_ARRAY_DEPTH];
+    err = err || cbor_value_enter_container(container, &insideArray);
+
+    err = err || cbor_value_get_uint64(&insideArray, &tempInt);
+    err = err || cbor_value_advance_fixed(&insideArray);
+    type = (OCRepPayloadPropType)tempInt;
+
+    for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++ i)
+    {
+         err = err || cbor_value_get_uint64(&insideArray, &tempInt);
+         err = err || cbor_value_advance_fixed(&insideArray);
+        dimensions[i] = tempInt;
+    }
+
+    size_t dimTotal = calcDimTotal(dimensions);
+
+    void* arr = NULL;
+    char* tempStr;
+    size_t len;
+    OCRepPayload* pl;
+    switch(type)
+    {
+        case OCREP_PROP_INT:
+            arr = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
+            for(size_t i = 0; i < dimTotal && !err; ++i)
+            {
+                 err = err || cbor_value_get_int64(&insideArray, &(((int64_t*)arr)[i]));
+                 err = err || cbor_value_advance_fixed(&insideArray);
+            }
+            if(!err &&
+                OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
+            {}
+            else
+            {
+                err = CborUnknownError;
+            }
+            break;
+        case OCREP_PROP_DOUBLE:
+            arr = (double*)OICMalloc(dimTotal * sizeof(double));
+            for(size_t i = 0; i < dimTotal && !err; ++i)
+            {
+                 err = err || cbor_value_get_double(&insideArray, &(((double*)arr)[i]));
+                 err = err || cbor_value_advance_fixed(&insideArray);
+            }
+            if(!err &&
+                OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
+            {}
+            else
+            {
+                err = CborUnknownError;
+            }
+            break;
+        case OCREP_PROP_BOOL:
+            arr = (bool*)OICMalloc(dimTotal * sizeof(bool));
+            for(size_t i = 0; i < dimTotal && !err; ++i)
+            {
+                 err = err || cbor_value_get_boolean(&insideArray, &(((bool*)arr)[i]));
+                 err = err || cbor_value_advance_fixed(&insideArray);
+            }
+            if(!err &&
+                OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
+            {}
+            else
+            {
+                err = CborUnknownError;
+            }
+            break;
+        case OCREP_PROP_STRING:
+            arr = (char**)OICMalloc(dimTotal * sizeof(char*));
+            for(size_t i = 0; i < dimTotal && !err; ++i)
+            {
+                 err = err || cbor_value_dup_text_string(&insideArray, &tempStr,
+                        &len, NULL);
+                ((char**)arr)[i] = tempStr;
+            }
+            if(!err &&
+                OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
+            {}
+            else
+            {
+                err = CborUnknownError;
+            }
+            break;
+        case OCREP_PROP_OBJECT:
+            arr = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
+            for(size_t i = 0; i < dimTotal && !err; ++i)
+            {
+                pl = NULL;
+                 err = err || OCParseSingleRepPayload(&pl, &insideArray);
+                ((OCRepPayload**)arr)[i] = pl;
+                 err = err || cbor_value_advance(&insideArray);
+            }
+            if(!err &&
+                OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
+            {}
+            else
+            {
+                err = CborUnknownError;
+            }
+            break;
+        default:
+            OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
+            err = CborUnknownError;
+            break;
+    }
+
+    return err;
+}
+
+static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent)
+{
+    *outPayload = OCRepPayloadCreate();
+    OCRepPayload* curPayload = *outPayload;
+    bool err = false;
+    if(!*outPayload)
+    {
+        return CborErrorOutOfMemory;
+    }
+
+    size_t len;
+    CborValue curVal;
+     err = err || cbor_value_map_find_value(repParent, OC_RSRVD_HREF, &curVal);
+    if(cbor_value_is_valid(&curVal))
+    {
+         err = err || cbor_value_dup_text_string(&curVal, &curPayload->uri, &len,
+            NULL);
+    }
+
+     err = err || cbor_value_map_find_value(repParent, OC_RSRVD_PROPERTY, &curVal);
+    if(cbor_value_is_valid(&curVal))
+    {
+        CborValue insidePropArray;
+         err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE,
+                &insidePropArray);
+
+        if(cbor_value_is_array(&insidePropArray))
+        {
+            CborValue rtArray;
+             err = err || cbor_value_enter_container(&insidePropArray, &rtArray);
+
+            while(!err && cbor_value_is_valid(&rtArray))
+            {
+                char* curRt;
+                cbor_value_dup_text_string(&rtArray, &curRt, &len, NULL);
+                OCRepPayloadAddResourceTypeAsOwner(curPayload, curRt);
+            }
+
+             err = err || cbor_value_leave_container(&insidePropArray, &rtArray);
+        }
+
+         err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &insidePropArray);
+
+        if(cbor_value_is_array(&insidePropArray))
+        {
+            CborValue ifArray;
+             err = err || cbor_value_enter_container(&insidePropArray, &ifArray);
+
+            while(!err && cbor_value_is_valid(&ifArray))
+            {
+                char* curIf;
+                 err = err || cbor_value_dup_text_string(&ifArray, &curIf, &len, NULL);
+                OCRepPayloadAddInterfaceAsOwner(curPayload, curIf);
+            }
+
+             err = err || cbor_value_leave_container(&insidePropArray, &ifArray);
+        }
+    }
+     err = err || cbor_value_map_find_value(repParent, OC_RSRVD_REPRESENTATION, &curVal);
+    if(cbor_value_is_map(&curVal))
+    {
+        CborValue repMap;
+         err = err || cbor_value_enter_container(&curVal, &repMap);
+
+        while(!err && cbor_value_is_valid(&repMap))
+        {
+            char* name;
+             err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
+
+             err = err || cbor_value_advance(&repMap);
+
+            int64_t intval = 0;
+            bool boolval = false;
+            char* strval = NULL;
+            double doubleval = 0;
+            OCRepPayload* pl;
+
+            switch(cbor_value_get_type(&repMap))
+            {
+                case CborNullType:
+                    OCRepPayloadSetNull(curPayload, name);
+                    break;
+                case CborIntegerType:
+                     err = err || cbor_value_get_int64(&repMap, &intval);
+                    OCRepPayloadSetPropInt(curPayload, name, intval);
+                    break;
+                case CborDoubleType:
+                     err = err || cbor_value_get_double(&repMap, &doubleval);
+                    OCRepPayloadSetPropDouble(curPayload, name, doubleval);
+                case CborBooleanType:
+                     err = err || cbor_value_get_boolean(&repMap, &boolval);
+                    OCRepPayloadSetPropBool(curPayload, name, boolval);
+                    break;
+                case CborTextStringType:
+                     err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
+                    OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
+                    break;
+                case CborMapType:
+                     err = err || OCParseSingleRepPayload(&pl, &repMap);
+                    OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
+                    break;
+                case CborArrayType:
+                     err = err || OCParseArray(curPayload, name, &repMap);
+                    break;
+                default:
+                    OC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
+                    err = true;
+            }
+
+             err = err || cbor_value_advance(&repMap);
+            OICFree(name);
+        }
+         err = err || cbor_value_leave_container(&curVal, &repMap);
+    }
+
+    if(err)
+    {
+        OCRepPayloadDestroy(*outPayload);
+    }
+
+    return err;
+}
+static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal)
+{
+    bool err = false;
+
+    OCRepPayload* rootPayload = NULL;
+    OCRepPayload* curPayload = NULL;
+    OCRepPayload* temp = NULL;
+    while(!err && cbor_value_is_map(arrayVal))
+    {
+         err = err || OCParseSingleRepPayload(&temp, arrayVal);
+
+        if(rootPayload == NULL)
+        {
+            rootPayload = temp;
+            curPayload = temp;
+        }
+        else
+        {
+            curPayload->next = temp;
+            curPayload = curPayload->next;
+        }
+
+
+         err = err || cbor_value_advance(arrayVal);
+        if(err)
+        {
+            OCRepPayloadDestroy(rootPayload);
+            OC_LOG_V(ERROR, TAG, PCF("CBOR error in ParseRepPayload"));
+            return OC_STACK_MALFORMED_RESPONSE;
+        }
+    }
+
+    *outPayload = (OCPayload*)rootPayload;
+
+    return OC_STACK_OK;
+}
+
+static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal)
+{
+    bool err = false;
+    if(cbor_value_is_map(arrayVal))
+    {
+        uint64_t seqNum = 0;
+        uint64_t maxAge = 0;
+        OCPresenceTrigger trigger = OC_PRESENCE_TRIGGER_CREATE;
+        char* tempStr = NULL;
+        size_t len = 0;
+
+        CborValue curVal;
+        // Sequence Number
+         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_NONCE, &curVal);
+         err = err || cbor_value_get_uint64(&curVal, &seqNum);
+
+        // Max Age
+         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TTL, &curVal);
+         err = err || cbor_value_get_uint64(&curVal, &maxAge);
+
+        // Trigger
+         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TRIGGER, &curVal);
+         err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
+        trigger = convertTriggerStringToEnum(tempStr);
+        OICFree(tempStr);
+        tempStr = NULL;
+
+        // Resource type name
+         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
+        if(cbor_value_is_valid(&curVal))
+        {
+             err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
+        }
+
+        err = err || cbor_value_advance(arrayVal);
+
+        if(!err)
+        {
+            *outPayload = (OCPayload*)OCPresencePayloadCreate(seqNum, maxAge, trigger, tempStr);
+        }
+        OICFree(tempStr);
+
+        if(err)
+        {
+            OCPayloadDestroy(*outPayload);
+            OC_LOG_V(ERROR, TAG, PCF("CBOR error Parse Presence Payload"));
+            return OC_STACK_MALFORMED_RESPONSE;
+        }
+
+        if(!*outPayload)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        return OC_STACK_OK;
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, PCF("Root presence node was not a map"));
+        return OC_STACK_MALFORMED_RESPONSE;
+    }
+}
index 063e7da..fc2b6b9 100644 (file)
@@ -34,6 +34,7 @@
 #include "oic_string.h"
 #include "logger.h"
 #include "cJSON.h"
+#include "ocpayload.h"
 
 #include "cacommon.h"
 #include "cainterface.h"
@@ -105,152 +106,6 @@ static OCStackResult GetSecurePortInfo(CATransportAdapter_t connType, uint16_t *
 }
 
 /*
- * Encodes platform info into json and returns a string on the heap.
- * Caller responsible for freeing the string.
- */
-static char* GetJSONStringFromPlatformInfo(OCPlatformInfo info)
-{
-    cJSON *rootObj = cJSON_CreateObject();
-
-    if (!rootObj)
-    {
-        return NULL;
-    }
-
-    cJSON *repObj = NULL;
-    char *jsonEncodedInfo = NULL;
-
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_HREF,
-            cJSON_CreateString(GetVirtualResourceUri(OC_PLATFORM_URI)));
-
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
-
-    if (!repObj)
-    {
-        return NULL;
-    }
-    if (info.platformID)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_ID,
-                cJSON_CreateString(info.platformID));
-    }
-
-    if (info.manufacturerName)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_NAME,
-                cJSON_CreateString(info.manufacturerName));
-    }
-
-    if (info.manufacturerUrl)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_URL,
-                cJSON_CreateString(info.manufacturerUrl));
-    }
-
-    if (info.modelNumber)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_MODEL_NUM,
-                cJSON_CreateString(info.modelNumber));
-    }
-
-    if (info.dateOfManufacture)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_DATE,
-                cJSON_CreateString(info.dateOfManufacture));
-    }
-
-    if (info.platformVersion)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_VERSION,
-                cJSON_CreateString(info.platformVersion));
-    }
-
-    if (info.operatingSystemVersion)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_OS_VERSION,
-                cJSON_CreateString(info.operatingSystemVersion));
-    }
-
-    if (info.hardwareVersion)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_HARDWARE_VERSION,
-                cJSON_CreateString(info.hardwareVersion));
-    }
-
-    if (info.firmwareVersion)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_FIRMWARE_VERSION,
-                cJSON_CreateString(info.firmwareVersion));
-    }
-
-    if (info.supportUrl)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_SUPPORT_URL,
-                cJSON_CreateString(info.supportUrl));
-    }
-
-    if (info.systemTime)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_SYSTEM_TIME,
-                cJSON_CreateString(info.systemTime));
-    }
-
-    jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
-
-    cJSON_Delete(rootObj);
-
-    return jsonEncodedInfo;
-}
-
-/*
- * Encodes device info into json and returns a string on the heap.
- * Caller responsible for freeing the string.
- */
-static char* GetJSONStringFromDeviceInfo(OCDeviceInfo info)
-{
-    cJSON *rootObj = cJSON_CreateObject();
-
-    if (!rootObj)
-    {
-        return NULL;
-    }
-
-    cJSON *repObj = NULL;
-    char *jsonEncodedInfo = NULL;
-
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_HREF,
-            cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI)));
-
-    cJSON_AddItemToObject (rootObj, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
-
-    if (!repObj)
-    {
-        return NULL;
-    }
-
-    cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_ID,
-                    cJSON_CreateString(OCGetServerInstanceIDString()));
-
-    if (info.deviceName)
-    {
-        cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_NAME,
-                        cJSON_CreateString(info.deviceName));
-    }
-
-    cJSON_AddItemToObject (repObj, OC_RSRVD_SPEC_VERSION,
-                        cJSON_CreateString(OC_SPEC_VERSION));
-
-    cJSON_AddItemToObject (repObj, OC_RSRVD_DATA_MODEL_VERSION,
-                        cJSON_CreateString(OC_DATA_MODEL_VERSION));
-
-    jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
-
-    cJSON_Delete(rootObj);
-
-    return jsonEncodedInfo;
-}
-
-/*
  * Function will extract 0, 1 or 2 filters from query.
  * More than 2 filters or unsupported filters will result in error.
  * If both filters are of the same supported type, the 2nd one will be picked.
@@ -361,162 +216,25 @@ static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *q
     return result;
 }
 
-OCStackResult copyStringIfEnoughSpace(char* dest, const char *src, uint16_t *remaining)
+OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
+                        OCDiscoveryPayload* payload, CATransportAdapter_t adapter )
 {
-    if (!dest || !src || !remaining)
+    if (!resourcePtr || !payload)
     {
         return OC_STACK_INVALID_PARAM;
     }
-
-    size_t srcLen = strlen(src);
-
-    if (srcLen < *remaining)
-    {
-        OICStrcpy(dest, *remaining, src);
-        *remaining = *remaining - srcLen;
-        return OC_STACK_OK;
-    }
-    else
+    uint16_t port = 0;
+    if (resourcePtr->resourceProperties & OC_SECURE)
     {
-        return OC_STACK_ERROR;
+       if(GetSecurePortInfo (adapter, &port) != OC_STACK_OK)
+       {
+           port = 0;
+       }
     }
-}
-
-OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, char *out,
-                        uint16_t *remaining, CATransportAdapter_t adapter )
-{
-    if(!resourcePtr || !out  || !remaining)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCResourceType *resourceTypePtr = NULL;
-    OCResourceInterface *interfacePtr = NULL;
-    cJSON *resObj = NULL;
-    cJSON *policyObj = NULL;
-    cJSON *rtArray = NULL;
-    char *jsonStr = NULL;
-    OCStackResult ret = OC_STACK_OK;
-
-    OC_LOG_V(INFO, TAG, PCF("Encoding resource %s"), resourcePtr->uri);
 
-    resObj = cJSON_CreateObject();
-
-    if (resourcePtr)
-    {
-        // URI
-        cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
-
-        // resource types
-        cJSON_AddItemToObject (resObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
-        resourceTypePtr = resourcePtr->rsrcType;
-        while (resourceTypePtr)
-        {
-            cJSON_AddItemToArray (rtArray,
-                                  cJSON_CreateString(resourceTypePtr->resourcetypename));
-            resourceTypePtr = resourceTypePtr->next;
-        }
-        // interfaces
-        cJSON_AddItemToObject (resObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
-        interfacePtr = resourcePtr->rsrcInterface;
-        while (interfacePtr)
-        {
-            cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
-            interfacePtr = interfacePtr->next;
-        }
-
-        // Policy
-        cJSON_AddItemToObject (resObj, OC_RSRVD_POLICY, policyObj = cJSON_CreateObject());
-
-        if (policyObj)
-        {
-            cJSON_AddNumberToObject (policyObj, OC_RSRVD_BITMAP,
-                             resourcePtr->resourceProperties & (OC_OBSERVABLE|OC_DISCOVERABLE));
-            // Set secure flag for secure resources
-            if (resourcePtr->resourceProperties & OC_SECURE)
-            {
-                cJSON_AddNumberToObject(policyObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE);
-                //Set the IP port also as secure resources are hosted on a different port
-                uint16_t port = 0;
-                if (GetSecurePortInfo(adapter, &port) == OC_STACK_OK)
-                {
-                    cJSON_AddNumberToObject(policyObj, OC_RSRVD_HOSTING_PORT, port);
-                }
-            }
-        }
-        else
-        {
-            cJSON_Delete(resObj);
-            return OC_STACK_NO_MEMORY;
-        }
-    }
-    jsonStr = cJSON_PrintUnformatted (resObj);
-
-    if(!jsonStr)
-    {
-        cJSON_Delete(resObj);
-        return OC_STACK_NO_MEMORY;
-    }
-
-    ret = copyStringIfEnoughSpace(out, jsonStr, remaining);
-
-    cJSON_Delete (resObj);
-    OICFree (jsonStr);
-
-    return ret;
-}
-
-OCStackResult BuildVirtualResourceResponseForDevice(char *out, uint16_t *remaining)
-{
-    if(!out || !remaining)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCStackResult ret = OC_STACK_ERROR;
-    char *jsonStr = NULL;
-
-    jsonStr = GetJSONStringFromDeviceInfo(savedDeviceInfo);
-
-    if(jsonStr)
-    {
-        ret = copyStringIfEnoughSpace(out, jsonStr, remaining);
-        OICFree(jsonStr);
-    }
-    else
-    {
-        OC_LOG(ERROR, TAG, PCF("Error encoding save device info."));
-        ret = OC_STACK_ERROR;
-    }
-    return ret;
-}
-
-OCStackResult BuildVirtualResourceResponseForPlatform(char *out, uint16_t *remaining)
-{
-    if(!out || !remaining)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCStackResult ret = OC_STACK_ERROR;
-    char *jsonStr = NULL;
-
-    jsonStr = GetJSONStringFromPlatformInfo(savedPlatformInfo);
-
-    if(jsonStr)
-    {
-        ret = copyStringIfEnoughSpace(out, jsonStr, remaining);
-        OICFree(jsonStr);
-    }
-    else
-    {
-        OC_LOG(ERROR, TAG, PCF("Error encoding save platform info."));
-        ret = OC_STACK_ERROR;
-    }
-
-    return ret;
+    OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
+    return OC_STACK_OK;
 }
-
 const char * GetVirtualResourceUri( OCVirtualResources resource)
 {
     if (resource < OC_MAX_VIRTUAL_RESOURCES)
@@ -783,13 +501,12 @@ static bool includeThisResourceInResponse(OCResource *resource,
 }
 
 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
-                                char *discoveryPayload)
+                                OCPayload *discoveryPayload)
 {
     OCEntityHandlerResponse response = {};
 
     response.ehResult = OC_EH_OK;
     response.payload = discoveryPayload;
-    response.payloadSize = strlen((const char *)discoveryPayload) + 1;
     response.persistentBufferFlag = 0;
     response.requestHandle = (OCRequestHandle) request;
     response.resourceHandle = (OCResourceHandle) resource;
@@ -797,36 +514,6 @@ OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCRes
     return OCDoResponse(&response);
 }
 
-static OCStackResult appendDeviceIDAndOpenLinksArray (char *out, uint16_t *remaining)
-{
-    if (!out || !remaining)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    const char *deviceID = OCGetServerInstanceIDString();
-
-    char deviceIDJSONField[MAX_RESPONSE_LENGTH] = {};
-
-    // Format is : {"di":"UUID","links":[
-    sprintf (deviceIDJSONField, "{\"%s\":\"%s\"%s\"%s\":[", OC_RSRVD_DEVICE_ID, deviceID,
-                            OC_JSON_SEPARATOR_STR, OC_RSRVD_LINKS);
-
-    uint16_t lenDeviceIDJSON = strlen(deviceIDJSONField);
-
-    if (lenDeviceIDJSON > *remaining)
-    {
-        return OC_STACK_ERROR;
-    }
-    else
-    {
-        OICStrcat(out, *remaining, deviceIDJSONField);
-        *remaining -= lenDeviceIDJSON;
-    }
-
-    return OC_STACK_OK;
-}
-
 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
 {
     if (!request || !resource)
@@ -835,99 +522,61 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
     }
 
     OCStackResult discoveryResult = OC_STACK_ERROR;
+    OCPayload* payload = NULL;
     char *filterOne = NULL;
     char *filterTwo = NULL;
-    uint16_t remaining  = 0;
-
-    char discoveryBuffer[MAX_RESPONSE_LENGTH] = {};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
 
     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
 
-    remaining = MAX_RESPONSE_LENGTH - sizeof ('\0');
 
     if (virtualUriInRequest == OC_WELL_KNOWN_URI)
     {
         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
-                                            &filterOne, &filterTwo);
+                                                            &filterOne, &filterTwo);
         if (discoveryResult != OC_STACK_OK)
         {
             OC_LOG_V(ERROR, TAG, "Error (%d) validating query.\n", discoveryResult);
             return discoveryResult;
         }
-        char *ptrIntoBuffer = discoveryBuffer;
+        payload = (OCPayload*)OCDiscoveryPayloadCreate();
 
-        discoveryResult = appendDeviceIDAndOpenLinksArray(ptrIntoBuffer, &remaining);
-
-        while(resource && discoveryResult == OC_STACK_OK)
+        if(!payload)
         {
-            if(includeThisResourceInResponse(resource, filterOne, filterTwo))
-            {
-                ptrIntoBuffer += strlen(ptrIntoBuffer);
-
-                discoveryResult = BuildVirtualResourceResponse(resource, ptrIntoBuffer,
-                                        &remaining, (CATransportAdapter_t)request->devAddr.adapter);
-
-                if (discoveryResult != OC_STACK_OK)
-                {
-                    OC_LOG_V(INFO, TAG, "Error (%d) encoding %s", discoveryResult, resource->uri);
-                    break;
-                }
-
-                ptrIntoBuffer += strlen(ptrIntoBuffer);
-                if (remaining > sizeof(OC_JSON_SEPARATOR))
-                {
-                    *ptrIntoBuffer = OC_JSON_SEPARATOR;
-                    ++ptrIntoBuffer;
-                    --remaining;
-                }
-                else
-                {
-                    OC_LOG(INFO, TAG, PCF("Out of space in buffer"));
-                    break;
-                }
-
-            }
-            resource = resource->next;
+            return OC_STACK_NO_MEMORY;
         }
 
-        size_t lenDiscoveryBuff = strlen (discoveryBuffer);
 
-        // Traling separator replaced with closing of "links" array.
-        // discoveryBuffer guaranteed to be null terminated as "remaining"
-        // accounts for '\0' when initialized.
-        if (lenDiscoveryBuff > 0 && discoveryBuffer[lenDiscoveryBuff - 1] == OC_JSON_SEPARATOR)
-        {
-            discoveryBuffer[lenDiscoveryBuff - 1] = ']';
-        }
-        else
+        for(;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
         {
-            // If No trailing separator then close links array anyway.
-            discoveryBuffer[lenDiscoveryBuff] = ']';
-        }
-        --remaining;
-        ptrIntoBuffer += strlen(ptrIntoBuffer);
-
-        // Close array element brace.
-        if (remaining > sizeof ('}'))
-        {
-            *ptrIntoBuffer = '}';
-            --remaining;
-        }
-        else
-        {
-            discoveryResult = OC_STACK_ERROR;
+            if(includeThisResourceInResponse(resource, filterOne, filterTwo))
+            {
+                discoveryResult = BuildVirtualResourceResponse(resource,
+                    (OCDiscoveryPayload*)payload,
+                    (CATransportAdapter_t)request->devAddr.adapter);
+            }
         }
     }
-
     else if (virtualUriInRequest == OC_DEVICE_URI)
     {
-        discoveryResult = BuildVirtualResourceResponseForDevice(discoveryBuffer, &remaining);
+            payload = (OCPayload*)OCDevicePayloadCreate(GetVirtualResourceUri(OC_DEVICE_URI),
+                        OCGetServerInstanceID(), savedDeviceInfo.deviceName,
+                        OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
+            if (!payload)
+            {
+                discoveryResult = OC_STACK_NO_MEMORY;
+            }
     }
     else if (virtualUriInRequest == OC_PLATFORM_URI)
     {
-        discoveryResult = BuildVirtualResourceResponseForPlatform(discoveryBuffer, &remaining);
+            OCPlatformPayload* payload = OCPlatformPayloadCreate(
+                    GetVirtualResourceUri(OC_PLATFORM_URI),
+                    &savedPlatformInfo);
+            if (!payload)
+            {
+                discoveryResult = OC_STACK_NO_MEMORY;
+            }
     }
 
     #ifdef WITH_PRESENCE
@@ -947,7 +596,8 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
         if(discoveryResult == OC_STACK_OK)
         {
             discoveryResult = SendNonPersistantDiscoveryResponse(request, resource,
-                                                        discoveryBuffer);
+                                                        payload);
+            OCPayloadDestroy(payload);
         }
         else
         {
@@ -974,7 +624,8 @@ HandleDefaultDeviceEntityHandler (OCServerRequest *request)
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
             request->method, (OCResourceHandle) NULL, request->query,
-            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->payload, request->payloadSize,
+            request->numRcvdVendorSpecificHeaderOptions,
             request->rcvdVendorSpecificHeaderOptions,
             (OCObserveAction)request->observationOption, (OCObservationId)0);
     VERIFY_SUCCESS(result, OC_STACK_OK);
@@ -1017,7 +668,7 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
 
     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
             request->method, (OCResourceHandle) resource, request->query,
-            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions,
             request->rcvdVendorSpecificHeaderOptions,
             (OCObserveAction)request->observationOption, 0);
     VERIFY_SUCCESS(result, OC_STACK_OK);
@@ -1124,7 +775,7 @@ HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
 
     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
             request->method, (OCResourceHandle) resource, request->query,
-            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions,
             request->rcvdVendorSpecificHeaderOptions,
             (OCObserveAction)request->observationOption, (OCObservationId) 0);
     if(result != OC_STACK_OK)
index 04797a6..2d4bda8 100644 (file)
@@ -24,6 +24,8 @@
 #include "ocresourcehandler.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
+#include "ocpayload.h"
+#include "ocpayloadcbor.h"
 
 #include "cacommon.h"
 #include "cainterface.h"
@@ -59,10 +61,8 @@ static OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestH
     serverResponse = (OCServerResponse *) OICCalloc(1, sizeof(OCServerResponse));
     VERIFY_NON_NULL(serverResponse);
 
-    serverResponse->payload = (char *) OICCalloc(1, MAX_RESPONSE_LENGTH);
-    VERIFY_NON_NULL(serverResponse->payload);
+    serverResponse->payload = NULL;
 
-    serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
     serverResponse->requestHandle = requestHandle;
 
     *response = serverResponse;
@@ -213,44 +213,16 @@ OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
     return NULL;
 }
 
-/**
- * Add a server request to the server request list
- *
- * @param request - initialized server request that is created by this function
- * @param coapID - ID of CoAP pdu
- * @param delayedResNeeded - delayed response required 0=no 1=yes
- * @param secured - secure endpoint 0=no 1=yes
- * @param notificationFlag - //TODO: remove - does not appear to be used any longer
- * @param method - RESTful method
- * @param numRcvdVendorSpecificHeaderOptions - number of received vendor specific header options
- * @param observationOption - value of observation option
- * @param qos - request QOS
- * @param query - request query
- * @param rcvdVendorSpecificHeaderOptions - received vendor specific header options
- * @param reqJSONPayload - request JSON payload
- * @param requestToken - request token
- * @param tokenLength - request token length
- * @param resourceUrl - URL of resource
- * @param reqTotalSize - total size of the request
- * @param addressInfo - CA Address
- * @param connectivityType - connection type
- *
- * @return
- *     OCStackResult
- */
 OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
         uint8_t delayedResNeeded, uint8_t notificationFlag, OCMethod method,
         uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
         OCQualityOfService qos, char * query,
         OCHeaderOption * rcvdVendorSpecificHeaderOptions,
-        char * reqJSONPayload, CAToken_t requestToken, uint8_t tokenLength,
+        uint8_t * payload, CAToken_t requestToken, uint8_t tokenLength,
         char * resourceUrl, size_t reqTotalSize, const OCDevAddr *devAddr)
 {
     OCServerRequest * serverRequest = NULL;
 
-    //Note: OCServerRequest includes 1 byte for the JSON Payload.  payloadSize is calculated
-    //as the required length of the string, so this will result in enough room for the
-    //null terminator as well.
     serverRequest = (OCServerRequest *) OICCalloc(1, sizeof(OCServerRequest) +
         (reqTotalSize ? reqTotalSize : 1) - 1);
     VERIFY_NON_NULL(devAddr);
@@ -278,10 +250,14 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
         memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
             MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
     }
-    if(reqJSONPayload && reqTotalSize)
+    if(payload && reqTotalSize)
     {
-        OICStrcpy(serverRequest->reqJSONPayload, reqTotalSize, reqJSONPayload);
+       // destination is at least 1 greater than the source, so a NULL always exists in the
+        // last character
+        memcpy(serverRequest->payload, payload, reqTotalSize);
+        serverRequest->payloadSize = reqTotalSize;
     }
+
     serverRequest->requestComplete = 0;
     if(requestToken)
     {
@@ -320,31 +296,14 @@ exit:
     return OC_STACK_NO_MEMORY;
 }
 
-/**
- * Form the OCEntityHandlerRequest struct that is passed to a resource's entity handler
- *
- * @param entityHandlerRequest - pointer to the OCEntityHandlerRequest struct that is created.
- *                              Required to be zero-initialized before calling this function.
- * @param request          - request handle
- * @param method           - RESTful method
- * @param resource         - resource handle
- * @param queryBuf         - resource query of request
- * @param bufReqPayload    - JSON payload of request
- * @param numVendorOptions - number of vendor options
- * @param vendorOptions    - vendor options
- * @param observeAction    - observe action flag
- * @param observeID        - observe ID
- *
- * @return
- *     OCStackResult
- */
 OCStackResult FormOCEntityHandlerRequest(
         OCEntityHandlerRequest * entityHandlerRequest,
         OCRequestHandle request,
         OCMethod method,
         OCResourceHandle resource,
         char * queryBuf,
-        char * bufReqPayload,
+        uint8_t * payload,
+        size_t payloadSize,
         uint8_t numVendorOptions,
         OCHeaderOption * vendorOptions,
         OCObserveAction observeAction,
@@ -358,9 +317,21 @@ OCStackResult FormOCEntityHandlerRequest(
         entityHandlerRequest->query = queryBuf;
         entityHandlerRequest->obsInfo.action = observeAction;
         entityHandlerRequest->obsInfo.obsId = observeID;
+
+        if(payload && payloadSize)
+        {
+            if(OCParsePayload(&entityHandlerRequest->payload, payload, payloadSize) != OC_STACK_OK)
+            {
+                return OC_STACK_ERROR;
+            }
+        }
+        else
+        {
+            entityHandlerRequest->payload = NULL;
+        }
+
         entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
         entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
-        entityHandlerRequest->reqJSONPayload = bufReqPayload;
 
         return OC_STACK_OK;
     }
@@ -445,15 +416,6 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
         return OC_STACK_ERROR;
     }
 
-    OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
-
-    if(ehResponse->payloadSize >= (MAX_RESPONSE_LENGTH))// - OC_JSON_PREFIX_LEN - OC_JSON_SUFFIX_LEN))
-    {
-        OC_LOG_V(ERROR, TAG, "Response payload size was too large.  Max is %hu, payload size was %hu",
-                (MAX_RESPONSE_LENGTH - OC_JSON_PREFIX_LEN - OC_JSON_SUFFIX_LEN), ehResponse->payloadSize);
-        return OC_STACK_INVALID_PARAM;
-    }
-
     OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
 
     CopyDevAddrToEndpoint(&serverRequest->devAddr, &responseEndpoint);
@@ -545,19 +507,30 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
         responseInfo.info.options = NULL;
     }
 
-    char payload[MAX_RESPONSE_LENGTH + OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN + 1] = {};
-
     // Put the JSON prefix and suffix around the payload
-    OICStrcpy(payload, sizeof(payload), OC_JSON_PREFIX);
-    if(ehResponse->payloadSize)
+    if(ehResponse->payload)
     {
-        OICStrcatPartial(payload, sizeof(payload),
-            ehResponse->payload,
-            ehResponse->payloadSize < MAX_RESPONSE_LENGTH ?
-            ehResponse->payloadSize : MAX_RESPONSE_LENGTH);
+        OCStackResult result;
+        if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
+                    &responseInfo.info.payloadSize))
+                != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "Error converting payload");
+            return result;
+        }
+
+        if(responseInfo.info.payloadSize > MAX_RESPONSE_LENGTH)
+        {
+            OICFree(responseInfo.info.payload);
+            OC_LOG(ERROR, TAG, "Payload too long!");
+            return OC_STACK_INVALID_PARAM;
+        }
+    }
+    else
+    {
+        responseInfo.info.payload = NULL;
+        responseInfo.info.payloadSize = 0;
     }
-    OICStrcat(payload, sizeof(payload), OC_JSON_SUFFIX);
-    responseInfo.info.payload = (CAPayload_t)payload;
 
     #ifdef WITH_PRESENCE
     //TODO: Add other connectivity types to CAConnTypes[] when enabled
@@ -607,6 +580,7 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
     }
     #endif
 
+    OICFree(responseInfo.info.payload);
     OICFree(responseInfo.info.token);
     OICFree(responseInfo.info.options);
     //Delete the request
@@ -631,7 +605,6 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
     OCStackResult stackRet = OC_STACK_ERROR;
     OCServerRequest * serverRequest = NULL;
     OCServerResponse * serverResponse = NULL;
-    uint16_t bufferNeeded = 0;
 
     if(!ehResponse || !ehResponse->payload)
     {
@@ -639,7 +612,7 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
         return OC_STACK_INVALID_PARAM;
     }
 
-    OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload);
+    OC_LOG(INFO, TAG, "Inside HandleAggregateResponse");
 
     serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
     serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
@@ -656,58 +629,34 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
                 return stackRet;
             }
             VERIFY_NON_NULL(serverResponse);
-            VERIFY_NON_NULL(serverResponse->payload);
         }
 
-        // If there is more than 1 response, then we need to allow for a null-termination
-        // in the server response payload buffer AND the JSON response separator
-        bufferNeeded = ehResponse->payloadSize + 1;
-        if (serverRequest->numResponses > 1)
+        if(serverResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION ||
+                ehResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
         {
-            bufferNeeded += strlen(OC_JSON_SEPARATOR_STR);
+            stackRet = OC_STACK_ERROR;
+            OC_LOG(ERROR, TAG, PCF("Error adding payload, as it was the incorrect type"));
+            goto exit;
         }
-        if(serverResponse->remainingPayloadSize >= bufferNeeded)
-        {
-            OC_LOG(ERROR, TAG, PCF("There is room in response buffer"));
-            // append
-            // allocated size of the payload is assumed, since a search of the code
-            // shows that it is OICCalloc'ed to this size in AddServerResponse above
-            OICStrcatPartial(serverResponse->payload,
-                    MAX_RESPONSE_LENGTH,
-                    ehResponse->payload,
-                    serverResponse->remainingPayloadSize);
-            OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
-            serverResponse->remainingPayloadSize -= strlen((char *)ehResponse->payload);
-            (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 fragments to come"));
-                OICStrcatPartial(serverResponse->payload,
-                        MAX_RESPONSE_LENGTH,
-                        OC_JSON_SEPARATOR_STR,
-                        serverResponse->remainingPayloadSize);
-                OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
-                serverResponse->remainingPayloadSize -= strlen(OC_JSON_SEPARATOR_STR);
-                stackRet = OC_STACK_OK;
-            }
-        }
-        else
+
+        OCRepPayloadAppend((OCRepPayload*)serverResponse->payload,
+                (OCRepPayload*)ehResponse->payload);
+
+        (serverRequest->numResponses)--;
+
+        if(serverRequest->numResponses == 0)
         {
-            OC_LOG(ERROR, TAG, PCF("No room in response buffer"));
+            OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
+            ehResponse->payload = serverResponse->payload;
+            stackRet = HandleSingleResponse(ehResponse);
             //Delete the request and response
             FindAndDeleteServerRequest(serverRequest);
             FindAndDeleteServerResponse(serverResponse);
-            stackRet = OC_STACK_NO_MEMORY;
+        }
+        else
+        {
+            OC_LOG(INFO, TAG, PCF("More response fragments to come"));
+            stackRet = OC_STACK_OK;
         }
     }
 exit:
index 7447960..9790d46 100644 (file)
@@ -45,6 +45,8 @@
 #include "secureresourcemanager.h"
 #include "cacommon.h"
 #include "cainterface.h"
+#include "ocpayload.h"
+#include "ocpayloadcbor.h"
 
 #ifdef WITH_ARDUINO
 #include "Time.h"
@@ -54,7 +56,6 @@
 #include "coap_time.h"
 #include "utlist.h"
 #include "pdu.h"
-#include "cJSON.h"
 
 #ifndef ARDUINO
 #include <arpa/inet.h>
@@ -117,17 +118,6 @@ void* defaultDeviceHandlerCallbackParameter = NULL;
 #define MAX_OBSERVE_AGE (0x2FFFFUL)
 
 #define MILLISECONDS_PER_SECOND   (1000)
-/**
- * Parse the presence payload and extract various parameters.
- * Note: Caller should invoke OICFree after done with resType pointer.
- *
- * @param payload Presence payload.
- * @param seqNum Sequence number.
- * @param maxAge Time To Live (in seconds).
- * @param resType Resource type.
- */
-void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge,
-        OCPresenceTrigger *presenceTrigger, char** resType);
 
 //-----------------------------------------------------------------------------
 // Private internal function prototypes
@@ -263,22 +253,6 @@ static void incrementSequenceNumber(OCResource * resPtr);
 static OCStackResult verifyUriQueryLength(const char * inputUri,
         uint16_t uriLen);
 
-/**
- * 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.
- * Note:  Either the request or response parameter should be non-NULL (i.e. only one, not both).
- *
- * @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
- *    false - packet transfer NOT required (i.e. normal request/response).
- *    true  - packet transfer required (i.e. block transfer needed).
- */
-static bool OCIsPacketTransferRequired(const char *request, const char *response, size_t size);
-
 /*
  * Attempts to initialize every network interface that the CA Layer might have compiled in.
  *
@@ -490,7 +464,7 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
         if(observer)
         {
             result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
-                    OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+                    OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, 0,
                     NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
             if(result != OC_STACK_OK)
             {
@@ -536,7 +510,7 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
             if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
             {
                 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
-                        OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+                        OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, 0,
                         NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
                 if(result != OC_STACK_OK)
                 {
@@ -750,7 +724,8 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr)
  *
  * requestUri must be a char array of size CA_MAX_URI_LENGTH
  */
-static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resourceUri, char *presenceUri)
+static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resourceUri,
+        char *presenceUri)
 {
     VERIFY_NON_NULL(endpoint   , FATAL, OC_STACK_INVALID_PARAM);
     VERIFY_NON_NULL(resourceUri, FATAL, OC_STACK_INVALID_PARAM);
@@ -771,110 +746,6 @@ static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resource
                                                endpoint->port, OC_PRESENCE_URI);
 }
 
-void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge,
-        OCPresenceTrigger *presenceTrigger, char** resType)
-{
-    if(!payload || !seqNum || !maxAge || !presenceTrigger || !resType)
-    {
-        return;
-    }
-
-    cJSON *repObj = cJSON_Parse(payload);
-    cJSON *ocObj = NULL;
-    cJSON *presenceObj = NULL;
-    cJSON *seqNumObj = NULL;
-    cJSON *maxAgeObj = NULL;
-    cJSON *triggerObj = NULL;
-    cJSON *resObj = NULL;
-    if(repObj)
-    {
-        ocObj = cJSON_GetObjectItem(repObj, OC_RSRVD_OC);
-        if(ocObj)
-        {
-            //Presence payloads should only carry one JSON payload. The first
-            //    & only array item is retrieved.
-            presenceObj = cJSON_GetArrayItem(ocObj, 0);
-            if(presenceObj)
-            {
-                seqNumObj = cJSON_GetObjectItem(presenceObj, OC_RSRVD_NONCE);
-                if(seqNumObj)
-                {
-                    *seqNum = (uint32_t)seqNumObj->valuedouble;
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, PCF("Nonce (AKA SeqNum) not found in"
-                            " JSON Presence Payload."));
-                    goto exit;
-                }
-                maxAgeObj = cJSON_GetObjectItem(presenceObj, OC_RSRVD_TTL);
-                if(maxAgeObj)
-                {
-                    *maxAge = maxAgeObj->valueint;
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, PCF("TTL (AKA MaxAge) not found in"
-                            " JSON Presence Payload."));
-                    goto exit;
-                }
-                triggerObj = cJSON_GetObjectItem(presenceObj,
-                        OC_RSRVD_TRIGGER);
-                if(triggerObj)
-                {
-                    char * triggerStr = triggerObj->valuestring;
-                    *presenceTrigger = convertTriggerStringToEnum(triggerStr);
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, PCF("Trigger Reason not found in"
-                            " JSON Presence Payload."));
-                    goto exit;
-                }
-                resObj = cJSON_GetObjectItem(presenceObj,
-                        OC_RSRVD_RESOURCE_TYPE);
-                if(resObj)
-                {
-                    *resType = OICStrdup(resObj->valuestring);
-                    if(!*resType)
-                    {
-                        goto exit;
-                    }
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, PCF("Resource Type not found in"
-                            " JSON Presence Payload."));
-                    goto exit;
-                }
-            }
-            else
-            {
-                OC_LOG(ERROR, TAG, PCF("JSON Presence Object not found in"
-                        " Presence Payload."));
-                OICFree(*resType);
-                goto exit;
-            }
-        }
-        else
-        {
-            OC_LOG(ERROR, TAG, PCF("JSON Presence Payload does not contain a"
-                                    " valid \"oic\" JSON representation."));
-            OICFree(*resType);
-            goto exit;
-        }
-    }
-    else
-    {
-        OC_LOG(ERROR, TAG, PCF("JSON Presence Payload does map to a valid JSON"
-                " representation."));
-        OICFree(*resType);
-        goto exit;
-    }
-
-exit:
-    cJSON_Delete(repObj);
-}
 
 OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
                             const CAResponseInfo_t *responseInfo)
@@ -888,7 +759,6 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
     OCClientResponse response;
     OCStackResult result = OC_STACK_ERROR;
     uint32_t maxAge = 0;
-    OCPresenceTrigger presenceTrigger = OC_PRESENCE_TRIGGER_CHANGE;
     int uriLen;
     char presenceUri[CA_MAX_URI_LENGTH];
 
@@ -929,7 +799,7 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
         goto exit;
     }
 
-    response.resJSONPayload = responseInfo->info.payload;
+    response.payload = NULL;
     response.result = OC_STACK_OK;
 
     CopyEndpointToDevAddr(endpoint, &response.devAddr);
@@ -937,11 +807,17 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
 
     if (responseInfo->info.payload)
     {
-        parsePresencePayload(responseInfo->info.payload,
-                                &(response.sequenceNumber),
-                                &maxAge,
-                                &presenceTrigger,
-                                &resourceTypeName);
+        result = OCParsePayload(&response.payload,  responseInfo->info.payload,
+                responseInfo->info.payloadSize);
+
+        if(result != OC_STACK_OK || response.payload->type != PAYLOAD_TYPE_PRESENCE)
+        {
+            OC_LOG(ERROR, TAG, PCF("Presence parse failed"));
+            goto exit;
+        }
+        response.sequenceNumber = ((OCPresencePayload*)response.payload)->sequenceNumber;
+        resourceTypeName = ((OCPresencePayload*)response.payload)->resourceType;
+        maxAge = ((OCPresencePayload*)response.payload)->maxAge;
     }
 
     if (presenceSubscribe)
@@ -994,7 +870,7 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
             cbNode->sequenceNumber = response.sequenceNumber;
 
             // Ensure that a filter is actually applied.
-            if(resourceTypeName && cbNode->filterResourceType)
+            if( resourceTypeName && cbNode->filterResourceType)
             {
                 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
                 {
@@ -1073,6 +949,7 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res
     VERIFY_NON_NULL_NR(endPoint, FATAL);
     VERIFY_NON_NULL_NR(responseInfo, FATAL);
     VERIFY_NON_NULL_NR(responseInfo->info.resourceUri, FATAL);
+    OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
 
     if(strcmp(responseInfo->info.resourceUri, OC_PRESENCE_URI) == 0)
     {
@@ -1082,7 +959,8 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res
 
     ClientCB *cbNode = GetClientCB(responseInfo->info.token,
             responseInfo->info.tokenLength, NULL, NULL);
-    OC_LOG_V(DEBUG, TAG, "Response has the token %s", responseInfo->info.token);
+    OC_LOG(DEBUG, TAG, PCF("Response has the token:"));
+    OC_LOG_BUFFER(DEBUG, TAG, (const uint8_t*)responseInfo->info.token, responseInfo->info.tokenLength);
     ResourceObserver * observer = GetObserverUsingToken (responseInfo->info.token,
             responseInfo->info.tokenLength);
 
@@ -1127,7 +1005,15 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res
             response.resourceUri = responseInfo->info.resourceUri;
 
             response.result = CAToOCStackResult(responseInfo->result);
-            response.resJSONPayload = (const char*)responseInfo->info.payload;
+            if(responseInfo->info.payload &&
+               responseInfo->info.payloadSize &&
+               OC_STACK_OK != OCParsePayload(&response.payload, responseInfo->info.payload,
+                                           responseInfo->info.payloadSize))
+            {
+                OC_LOG(ERROR, TAG, PCF("Error converting payload"));
+                return;
+            }
+
             response.numRcvdVendorSpecificHeaderOptions = 0;
             if(responseInfo->info.numOptions > 0)
             {
@@ -1182,6 +1068,7 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res
                     cbNode->TTL = GetTicks(MAX_CB_TIMEOUT_SECONDS *
                                             MILLISECONDS_PER_SECOND);
                 }
+                OCPayloadDestroy(response.payload);
             }
 
             //Need to send ACK when the response is CON
@@ -1257,7 +1144,6 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res
         return;
     }
 
-    OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
     OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
 }
 
@@ -1385,15 +1271,13 @@ void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque
     //copy request payload
     if (requestInfo->info.payload)
     {
-        size_t payloadLen = strlen(requestInfo->info.payload);
-        serverRequest.reqTotalSize = payloadLen + 1;
-        OICStrcpy(serverRequest.reqJSONPayload, sizeof(serverRequest.reqJSONPayload),
-                requestInfo->info.payload);
+        serverRequest.reqTotalSize = requestInfo->info.payloadSize;
+        memcpy (&(serverRequest.payload), requestInfo->info.payload,
+                requestInfo->info.payloadSize);
     }
     else
     {
-        serverRequest.reqTotalSize = 1;
-        serverRequest.reqJSONPayload[0] = '\0';
+        serverRequest.reqTotalSize = 0;
     }
 
     switch (requestInfo->method)
@@ -1522,7 +1406,7 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
                 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
                 protocolRequest->observationOption, protocolRequest->qos,
                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
-                protocolRequest->reqJSONPayload, protocolRequest->requestToken,
+                protocolRequest->payload, protocolRequest->requestToken,
                 protocolRequest->tokenLength,
                 protocolRequest->resourceUrl, protocolRequest->reqTotalSize,
                 &protocolRequest->devAddr);
@@ -1727,6 +1611,7 @@ OCStackResult OCStop()
     // Free memory dynamically allocated for resources
     deleteAllResources();
     DeleteDeviceInfo();
+    DeletePlatformInfo();
     CATerminate();
     // Remove all observers
     DeleteObserverList();
@@ -1737,6 +1622,7 @@ OCStackResult OCStop()
     // TODO after BeachHead delivery: consolidate into single SRMDeInit()
     SRMDeInitPolicyEngine();
 
+
     stackState = OC_STACK_UNINITIALIZED;
     return OC_STACK_OK;
 }
@@ -1974,7 +1860,7 @@ OCStackResult OCDoResource(OCDoHandle *handle,
                             OCMethod method,
                             const char *requestUri,
                             const OCDevAddr *destination,
-                            const char *request,
+                            OCPayload* payload,
                             OCConnectivityType connectivityType,
                             OCQualityOfService qos,
                             OCCallbackData *cbData,
@@ -2016,12 +1902,6 @@ OCStackResult OCDoResource(OCDoHandle *handle,
         goto exit;
     }
 
-    if ((request) && (strlen(request) > MAX_REQUEST_LENGTH))
-    {
-        result = OC_STACK_INVALID_PARAM;
-        goto exit;
-    }
-
     /*
      * Support original behavior with address on resourceUri argument.
      */
@@ -2113,7 +1993,7 @@ OCStackResult OCDoResource(OCDoHandle *handle,
     requestInfo.info.token = token;
     requestInfo.info.tokenLength = tokenLength;
     requestInfo.info.resourceUri = resourceUri;
-    requestInfo.info.payload = (char *)request;
+
     if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
     {
         result = CreateObserveHeaderOption (&(requestInfo.info.options),
@@ -2133,6 +2013,24 @@ OCStackResult OCDoResource(OCDoHandle *handle,
 
     // create remote endpoint
     result = OCCreateEndpoint(devAddr, &endpoint);
+    if(payload)
+    {
+        if((result =
+            OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
+                != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, PCF("Failed to create CBOR Payload"));
+            goto exit;
+        }
+    }
+    else
+    {
+        requestInfo.info.payload = NULL;
+        requestInfo.info.payloadSize = 0;
+    }
+
+
+
     if (result != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
@@ -2195,6 +2093,9 @@ exit:
         }
         OICFree(resHandle);
     }
+
+    // This is the owner of the payload object, so we free it
+    OCPayloadDestroy(payload);
     OICFree(devAddr);
     OICFree(resourceUri);
     OICFree(resourceType);
@@ -2387,7 +2288,7 @@ OCStackResult OCProcessPresence()
             clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
             clientResponse.devAddr = *cbNode->devAddr;
             FixUpClientResponse(&clientResponse);
-            clientResponse.resJSONPayload = NULL;
+            clientResponse.payload = NULL;
 
             // Increment the TTLLevel (going to a next state), so we don't keep
             // sending presence notification to client.
@@ -3301,7 +3202,7 @@ OCStackResult
 OCNotifyListOfObservers (OCResourceHandle handle,
                          OCObservationId  *obsIdList,
                          uint8_t          numberOfIds,
-                         const char       *notificationJSONPayload,
+                         const OCRepPayload       *payload,
                          OCQualityOfService qos)
 {
     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
@@ -3312,7 +3213,7 @@ OCNotifyListOfObservers (OCResourceHandle handle,
 
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
-    VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
+    VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
 
     // Verify that the resource exists
     resPtr = findResource ((OCResource *) handle);
@@ -3325,7 +3226,7 @@ OCNotifyListOfObservers (OCResourceHandle handle,
         incrementSequenceNumber(resPtr);
     }
     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
-            notificationJSONPayload, maxAge, qos));
+            payload, maxAge, qos));
 }
 
 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
@@ -3339,35 +3240,14 @@ OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
     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(INFO, TAG, PCF("Block transfer required"));
-
-        // Persistent response buffer is needed for block transfer
-        if (!ehResponse->persistentBufferFlag)
-        {
-            OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
-            return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
-        }
-        // 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
+    // Normal response
+    // Get pointer to request info
+    serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+    if(serverRequest)
     {
-        // Normal response
-        // Get pointer to request info
-        serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
-        if(serverRequest)
-        {
-            result = serverRequest->ehResponseHandler(ehResponse);
-        }
+        result = serverRequest->ehResponseHandler(ehResponse);
     }
+
     return result;
 }
 
@@ -3769,32 +3649,6 @@ OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
     return pointer;
 }
 
-bool OCIsPacketTransferRequired(const char *request, const char *response, size_t size)
-{
-    bool result = false;
-
-    // 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 = true;
-        }
-    }
-    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 = true;
-        }
-    }
-    return result;
-}
-
 /*
  * This function splits the uri using the '?' delimiter.
  * "uriWithoutQuery" is the block of characters between the beginning
index 2e380fa..4068852 100755 (executable)
@@ -801,26 +801,29 @@ OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
     {
         int idx;
 
-        unsigned char *responseJson;
-        responseJson = (unsigned char *) OICMalloc(
-                (unsigned int) (strlen((char *) clientResponse->resJSONPayload)
-                        + 1));
+        unsigned char *responseJson = NULL;
+        // TODO: Figure out what this does, change implementation
+        //responseJson = (unsigned char *) OICMalloc(
+        //        (unsigned int) (strlen((char *) clientResponse->resJSONPayload)
+        //                + 1));
 
         if( responseJson == NULL )
             return OC_STACK_DELETE_TRANSACTION;
 
         // We need the body of response.
         // Copy the body from the response
-        strcpy((char *) responseJson,
-                ((char *) clientResponse->resJSONPayload + OC_JSON_PREFIX_LEN));
-        idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
+        // TODO: Taken out
+        //strcpy((char *) responseJson,
+        //        ((char *) clientResponse->resJSONPayload + OC_JSON_PREFIX_LEN));
+        //idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
         // And insert NULL at the end of body.
         (responseJson[idx]) = 0;
 
         OCEntityHandlerResponse response = { 0 };
         response.ehResult = OC_EH_OK;
-        response.payload = (char*)responseJson;
-        response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
+        // TODO: Removing payload size, waht goes here?
+        // response.payload = (char*)responseJson;
+        //response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
         response.persistentBufferFlag = 0;
         response.requestHandle = (OCRequestHandle) info->ehRequest;
         response.resourceHandle = (OCResourceHandle) info->collResource;
@@ -905,8 +908,10 @@ OCStackResult SendAction(OCDoHandle *handle, const char *targetUri,
     cbdata.cd = NULL;
     cbdata.context = (void*)DEFAULT_CONTEXT_VALUE;
 
-    return OCDoResource(handle, OC_REST_PUT, targetUri,
-            NULL, (char *) action, CT_ADAPTER_IP, OC_NA_QOS, &cbdata, NULL, 0);
+    // TODO: disabled since this is no longer compatible
+    return OC_STACK_NOTIMPL;
+    //return OCDoResource(handle, OC_REST_PUT, targetUri,
+    //        NULL, (char *) action, CT_ADAPTER_IP, OC_NA_QOS, &cbdata, NULL, 0);
 }
 
 OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
@@ -1049,8 +1054,10 @@ OCStackResult BuildCollectionGroupActionJSONResponse(
 
         char *jsonResponse;
 
-        stackRet = ExtractKeyValueFromRequest((char *) ehRequest->reqJSONPayload,
-                &doWhat, &details);
+        stackRet = OC_STACK_NOTIMPL;
+        // TODO: Fix?
+        //stackRet = ExtractKeyValueFromRequest((char *) ehRequest->reqJSONPayload,
+        //        &doWhat, &details);
 
         if(stackRet != OC_STACK_OK)
         {
@@ -1123,8 +1130,9 @@ OCStackResult BuildCollectionGroupActionJSONResponse(
                     response.ehResult = OC_EH_OK;
                 else
                     response.ehResult = OC_EH_ERROR;
-                response.payload = (char*)buffer;
-                response.payloadSize = bufferLength + 1;
+                // TODO: Fix
+                //response.payload = (char*)buffer;
+                //response.payloadSize = bufferLength + 1;
                 response.persistentBufferFlag = 0;
                 response.requestHandle =
                         (OCRequestHandle) ehRequest->requestHandle;
@@ -1290,8 +1298,9 @@ OCStackResult BuildCollectionGroupActionJSONResponse(
                     response.ehResult = OC_EH_OK;
                 else
                     response.ehResult = OC_EH_ERROR;
-                response.payload = (char *)buffer;
-                response.payloadSize = bufferLength + 1;
+                // TODO: Implement
+                //response.payload = (char *)buffer;
+                //response.payloadSize = bufferLength + 1;
                 response.persistentBufferFlag = 0;
                 response.requestHandle =
                         (OCRequestHandle) ehRequest->requestHandle;
index dff43c6..928ca8e 100644 (file)
@@ -1481,7 +1481,7 @@ TEST(StackResourceAccess, DeleteLastResource)
     uint8_t numExpectedResources = 0;
 
     EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
+
     OCResourceHandle handle0;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
                                             "core.led",
@@ -1586,97 +1586,6 @@ TEST(StackResourceAccess, DeleteMiddleResource)
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-    void parsePresencePayload(char* payload, uint32_t* seqNum,
-            uint32_t* maxAge, OCPresenceTrigger* presenceTrigger, char** resType);
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-TEST(StackPresence, ParsePresencePayload)
-{
-    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
-    OC_LOG(INFO, TAG, "Starting ParsePresencePayload test");
-
-    char payload[100];
-    uint32_t seqNum = 0, maxAge = 0;
-    OCPresenceTrigger presenceTrigger = OC_PRESENCE_TRIGGER_CHANGE;
-    char * resType = NULL;
-
-    //Good Scenario
-    strncpy(payload, "{\"oic\":[{\"ttl\":99,\"non\":100,\"trg\":"
-            "\"delete\",\"rt\":\"presence\"}]}", sizeof(payload));
-    parsePresencePayload(payload, &seqNum, &maxAge,
-            &presenceTrigger, &resType);
-    EXPECT_TRUE(100 == seqNum);
-    EXPECT_TRUE(99 == maxAge);
-    EXPECT_TRUE(OC_PRESENCE_TRIGGER_DELETE == presenceTrigger);
-    EXPECT_TRUE(NULL != resType);
-    EXPECT_STREQ("presence", resType);
-    OICFree(resType);
-
-    presenceTrigger = OC_PRESENCE_TRIGGER_CHANGE;
-
-    //Bad Scenario -- should not result in Seg Fault
-    parsePresencePayload(payload, NULL, &maxAge, &presenceTrigger, &resType);
-
-    //Bad Scenario
-    seqNum = 0; maxAge = 0; resType = NULL;
-    strncpy(payload, "{abracadabra}", sizeof(payload));
-    parsePresencePayload(payload, &seqNum, &maxAge, &presenceTrigger, &resType);
-    EXPECT_TRUE(0 == seqNum);
-    EXPECT_TRUE(0 == maxAge);
-    EXPECT_TRUE(OC_PRESENCE_TRIGGER_CHANGE == presenceTrigger);
-    EXPECT_TRUE(NULL == resType);
-    EXPECT_EQ(NULL, resType);
-    OICFree(resType);
-
-    //Bad Scenario
-    seqNum = 0; maxAge = 0; resType = NULL;
-    strncpy(payload, "{\"oic\":[100]}", sizeof(payload));
-    parsePresencePayload(payload, &seqNum, &maxAge, &presenceTrigger, &resType);
-    EXPECT_TRUE(0 == seqNum);
-    EXPECT_TRUE(0 == maxAge);
-    EXPECT_TRUE(OC_PRESENCE_TRIGGER_CHANGE == presenceTrigger);
-    EXPECT_TRUE(NULL == resType);
-    EXPECT_EQ(NULL, resType);
-    OICFree(resType);
-
-    //Bad Scenario
-    seqNum = 0; maxAge = 0; resType = NULL;
-    strncpy(payload, "{\"oic\":[]}", sizeof(payload));
-    parsePresencePayload(payload, &seqNum, &maxAge, &presenceTrigger, &resType);
-    EXPECT_TRUE(0 == seqNum);
-    EXPECT_TRUE(0 == maxAge);
-    EXPECT_TRUE(OC_PRESENCE_TRIGGER_CHANGE == presenceTrigger);
-    EXPECT_TRUE(NULL == resType);
-    EXPECT_EQ(NULL, resType);
-    OICFree(resType);
-
-    //Bad Scenario
-    strncpy(payload, "{:]}", sizeof(payload));
-    parsePresencePayload(payload, &seqNum, &maxAge, &presenceTrigger, &resType);
-    EXPECT_TRUE(0 == seqNum);
-    EXPECT_TRUE(0 == maxAge);
-    EXPECT_TRUE(OC_PRESENCE_TRIGGER_CHANGE == presenceTrigger);
-    EXPECT_TRUE(NULL == resType);
-    EXPECT_EQ(NULL, resType);
-    OICFree(resType);
-
-    //Bad Scenario
-    strncpy(payload, "{:[presence}", sizeof(payload));
-    parsePresencePayload(payload, &seqNum, &maxAge, &presenceTrigger, &resType);
-    EXPECT_TRUE(0 == seqNum);
-    EXPECT_TRUE(0 == maxAge);
-    EXPECT_TRUE(OC_PRESENCE_TRIGGER_CHANGE == presenceTrigger);
-    EXPECT_TRUE(NULL == resType);
-    EXPECT_EQ(NULL, resType);
-    OICFree(resType);
-}
-
 TEST(PODTests, OCHeaderOption)
 {
     EXPECT_TRUE(std::is_pod<OCHeaderOption>::value);
index ddcc86c..f6b7764 100644 (file)
@@ -149,7 +149,7 @@ namespace OC
     private:
         void listeningFunc();
         std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams);
-        std::string assembleSetResourcePayload(const OCRepresentation& attributes);
+        OCPayload* assembleSetResourcePayload(const OCRepresentation& attributes);
         OCHeaderOption* assembleHeaderOptions(OCHeaderOption options[],
            const HeaderOptions& headerOptions);
         std::thread m_listeningThread;
index 045f4df..d3431ba 100755 (executable)
@@ -21,6 +21,7 @@
 #ifndef __INTEL_OCAPI_H_2014_07_10
 #define __INTEL_OCAPI_H_2014_07_10
 
+
 #include <string>
 #include <sstream>
 #include <vector>
index 534bb5a..7856613 100644 (file)
 
 #include <OCException.h>
 
-namespace cereal
-{
-    class access;
-}
-
 namespace OC
 {
 
@@ -62,24 +57,18 @@ namespace OC
         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 setPayload(const OCPayload* rep);
+
+            void setPayload(const OCDevicePayload* rep);
 
-            void setJSONRepresentation(const char* payload);
+            void setPayload(const OCPlatformPayload* rep);
 
-            std::string getJSONRepresentation(OCInfoFormat f) const;
+            void setPayload(const OCRepPayload* rep);
+
+            OCRepPayload* getPayload() const;
 
             const std::vector<OCRepresentation>& representations() const;
 
@@ -119,7 +108,7 @@ namespace OC
 
             virtual ~OCRepresentation(){}
 
-            std::string getJSONRepresentation() const;
+            OCRepPayload* getPayload() const;
 
             void addChild(const OCRepresentation&);
 
@@ -137,10 +126,14 @@ namespace OC
 
             void setResourceTypes(const std::vector<std::string>& resourceTypes);
 
+            void addResourceType(const std::string& str);
+
             const std::vector<std::string>& getResourceInterfaces() const;
 
             void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces);
 
+            void addResourceInterface(const std::string& str);
+
             bool emptyData() const;
 
             int numberOfAttributes() const;
@@ -389,8 +382,16 @@ namespace OC
             const AttributeItem operator[](const std::string& key) const;
         private:
             friend class OCResourceResponse;
-            friend class cereal::access;
-
+            friend class MessageContainer;
+
+            template<typename T>
+            void payload_array_helper(const OCRepPayloadValue* pl, size_t depth);
+            template<typename T>
+            T payload_array_helper_copy(size_t index, const OCRepPayloadValue* pl);
+            void setPayload(const OCRepPayload* payload);
+            void setPayloadArray(const OCRepPayloadValue* pl);
+            void getPayloadArray(OCRepPayload* payload,
+                    const OCRepresentation::AttributeItem& item) const;
             // 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
@@ -415,25 +416,9 @@ namespace OC
                     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;
index f4b8f84..962ddb2 100644 (file)
@@ -174,7 +174,7 @@ namespace OC
             m_requestType = requestType;
         }
 
-        void setPayload(const std::string& requestPayload);
+        void setPayload(OCPayload* requestPayload);
 
         void setQueryParams(QueryParamsMap& queryParams)
         {
index c654834..ea863ac 100644 (file)
@@ -174,7 +174,7 @@ namespace OC
     private:
         friend class InProcServerWrapper;
 
-        std::string getPayload() const
+        OCRepPayload* getPayload() const
         {
             MessageContainer inf;
             OCRepresentation first(m_representation);
@@ -215,7 +215,7 @@ namespace OC
 
             }
 
-            return inf.getJSONRepresentation(OCInfoFormat::ExcludeOC);
+            return inf.getPayload();
         }
     public:
 
index 3668116..41cea2c 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#include <cereal/cereal.hpp>
-#include <cereal/types/memory.hpp>
-#include <cereal/types/vector.hpp>
-#include <cereal/archives/json.hpp>
-
 #include <StringConstants.h>
+#include "ocpayload.h"
+#include "ocrandom.h"
 
 namespace OC
 {
     class ListenOCContainer
     {
         private:
+            static std::vector<std::string> StringLLToVector(OCStringLL* ll)
+            {
+                std::vector<std::string> strs;
+                while(ll)
+                {
+                    strs.push_back(ll->value);
+                    ll = ll->next;
+                }
+                return strs;
+            }
+
+        public:
+            ListenOCContainer(std::weak_ptr<IClientWrapper> cw,
+                    const OCDevAddr& devAddr, OCDiscoveryPayload* payload)
+                    : m_clientWrapper(cw), m_devAddr(devAddr)
+            {
+                OCResourcePayload* res = payload->resources;
+
+                while(res)
+                {
+                    char uuidString[UUID_STRING_SIZE];
+                    if(OCConvertUuidToString(res->sid, uuidString) != RAND_UUID_OK)
+                    {
+                        uuidString[0]= '\0';
+                    }
+
+                    m_resources.push_back(std::shared_ptr<OC::OCResource>(
+                                new OC::OCResource(m_clientWrapper, m_devAddr,
+                                    std::string(res->uri),
+                                    std::string(uuidString),
+                                    (res->bitmap & OC_OBSERVABLE) == OC_OBSERVABLE,
+                                    StringLLToVector(res->types),
+                                    StringLLToVector(res->interfaces)
+                                    )));
+                    res = res->next;
+                }
+
+            }
+
+            const std::vector<std::shared_ptr<OCResource>>& Resources() const
+            {
+                return m_resources;
+            }
+        private:
+            std::vector<std::shared_ptr<OC::OCResource>> m_resources;
+            std::weak_ptr<IClientWrapper> m_clientWrapper;
+            const OCDevAddr& m_devAddr;
+    };
+    /*
+    class ListenOCContainer
+    {
+        private:
         enum class OCSecureType
         {
             NotSecure,
@@ -276,8 +325,6 @@ namespace OC
                     }
                 }
             }
-            std::vector<std::shared_ptr<OC::OCResource>> m_resources;
-            std::weak_ptr<IClientWrapper> m_clientWrapper;
-            const OCDevAddr& m_devAddr;
     };
+*/
 }
diff --git a/resource/include/OicJsonSerializer.hpp b/resource/include/OicJsonSerializer.hpp
deleted file mode 100644 (file)
index 280ac28..0000000
+++ /dev/null
@@ -1,847 +0,0 @@
-/*! \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 serialized 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_
diff --git a/resource/patches/cereal_gcc46.patch b/resource/patches/cereal_gcc46.patch
deleted file mode 100644 (file)
index c4da84f..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-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
-
index 737be63..f4b48fd 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "OCPlatform.h"
 #include "OCResource.h"
+#include "ocpayload.h"
 #include <OCSerialization.h>
 using namespace std;
 
@@ -98,28 +99,21 @@ namespace OC
 
     OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
     {
-        if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0')
-        {
+        if(clientResponse->payload == nullptr ||
+                (
+                    clientResponse->payload->type != PAYLOAD_TYPE_DEVICE &&
+                    clientResponse->payload->type != PAYLOAD_TYPE_PLATFORM &&
+                    clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION
+                )
+          )
+        {
+            //OCPayloadDestroy(clientResponse->payload);
             return OCRepresentation();
         }
 
         MessageContainer oc;
-        try
-        {
-            oc.setJSONRepresentation(clientResponse->resJSONPayload);
-        }
-        catch (cereal::RapidJSONException& ex)
-        {
-            oclog() <<"RapidJSON Exception in parseGetSetCallback: "<<ex.what() <<std::endl<<
-                "Data was:"<< clientResponse->resJSONPayload<< ":" << std::flush;
-            throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_INVALID_JSON);
-        }
-        catch (cereal::Exception& ex)
-        {
-            oclog() <<"Cereal Exception in parseGetSetCallback: "<<ex.what() <<std::endl<<
-                "Data was:"<< clientResponse->resJSONPayload<< ":" << std::flush;
-            throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_INVALID_JSON);
-        }
+        oc.setPayload(clientResponse->payload);
+        //OCPayloadDestroy(clientResponse->payload);
 
         std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
         if(it == oc.representations().end())
@@ -153,6 +147,13 @@ namespace OC
             return OC_STACK_KEEP_TRANSACTION;
         }
 
+        if(!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
+        {
+            oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
+                << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
         auto clientWrapper = context->clientWrapper.lock();
 
         if(!clientWrapper)
@@ -162,34 +163,16 @@ namespace OC
             return OC_STACK_KEEP_TRANSACTION;
         }
 
-        std::stringstream requestStream;
-        requestStream << clientResponse->resJSONPayload;
-
-        try
-        {
-
-            ListenOCContainer container(clientWrapper, clientResponse->devAddr,
-                                    requestStream);
-            // loop to ensure valid construction of all resources
-            for(auto resource : container.Resources())
-            {
-                std::thread exec(context->callback, resource);
-                exec.detach();
-            }
-
-        }
-        catch(const std::exception& e)
+        ListenOCContainer container(clientWrapper, clientResponse->devAddr,
+                                reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
+        // loop to ensure valid construction of all resources
+        for(auto resource : container.Resources())
         {
-            oclog() << "listenCallback failed to parse a malformed message: "
-                    << e.what()
-                    << std::endl
-                    << clientResponse->resJSONPayload
-                    << std::endl
-                    << clientResponse->result
-                    << std::flush;
-            return OC_STACK_KEEP_TRANSACTION;
+            std::thread exec(context->callback, resource);
+            exec.detach();
         }
 
+
         return OC_STACK_KEEP_TRANSACTION;
     }
 
@@ -452,11 +435,11 @@ namespace OC
         return ret;
     }
 
-    std::string InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
+    OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
     {
         MessageContainer ocInfo;
         ocInfo.addRepresentation(rep);
-        return ocInfo.getJSONRepresentation(OCInfoFormat::IncludeOC);
+        return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
     }
 
     OCStackResult InProcClientWrapper::PostResourceRepresentation(
@@ -489,7 +472,7 @@ namespace OC
 
             result = OCDoResource(nullptr, OC_REST_POST,
                                   url.c_str(), &devAddr,
-                                  assembleSetResourcePayload(rep).c_str(),
+                                  assembleSetResourcePayload(rep),
                                   CT_DEFAULT,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
@@ -536,7 +519,7 @@ namespace OC
 
             result = OCDoResource(&handle, OC_REST_PUT,
                                   url.c_str(), &devAddr,
-                                  assembleSetResourcePayload(rep).c_str(),
+                                  assembleSetResourcePayload(rep),
                                   CT_DEFAULT,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
index 7731952..e37022b 100644 (file)
@@ -104,14 +104,12 @@ void formResourceRequest(OCEntityHandlerFlag flag,
             else if(OC_REST_PUT == entityHandlerRequest->method)
             {
                 pRequest->setRequestType(OC::PlatformCommands::PUT);
-                pRequest->setPayload(std::string(reinterpret_cast<const char*>
-                                            (entityHandlerRequest->reqJSONPayload)));
+                pRequest->setPayload(entityHandlerRequest->payload);
             }
             else if(OC_REST_POST == entityHandlerRequest->method)
             {
                 pRequest->setRequestType(OC::PlatformCommands::POST);
-                pRequest->setPayload(std::string(reinterpret_cast<const char*>
-                                            (entityHandlerRequest->reqJSONPayload)));
+                pRequest->setPayload(entityHandlerRequest->payload);
             }
             else if(OC_REST_DELETE == entityHandlerRequest->method)
             {
@@ -532,23 +530,15 @@ namespace OC
         else
         {
             OCEntityHandlerResponse response;
-            std::string payLoad = pResponse->getPayload();
+//            OCRepPayload* payLoad = pResponse->getPayload();
             HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
 
             response.requestHandle = pResponse->getRequestHandle();
             response.resourceHandle = pResponse->getResourceHandle();
             response.ehResult = pResponse->getResponseResult();
 
-            response.payload = static_cast<char*>(OICMalloc(payLoad.length() + 1));
-            if(!response.payload)
-            {
-                result = OC_STACK_NO_MEMORY;
-                throw OCException(OC::Exception::NO_MEMORY, OC_STACK_NO_MEMORY);
-            }
+            response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
 
-            payLoad.copy(response.payload, payLoad.length());
-            response.payload[payLoad.length()] = '\0';
-            response.payloadSize = payLoad.length() + 1;
             response.persistentBufferFlag = 0;
 
             response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
index db816de..04d2673 100644 (file)
@@ -42,6 +42,7 @@
 #include "OCApi.h"
 #include "OCException.h"
 #include "OCUtilities.h"
+#include "ocpayload.h"
 
 #include "oc_logger.hpp"
 
@@ -131,13 +132,14 @@ namespace OC
          return result_guard(OC_STACK_ERROR);
         }
 
-        std::string payload(pResponse->getResourceRepresentation().getJSONRepresentation());
-
-        return result_guard(
+        OCRepPayload* pl = pResponse->getResourceRepresentation().getPayload();
+        OCStackResult result =
                    OCNotifyListOfObservers(resourceHandle,
                             &observationIds[0], observationIds.size(),
-                            payload.c_str(),
-                            static_cast<OCQualityOfService>(QoS)));
+                            pl,
+                            static_cast<OCQualityOfService>(QoS));
+        OCRepPayloadDestroy(pl);
+        return result_guard(result);
     }
 
     OCResource::Ptr OCPlatform_impl::constructResourceObject(const std::string& host,
index 494f9aa..d439bbe 100644 (file)
 #include <OCRepresentation.h>
 
 #include <boost/lexical_cast.hpp>
-#include <cereal/cereal.hpp>
-#include <cereal/types/map.hpp>
-#include <cereal/types/vector.hpp>
-#include <cereal/types/utility.hpp>
-#include <OicJsonSerializer.hpp>
 #include <algorithm>
+#include "ocpayload.h"
+#include "ocrandom.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
 
-// code needed to serialize a string=>Attribute value map
 namespace OC
 {
-    namespace detail
+
+    void MessageContainer::setPayload(const OCPayload* rep)
     {
-        template<class Archive>
-        class WriteAttributeValue : public boost::static_visitor<>
+        switch(rep->type)
         {
-            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;
-        };
+            case PAYLOAD_TYPE_REPRESENTATION:
+                setPayload(reinterpret_cast<const OCRepPayload*>(rep));
+                break;
+            case PAYLOAD_TYPE_DEVICE:
+                setPayload(reinterpret_cast<const OCDevicePayload*>(rep));
+                break;
+            case PAYLOAD_TYPE_PLATFORM:
+                setPayload(reinterpret_cast<const OCPlatformPayload*>(rep));
+                break;
+            default:
+                throw OC::OCException("Invalid Payload type in setPayload");
+                break;
+        }
     }
-}
-
-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)
+    void MessageContainer::setPayload(const OCDevicePayload* payload)
     {
-        for(const auto& kv : vals)
+        OCRepresentation rep;
+        rep.setUri(payload->uri);
+        char uuidString[UUID_STRING_SIZE];
+        if(payload->sid && RAND_UUID_OK == OCConvertUuidToString(payload->sid, uuidString))
         {
-            const auto& k = kv.first;
-            const auto& v = kv.second;
+            rep[OC_RSRVD_DEVICE_ID] = std::string(uuidString);
+        }
+        else
+        {
+            rep[OC_RSRVD_DEVICE_ID] = std::string();
+        }
+        rep[OC_RSRVD_DEVICE_NAME] = payload->deviceName ?
+            std::string(payload->deviceName) :
+            std::string();
+        rep[OC_RSRVD_SPEC_VERSION] = payload->specVersion ?
+            std::string(payload->specVersion) :
+            std::string();
+        rep[OC_RSRVD_DATA_MODEL_VERSION] = payload->dataModelVersion ?
+            std::string(payload->dataModelVersion) :
+            std::string();
+        m_reps.push_back(std::move(rep));
+    }
+
+    void MessageContainer::setPayload(const OCPlatformPayload* payload)
+    {
+        OCRepresentation rep;
+        rep.setUri(payload->uri);
+
+        rep[OC_RSRVD_PLATFORM_ID] = payload->info.platformID ?
+            std::string(payload->info.platformID) :
+            std::string();
+        rep[OC_RSRVD_MFG_NAME] = payload->info.manufacturerName ?
+            std::string(payload->info.manufacturerName) :
+            std::string();
+        rep[OC_RSRVD_MFG_URL] = payload->info.manufacturerUrl ?
+            std::string(payload->info.manufacturerUrl) :
+            std::string();
+        rep[OC_RSRVD_MODEL_NUM] = payload->info.modelNumber ?
+            std::string(payload->info.modelNumber) :
+            std::string();
+        rep[OC_RSRVD_MFG_DATE] = payload->info.dateOfManufacture ?
+            std::string(payload->info.dateOfManufacture) :
+            std::string();
+        rep[OC_RSRVD_PLATFORM_VERSION] = payload->info.platformVersion ?
+            std::string(payload->info.platformVersion) :
+            std::string();
+        rep[OC_RSRVD_OS_VERSION] = payload->info.operatingSystemVersion ?
+            std::string(payload->info.operatingSystemVersion) :
+            std::string();
+        rep[OC_RSRVD_HARDWARE_VERSION] = payload->info.hardwareVersion ?
+            std::string(payload->info.hardwareVersion) :
+            std::string();
+        rep[OC_RSRVD_FIRMWARE_VERSION] = payload->info.firmwareVersion ?
+            std::string(payload->info.firmwareVersion) :
+            std::string();
+        rep[OC_RSRVD_SUPPORT_URL] = payload->info.supportUrl ?
+            std::string(payload->info.supportUrl) :
+            std::string();
+        rep[OC_RSRVD_SYSTEM_TIME] = payload->info.systemTime ?
+            std::string(payload->info.systemTime) :
+            std::string();
+
+        m_reps.push_back(std::move(rep));
+    }
+
+    void MessageContainer::setPayload(const OCRepPayload* payload)
+    {
+        const OCRepPayload* pl = payload;
+        while(pl)
+        {
+            OCRepresentation cur;
+            cur.setPayload(pl);
+
+            pl = pl->next;
+            this->addRepresentation(cur);
+        }
+    }
 
-            if(v.which() != OC::AttributeValueNullIndex)
+    OCRepPayload* MessageContainer::getPayload() const
+    {
+        OCRepPayload* root = nullptr;
+        for(const auto& r : representations())
+        {
+            if(!root)
             {
-                OC::detail::WriteAttributeValue<Archive> writer(k,ar);
-                boost::apply_visitor(writer, v);
+                root = r.getPayload();
             }
             else
             {
-                ar.setNextName(k.c_str());
-                ar.writeName();
-                ar.saveValue();
+                OCRepPayloadAppend(root, r.getPayload());
             }
         }
+
+        return root;
     }
 
-    template<class Archive>
-    void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
+    const std::vector<OCRepresentation>& MessageContainer::representations() const
     {
-        ar.loadAttributeValues(vals);
+        return m_reps;
+    }
+
+    void MessageContainer::addRepresentation(const OCRepresentation& rep)
+    {
+        m_reps.push_back(rep);
     }
 }
 
 namespace OC
 {
-    typedef cereal::JSONOutputArchive OutputArchiveType;
-    typedef cereal::JSONInputArchive InputArchiveType;
+    struct get_payload_array: boost::static_visitor<>
+    {
+        template<typename T>
+        void operator()(T& arr)
+        {
+            throw std::logic_error("Invalid calc_dimensions_visitor type");
+        }
+
+        template<typename T>
+        void operator()(std::vector<T>& arr)
+        {
+            root_size_calc<T>();
+            dimensions[0] = arr.size();
+            dimTotal = calcDimTotal(dimensions);
+
+            array = (void*)OICMalloc(dimTotal * root_size);
+
+            for(size_t i = 0; i < dimensions[0]; ++i)
+            {
+                copy_to_array(arr[i], array, i);
+            }
+
+        }
+        template<typename T>
+        void operator()(std::vector<std::vector<T>>& arr)
+        {
+            root_size_calc<T>();
+            dimensions[0] = arr.size();
+            for(size_t i = 0; i < arr.size(); ++i)
+            {
+                dimensions[1] = std::max(dimensions[1], arr[i].size());
+            }
+            dimTotal = calcDimTotal(dimensions);
+            array = (void*)OICCalloc(1, dimTotal * root_size);
+
+            for(size_t i = 0; i < dimensions[0]; ++i)
+            {
+                for(size_t j = 0; j < dimensions[1] && j < arr[i].size(); ++j)
+                {
+                    copy_to_array(arr[i][j], array, i*dimensions[1] + j);
+                }
+            }
+        }
+        template<typename T>
+        void operator()(std::vector<std::vector<std::vector<T>>>& arr)
+        {
+            root_size_calc<T>();
+            dimensions[0] = arr.size();
+            for(size_t i = 0; i < arr.size(); ++i)
+            {
+                dimensions[1] = std::max(dimensions[1], arr[i].size());
+
+                for(size_t j = 0; j < arr[i].size(); ++j)
+                {
+                    dimensions[2] = std::max(dimensions[2], arr[i][j].size());
+                }
+            }
+
+            dimTotal = calcDimTotal(dimensions);
+            array = (void*)OICCalloc(1, dimTotal * root_size);
+
+            for(size_t i = 0; i < dimensions[0]; ++i)
+            {
+                for(size_t j = 0; j < dimensions[1] && j < arr[i].size(); ++j)
+                {
+                    for(size_t k = 0; k < dimensions[2] && k < arr[i][j].size(); ++k)
+                    {
+                        copy_to_array(arr[i][j][k], array,
+                                dimensions[2] * j +
+                                dimensions[2] * dimensions[1] * i +
+                                k);
+                    }
+                }
+            }
+        }
+
+        template<typename T>
+        void root_size_calc()
+        {
+            root_size = sizeof(T);
+        }
+
+        template<typename T>
+        void copy_to_array(T item, void* array, size_t pos)
+        {
+            ((T*)array)[pos] = item;
+        }
+
+        size_t dimensions[MAX_REP_ARRAY_DEPTH];
+        size_t root_size;
+        size_t dimTotal;
+        void* array;
+    };
+
+    template<>
+    void get_payload_array::root_size_calc<int>()
+    {
+        root_size = sizeof(int64_t);
+    }
+
+    template<>
+    void get_payload_array::root_size_calc<std::string>()
+    {
+        root_size = sizeof(char*);
+    }
+
+    template<>
+    void get_payload_array::root_size_calc<OC::OCRepresentation>()
+    {
+        root_size = sizeof(OCRepPayload*);
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(int item, void* array, size_t pos)
+    {
+        ((int64_t*)array)[pos] = item;
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(std::_Bit_reference br, void* array, size_t pos)
+    {
+        ((bool*)array)[pos] = static_cast<bool>(br);
+    }
 
-    void MessageContainer::setJSONRepresentation(const std::string& payload)
+    template<>
+    void get_payload_array::copy_to_array(const std::string& item, void* array, size_t pos)
+    {
+        ((char**)array)[pos] = OICStrdup(item.c_str());
+    }
+
+    template<>
+    void get_payload_array::copy_to_array(OC::OCRepresentation item, void* array, size_t pos)
+    {
+        ((OCRepPayload**)array)[pos] = item.getPayload();
+    }
+
+    void OCRepresentation::getPayloadArray(OCRepPayload* payload,
+                    const OCRepresentation::AttributeItem& item) const
     {
-        std::stringstream os(payload);
+        get_payload_array vis{};
+        boost::apply_visitor(vis, m_values[item.attrname()]);
+
+
+        switch(item.base_type())
         {
-            InputArchiveType archive(os);
-            archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+            case AttributeType::Integer:
+                OCRepPayloadSetIntArrayAsOwner(payload, item.attrname().c_str(),
+                        (int64_t*)vis.array,
+                        vis.dimensions);
+                break;
+            case AttributeType::Double:
+                OCRepPayloadSetDoubleArrayAsOwner(payload, item.attrname().c_str(),
+                        (double*)vis.array,
+                        vis.dimensions);
+                break;
+            case AttributeType::Boolean:
+                OCRepPayloadSetBoolArrayAsOwner(payload, item.attrname().c_str(),
+                        (bool*)vis.array,
+                        vis.dimensions);
+                break;
+            case AttributeType::String:
+                OCRepPayloadSetStringArrayAsOwner(payload, item.attrname().c_str(),
+                        (char**)vis.array,
+                        vis.dimensions);
+                break;
+            case AttributeType::OCRepresentation:
+                OCRepPayloadSetPropObjectArrayAsOwner(payload, item.attrname().c_str(),
+                        (OCRepPayload**)vis.array, vis.dimensions);
+                break;
+            default:
+                throw std::logic_error(std::string("GetPayloadArray: Not Implemented") +
+                        std::to_string((int)item.base_type()));
         }
     }
 
-    void MessageContainer::setJSONRepresentation(const char* payload)
+    OCRepPayload* OCRepresentation::getPayload() const
     {
-        setJSONRepresentation(std::string(payload));
+        OCRepPayload* root = OCRepPayloadCreate();
+        if(!root)
+        {
+            throw std::bad_alloc();
+        }
+
+        OCRepPayloadSetUri(root, getUri().c_str());
+
+        for(const std::string& type : getResourceTypes())
+        {
+            OCRepPayloadAddResourceType(root, type.c_str());
+        }
+
+        for(const std::string& iface : getResourceInterfaces())
+        {
+            OCRepPayloadAddInterface(root, iface.c_str());
+        }
+
+        for(auto& val : *this)
+        {
+            switch(val.type())
+            {
+                case AttributeType::Null:
+                    OCRepPayloadSetNull(root, val.attrname().c_str());
+                    break;
+                case AttributeType::Integer:
+                    OCRepPayloadSetPropInt(root, val.attrname().c_str(), static_cast<int>(val));
+                    break;
+                case AttributeType::Double:
+                    OCRepPayloadSetPropDouble(root, val.attrname().c_str(), val);
+                    break;
+                case AttributeType::Boolean:
+                    OCRepPayloadSetPropBool(root, val.attrname().c_str(), val);
+                    break;
+                case AttributeType::String:
+                    OCRepPayloadSetPropString(root, val.attrname().c_str(),
+                            static_cast<std::string>(val).c_str());
+                    break;
+                case AttributeType::OCRepresentation:
+                    OCRepPayloadSetPropObjectAsOwner(root, val.attrname().c_str(),
+                            static_cast<OCRepresentation>(val).getPayload());
+                    break;
+                case AttributeType::Vector:
+                    getPayloadArray(root, val);
+                    break;
+                default:
+                    throw std::logic_error(std::string("Getpayload: Not Implemented") +
+                            std::to_string((int)val.type()));
+                    break;
+            }
+        }
+
+        OCRepPayload* cur = root;
+        for(auto& child : this->getChildren())
+        {
+            cur->next = child.getPayload();
+            cur = cur->next;
+        }
+
+        return root;
     }
 
-    std::string MessageContainer::getJSONRepresentation(OCInfoFormat f) const
+    size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
     {
-        std::stringstream os;
+        if(dimensions[0] == 0)
+        {
+            throw std::logic_error("invalid calcArrayDepth");
+        }
+        else if(dimensions[1] == 0)
+        {
+            return 1;
+        }
+        else if (dimensions[2] == 0)
+        {
+            return 2;
+        }
+        else
+        {
+            return 3;
+        }
+    }
+
+    template<typename T>
+    T OCRepresentation::payload_array_helper_copy(size_t index, const OCRepPayloadValue* pl)
+    {
+        throw std::logic_error("payload_array_helper_copy: unsupported type");
+    }
+    template<>
+    int OCRepresentation::payload_array_helper_copy<int>(size_t index, const OCRepPayloadValue* pl)
+    {
+        return pl->arr.iArray[index];
+    }
+    template<>
+    double OCRepresentation::payload_array_helper_copy<double>(size_t index, const OCRepPayloadValue* pl)
+    {
+        return pl->arr.dArray[index];
+    }
+    template<>
+    bool OCRepresentation::payload_array_helper_copy<bool>(size_t index, const OCRepPayloadValue* pl)
+    {
+        return pl->arr.bArray[index];
+    }
+    template<>
+    std::string OCRepresentation::payload_array_helper_copy<std::string>(
+            size_t index, const OCRepPayloadValue* pl)
+    {
+        return std::string(pl->arr.strArray[index]);
+    }
+    template<>
+    OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
+            size_t index, const OCRepPayloadValue* pl)
+    {
+        OCRepresentation r;
+        r.setPayload(pl->arr.objArray[index]);
+        return r;
+    }
 
-        // note: the block is required because cereal closes the JSON string
-        // upon destruction, so the archive needs to be destroyed before accessing
-        // the data
+    template<typename T>
+    void OCRepresentation::payload_array_helper(const OCRepPayloadValue* pl, size_t depth)
+    {
+        if(depth == 1)
         {
-            if(f == OCInfoFormat::IncludeOC)
+            std::vector<T> val(pl->arr.dimensions[0]);
+
+            for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
             {
-                OutputArchiveType archive(os);
-                archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+                val[i] = payload_array_helper_copy<T>(i, pl);
             }
-            else if(f== OCInfoFormat::ExcludeOC)
+            this->setValue(std::string(pl->name), val);
+        }
+        else if (depth == 2)
+        {
+            std::vector<std::vector<T>> val(pl->arr.dimensions[0]);
+            for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
             {
-                bool firstPrinted = false;
-                for(std::vector<OCRepresentation>::size_type i = 0; i< m_reps.size();++i)
+                val[i].reserve(pl->arr.dimensions[1]);
+                for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
                 {
-                    if(!m_reps[i].emptyData())
+                    val[i][j] = payload_array_helper_copy<T>(
+                            i * pl->arr.dimensions[1] + j, pl);
+                }
+            }
+            this->setValue(std::string(pl->name), val);
+        }
+        else if (depth == 3)
+        {
+            std::vector<std::vector<std::vector<T>>> val;
+            for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
+            {
+                val[i].reserve(pl->arr.dimensions[1]);
+                for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
+                {
+                    val[i][j].reserve(pl->arr.dimensions[2]);
+                    for(size_t k = 0; k < pl->arr.dimensions[2]; ++k)
                     {
-                        if(firstPrinted)
-                        {
-                            os<<',';
-                        }
-                        firstPrinted=true;
-                        os << m_reps[i].getJSONRepresentation();
+                        val[i][j][k] = payload_array_helper_copy<T>(
+                                pl->arr.dimensions[2] * j +
+                                pl->arr.dimensions[2] * pl->arr.dimensions[1] * i +
+                                k,
+                                pl);
                     }
                 }
             }
+            this->setValue(std::string(pl->name), val);
+        }
+        else
+        {
+            throw std::logic_error("Invalid depth in payload_array_helper");
         }
-        return os.str();
     }
 
-    const std::vector<OCRepresentation>& MessageContainer::representations() const
+    void OCRepresentation::setPayloadArray(const OCRepPayloadValue* pl)
     {
-        return m_reps;
-    }
 
-    void MessageContainer::addRepresentation(const OCRepresentation& rep)
-    {
-        m_reps.push_back(rep);
+        switch(pl->arr.type)
+        {
+            case OCREP_PROP_INT:
+                payload_array_helper<int>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
+            case OCREP_PROP_DOUBLE:
+                payload_array_helper<double>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
+            case OCREP_PROP_BOOL:
+                payload_array_helper<bool>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
+            case OCREP_PROP_STRING:
+                payload_array_helper<std::string>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
+            case OCREP_PROP_OBJECT:
+                payload_array_helper<OCRepresentation>(pl, calcArrayDepth(pl->arr.dimensions));
+                break;
+            default:
+                throw std::logic_error("setPayload array invalid type");
+                break;
+        }
     }
-}
 
-namespace OC
-{
-    std::string OCRepresentation::getJSONRepresentation() const
+    void OCRepresentation::setPayload(const OCRepPayload* pl)
     {
-        if(emptyData())
+        setUri(pl->uri);
+
+        OCStringLL* ll = pl->types;
+        while(ll)
         {
-            return "{}";
+            addResourceType(ll->value);
+            ll = ll->next;
         }
 
-        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
+        ll = pl->interfaces;
+        while(ll)
         {
-            OutputArchiveType archive (os);
-            save(archive);
+            addResourceInterface(ll->value);
+            ll = ll->next;
         }
 
-        return os.str();
+        OCRepPayloadValue* val = pl->values;
+
+        while(val)
+        {
+            switch(val->type)
+            {
+                case OCREP_PROP_NULL:
+                    setNULL(val->name);
+                    break;
+                case OCREP_PROP_INT:
+                    setValue<int>(val->name, val->i);
+                    break;
+                case OCREP_PROP_DOUBLE:
+                    setValue<double>(val->name, val->d);
+                    break;
+                case OCREP_PROP_BOOL:
+                    setValue<bool>(val->name, val->b);
+                    break;
+                case OCREP_PROP_STRING:
+                    setValue<std::string>(val->name, val->str);
+                    break;
+                case OCREP_PROP_OBJECT:
+                    {
+                        OCRepresentation cur;
+                        cur.setPayload(val->obj);
+                        setValue<OCRepresentation>(val->name, cur);
+                    }
+                    break;
+                case OCREP_PROP_ARRAY:
+                    setPayloadArray(val);
+                    break;
+                default:
+                    throw std::logic_error(std::string("Not Implemented!") +
+                            std::to_string((int)val->type));
+                    break;
+            }
+            val = val->next;
+        }
     }
 
     void OCRepresentation::addChild(const OCRepresentation& rep)
@@ -223,11 +640,21 @@ namespace OC
         m_resourceTypes = resourceTypes;
     }
 
+    void OCRepresentation::addResourceType(const std::string& str)
+    {
+        m_resourceTypes.push_back(str);
+    }
+
     const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
     {
         return m_interfaces;
     }
 
+    void OCRepresentation::addResourceInterface(const std::string& str)
+    {
+        m_interfaces.push_back(str);
+    }
+
     void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
     {
         m_interfaces = resourceInterfaces;
@@ -305,355 +732,6 @@ namespace OC
 
 namespace OC
 {
-    template <class Archive, class Val>
-    void OCRepresentation::optional_load(Archive& ar, Val&& v)
-    {
-        try
-        {
-            ar(v);
-        }
-        catch(cereal::Exception&)
-        {
-            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::INTERFACESKEY)
-                        {
-                            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);
-       }
-   }
-}
-
-namespace OC
-{
     std::ostream& operator <<(std::ostream& os, const AttributeType at)
     {
         switch(at)
index 16abce1..e5850fb 100644 (file)
 
 #include <vector>
 #include <map>
-#include <cereal/cereal.hpp>
-#include <OicJsonSerializer.hpp>
+#include "ocpayload.h"
 
 using namespace OC;
-using namespace std;
 
-void OCResourceRequest::setPayload(const std::string& requestPayload)
+void OCResourceRequest::setPayload(OCPayload* payload)
 {
     MessageContainer info;
 
-    if(requestPayload.empty())
+    if(payload == nullptr || payload->type != PAYLOAD_TYPE_REPRESENTATION)
     {
+        throw std::logic_error("Wrong payload type");
         return;
     }
 
-    try
-    {
-        info.setJSONRepresentation(requestPayload);
-    }
-    catch(cereal::RapidJSONException& ex)
-    {
-        oclog() << "RapidJSON Exception in setPayload: "<<ex.what()<<std::endl<<
-            "Data was:"<<requestPayload<<std::flush;
-        return;
-    }
-    catch(cereal::Exception& ex)
-    {
-        oclog() << "Cereal Exception in setPayload: "<<ex.what()<<std::endl<<
-            "Data was:"<<requestPayload<<std::flush;
-        return;
-    }
+    info.setPayload(payload);
 
     const std::vector<OCRepresentation>& reps = info.representations();
     if(reps.size() >0)
index 10dc8b9..621e01c 100644 (file)
@@ -68,7 +68,6 @@ oclib_src = [
                'OCResourceRequest.cpp'
        ]
 
-oclib_env.AppendUnique(CPPPATH = [oclib_env.get('SRC_DIR') + '/extlibs/cereal/include'])
 oclib = oclib_env.SharedLibrary('oc', oclib_src)
 oclib_env.InstallTarget(oclib, 'liboc')
 oclib_env.UserInstallTargetLib(oclib, 'liboc')
index f0308a0..1957346 100644 (file)
@@ -472,11 +472,11 @@ OCStackApplicationResult requestPresenceCB(void *context, OCDoHandle handle,
     {
         OC_LOG_V(DEBUG, HOSTING_TAG, "\tStackResult: %s",  getResultString(clientResponse->result));
         OC_LOG_V(DEBUG, HOSTING_TAG, "\tStackResult: %d",  clientResponse->result);
-        OC_LOG_V(DEBUG, HOSTING_TAG,
-                 "\tPresence Device =============> Presence %s @ %s:%d",
-                 clientResponse->resJSONPayload,
-                 clientResponse->devAddr.addr,
-                 clientResponse->devAddr.port);
+        //OC_LOG_V(DEBUG, HOSTING_TAG,
+        //         "\tPresence Device =============> Presence %s @ %s:%d",
+        //         clientResponse->resJSONPayload,
+        //         clientResponse->devAddr.addr,
+        //         clientResponse->devAddr.port);
 
         snprintf(address, sizeof(address), "%s:%d",
                  clientResponse->devAddr.addr,
@@ -569,7 +569,7 @@ MirrorResourceList *buildMirrorResourceList(OCDoHandle handle, OCClientResponse
 {
 
     cJSON *discoveryJson = cJSON_CreateObject();
-    discoveryJson = cJSON_Parse((char *)clientResponse->resJSONPayload);
+    //discoveryJson = cJSON_Parse((char *)clientResponse->resJSONPayload);
 
     cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, "oc");
     char *ocArray_str = cJSON_PrintUnformatted(ocArray);
@@ -588,8 +588,8 @@ MirrorResourceList *buildMirrorResourceList(OCDoHandle handle, OCClientResponse
                                         clientResponse->devAddr.addr,
                                         clientResponse->devAddr.port);
 
-    OC_LOG_V(DEBUG, HOSTING_TAG, "Host Device =============> Discovered %s @ %s",
-             clientResponse->resJSONPayload, sourceaddr);
+    //OC_LOG_V(DEBUG, HOSTING_TAG, "Host Device =============> Discovered %s @ %s",
+    //         clientResponse->resJSONPayload, sourceaddr);
 
     int arraySize = cJSON_GetArraySize(ocArray);
     for (int i = 0; i < arraySize; ++i)
@@ -855,10 +855,10 @@ OCStackApplicationResult requestResourceObservationCB(void *context, OCDoHandle
         OC_LOG_V(DEBUG, HOSTING_TAG,
                  "<=============Callback Context for OBSERVE notification recvd successfully");
         OC_LOG_V(DEBUG, HOSTING_TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
-        OC_LOG_V(DEBUG, HOSTING_TAG, "JSON = %s =============> Obs Response",
-                 clientResponse->resJSONPayload);
+        //OC_LOG_V(DEBUG, HOSTING_TAG, "JSON = %s =============> Obs Response",
+        //         clientResponse->resJSONPayload);
 
-        MirrorResource *foundMirrorResource = updateMirrorResource(handle, clientResponse->resJSONPayload);
+        MirrorResource *foundMirrorResource = NULL;//updateMirrorResource(handle, clientResponse->resJSONPayload);
         if (foundMirrorResource == NULL)
         {
             OC_LOG_V(DEBUG, HOSTING_TAG, "Cannot found Mirror Resource : Fail");
@@ -993,7 +993,7 @@ char *buildResponsePayload (OCEntityHandlerRequest *entityHandlerRequest)
             mirrorResource->rep = NULL;
         }
         mirrorResource->rep = cJSON_CreateObject();
-        mirrorResource->rep = cJSON_Parse(entityHandlerRequest->reqJSONPayload);
+        //mirrorResource->rep = cJSON_Parse(entityHandlerRequest->reqJSONPayload);
     }
 
     OC_LOG_V(DEBUG, HOSTING_TAG, "node's uri : %s", mirrorResource->uri);
@@ -1107,8 +1107,8 @@ resourceEntityHandlerCB (OCEntityHandlerFlag entifyHandlerFlag,
             entityHandlerResponse.requestHandle = entityHandlerRequest->requestHandle;
             entityHandlerResponse.resourceHandle = entityHandlerRequest->resource;
             entityHandlerResponse.ehResult = entityHandlerResult;
-            entityHandlerResponse.payload = (char *)payload;
-            entityHandlerResponse.payloadSize = strlen(payload);
+            //entityHandlerResponse.payload = (char *)payload;
+            //entityHandlerResponse.payloadSize = strlen(payload);
             // Indicate that response is NOT in a persistent buffer
             entityHandlerResponse.persistentBufferFlag = 0;
 
@@ -1376,11 +1376,11 @@ OCStackResult requestQuery(RequestHandle *request, OCMethod method,
     if(method == OC_REST_PUT)
     {
         char payload[OIC_STRING_MAX_VALUE] = {'\0'};
-        snprintf(payload , sizeof(payload), "%s" ,
-         ((OCEntityHandlerRequest*)request->requestHandle[OIC_REQUEST_BY_CLIENT])->reqJSONPayload);
+        //snprintf(payload , sizeof(payload), "%s" ,
+        // ((OCEntityHandlerRequest*)request->requestHandle[OIC_REQUEST_BY_CLIENT])->reqJSONPayload);
 
-        result = OCDoResource(&request->requestHandle[OIC_REQUEST_BY_COORDINATOR],
-                method, queryFullUri, NULL, payload, OC_TRANSPORT, OC_LOW_QOS, &cbData, NULL, 0);
+        //result = OCDoResource(&request->requestHandle[OIC_REQUEST_BY_COORDINATOR],
+        //        method, queryFullUri, NULL, payload, OC_TRANSPORT, OC_LOW_QOS, &cbData, NULL, 0);
     }
     else
     {
@@ -1427,7 +1427,7 @@ OCStackApplicationResult requestQueryCB(void *context, OCDoHandle handle,
         }
         else
         {
-            OC_LOG_V(DEBUG, HOSTING_TAG, "requestCB's payload: %s", clientResponse->resJSONPayload);
+            //OC_LOG_V(DEBUG, HOSTING_TAG, "requestCB's payload: %s", clientResponse->resJSONPayload);
             OCEntityHandlerRequest *entityHandler = (OCEntityHandlerRequest *)(
                     request->requestHandle[OIC_REQUEST_BY_CLIENT]);
             OC_LOG_V(DEBUG, HOSTING_TAG, "requested resource handle : %u", entityHandler->resource
@@ -1437,8 +1437,8 @@ OCStackApplicationResult requestQueryCB(void *context, OCDoHandle handle,
             entityHandler->method = request->method;
             entityHandler->requestHandle = request->entityRequestHandle;
 
-            OCEntityHandlerResponse response = buildEntityHandlerResponse(
-                                                   entityHandler, clientResponse->resJSONPayload);
+            OCEntityHandlerResponse response; //= buildEntityHandlerResponse(
+                                                   //entityHandler, clientResponse->resJSONPayload);
             if (OCDoResponse(&response) != OC_STACK_OK)
             {
                 OC_LOG_V(DEBUG, HOSTING_TAG, "Error sending response");
@@ -1486,7 +1486,7 @@ OCEntityHandlerResponse buildEntityHandlerResponse(OCEntityHandlerRequest *entit
 
         cJSON_Delete(observeJson);
 
-        entityHandlerRequest->reqJSONPayload = temp;
+        //entityHandlerRequest->reqJSONPayload = temp;
     }
     entityHandlerResult = handleRequestPayload(entityHandlerRequest, payload, sizeof(payload) - 1);
 
@@ -1495,8 +1495,8 @@ OCEntityHandlerResponse buildEntityHandlerResponse(OCEntityHandlerRequest *entit
     response.resourceHandle = entityHandlerRequest->resource;
     response.ehResult = entityHandlerResult;
 
-    response.payload = (char *)payload;
-    response.payloadSize = strlen(payload);
+    //response.payload = (char *)payload;
+    //response.payloadSize = strlen(payload);
     // Indicate that response is NOT in a persistent buffer
     response.persistentBufferFlag = 0;
 
index 1de6847..78d675f 100644 (file)
@@ -28,18 +28,14 @@ then
        scp -p -P 29418 ${GIT_USER}@gerrit.iotivity.org:hooks/commit-msg iotivity/.git/hooks/
 fi
 
-export CEREAL_DIR=iotivity/extlibs/cereal
+export TINYCBOR_DIR=iotivity/extlibs/tinycbor
 if [ ! -d ${CEREAL_DIR} ]
 then
-       git clone https://github.com/USCiLab/cereal.git ${CEREAL_DIR}
-       pushd ${CEREAL_DIR}
-       git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245
-       git apply ../../resource/patches/cereal_gcc46.patch
-       popd
+       git clone https://github.com/01org/tinycbor ${CEREAL_DIR}
 fi
 
 #######################################
-# Android 
+# Android
 #######################################
 
 echo "Set up Android NDK"