Added C++ API for Provisioning Manager
authorAshwini Kumar <k.ashwini@samsung.com>
Mon, 31 Aug 2015 12:03:20 +0000 (17:33 +0530)
committerSachin Agrawal <sachin.agrawal@intel.com>
Sun, 13 Sep 2015 18:29:50 +0000 (18:29 +0000)
 - Unowned/Owned device discovery, ACL, Credential provisioning
 - Ownership transfer
 - Sample client.

[Patch#4]: Addressed review comments from Sakthivel
[Patch#5]: Added API for Unlink, device revocation, Dashboard
[Patch#6]: Rebase
[Patch#7]: Addressed review comments from Randeep & Woochul
[Patch#8]: removed extra env Clone from SConscript

Change-Id: I4fcca4d5efdc6f46514b1e2456aba2c7761fbc32
Signed-off-by: Ashwini Kumar <k.ashwini@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2320
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sachin Agrawal <sachin.agrawal@intel.com>
12 files changed:
resource/include/OCPlatform_impl.h
resource/include/OCProvisioningManager.h [new file with mode: 0644]
resource/provisioning/SConscript [new file with mode: 0644]
resource/provisioning/examples/SConscript [new file with mode: 0644]
resource/provisioning/examples/oic_svr_db_client.json [new file with mode: 0644]
resource/provisioning/examples/provisioningclient.cpp [new file with mode: 0644]
resource/provisioning/src/OCProvisioningManager.cpp [new file with mode: 0644]
resource/provisioning/unittests/OCProvisioningTest.cpp [new file with mode: 0644]
resource/provisioning/unittests/SConscript [new file with mode: 0644]
resource/src/OCPlatform_impl.cpp
resource/src/SConscript
resource/unit_tests.scons

index 78b95e8..fd221bb 100644 (file)
@@ -222,6 +222,8 @@ namespace OC
                         const std::vector<std::string>& interfaces);
         OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
 
+        std::weak_ptr<std::recursive_mutex> csdkLock();
+
     private:
         PlatformConfig m_cfg;
 
diff --git a/resource/include/OCProvisioningManager.h b/resource/include/OCProvisioningManager.h
new file mode 100644 (file)
index 0000000..ec8987b
--- /dev/null
@@ -0,0 +1,280 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#ifndef _OCPROVISIONINGMANAGER_CXX_H
+#define _OCPROVISIONINGMANAGER_CXX_H
+
+#include <thread>
+
+#include "pinoxmcommon.h"
+#include "ocprovisioningmanager.h"
+#include "OCApi.h"
+#include "OCPlatform_impl.h"
+
+namespace OC
+{
+    class OCSecureResource;
+
+    typedef std::vector<std::shared_ptr<OCSecureResource>> DeviceList_t;
+    typedef std::vector<OicUuid_t> UuidList_t;
+    typedef std::vector<OCProvisionResult_t> PMResultList_t;
+    typedef std::function<void(PMResultList_t *result, int hasError)> ResultCallBack;
+
+    struct ProvisionContext
+    {
+        ResultCallBack callback;
+        ProvisionContext(ResultCallBack cb) : callback(cb){}
+    };
+
+    /**
+     * @brief: This class is for credential's to be set to devices.
+     * The types supported are
+     *              0:  no security mode
+     *              1:  symmetric pair-wise key
+     *              2:  symmetric group key
+     *              4:  asymmetric key
+     *              8:  signed asymmetric key (aka certificate)
+     *              16: PIN /password
+     */
+    class Credential
+    {
+            OicSecCredType_t type;
+            size_t keySize;
+        public:
+            Credential() = default;
+            Credential(OicSecCredType_t type, size_t size) : type(type), keySize(size)
+            {}
+
+            OicSecCredType_t getCredentialType() const
+            {
+                return type;
+            }
+
+            size_t getCredentialKeySize() const
+            {
+                return keySize;
+            }
+
+            void setCredentialType(OicSecCredType_t type)
+            {
+                this->type = type;
+            }
+
+            void setCredentialKeySize(size_t keySize)
+            {
+                this->keySize = keySize;
+            }
+    };
+
+    class OCSecure
+    {
+        public:
+            /**
+             * The API is responsible for initializaton of the provisioning manager. It will load
+             * provisioning database which have owned device's list and their linked status.
+             *
+             * @param[in] dbPath file path of the sqlite3 db
+             *
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult provisionInit(const std::string& dbPath);
+
+            /**
+             * API is responsible for discovery of devices in it's subnet. It will list
+             * all the device in subnet which are not yet owned.
+             *
+             * @param[in] timeout Timeout in seconds, time util which function will listen to
+             *                    responses from client before returning the list of devices.
+             * @param[out] list List of candidate devices to be provisioned
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult discoverUnownedDevices(unsigned short timeout,
+                    DeviceList_t &list);
+
+            /**
+             * API is responsible for discovery of devices in it's subnet. It will list
+             * all the device in subnet which are already owned by calling provioning client
+             *
+             * @param[in] timeout Timeout in seconds, time util which function will listen to
+             *                    responses from client before returning the list of devices.
+             * @param[out] list List of owned devices
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult discoverOwnedDevices(unsigned short timeout,
+                    DeviceList_t &list);
+
+            /**
+             * API for registering Ownershipt transfer methods for a particular transfer Type
+             *
+             * @param[in] oxm Ownership transfer method
+             * @param[in] callbackData Methods for ownership transfer
+             * @param[in] InputPinCallback Method to input pin for verification
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult setOwnerTransferCallbackData(OicSecOxm_t oxm,
+                    OTMCallbackData_t* callbackData, InputPinCallback inputPin);
+
+            /**
+             * API to get status of all the devices in current subnet. The status include endpoint
+             * information and doxm information which can be extracted duing owned and unowned
+             * discovery. Along with this information, API will provide information about
+             * devices' status.
+             * Device can have following states
+             *  - ON/OFF: Device is switched on or off.
+             *
+             * @param[in] timeout waitime for the API.
+             * @param[out] pOwnedDevList  list of owned devices.
+             * @param[out] pUnownedDevList  list of unowned devices.
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult getDevInfoFromNetwork(unsigned short timeout,
+                    DeviceList_t &ownedDevList,
+                    DeviceList_t &unownedDevList);
+
+    };
+
+    /**
+     * This class represents a Secure virtual Device, which can be provisioned by the
+     * provisioning client.
+     */
+    class OCSecureResource
+    {
+        private:
+            std::weak_ptr<std::recursive_mutex> m_csdkLock;
+            OCProvisionDev_t *devPtr;   // pointer to device.
+
+        public:
+            OCSecureResource();
+            OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock, OCProvisionDev_t *dPtr);
+
+            ~OCSecureResource();
+
+            /**
+             * API to provision credentials between two devices and ACLs for the devices who
+             * act as a server.
+             *
+             * @param[in] cred  Type of credentials & key size to be provisioned to the device.
+             * @param[in] acl1  ACL for device 1. If this is not required set NULL.
+             * @param[in] device2  Second device to be provsioned.
+             * @param[in] acl2  ACL for device 2. If this is not required set NULL.
+             * @param[in] resultCallback Callback will be called when provisioning request recieves
+             *                           a response from first resource server.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+             */
+            OCStackResult provisionPairwiseDevices(const Credential &cred, const OicSecAcl_t* acl1,
+                    const OCSecureResource &device2, const OicSecAcl_t* acl2,
+                    ResultCallBack resultCallback);
+
+            /**
+             * API to do ownership transfer for un-owned device.
+             *
+             * @param[in] resultCallback Result callback function to be invoked when
+             *                           ownership transfer finished.
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            OCStackResult doOwnershipTransfer(ResultCallBack resultCallback);
+
+            /**
+             * API to send ACL information to resource.
+             *
+             * @param[in] acl ACL to provision.
+             * @param[in] resultCallback callback will be called when provisioning request
+             *                           recieves a response from resource server.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+             */
+            OCStackResult provisionACL(const OicSecAcl_t* acl,
+                    ResultCallBack resultCallback);
+
+            /**
+             * API to provision credential to devices.
+             *
+             * @param[in] cred Type of credentials to be provisioned to the device.
+             * @param[in] device2 Second device' instance,respresenting resourceto be provsioned.
+             * @param[in] resultCallback callback will be called when provisioning request recieves
+             *                           a response from first resource server.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+             */
+            OCStackResult provisionCredentials(const Credential &cred,
+                    const OCSecureResource &device2,
+                    ResultCallBack resultCallback);
+
+            /*
+            * API to remove the credential & relasionship between the two devices.
+            *
+            * @param[in] pTargetDev2 second device information to be unlinked.
+            * @param[in] resultCallback callback provided by API user, callback will be called when
+            *            device unlink is finished.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+            */
+            OCStackResult unlinkDevices(const OCSecureResource &device2,
+                    ResultCallBack resultCallback);
+
+            /*
+            * API to remove device credential from all devices in subnet.
+            *
+            * @param[in] resultCallback callback provided by API user, callback will be called when
+            *            credential revocation is finished.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+            */
+            OCStackResult removeDevice(ResultCallBack resultCallback);
+
+            /**
+             * This method is used to get linked devices' IDs.
+             *
+             * @param[out] uuidList information about the list of linked devices' uuids.
+             * @param[out] numOfDevices total number of linked devices.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+             */
+            OCStackResult getLinkedDevices(UuidList_t &uuidList);
+
+            /**
+             * API to get the DeviceID of this resource
+             */
+            std::string getDeviceID();
+
+            OCProvisionDev_t* getDevPtr()const;
+
+            /**
+             * This function returns the Device's IP addr.
+             */
+            std::string getDevAddr();
+
+            /**
+             * This function returns the Device's Status
+             */
+            int getDeviceStatus();
+
+            /**
+             * This function provides the OWNED status of the device.
+             */
+            bool getOwnedStatus();
+
+        private:
+            /**
+             * Common callback wrapper, which will be called from OC-APIs.
+             */
+            static void callbackWrapper(void* ctx, int nOfRes,
+                    OCProvisionResult_t *arr, bool hasError);
+
+            void validateSecureResource();
+    };
+
+}
+#endif //_OCPROVISIONINGMANAGER_CXX_H
diff --git a/resource/provisioning/SConscript b/resource/provisioning/SConscript
new file mode 100644 (file)
index 0000000..a7c035d
--- /dev/null
@@ -0,0 +1,63 @@
+#******************************************************************
+#
+# Copyright 2015 Samsung Electronics All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+
+ocprovision_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+ocprovision_env.AppendUnique(CPPPATH = [
+               '../include/',
+        '../csdk/stack/include',
+        '../csdk/logger/include',
+        '../oc_logger/include',
+               '../csdk/security/include',
+               '../csdk/security/provisioning/include',
+               '../csdk/security/provisioning/include/oxm',
+               '../csdk/security/provisioning/include/internal'
+               ])
+
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       ocprovision_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC'])
+
+if target_os == 'android':
+       ocprovision_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       ocprovision_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       ocprovision_env.AppendUnique(LIBS = ['ocspapi', 'octbstack', 'oc_logger', 'boost_thread', 'gnustl_shared', 'log'])
+
+if target_os in ['darwin', 'ios']:
+       ocprovision_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       ocprovision_env.AppendUnique(LIBS = ['octbstack', 'oc_logger'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+ocprovision_src = [
+               'src/OCProvisioningManager.cpp'
+       ]
+
+ocprovision = ocprovision_env.StaticLibrary('ocprovision', ocprovision_src)
+ocprovision_env.InstallTarget(ocprovision, 'libocprovision')
+
+if target_os in ['linux']:
+    SConscript('examples/SConscript')
diff --git a/resource/provisioning/examples/SConscript b/resource/provisioning/examples/SConscript
new file mode 100644 (file)
index 0000000..6f905ef
--- /dev/null
@@ -0,0 +1,83 @@
+#******************************************************************
+#
+# Copyright 2015 Samsung Electronics All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# Examples build script
+##
+Import('env')
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+examples_env.AppendUnique(CPPPATH = [
+        '../../include/',
+        '../../csdk/stack/include',
+        '../../csdk/logger/include',
+        '../../oc_logger/include',
+        '../../csdk/security/include',
+        '../../csdk/security/provisioning/include',
+        '../../csdk/security/provisioning/include/oxm',
+        '../../csdk/security/provisioning/include/internal'
+               ])
+
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       examples_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+       # Note: 'pthread' is in libc for android. On other platform, if use
+       # new gcc(>4.9?) it isn't required, otherwise, it's required
+       if target_os != 'android':
+               examples_env.AppendUnique(LIBS = ['-lpthread'])
+
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+examples_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
+examples_env.PrependUnique(LIBS = ['ocprovision', 'oc', 'ocpmapi', 'octbstack',
+                                    'oc_logger', 'connectivity_abstraction', 'coap'])
+if env.get('SECURED') == '1':
+    examples_env.AppendUnique(LIBS = ['tinydtls'])
+
+if target_os == 'android':
+       examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       examples_env.AppendUnique(LIBS = ['gnustl_shared'])
+
+       if not env.get('RELEASE'):
+               examples_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+       examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+provisioningclient = examples_env.Program('provisioningclient', 'provisioningclient.cpp')
+
+Alias("examples", [provisioningclient])
+env.AppendTarget('examples')
+
+src_dir = examples_env.get('SRC_DIR')
+svr_db_src_dir = src_dir + '/resource/provisioning/examples/'
+svr_db_build_dir = env.get('BUILD_DIR') +'/resource/provisioning/examples/'
+examples_env.Alias("install", examples_env.Install( svr_db_build_dir,
+                svr_db_src_dir + 'oic_svr_db_client.json'))
diff --git a/resource/provisioning/examples/oic_svr_db_client.json b/resource/provisioning/examples/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..49fb2a8
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 7,
+             "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlEMA==",
+               "ch": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlEMA==",
+               "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+       }
+}
diff --git a/resource/provisioning/examples/provisioningclient.cpp b/resource/provisioning/examples/provisioningclient.cpp
new file mode 100644 (file)
index 0000000..5a9af7d
--- /dev/null
@@ -0,0 +1,900 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <string>
+#include <map>
+#include <cstdlib>
+#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCProvisioningManager.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+
+#define MAX_URI_LENGTH (64)
+#define MAX_PERMISSION_LENGTH (5)
+#define CREATE (1)
+#define READ (2)
+#define UPDATE (4)
+#define DELETE (8)
+#define NOTIFY (16)
+#define DASH '-'
+#define PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
+#define TAG  "provisioningclient"
+
+#define JSON_DB_PATH "./oic_svr_db_client.json"
+#define DEV_STATUS_ON "DEV_STATUS_ON"
+#define DEV_STATUS_OFF "DEV_STATUS_OFF"
+
+#define DISCOVERY_TIMEOUT 5
+
+using namespace OC;
+
+DeviceList_t pUnownedDevList, pOwnedDevList;
+static int transferDevIdx, ask = 1;
+
+OicSecAcl_t defaultAcl =
+{
+    {},
+    1,
+    NULL,
+    0x001F,
+    0,
+    NULL,
+    NULL,
+    1,
+    NULL,
+    NULL,
+};
+
+static FILE* client_open(const char *path, const char *mode)
+{
+    return fopen(JSON_DB_PATH, mode);
+}
+
+void printMenu()
+{
+    std::cout << "\nChoose an option:"<<std::endl;
+    std::cout << "   1. UnOwned Device discovery"<<std::endl;
+    std::cout << "   2. Owned Device discovery"<<std::endl;
+    std::cout << "   3. Ownership transfer"<<std::endl;
+    std::cout << "   4. Provision ACL"<<std::endl;
+    std::cout << "   5. Provision Credentials"<<std::endl;
+    std::cout << "   6. Credential & ACL provisioning b/w two devices"<<std::endl;
+    std::cout << "   7. Unlink Devices"<<std::endl;
+    std::cout << "   8. Remove Device"<<std::endl;
+    std::cout << "   9. Get Linked Devices"<<std::endl;
+    std::cout << "   10. Get Device Status"<<std::endl;
+    std::cout << "   11. Exit loop"<<std::endl;
+}
+
+void moveTransferredDevice()
+{
+    pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
+    pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
+}
+
+void InputPinCB(char* pinBuf, size_t bufSize)
+{
+    if(pinBuf)
+    {
+        std::cout <<"INPUT PIN : ";
+        std::string ptr;
+        std::cin >> ptr;
+        OICStrcpy(pinBuf, bufSize, ptr.c_str());
+        return;
+    }
+}
+
+void printUuid(OicUuid_t uuid)
+{
+    for (int i = 0; i < UUID_LENGTH; i++)
+    {
+        std::cout << uuid.id[i];
+    }
+    std::cout<<std::endl;
+}
+
+void ownershipTransferCB(PMResultList_t *result, int hasError)
+{
+    if (hasError)
+    {
+        std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
+    }
+    else
+    {
+        std::cout<< "\nTransferred Ownership successfuly for device : ";
+        printUuid(result->at(0).deviceId);
+        delete result;
+
+        moveTransferredDevice();
+    }
+    ask = 1;
+}
+
+void printStatus(int status)
+{
+    static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
+
+    std::cout <<devStatus[status] <<std::endl;
+}
+
+void printDevices(DeviceList_t &list)
+{
+   for (unsigned int i = 0; i < list.size(); i++ )
+   {
+      std::cout << "Device "<< i+1 <<" ID: ";
+      std::cout << list[i]->getDeviceID() << " From IP: ";
+      std::cout << list[i]->getDevAddr() << std::endl;
+   }
+}
+
+/**
+ * Callback function for provisioning ACL, Credentials.
+ *
+ * @param[in]    result Result list
+ * @param[in] hasError indicates if the result has error
+ */
+void provisionCB(PMResultList_t *result, int hasError)
+{
+   if (hasError)
+   {
+       std::cout << "Error in provisioning operation!"<<std::endl;
+   }
+   else
+   {
+       std::cout<< "\nReceived provisioning results: ";
+       for (unsigned int i = 0; i < result->size(); i++)
+       {
+           for (int j = 0; j < UUID_LENGTH; j++) std::cout << result->at(i).deviceId.id[j];
+           std::cout << ", result = " << result->at(i).res << std::endl;
+       }
+
+       delete result;
+   }
+   printMenu();
+   ask = 1;
+}
+/**
+ *
+ * Ask user with which devices it wants to make further actions.
+ * All possible error checks included.
+ * Default behavior in case if only one options leaves are included too.
+ * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
+ * Use DeviceList_t instead of devicesCount because of print devices info
+ *
+ * @param[in] list owned devices list.
+ * @param[out] out device number array.
+ * @param[in] count how many device numbers need to read.
+ * @return 0 in case of success and other value otherwise.
+ */
+int readDeviceNumber(DeviceList_t &list, int count, int *out)
+{
+   if (out == NULL || count <= 0)
+   {
+      std::cout << "Error! Please put valid input parameters" << std::endl;
+      return -1;
+   }
+
+   int devicesCount = list.size();
+
+   //Print current list of owned devices
+   std::cout <<"Owned devices, count = " << devicesCount << std::endl;
+   printDevices(list);
+
+   if (devicesCount < count)
+   {
+      std::cout << "You can't proceed with selected action because Owned devices count ( ";
+      std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
+      std::cout << "You may need to discover devices again" << std::endl;
+      return -2;
+   }
+
+   std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
+
+   for (int curr = 0; curr < count; curr++)
+   {
+      //select last device by default if only 1 option exist
+      //from user's point of view device counting starts from 1,
+      //so 1st, 2nd, 3rd, etc devices
+      if ((curr == count - 1) && (devicesCount == count))
+      {
+         int sum = 0;
+         for (int i = 0; i < curr; i++)
+         {
+             sum += out[i];
+         }
+
+         out[curr] = (count*(count+1))/2 - sum;
+
+         std::cout << "Device " << curr + 1 << " : " << out[curr];
+         std::cout << " - selected automatically (because no other options exist)" << std::endl;
+         break;
+      }
+
+      int choice;
+      std::cout << "Device " << curr + 1 << " : ";
+      std::cin >> choice;
+
+      if (choice < 1 || choice > devicesCount)
+      {
+         std::cout << "Error! You should enter valid device number!" << std::endl;
+         return -3;
+      }
+
+      //check that user doesn't select the same device twice
+      for (int i = 0; i < curr; i++)
+      {
+         if (out[i] == choice)
+         {
+            std::cout << "Error! You cannot select the same device twice!" << std::endl;
+            return -4;
+         }
+      }
+
+      out[curr] = choice;
+   }
+
+   //Users count devices from 1, so 1st, 2nd, 3rd, etc device
+   //But deviceList array start index is 0, so need to decrease all numbers to 1
+   for (int i = 0; i < count; i++) out[i] -= 1;
+
+   return 0;
+}
+
+/**
+ * Perform cleanup for ACL
+ * @param[in]    ACL
+ */
+static void deleteACL(OicSecAcl_t *acl)
+{
+    if (acl)
+    {
+        /* Clean Resources */
+        for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
+        {
+            OICFree((acl)->resources[i]);
+        }
+        OICFree((acl)->resources);
+
+        /* Clean Owners */
+        OICFree((acl)->owners);
+
+        /* Clean ACL node itself */
+        /* Required only if acl was created in heap */
+        //OICFree((acl));
+    }
+}
+
+/**
+ * Calculate ACL permission from string to bit
+ *
+ * @param[in] temp_psm    Input data of ACL permission string
+ * @param[in,out] pms    The pointer of ACL permission value
+ * @return  0 on success otherwise -1.
+ */
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+{
+    int i = 0;
+
+    if (NULL == temp_pms || NULL == pms)
+    {
+        return -1;
+    }
+    *pms = 0;
+    while (temp_pms[i] != '\0')
+    {
+        switch (temp_pms[i])
+        {
+            case 'C':
+                {
+                    *pms += CREATE;
+                    i++;
+                    break;
+                }
+            case 'R':
+                {
+                    *pms += READ;
+                    i++;
+                    break;
+                }
+            case 'U':
+                {
+                    *pms += UPDATE;
+                    i++;
+                    break;
+                }
+            case 'D':
+                {
+                    *pms += DELETE;
+                    i++;
+                    break;
+                }
+            case 'N':
+                {
+                    *pms += NOTIFY;
+                    i++;
+                    break;
+                }
+            case '_':
+                {
+                    i++;
+                    break;
+                }
+            default:
+                {
+                    return -1;
+                }
+        }
+    }
+    return 0;
+}
+
+/**
+ * Get the ACL property from user
+ *
+ * @param[in]    ACL Datastructure to save user inputs
+ * @return  0 on success otherwise -1.
+ */
+static int InputACL(OicSecAcl_t *acl)
+{
+    int ret;
+    char *temp_id, *temp_rsc, *temp_pms;
+
+    printf("******************************************************************************\n");
+    printf("-Set ACL policy for target device\n");
+    printf("******************************************************************************\n");
+    //Set Subject.
+    printf("-URN identifying the subject\n");
+    printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
+    printf("Subject : ");
+    ret = scanf("%19ms", &temp_id);
+
+    if (1 == ret)
+    {
+        for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
+        {
+            if (DASH != temp_id[i])
+                acl->subject.id[j++] = temp_id[i];
+        }
+        OICFree(temp_id);
+    }
+    else
+    {
+        printf("Error while input\n");
+        return -1;
+    }
+
+    //Set Resource.
+    printf("Num. of Resource : ");
+    ret = scanf("%zu", &acl->resourcesLen);
+    printf("-URI of resource\n");
+    printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
+    acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
+    if (NULL == acl->resources)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        return -1;
+    }
+    for (size_t i = 0; i < acl->resourcesLen; i++)
+    {
+        printf("[%zu]Resource : ", i + 1);
+        ret = scanf("%64ms", &temp_rsc);
+        if (1 != ret)
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+
+        acl->resources[i] = OICStrdup(temp_rsc);
+        OICFree(temp_rsc);
+        if (NULL == acl->resources[i])
+        {
+            OC_LOG(ERROR, TAG, "Error while memory allocation");
+            return -1;
+        }
+    }
+    // Set Permission
+    do
+    {
+        printf("-Set the permission(C,R,U,D,N)\n");
+        printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
+        printf("Permission : ");
+        ret = scanf("%5ms", &temp_pms);
+        if (1 != ret)
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+        ret = CalculateAclPermission(temp_pms, &(acl->permission));
+        OICFree(temp_pms);
+    } while (0 != ret );
+
+    // Set Rowner
+    printf("Num. of Rowner : ");
+    ret = scanf("%zu", &acl->ownersLen);
+    printf("-URN identifying the rowner\n");
+    printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
+    acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+    if (NULL == acl->owners)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        return -1;
+    }
+    for (size_t i = 0; i < acl->ownersLen; i++)
+    {
+        printf("[%zu]Rowner : ", i + 1);
+        ret = scanf("%19ms", &temp_id);
+        if (1 != ret)
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+
+        for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
+        {
+            if (DASH != temp_id[k])
+            {
+                acl->owners[i].id[j++] = temp_id[k];
+            }
+        }
+        OICFree(temp_id);
+    }
+    return 0;
+}
+
+static int InputCredentials(Credential &cred)
+{
+   int choice;
+
+   do
+   {
+       std::cout << "Select credential type from following values:" << std::endl;
+       std::cout << "1:  symmetric pair-wise key" << std::endl;
+       std::cout << "2:  symmetric group key" << std::endl;
+       std::cout << "4:  asymmetric key" << std::endl;
+       std::cout << "8:  signed asymmetric key (aka certificate)" << std::endl;
+       std::cout << "16: PIN /password" << std::endl;
+       std::cout << "Your choice: ";
+
+       std::cin >> choice;
+
+       switch (choice){
+           case 1:
+               cred.setCredentialType(choice);
+               choice = 0; //validation of the accepted choice.
+               break;
+           case 2:
+           case 4:
+           case 8:
+           case 16:
+               std::cout << "selected type is not supported yet" << std::endl;
+               break;
+           default:
+               std::cout << "Error! Please select valid credential type" << std::endl;
+               break;
+       }
+   } while(0 != choice);
+
+   std::cout << "Please enter key size (valid size is 128 or 256) :";
+   std::cin >> choice;
+
+   if(128 == choice)
+   {
+       cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
+   }
+   else if(256 == choice)
+   {
+        cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
+   }
+   else
+   {
+      std::cout << "Error! Please enter valid key size!" << std::endl;
+      return -2;
+   }
+
+   return 0;
+}
+
+int main(void)
+{
+    OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
+
+    // Create PlatformConfig object
+    PlatformConfig cfg {
+        OC::ServiceType::InProc,
+            OC::ModeType::Both,
+            "0.0.0.0",
+            0,
+            OC::QualityOfService::LowQos,
+            &ps
+    };
+
+    OCPlatform::Configure(cfg);
+
+    try
+    {
+        int choice;
+        if (OCSecure::provisionInit("") != OC_STACK_OK)
+        {
+            std::cout <<"PM Init failed"<< std::endl;
+            //return 1;
+        }
+
+        for (int out = 0; !out;)
+        {
+            while (!ask)
+            {
+                sleep(1);
+            }
+            printMenu();
+            std::cin >> choice;
+            switch(choice) {
+                case 1:
+                    {
+                        //Secure resource discovery.
+
+                        pUnownedDevList.clear();
+                        std::cout << "Started discovery..." <<std::endl;
+                        OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
+                                pUnownedDevList);
+                        if (result != OC_STACK_OK)
+                        {
+                            std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
+                        }
+                        else if (pUnownedDevList.size())
+                        {
+                            std::cout <<"Found secure devices, count = " <<
+                                pUnownedDevList.size() << std::endl;
+                            printDevices(pUnownedDevList);
+                        }
+                        else
+                        {
+                            std::cout <<"No Secure devices found"<<std::endl;
+                        }
+                        break;
+                    }
+                case 2:
+                    {
+                        pOwnedDevList.clear();
+                        std::cout << "Started discovery..." <<std::endl;
+                        OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
+                                pOwnedDevList);
+                        if (result != OC_STACK_OK)
+                        {
+                            std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
+                        }
+                        else if (pOwnedDevList.size())
+                        {
+                            std::cout <<"Found owned devices, count = " <<
+                                pOwnedDevList.size() << std::endl;
+                            printDevices(pOwnedDevList);
+                        }
+                        else
+                        {
+                            std::cout <<"No Secure devices found"<<std::endl;
+                        }
+                        break;
+                    }
+                case 3:
+                    {
+                        unsigned int devNum;
+
+                        if (!pUnownedDevList.size())
+                        {
+                            std::cout <<"There are no more Unowned devices"<<std::endl;
+                            break;
+                        }
+
+                        for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
+                        {
+                            std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
+                            std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
+                        }
+
+                        std::cout <<"Select device number: "<<std::endl;
+                        std::cin >> devNum;
+                        if (devNum > pUnownedDevList.size())
+                        {
+                            std::cout <<"Invalid device number"<<std::endl;
+                            break;
+                        }
+                        transferDevIdx = devNum - 1;
+
+                        //register callbacks for JUST WORKS and PIN methods
+                        std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
+
+                        {
+                            OTMCallbackData_t justWorksCBData;
+                            justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+                            justWorksCBData.createSecureSessionCB =
+                                CreateSecureSessionJustWorksCallback;
+                            justWorksCBData.createSelectOxmPayloadCB =
+                                CreateJustWorksSelectOxmPayload;
+                            justWorksCBData.createOwnerTransferPayloadCB =
+                                CreateJustWorksOwnerTransferPayload;
+                            OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
+                                    &justWorksCBData, NULL);
+                        }
+
+                        {
+                            OTMCallbackData_t pinBasedCBData;
+                            pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+                            pinBasedCBData.createSecureSessionCB =
+                                CreateSecureSessionRandomPinCallbak;
+                            pinBasedCBData.createSelectOxmPayloadCB =
+                                CreatePinBasedSelectOxmPayload;
+                            pinBasedCBData.createOwnerTransferPayloadCB =
+                                CreatePinBasedOwnerTransferPayload;
+                            OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
+                                    &pinBasedCBData, InputPinCB);
+                        }
+
+                        ask = 0;
+                        std::cout << "Transfering ownership for : "<<
+                            pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
+                        if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
+                                != OC_STACK_OK)
+                        {
+                            std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
+                            ask = 1;
+                        }
+                        break;
+                    }
+                case 4: //Provision ACL
+                    {
+                        int index;
+
+                        if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+                        std::cout << "Provision ACL for : "<<
+                            pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+                        OicSecAcl_t acl = defaultAcl;
+
+                        std::cout << "Please input ACL for selected device: " << std::endl;
+                        if (0 != InputACL(&acl))
+                        {
+                            deleteACL(&acl);
+                            break;
+                        }
+
+                        ask = 0;
+
+                        if (pOwnedDevList[index]->provisionACL(&acl, provisionCB) != OC_STACK_OK)
+                        {
+                            ask = 1;
+                            std::cout <<"provisionACL is failed"<< std::endl;
+                        }
+                        deleteACL(&acl);
+                    }
+                    break;
+                case 5: //Provision Credentials
+                    {
+                        int devices[2];
+
+                        if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+                        int first  = devices[0];
+                        int second = devices[1];
+
+                        std::cout << "Provision Credentials to devices: "<<
+                            pOwnedDevList[first]->getDeviceID();
+                        std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+                        Credential cred(0,0);
+                        std::cout << "Please input credentials for selected devices: " << std::endl;
+                        if (0 != InputCredentials(cred))
+                            break;
+
+                        ask = 0;
+
+                        if (pOwnedDevList[first]->provisionCredentials(cred,
+                                    *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
+                        {
+                            ask = 1;
+                            std::cout <<"provisionCredentials is failed"<< std::endl;
+                        }
+                    }
+                    break;
+                case 6: //Provision ACL & Creds b/w two devices.
+                    {
+                        int devices[2];
+
+                        if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+                        int first  = devices[0];
+                        int second = devices[1];
+
+                        std::cout << "Provision pairwise devices: "<<
+                            pOwnedDevList[first]->getDeviceID();
+                        std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+                        Credential cred(0,0);
+                        std::cout << "Please input credentials for selected devices: " << std::endl;
+                        if (0 != InputCredentials(cred))
+                            break;
+
+                        OicSecAcl_t acl1 = defaultAcl;
+
+                        std::cout << "Please input ACL for selected device: " << std::endl;
+                        if (0 != InputACL(&acl1))
+                        {
+                            deleteACL(&acl1);
+                            break;
+                        }
+
+                        OicSecAcl_t acl2 = defaultAcl;
+
+                        std::cout << "Please input ACL for selected device: " << std::endl;
+                        if (0 != InputACL(&acl2))
+                        {
+                            deleteACL(&acl2);
+                            break;
+                        }
+
+                        ask = 0;
+
+                        if (pOwnedDevList[first]->provisionPairwiseDevices(cred, &acl1,
+                               *pOwnedDevList[second].get(), &acl2, provisionCB) != OC_STACK_OK)
+                        {
+                            ask = 1;
+                            std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
+                        }
+                        deleteACL(&acl1);
+                        deleteACL(&acl2);
+                    }
+                    break;
+                case 7: //Unlink Devices
+                {
+                   int devices[2];
+
+                   if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+                   int first  = devices[0];
+                   int second = devices[1];
+
+                   std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
+                   std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+                   ask = 0;
+
+                   if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
+                         provisionCB) != OC_STACK_OK)
+                   {
+                       ask = 1;
+                       std::cout <<"removeDevice is failed"<< std::endl;
+                   }
+                   break;
+                }
+                case 8: //Remove Device
+                {
+                   int index;
+
+                   if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+                   std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+                   ask = 0;
+
+                   if (pOwnedDevList[index]->removeDevice(provisionCB) != OC_STACK_OK)
+                   {
+                       ask = 1;
+                       std::cout <<"removeDevice is failed"<< std::endl;
+                   }
+                   break;
+                }
+                case 9: //Get Linked devices
+                    {
+                        UuidList_t linkedUuid;
+                        unsigned int devNum;
+
+                        if (!pOwnedDevList.size())
+                        {
+                            std::cout <<"There are no Owned devices yet,"
+                                " may need to discover"<<std::endl;
+                            break;
+                        }
+
+                        for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
+                        {
+                            std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
+                            std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
+                        }
+
+                        std::cout <<"Select device number: "<<std::endl;
+                        std::cin >> devNum;
+                        if (devNum > pOwnedDevList.size())
+                        {
+                            std::cout <<"Invalid device number"<<std::endl;
+                            break;
+                        }
+
+                        if(pOwnedDevList[devNum  -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
+                        {
+                            if (!linkedUuid.size())
+                            {
+                                std::cout <<"No devices are linked to "<<
+                                    pOwnedDevList[devNum  -1]->getDeviceID() << std::endl;
+                            }
+                            //display the Linked devices (UUIDs)
+                            for(unsigned int i = 0; i < linkedUuid.size(); i++)
+                            {
+                                printUuid(linkedUuid[i]);
+                            }
+                        }
+                        else
+                        {
+                            std::cout <<"Error! in getLinkedDevices"<<std::endl;
+                        }
+                        break;
+                    }
+                case 10: //Get device' status
+                    {
+                        DeviceList_t unownedList, ownedList;
+
+                        if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
+                                    unownedList) == OC_STACK_OK)
+                        {
+                            std::cout <<"Owned Device' status for" <<std::endl;
+                            for (unsigned int i = 0; i < ownedList.size(); i++ )
+                            {
+                                std::cout << "Device "<<i+1 <<" ID: '";
+                                std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
+                                std::cout << ownedList[i]->getDevAddr() << " Status: ";
+                                printStatus(ownedList[i]->getDeviceStatus());
+                            }
+                            std::cout <<"\nUnOwned Device' status for" <<std::endl;
+                            for (unsigned int i = 0; i < unownedList.size(); i++ )
+                            {
+                                std::cout << "Device "<<i+1 <<" ID: '";
+                                std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
+                                std::cout << unownedList[i]->getDevAddr() << " Status: ";
+                                printStatus(unownedList[i]->getDeviceStatus());
+                            }
+
+                        }
+                        break;
+                    }
+
+                case 11:
+                default:
+                    out = 1;
+                    break;
+            }
+        }
+    }
+    catch(OCException& e)
+    {
+        oclog() << "Exception in main: "<<e.what();
+    }
+
+    return 0;
+}
diff --git a/resource/provisioning/src/OCProvisioningManager.cpp b/resource/provisioning/src/OCProvisioningManager.cpp
new file mode 100644 (file)
index 0000000..31509e8
--- /dev/null
@@ -0,0 +1,509 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include "ocstack.h"
+#include "base64.h"
+#include "OCProvisioningManager.h"
+
+namespace OC
+{
+    OCStackResult OCSecure::provisionInit(const std::string& dbPath)
+    {
+        OCStackResult result;
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCInitPM(dbPath.c_str());
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
+    OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
+            DeviceList_t &list)
+    {
+        OCStackResult result;
+        OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
+        auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+        auto cLock = csdkLock.lock();
+
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCDiscoverUnownedDevices(timeout, &pDevList);
+            if (result == OC_STACK_OK)
+            {
+                // Create DeviceList of OCSecureResource's
+                pCurDev = pDevList;
+                while (pCurDev)
+                {
+                    tmp = pCurDev;
+                    list.push_back(std::shared_ptr<OCSecureResource>(
+                                new OCSecureResource(csdkLock, pCurDev)));
+                    pCurDev = pCurDev->next;
+                    tmp->next = nullptr;
+                }
+            }
+            else
+            {
+                oclog() <<"Unowned device discovery failed!";
+            }
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
+    OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
+            DeviceList_t &list)
+    {
+        OCStackResult result;
+        OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
+        auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+        auto cLock = csdkLock.lock();
+
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCDiscoverOwnedDevices(timeout, &pDevList);
+            if (result == OC_STACK_OK)
+            {
+                pCurDev = pDevList;
+                while (pCurDev)
+                {
+                    tmp = pCurDev;
+                    list.push_back(std::shared_ptr<OCSecureResource>(
+                                new OCSecureResource(csdkLock, pCurDev)));
+                    pCurDev = pCurDev->next;
+                    tmp->next = nullptr;
+                }
+            }
+            else
+            {
+                oclog() <<"Owned device discovery failed!";
+            }
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
+    OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
+            OTMCallbackData_t* callbackData, InputPinCallback inputPin)
+    {
+        if(NULL == callbackData || oxm >= OIC_OXM_COUNT)
+        {
+            oclog() <<"Invalid callbackData or OXM type";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        if((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
+        {
+            oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCSetOwnerTransferCallbackData(oxm, callbackData);
+            if(result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN & oxm))
+            {
+                SetInputPinCB(inputPin);
+            }
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+
+    }
+
+    OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
+            DeviceList_t &ownedDevList,
+            DeviceList_t &unownedDevList)
+    {
+        OCStackResult result = OC_STACK_OK;
+        OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
+        auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+        auto cLock = csdkLock.lock();
+
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2333, 2316. Once these are merged, this code will be
+//      updated
+
+//            result = OCGetDevInfoFromNetwork(nullptr, timeout, &owned, &unowned);
+
+            if (result == OC_STACK_OK)
+            {
+                dev = owned;
+                while (dev)
+                {
+                    tmp = dev;
+                    ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
+                                new OCSecureResource(csdkLock, dev)));
+                    dev = dev->next;
+                    tmp->next = nullptr;
+                }
+
+                dev = unowned;
+                while (dev)
+                {
+                    tmp = dev;
+                    unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
+                                new OCSecureResource(csdkLock,  dev)));
+                    dev = dev->next;
+                    tmp->next = nullptr;
+                }
+            }
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
+    void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+    {
+        PMResultList_t *results = nullptr;
+        ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
+
+        results = new PMResultList_t;
+        for (int i = 0; i < nOfRes; i++)
+        {
+            results->push_back(arr[i]);
+        }
+
+        std::thread exec(context->callback, results, hasError);
+        exec.detach();
+
+        delete context;
+    }
+
+    OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
+                                        devPtr(nullptr)
+    {
+    }
+
+    OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
+            OCProvisionDev_t *dPtr)
+        :m_csdkLock(csdkLock), devPtr(dPtr)
+    {
+    }
+
+    OCSecureResource::~OCSecureResource()
+    {
+        if(devPtr)
+        {
+            OCDeleteDiscoveredDevices(devPtr);
+        }
+    }
+
+    OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
+    {
+        if(!resultCallback)
+        {
+            oclog() <<"Result callback can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            ProvisionContext* context = new ProvisionContext(resultCallback);
+
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCDoOwnershipTransfer(static_cast<void*>(context),
+                    devPtr, &OCSecureResource::callbackWrapper);
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
+            ResultCallBack resultCallback)
+    {
+        if(!resultCallback || !acl)
+        {
+            oclog() <<"Result callback or ACL can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            ProvisionContext* context = new ProvisionContext(resultCallback);
+
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCProvisionACL(static_cast<void*>(context),
+                    devPtr, const_cast<OicSecAcl_t*>(acl),
+                    &OCSecureResource::callbackWrapper);
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
+            const OCSecureResource &device2, ResultCallBack resultCallback)
+    {
+        if(!resultCallback)
+        {
+            oclog() << "Result calback can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            ProvisionContext* context = new ProvisionContext(resultCallback);
+
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCProvisionCredentials(static_cast<void*>(context),
+                    cred.getCredentialType(),
+                    cred.getCredentialKeySize(),
+                    devPtr, device2.getDevPtr(),
+                    &OCSecureResource::callbackWrapper);
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
+            const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
+            ResultCallBack resultCallback)
+    {
+        if(!resultCallback)
+        {
+            oclog() << "Result calback can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            ProvisionContext* context = new ProvisionContext(resultCallback);
+
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCProvisionPairwiseDevices(static_cast<void*>(context),
+                    cred.getCredentialType(),
+                    cred.getCredentialKeySize(),
+                    devPtr, const_cast<OicSecAcl_t*>(acl1),
+                    device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
+                    &OCSecureResource::callbackWrapper);
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
+            ResultCallBack resultCallback)
+    {
+        if(!resultCallback)
+        {
+            oclog() << "Result calback can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            ProvisionContext* context = new ProvisionContext(resultCallback);
+
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2344. Once these are merged, this code will be
+//      updated
+
+//           result = OCUnlinkDevices(static_cast<void*>(context),
+//                   devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult OCSecureResource::removeDevice(ResultCallBack resultCallback)
+    {
+        if(!resultCallback)
+        {
+            oclog() << "Result calback can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            ProvisionContext* context = new ProvisionContext(resultCallback);
+
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2344. Once these are merged, this code will be
+//      updated
+
+//           result = OCRemoveDevice(static_cast<void*>(context),
+//                   devPtr, &OCSecureResource::callbackWrapper);
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
+    {
+        OCStackResult result;
+        size_t numOfDevices = -1;
+        auto devUuid = devPtr->doxm->deviceID;
+        auto cLock = m_csdkLock.lock();
+
+        if(cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2333, 2316. Once these are merged, this code will be 
+//      updated
+
+#if CHANGESET_2316
+            OicUuidList* linkedDevs = nullptr, *tmp = nullptr;
+            result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
+            if (result == OC_STACK_OK)
+            {
+                for (tmp = linkedDevs; tmp; tmp = tmp->next)
+                {
+                    uuidList.push_back(tmp->dev);
+                }
+                OCDeleteUuidList(&linkedDevs);
+            }
+#endif
+        }
+        else
+        {
+            oclog() <<"Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    std::string OCSecureResource::getDeviceID()
+    {
+        char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
+        uint32_t outLen = 0;
+        B64Result b64Ret = B64_OK;
+        std::ostringstream deviceId("");
+
+        validateSecureResource();
+        b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff,
+                sizeof(base64Buff), &outLen);
+
+        deviceId << base64Buff;
+        return deviceId.str();
+    }
+
+    OCProvisionDev_t* OCSecureResource::getDevPtr() const
+    {
+        return devPtr;
+    }
+
+    std::string OCSecureResource::getDevAddr()
+    {
+        validateSecureResource();
+        std::string ipAddr(devPtr->endpoint.addr);
+        return ipAddr;
+    }
+
+    int OCSecureResource::getDeviceStatus()
+    {
+        validateSecureResource();
+//TODO: this change is dependent on changesets #2333, 2316. Once these are merged, this code will be 
+//      updated
+//      return (int)devPtr->devStatus;
+        return 0;
+    }
+
+    bool OCSecureResource::getOwnedStatus()
+    {
+        validateSecureResource();
+        return devPtr->doxm->owned;
+    }
+
+    void OCSecureResource::validateSecureResource()
+    {
+        if (!devPtr)
+        {
+            throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
+        }
+    }
+}
diff --git a/resource/provisioning/unittests/OCProvisioningTest.cpp b/resource/provisioning/unittests/OCProvisioningTest.cpp
new file mode 100644 (file)
index 0000000..a3f4032
--- /dev/null
@@ -0,0 +1,177 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+//#include <ocprovisioningmanager.h>
+#include <OCApi.h>
+#include <OCPlatform_impl.h>
+#include <oxmjustworks.h>
+#include <oxmrandompin.h>
+#include <OCProvisioningManager.h>
+#include <gtest/gtest.h>
+
+#define TIMEOUT 5
+
+namespace OCProvisioningTest
+{
+    using namespace OC;
+
+    static OicSecAcl_t defaultAcl =
+    { {},
+        1,
+        NULL,
+        0x001F,
+        0,
+        NULL,
+        NULL,
+        1,
+        NULL,
+        NULL,
+    };
+
+    void resultCallback(PMResultList_t *result, int hasError)
+    {
+    }
+
+    TEST(ProvisionInitTest, TestWithEmptyPath)
+    {
+        std::string dbPath("");
+        EXPECT_EQ(OC_STACK_OK, OCSecure::provisionInit(dbPath));
+    }
+
+    TEST(ProvisionInitTest, TestValidPath)
+    {
+        std::string dbPath("./dbPath");
+        EXPECT_EQ(OC_STACK_OK, OCSecure::provisionInit(dbPath));
+    }
+
+    TEST(DiscoveryTest, UnownedDevices)
+    {
+        DeviceList_t list;
+        EXPECT_EQ(OC_STACK_OK, OCSecure::discoverUnownedDevices(TIMEOUT, list));
+    }
+
+    TEST(DiscoveryTest, UnownedDevicesZeroTimeout)
+    {
+        DeviceList_t list;
+        EXPECT_EQ(OC_STACK_OK, OCSecure::discoverUnownedDevices(0, list));
+    }
+
+    TEST(DiscoveryTest, OwnedDevices)
+    {
+        DeviceList_t list;
+        EXPECT_EQ(OC_STACK_OK, OCSecure::discoverOwnedDevices(TIMEOUT, list));
+    }
+
+    TEST(DiscoveryTest, OwnedDevicesZeroTimeout)
+    {
+        DeviceList_t list;
+        EXPECT_EQ(OC_STACK_OK, OCSecure::discoverOwnedDevices(0, list));
+    }
+
+    TEST(OwnershipTest, SetOwnershipTransferCBDataNull)
+    {
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(
+                    OIC_JUST_WORKS, NULL, NULL));
+    }
+
+    TEST(OwnershipTest, SetOwnershipTransferCBData)
+    {
+        OTMCallbackData_t justWorksCBData;
+        justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+        justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+        justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+        justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+        EXPECT_EQ(OC_STACK_OK, OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
+                                        &justWorksCBData, NULL));
+    }
+
+    TEST(OwnershipTest, SetOwnershipTransferCBDataInvalidType)
+    {
+        OTMCallbackData_t justWorksCBData;
+        justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+        justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+        justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+        justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(OIC_OXM_COUNT,
+                                        &justWorksCBData, NULL));
+    }
+
+    TEST(OwnershipTest, SetOwnershipTransferCBDataNullInputPin)
+    {
+        OTMCallbackData_t pinBasedCBData;
+        pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+        pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+        pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+        pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+        OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(
+                    OIC_RANDOM_DEVICE_PIN, &pinBasedCBData, NULL));
+    }
+
+    TEST(OwnershipTest, OwnershipTransferNullCallback)
+    {
+        OCSecureResource device;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, device.doOwnershipTransfer(nullptr));
+    }
+
+    TEST(DeviceInfoTest, DevInfoFromNetwork)
+    {
+        DeviceList_t owned, unowned;
+        EXPECT_EQ(OC_STACK_OK, OCSecure::getDevInfoFromNetwork(TIMEOUT,
+                    owned, unowned));
+    }
+
+    TEST(ProvisionAclTest, ProvisionAclTestNullAcl)
+    {
+        OCSecureResource device;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(nullptr, resultCallback));
+    }
+
+    TEST(ProvisionAclTest, ProvisionAclTestNullCallback)
+    {
+        OCSecureResource device;
+        OicSecAcl_t acl = defaultAcl;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(&acl, nullptr));
+    }
+
+    TEST(ProvisionAclTest, ProvisionAclTestNullCallbackNUllAcl)
+    {
+        OCSecureResource device;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(nullptr, nullptr));
+    }
+
+    TEST(ProvisionCredTest, ProvisionCredTestNullCallback)
+    {
+        OCSecureResource device, dev2;
+        Credential cred;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionCredentials(cred, dev2, nullptr));
+    }
+
+    TEST(ProvisionPairwiseTest, ProvisionPairwiseTestNullCallback)
+    {
+        OCSecureResource device, dev2;
+        Credential cred;
+        OicSecAcl_t acl1 = defaultAcl, acl2 = defaultAcl;
+        EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionPairwiseDevices(cred, &acl1,
+                    dev2, &acl2, nullptr));
+    }
+
+}
diff --git a/resource/provisioning/unittests/SConscript b/resource/provisioning/unittests/SConscript
new file mode 100644 (file)
index 0000000..458a2ab
--- /dev/null
@@ -0,0 +1,96 @@
+#******************************************************************
+#
+# Copyright 2015 Samsung Electronics All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+import os
+import os.path
+provisiontests_env = env.Clone()
+
+src_dir = provisiontests_env.get('SRC_DIR')
+######################################################################
+# Build flags
+######################################################################
+provisiontests_env.PrependUnique(CPPPATH = [
+               '../../include',
+               '../../oc_logger/include',
+               '../../csdk/stack/include',
+               '../../csdk/security/include',
+               '../../csdk/security/provisioning/include',
+               '../../csdk/security/provisioning/include/oxm',
+               '../../csdk/security/provisioning/include/internal',
+               '../../csdk/stack/include/internal',
+               '../../csdk/connectivity/api',
+               '../../csdk/connectivity/external/inc',
+               '../../csdk/ocsocket/include',
+               '../../csdk/ocrandom/include',
+               '../../csdk/logger/include',
+               '../../../extlibs/gtest/gtest-1.7.0/include',
+               '../../../extlibs/hippomocks-master/HippoMocks',
+               '../../../extlibs/hippomocks-master/HippoMocksTest'
+               ])
+
+provisiontests_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+provisiontests_env.AppendUnique(LIBS = ['-lpthread'])
+provisiontests_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+provisiontests_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+provisiontests_env.PrependUnique(LIBS = [
+        'ocprovision',
+               'oc',
+               'ocpmapi',
+               'octbstack',
+               'oc_logger',
+               'connectivity_abstraction',
+               'coap',
+               'gtest',
+               'gtest_main',
+               ])
+
+if env.get('SECURED') == '1':
+    provisiontests_env.AppendUnique(LIBS = ['tinydtls'])
+
+if env.get('LOGGING'):
+       provisiontests_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+unittests = provisiontests_env.Program('provisiontests', ['OCProvisioningTest.cpp'])
+
+Alias("provisiontests", [unittests])
+
+env.AppendTarget('provisiontests')
+if env.get('TEST') == '1':
+       target_os = env.get('TARGET_OS')
+       if target_os == 'linux':
+               out_dir = env.get('BUILD_DIR')
+               result_dir = env.get('BUILD_DIR') + '/test_out/'
+               if not os.path.isdir(result_dir):
+                       os.makedirs(result_dir)
+               provisiontests_env.AppendENVPath('GTEST_OUTPUT', ['xml:'+ result_dir])
+               provisiontests_env.AppendENVPath('LD_LIBRARY_PATH', [out_dir])
+               provisiontests_env.AppendENVPath('LD_LIBRARY_PATH', ['./extlibs/gtest/gtest-1.7.0/lib/.libs'])
+               ut = provisiontests_env.Command ('ut', None, out_dir + 'resource/provisioning/unittests/provisiontests')
+               AlwaysBuild ('ut')
+
+src_dir = provisiontests_env.get('SRC_DIR')
+svr_db_src_dir = src_dir + '/resource/provisioning/examples/'
+svr_db_build_dir = env.get('BUILD_DIR') +'/resource/provisioning/unittests/'
+provisiontests_env.Alias("install", provisiontests_env.Install( svr_db_build_dir,
+                                svr_db_src_dir + 'oic_svr_db_client.json'))
index 2a612a6..09c32df 100644 (file)
@@ -359,5 +359,10 @@ namespace OC
         return checked_guard(m_server, &IServerWrapper::sendResponse,
                              pResponse);
     }
+
+    std::weak_ptr<std::recursive_mutex> OCPlatform_impl::csdkLock()
+    {
+        return m_csdkLock;
+    }
 } //namespace OC
 
index 28118f1..6c6d9c6 100644 (file)
@@ -77,3 +77,5 @@ oclib = oclib_env.SharedLibrary('oc', oclib_src)
 oclib_env.InstallTarget(oclib, 'liboc')
 oclib_env.UserInstallTargetLib(oclib, 'liboc')
 
+if target_os in ['linux', 'android'] and env.get('SECURED') == '1':
+        SConscript('../provisioning/SConscript')
index 14b13e2..c254785 100644 (file)
@@ -57,6 +57,7 @@ if target_os == 'linux':
        # Build Provisioning API unit test
        if env.get('SECURED') == '1':
                SConscript('csdk/security/provisioning/unittest/SConscript')
+               SConscript('provisioning/unittests/SConscript')
 
 elif target_os == 'darwin':
        # Verify that 'google unit test' library is installed.  If not,