Added PDM Module to Provisioning APIs
authorRandeep Singh <randeep.s@samsung.com>
Mon, 7 Sep 2015 07:33:01 +0000 (16:33 +0900)
committerSachin Agrawal <sachin.agrawal@intel.com>
Mon, 7 Sep 2015 17:10:54 +0000 (17:10 +0000)
This module will save the information for provisioning APIs in database.

[Patch #4] Resolve Build Error
[patch #5] Added unit test case in build
[patch #6] Removed jenkins UT error
[patch #8] Changed code according chul lee's comments
[patch #9] Updated code according to sakthivel's comments
[patch #14] Rebase & Remove compilation warning
[patch #15] Added new error code and corrected PDMDeleteDevice API

Change-Id: I4281b9596870553834cef3efe38e8e6dbf34517a
Signed-off-by: Randeep Singh <randeep.s@samsung.com>
Signed-off-by: Woochul Shim <woochul.shim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2316
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sachin Agrawal <sachin.agrawal@intel.com>
18 files changed:
build_common/external_libs.scons
extlibs/sqlite3/SConscript [new file with mode: 0644]
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/internal/provisioningdatabasemanager.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/ocprovisioningmanager.h
resource/csdk/security/provisioning/include/pmtypes.h
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/provisioningdatabasemanager.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/provisioning/unittest/SConscript
resource/csdk/security/provisioning/unittest/provisioningdatabasemanager.cpp [new file with mode: 0644]
resource/csdk/stack/include/octypes.h
resource/include/StringConstants.h
resource/src/OCException.cpp
resource/unittests/OCExceptionTest.cpp

index 52f0546..8ab0cd4 100644 (file)
@@ -134,3 +134,6 @@ env.AddMethod(__configure, "Configure")
 env.AddMethod(__download, "Download")
 env.AddMethod(__install_head_file, "InstallHeadFile")
 env.AddMethod(__install_lib, "InstallLib")
+
+if env.get('SECURED') == '1':
+       SConscript(os.path.join(env.get('SRC_DIR'), 'extlibs', 'sqlite3', 'SConscript'))
\ No newline at end of file
diff --git a/extlibs/sqlite3/SConscript b/extlibs/sqlite3/SConscript
new file mode 100644 (file)
index 0000000..df92613
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Script to install (if they do not exist) the SQLite library
+##
+
+import os
+import shutil
+
+Import('env')
+sqlite_env = env.Clone()
+
+target_os = sqlite_env.get('TARGET_OS')
+src_dir = sqlite_env.get('SRC_DIR')
+
+targets_need_sqlite = ['linux', 'android']
+sqlite_dir      = src_dir + '/extlibs/sqlite3/'
+sqlite_build_dir      = src_dir + '/extlibs/sqlite3/sqlite-amalgamation-3081101/'
+sqlite_zip_file = src_dir + '/extlibs/sqlite3/sqlite-amalgamation-3081101.zip'
+sqlite_url      = 'http://www.sqlite.org/2015/sqlite-amalgamation-3081101.zip'
+
+# Download
+if target_os in targets_need_sqlite:
+       print '*** Checking for installation of SQLite 3.8.11.1 ***'
+       if not os.path.exists(sqlite_dir + 'sqlite3.c') or not os.path.exists(sqlite_dir + 'sqlite3.h'):
+
+           # If the zip file is not already present, download it
+               if not os.path.exists(sqlite_zip_file):
+                       sqlite_zip = sqlite_env.Download(sqlite_zip_file, sqlite_url)
+               else:
+                       sqlite_zip = sqlite_zip_file
+
+               # Unzip the lib
+               print 'Unzipping SQLite amalgamation src...'
+               sqlite_env.UnpackAll(sqlite_build_dir, sqlite_zip)
+               print 'Unzipping SQLite amalgamation src complete'
+
+               # Move requried src and header
+               os.rename(sqlite_build_dir + 'sqlite3.c', sqlite_dir + 'sqlite3.c')
+               os.rename(sqlite_build_dir + 'sqlite3.h', sqlite_dir + 'sqlite3.h')
+               os.remove(sqlite_zip_file)
+               shutil.rmtree(sqlite_build_dir)
+
+# Build will be done with provisioning manager module.
\ No newline at end of file
index 86317a1..980c260 100644 (file)
@@ -22,6 +22,7 @@
 Import('env')
 
 provisioning_env = env.Clone()
+root_dir = './../../../../'
 
 ######################################################################
 # Build flags
@@ -38,14 +39,14 @@ provisioning_env.AppendUnique(CPPPATH = [
                'include/oxm',
                '../../resource/csdk/security/include',
                '../../../../extlibs/cjson/',
-               '../../../../../extlibs/tinydtls/',
                '../../connectivity/inc',
                '../../connectivity/external/inc',
                '../../connectivity/common/inc',
                '../../connectivity/lib/libcoap-4.1.1',
                '../../connectivity/api',
                '../include',
-               '../include/internal'
+               '../include/internal',
+               '../../../../extlibs/sqlite3'
                ])
 target_os = env.get('TARGET_OS')
 provisioning_env.AppendUnique(CFLAGS = ['-D__WITH_DTLS__'])
@@ -86,7 +87,9 @@ provisioning_src = [
        'src/secureresourceprovider.c',
        'src/ocprovisioningmanager.c',
        'src/oxmjustworks.c',
-       'src/oxmrandompin.c' ]
+       'src/oxmrandompin.c',
+       'src/provisioningdatabasemanager.c',
+       root_dir+'/extlibs/sqlite3/sqlite3.c' ]
 provisioningserver = provisioning_env.StaticLibrary('ocpmapi', provisioning_src)
 
 provisioning_env.InstallTarget(provisioningserver, 'libocpmapi')
diff --git a/resource/csdk/security/provisioning/include/internal/provisioningdatabasemanager.h b/resource/csdk/security/provisioning/include/internal/provisioningdatabasemanager.h
new file mode 100644 (file)
index 0000000..13cd8a4
--- /dev/null
@@ -0,0 +1,159 @@
+/* *****************************************************************
+ *
+ * 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 PROVISIONING_DATABASE_MANAGER_H
+#define PROVISIONING_DATABASE_MANAGER_H
+#include "securevirtualresourcetypes.h"
+#include "ocstack.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * This method is used by provisioning manager to open provisioning database.
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMInit(const char* dbPath);
+
+/**
+ * This method is used by provisioning manager to check duplication of device's Device ID with
+ * provisioning database.
+ *
+ * @param[in] uuidOfDevice information about the target device's uuid.
+ *
+ * @return  false when non-duplication and true when duplication or uuidOfDevicea is NULL .
+ */
+bool PDMIsDuplicateDevice(const OicUuid_t* uuidOfDevice);
+
+/**
+ * This method is used by provisioning manager to add owned device's Device ID.
+ *
+ * @param[in] uuidOfDevice information about the owned device's uuid.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMAddDevice(const OicUuid_t* uuidOfDevice);
+
+/**
+ * This method is used by provisioning manager to update linked status of owned devices.
+ *
+ * @param[in] uuidOfDevice1 DeviceID which is going to be linked with uuid of device 2.
+ * @param[in] uuidOfDevice2 DeviceID which is going to be linked with uuid of device 1.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMLinkDevices(const OicUuid_t *uuidOfDevice1, const OicUuid_t *uuidOfDevice2);
+
+/**
+ * This method is used by provisioning manager to unlink pairwise devices.
+ *
+ * @param[in] uuidOfDevice1 DeviceID which is going to be unlinked with uuid of device 2.
+ * @param[in] uuidOfDevice2 DeviceID which is going to be unlinked with uuid of device 1.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMUnlinkDevices(const OicUuid_t *uuidOfDevice1, const OicUuid_t *uuidOfDevice2);
+
+/**
+ * This method is used by provisioning manager to delete owned device's Device ID.
+ *
+ * @param[in] uuidOfDevice information about the owned device's uuid to be deleted.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMDeleteDevice(const OicUuid_t *uuidOfDevice);
+
+/**
+ * This method is used by provisioning manager to get owned devices' Device IDs.
+ *
+ * @param[out] uuidList information about the list of owned devices' uuids.
+ * @param[out] numOfDevices total number of owned devices.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMGetOwnedDevices(OCUuidList_t** uuidList, size_t* numOfDevices);
+
+/**
+ * This method is used by provisioning manager to get linked devices' IDs.
+ *
+ * @param[in] uuidOfDevice a target device's uuid.
+ * @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 PDMGetLinkedDevices(const OicUuid_t* uuidOfDevice, OCUuidList_t** uuidList,
+                                    size_t* numOfDevices);
+
+/**
+ * This method is used by provisioning manager to update linked status as stale.
+ *
+ * @param[in] uuidOfDevice1 first id of stale link.
+ * @param[in] uuidOfDevice2 other id for stale link.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2);
+
+/**
+ * This method is used by provisioning manager to get stale devices.
+ *
+ * @note in case of sqllite, the caller should set NULL for parameters.
+ *
+ * @param[out] staleDevices information about the list of "To be Removed" devices' uuid.
+ * @param[out] numOfDevices total number of devices to be removed.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t** staleDevList, size_t* numOfDevices);
+
+/**
+ * This method is used by provisioning manager to close provisioning database.
+ *
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMClose();
+
+/**
+ * This method is used by provisioning manager free memory allocated to  OicUuidList lists.
+ *
+ * @param[in] ptr start pointer of link list.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMDestoryOicUuidLinkList(OCUuidList_t* ptr);
+
+/**
+ * This method is used by provisioning manager free memory allocated to Stalelist.
+ *
+ * @param[in] ptr start pointer of link list.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMDestoryStaleLinkList(OCPairList_t* ptr);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //PROVISIONING_DATABASE_MANAGER_H
index 8a51f0a..19fbc4e 100644 (file)
@@ -32,14 +32,14 @@ extern "C" {
 /**\r
  * The function is responsible for initializaton of the provisioning manager. It will load\r
  * provisioning database which have owned device's list and their linked status.\r
- * In addition, if there is a device(s) which has not up-to-date credentials, this function will\r
+ * TODO: In addition, if there is a device(s) which has not up-to-date credentials, this function will\r
  * automatically try to update the deivce(s).\r
  *\r
  * @param[in] dbPath file path of the sqlite3 db\r
  *\r
  * @return OC_STACK_OK in case of success and other value otherwise.\r
  */\r
-OCStackResult OCProvisionInit(const char* dbPath);\r
+OCStackResult OCInitPM(const char* dbPath);\r
 \r
 /**\r
  * The function is responsible for discovery of device is current subnet. It will list\r
index 08f21c3..a1ce5af 100644 (file)
@@ -29,6 +29,28 @@ extern "C" {
 #endif
 
 /**
+ * Node to construct list of UUID pair list.
+ */
+typedef struct OCPairList OCPairList_t;
+struct OCPairList
+{
+    OicUuid_t dev;
+    OicUuid_t dev2;
+    OCPairList_t *next;
+};
+
+/**
+ * Node to construct UUID linked list.
+ */
+typedef struct OCUuidList  OCUuidList_t;
+struct OCUuidList
+{
+    OicUuid_t dev;
+    OCUuidList_t *next;
+};
+
+
+/**
  * Device Information of discoverd unowned/owned device(s) for provisioning.
  */
 typedef struct OCProvisionDev
@@ -64,4 +86,4 @@ typedef void (*OCProvisionResultCB)(void* ctx, int nOfRes, OCProvisionResult_t *
 }
 #endif
 
-#endif //OC_PROVISIONING_TYPES_H
\ No newline at end of file
+#endif //OC_PROVISIONING_TYPES_H
index 46e270e..491f9dc 100644 (file)
@@ -49,7 +49,7 @@ provisioning_env.AppendUnique(CPPPATH = [
 provisioning_env.AppendUnique(CFLAGS = ['-D__WITH_DTLS__','-std=c99'])
 provisioning_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread', '-fpermissive'])
 provisioning_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
-provisioning_env.AppendUnique(LIBS = ['-lpthread'])
+provisioning_env.AppendUnique(LIBS = ['-lpthread','-ldl'])
 provisioning_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 provisioning_env.PrependUnique(LIBS = ['ocpmapi','oc', 'oc_logger', 'ocsrm','m', 'octbstack', 'connectivity_abstraction', 'coap'])
 
index c1073e7..86c53b1 100644 (file)
@@ -387,16 +387,12 @@ int main()
     (void)unused;
 
     // Initialize Persistent Storage for SVR database
-    OCPersistentStorage ps = { .open = NULL,
-                               .read = NULL,
-                               .write = NULL,
-                               .close = NULL,
-                               .unlink = NULL };
-    ps.open = client_fopen;
-    ps.read = fread;
-    ps.write = fwrite;
-    ps.close = fclose;
-    ps.unlink = unlink;
+    OCPersistentStorage ps = { .open = client_fopen,
+                               .read = fread,
+                               .write = fwrite,
+                               .close = fclose,
+                               .unlink = unlink };
+
     OCRegisterPersistentStorageHandler(&ps);
 
     if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
@@ -405,6 +401,12 @@ int main()
         goto error;
     }
 
+    if (OC_STACK_OK != OCInitPM(NULL))
+    {
+        OC_LOG(ERROR, TAG, "Initializing DB failure");
+        goto error;
+    }
+
     OCProvisionDev_t* pDeviceList = NULL;
     res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
     if(OC_STACK_OK != res)
index aff6414..f3488f6 100644 (file)
@@ -26,6 +26,7 @@
 #include "oic_malloc.h"
 #include "logger.h"
 #include "secureresourceprovider.h"
+#include "provisioningdatabasemanager.h"
 
 #define TAG "OCPMAPI"
 
@@ -45,6 +46,21 @@ struct Linkdata
 };
 
 /**
+ * The function is responsible for initializaton of the provisioning manager. It will load
+ * provisioning database which have owned device's list and their linked status.
+ * TODO: In addition, if there is a device(s) which has not up-to-date credentials, this function will
+ * automatically try to update the deivce(s).
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCInitPM(const char* dbPath)
+{
+    return PDMInit(dbPath);
+}
+
+/**
  * The function is responsible for discovery of device is current subnet. It will list
  * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
  * OCMode.
index ced4d1b..692363d 100644 (file)
@@ -55,6 +55,7 @@
 #include "pmtypes.h"
 #include "pmutility.h"
 #include "srmutility.h"
+#include "provisioningdatabasemanager.h"
 
 // TODO: Not yet supported.
 //#include "oxmrandompin.h"
@@ -851,6 +852,12 @@ static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
 {
     OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
+    //Checking duplication of Device ID.
+    if(true == PDMIsDuplicateDevice(&selectedDevice->doxm->deviceID))
+    {
+        OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicated");
+        return OC_STACK_INVALID_PARAM;
+    }
     OTMContext_t* otmCtx = (OTMContext_t*)OICMalloc(sizeof(OTMContext_t));
     if(!otmCtx)
     {
@@ -990,7 +997,18 @@ static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNU
     (void)UNUSED;
     if(OC_STACK_OK == clientResponse->result)
     {
-        SetResult(otmCtx, OC_STACK_OK);
+        OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
+
+         if (OC_STACK_OK == res)
+         {
+                OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
+                SetResult(otmCtx, OC_STACK_OK);
+                return OC_STACK_DELETE_TRANSACTION;
+         }
+         else
+         {
+              OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
+         }
     }
 exit:
     return OC_STACK_DELETE_TRANSACTION;
diff --git a/resource/csdk/security/provisioning/src/provisioningdatabasemanager.c b/resource/csdk/security/provisioning/src/provisioningdatabasemanager.c
new file mode 100644 (file)
index 0000000..ccbbbba
--- /dev/null
@@ -0,0 +1,657 @@
+/* *****************************************************************
+ *
+ * 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 <stdbool.h>
+#include <sqlite3.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "provisioningdatabasemanager.h"
+#include "pmutility.h"
+#include "oic_string.h"
+#include "utlist.h"
+
+
+#define DB_FILE "PDM.db"
+
+#define TAG "PDM"
+
+#define PDM_STALE_STATE 1
+#define PDM_ACTIVE_STATE 0
+
+#define PDM_FIRST_INDEX 0
+#define PDM_SECOND_INDEX 1
+
+#define PDM_BIND_INDEX_FIRST 1
+#define PDM_BIND_INDEX_SECOND 2
+#define PDM_BIND_INDEX_THIRD 3
+
+#define PDM_CREATE_T_DEVICE_LIST "create table T_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT,\
+                                  UUID BLOB NOT NULL UNIQUE);"
+
+#define PDM_CREATE_T_DEVICE_LINK  "create table T_DEVICE_LINK_STATE(ID INT NOT NULL, ID2 INT NOT \
+                                   NULL,STATE INT NOT NULL, PRIMARY KEY (ID, ID2));"
+/**
+ * Macro to verify sqlite success.
+ * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
+ */
+#define PDM_VERIFY_SQLITE_OK(tag, arg, logLevel, retValue) do{ if (SQLITE_OK != (arg)) \
+            { OC_LOG_V((logLevel), tag, ("Error in " #arg ", Error Message: %s"), \
+               sqlite3_errmsg(g_db)); return retValue; }}while(0)
+
+#define PDM_SQLITE_TRANSACTION_BEGIN "BEGIN TRANSACTION;"
+#define PDM_SQLITE_TRANSACTION_COMMIT "COMMIT;"
+#define PDM_SQLITE_TRANSACTION_ROLLBACK "ROLLBACK;"
+#define PDM_SQLITE_GET_STALE_INFO "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE STATE = ?"
+#define PDM_SQLITE_INSERT_T_DEVICE_LIST "INSERT INTO T_DEVICE_LIST VALUES(?,?)"
+#define PDM_SQLITE_GET_ID "SELECT ID FROM T_DEVICE_LIST WHERE UUID like ?"
+#define PDM_SQLITE_INSERT_LINK_DATA "INSERT INTO T_DEVICE_LINK_STATE VALUES(?,?,?)"
+#define PDM_SQLITE_DELETE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? and ID2 = ?"
+#define PDM_SQLITE_DELETE_DEVICE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
+#define PDM_SQLITE_DELETE_DEVICE "DELETE FROM T_DEVICE_LIST  WHERE ID = ?"
+#define PDM_SQLITE_UPDATE_LINK "UPDATE T_DEVICE_LINK_STATE SET STATE = ?  WHERE ID = ? and ID2 = ?"
+#define PDM_SQLITE_LIST_ALL_UUID "SELECT UUID FROM T_DEVICE_LIST"
+#define PDM_SQLITE_GET_UUID "SELECT UUID FROM T_DEVICE_LIST WHERE ID = ?"
+#define PDM_SQLITE_GET_LINKED_DEVICES "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
+
+#define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
+  { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
+
+static sqlite3 *g_db = NULL;
+
+/**
+ * function to create DB in case DB doesn't exists
+ */
+static OCStackResult createDB(const char* path)
+{
+
+    int result = 0;
+    result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
+
+    result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
+
+    OC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
+    result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
+
+    OC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
+    return OC_STACK_OK;
+}
+
+
+/**
+ * Function to begin any transaction
+ */
+static OCStackResult begin()
+{
+    int res = 0;
+    res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
+
+/**
+ * Function to commit any transaction
+ */
+static OCStackResult commit()
+{
+    int res = 0;
+    res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
+
+/**
+ * Function to rollback any transaction
+ */
+static OCStackResult rollback()
+{
+    int res = 0;
+    res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
+
+/**
+ * Error log callback called by SQLite stack in case of error
+ */
+void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
+{
+    (void) pArg;
+    (void) iErrCode;
+    (void) zMsg;
+    OC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
+}
+
+OCStackResult PDMInit(const char *path)
+{
+    int rc;
+    const char *dbPath = NULL;
+    if (SQLITE_OK !=  sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
+    {
+        OC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
+    }
+
+    if (NULL == path || !*path)
+    {
+        dbPath = DB_FILE;
+    }
+    else
+    {
+        dbPath = path;
+    }
+    rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
+    if (SQLITE_OK != rc)
+    {
+        OC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
+        return createDB(dbPath);
+    }
+    return OC_STACK_OK;
+}
+
+
+OCStackResult PDMAddDevice(const OicUuid_t *UUID)
+{
+    if (NULL == UUID)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    sqlite3_stmt *stmt = 0;
+    int res =0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
+                              strlen(PDM_SQLITE_INSERT_T_DEVICE_LIST) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_step(stmt);
+    if (SQLITE_DONE != res)
+    {
+        if (SQLITE_CONSTRAINT == res)
+        {
+            //new OCStack result code
+            OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
+            sqlite3_finalize(stmt);
+            return OC_STACK_DUPLICATE_UUID;
+        }
+        OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
+        sqlite3_finalize(stmt);
+        return OC_STACK_ERROR;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+/**
+ *function to get Id for given UUID
+ */
+static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
+{
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    OC_LOG(DEBUG, TAG, "Binding Done");
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+        int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+        OC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
+        *id = tempId;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+/**
+ * Function to check duplication of device's Device ID.
+ */
+bool PDMIsDuplicateDevice(const OicUuid_t* UUID)
+{
+    if (NULL == UUID)
+    {
+        OC_LOG(ERROR, TAG, "UUID is NULL");
+        return true;
+    }
+
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    OC_LOG(DEBUG, TAG, "Binding Done");
+
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+        OC_LOG(ERROR, TAG, "UUID is duplicated");
+        sqlite3_finalize(stmt);
+        return true;
+    }
+    sqlite3_finalize(stmt);
+    return false;
+}
+
+/**
+ * Function to add link in sqlite
+ */
+static OCStackResult addlink(int id1, int id2)
+{
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_LINK_DATA,
+                              strlen(PDM_SQLITE_INSERT_LINK_DATA) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    if (sqlite3_step(stmt) != SQLITE_DONE)
+    {
+        OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
+        sqlite3_finalize(stmt);
+        return OC_STACK_ERROR;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
+{
+
+    if (NULL == UUID1 || NULL == UUID2)
+    {
+        OC_LOG(ERROR, TAG, "Invalid PARAM");
+        return  OC_STACK_INVALID_PARAM;
+    }
+    int id1 = 0;
+    if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+    int id2 = 0;
+    if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+    ASCENDING_ORDER(id1, id2);
+    return addlink(id1, id2);
+}
+
+/**
+ * Function to remove created link
+ */
+static OCStackResult removeLink(int id1, int id2)
+{
+    int res = 0;
+    sqlite3_stmt *stmt = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_LINK, strlen(PDM_SQLITE_DELETE_LINK) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    if (SQLITE_DONE != sqlite3_step(stmt))
+    {
+        OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
+        sqlite3_finalize(stmt);
+        return OC_STACK_ERROR;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMUnlinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
+{
+    if (NULL == UUID1 || NULL == UUID2)
+    {
+        OC_LOG(ERROR, TAG, "Invalid PARAM");
+        return  OC_STACK_INVALID_PARAM;
+    }
+
+    int id1 = 0;
+    if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    int id2 = 0;
+    if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+    ASCENDING_ORDER(id1, id2);
+    return removeLink(id1, id2);
+}
+
+static OCStackResult removeFromDeviceList(int id)
+{
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_DEVICE,
+                              strlen(PDM_SQLITE_DELETE_DEVICE) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    if (sqlite3_step(stmt) != SQLITE_DONE)
+    {
+        OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
+        sqlite3_finalize(stmt);
+        return OC_STACK_ERROR;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMDeleteDevice(const OicUuid_t *UUID)
+{
+    if (NULL == UUID)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+    int id = 0;
+    if (OC_STACK_OK != getIdForUUID(UUID, &id))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+    begin();
+    if(OC_STACK_OK != removeFromDeviceList(id))
+    {
+        rollback();
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_ERROR;
+    }
+    commit();
+    return OC_STACK_OK;
+}
+
+
+OCStackResult updateLinkState(int id1, int id2, int state)
+{
+    sqlite3_stmt *stmt = 0;
+    int res = 0 ;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK,
+                              strlen(PDM_SQLITE_UPDATE_LINK) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id1);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, id2);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    if (SQLITE_DONE != sqlite3_step(stmt))
+    {
+        OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
+        sqlite3_finalize(stmt);
+        return OC_STACK_OK;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2)
+{
+    if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2)
+    {
+        OC_LOG(ERROR, TAG, "Invalid PARAM");
+        return  OC_STACK_INVALID_PARAM;
+    }
+
+    int id1 = 0;
+    if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    int id2 = 0;
+    if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+    ASCENDING_ORDER(id1, id2);
+    return updateLinkState(id1, id2, PDM_STALE_STATE);
+
+}
+
+OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
+{
+    if (NULL != *uuidList)
+    {
+        OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
+        return OC_STACK_INVALID_PARAM;
+    }
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_LIST_ALL_UUID,
+                              strlen(PDM_SQLITE_LIST_ALL_UUID) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    int counter  = 0;
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+
+        const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
+        OicUuid_t *uid = (OicUuid_t *)ptr;
+        OCUuidList_t *temp = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
+        if (NULL == temp)
+        {
+            OC_LOG_V(ERROR, TAG, "Memory allocation problem");
+            sqlite3_finalize(stmt);
+            return OC_STACK_NO_MEMORY;
+        }
+        memcpy(&temp->dev.id, uid->id, UUID_LENGTH);
+        LL_PREPEND(*uuidList,temp);
+        ++counter;
+    }
+    *numOfDevices = counter;
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+static OCStackResult getUUIDforId(int id, OicUuid_t *uid)
+{
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_UUID,
+                              strlen(PDM_SQLITE_GET_UUID) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+        const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
+        memcpy(uid, ptr, sizeof(OicUuid_t));
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST, size_t *numOfDevices)
+{
+    if (NULL != *UUIDLIST)
+    {
+        OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (NULL == UUID)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+    int id = 0;
+    if (OC_STACK_OK != getIdForUUID(UUID, &id))
+    {
+        OC_LOG(ERROR, TAG, "Requested value not found");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
+                              strlen(PDM_SQLITE_GET_LINKED_DEVICES) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    int counter  = 0;
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+        int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+        int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
+
+        OicUuid_t temp = {{0,}};
+        if (i1 != id)
+        {
+            getUUIDforId(i1, &temp);
+        }
+        if (i2 != id)
+        {
+            getUUIDforId(i2, &temp);
+        }
+
+        OCUuidList_t *tempNode = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
+        if (NULL == tempNode)
+        {
+            OC_LOG(ERROR, TAG, "No Memory");
+            sqlite3_finalize(stmt);
+            return OC_STACK_NO_MEMORY;
+        }
+        memcpy(&tempNode->dev.id, &temp.id, UUID_LENGTH);
+        LL_PREPEND(*UUIDLIST,tempNode);
+        ++counter;
+    }
+    *numOfDevices = counter;
+     sqlite3_finalize(stmt);
+     return OC_STACK_OK;
+}
+
+OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *numOfDevices)
+{
+    if (NULL != *staleDevList)
+    {
+        OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_STALE_INFO,
+                              strlen(PDM_SQLITE_GET_STALE_INFO) + 1, &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_STALE_STATE);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    int counter  = 0;
+    while (SQLITE_ROW == sqlite3_step(stmt))
+    {
+        int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+        int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
+        OicUuid_t temp1 = {{0,}};
+        OicUuid_t temp2 = {{0,}};;
+        getUUIDforId(i1, &temp1);
+        getUUIDforId(i2, &temp2);
+
+        OCPairList_t *tempNode = (OCPairList_t *) OICCalloc(1, sizeof(OCPairList_t));
+        if (NULL == tempNode)
+        {
+            OC_LOG(ERROR, TAG, "No Memory");
+            sqlite3_finalize(stmt);
+            return OC_STACK_NO_MEMORY;
+        }
+        memcpy(&tempNode->dev.id, &temp1.id, UUID_LENGTH);
+        memcpy(&tempNode->dev2.id, &temp2.id, UUID_LENGTH);
+        LL_PREPEND(*staleDevList, tempNode);
+        ++counter;
+    }
+    *numOfDevices = counter;
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMClose()
+{
+    int res = 0;
+    res = sqlite3_close(g_db);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
+{
+    OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
+    LL_FOREACH_SAFE(ptr, tmp1, tmp2)
+    {
+        LL_DELETE(ptr, tmp1);
+        OICFree(tmp1);
+    }
+    return OC_STACK_OK;
+}
+
+OCStackResult PDMDestoryStaleLinkList(OCPairList_t* ptr)
+{
+    OCPairList_t *tmp1 = NULL,*tmp2=NULL;
+    LL_FOREACH_SAFE(ptr, tmp1, tmp2)
+    {
+        LL_DELETE(ptr, tmp1);
+        OICFree(tmp1);
+    }
+    return OC_STACK_OK;
+}
index f7ebcea..7fb451b 100644 (file)
@@ -36,6 +36,7 @@
 #include "cJSON.h"
 #include "pmtypes.h"
 #include "pmutility.h"
+#include "provisioningdatabasemanager.h"
 
 #define SRP_MAX_URI_LENGTH 512
 #define TAG "SRPAPI"
@@ -136,6 +137,15 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU
         if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
         {
             registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED, 2);
+            OCStackResult res =  PDMLinkDevices(&credData->deviceInfo1->doxm->deviceID,
+                    &credData->deviceInfo2->doxm->deviceID);
+            if (OC_STACK_OK != res)
+            {
+                OC_LOG(ERROR, TAG, "Error occured on PDMlinkDevices");
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+            OC_LOG(INFO, TAG, "Link created successfully");
+
             ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
                                                     credData->resArr,
                                                     false);
index 8a95db0..a6b867a 100644 (file)
@@ -44,7 +44,7 @@ sptest_env.PrependUnique(CPPPATH = [
                '../include/internal'
                ])
 sptest_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
-sptest_env.AppendUnique(LIBS = ['-lpthread'])
+sptest_env.AppendUnique(LIBS = ['-lpthread','-ldl'])
 sptest_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 sptest_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
 sptest_env.PrependUnique(LIBS = [   'ocpmapi',
@@ -65,7 +65,9 @@ if not env.get('RELEASE'):
 ######################################################################
 # Source files and Targets
 ######################################################################
-unittest = sptest_env.Program('unittest', ['pmutilitytest.cpp', 'otmunittest.cpp', 'secureresourceprovider.cpp'])
+unittest = sptest_env.Program('unittest', ['pmutilitytest.cpp', 'otmunittest.cpp',
+                                           'secureresourceprovider.cpp',
+                                           'provisioningdatabasemanager.cpp'])
 
 Alias("test", [unittest])
 
diff --git a/resource/csdk/security/provisioning/unittest/provisioningdatabasemanager.cpp b/resource/csdk/security/provisioning/unittest/provisioningdatabasemanager.cpp
new file mode 100644 (file)
index 0000000..e1e3ec3
--- /dev/null
@@ -0,0 +1,215 @@
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "provisioningdatabasemanager.h"
+
+const char ID_1[] = "1111111111111111";
+const char ID_2[] = "2111111111111111";
+const char ID_3[] = "3111111111111111";
+const char ID_4[] = "4111111111111111";
+const char ID_5[] = "5111111111111111";
+const char ID_6[] = "6111111111111111";
+
+TEST(PDMInitTest, PDMInitWithNULL)
+{
+    EXPECT_EQ(OC_STACK_OK, PDMInit(NULL));
+}
+
+TEST(PDMAddDeviceTest, NullUUID)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMAddDevice(NULL));
+}
+
+TEST(PDMIsDuplicateDeviceTest, NullUUID)
+{
+    EXPECT_TRUE(PDMIsDuplicateDevice(NULL));
+}
+
+
+TEST(PDMIsDuplicateDeviceTest, ValidUUID)
+{
+    OicUuid_t uid1 = {{0,}};
+    memcpy(&uid1.id, ID_1, sizeof(uid1.id));
+    PDMAddDevice(&uid1);
+    OicUuid_t uid2 = {{0,}};
+    memcpy(&uid2.id, ID_2, sizeof(uid2.id));
+    PDMAddDevice(&uid2);
+    OicUuid_t uid3 = {{0,}};
+    memcpy(&uid3.id, ID_3, sizeof(uid3.id));
+
+    EXPECT_TRUE(PDMIsDuplicateDevice(&uid1));
+    EXPECT_FALSE(PDMIsDuplicateDevice(&uid3));
+}
+
+TEST(PDMAddDeviceTest, ValidUUID)
+{
+    OicUuid_t uid = {{0,}};
+
+    uint8_t id[UUID_LENGTH] = {0,};
+    for (size_t i = 0 ; i < sizeof(id) ; i++)
+    {
+        int tem = rand() % 25;
+
+        id[i] = tem + 65;
+    }
+
+    memcpy(&uid.id, &id, UUID_LENGTH);
+
+    EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid));
+    PDMDeleteDevice(&uid);
+}
+
+TEST(PDMLinkDevicesTest, NULLDevice1)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_2, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMLinkDevices(NULL, &uid));
+}
+
+TEST(PDMLinkDevicesTest, NULLDevice2)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_3, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMLinkDevices(&uid, NULL));
+}
+
+TEST(PDMLinkDevicesTest, ValidCase)
+{
+    OicUuid_t uid1 = {{0,}};
+    memcpy(&uid1.id, ID_4, sizeof(uid1.id));
+    PDMAddDevice(&uid1);
+    OicUuid_t uid2 = {{0,}};
+    memcpy(&uid2.id, ID_5, sizeof(uid2.id));
+    PDMAddDevice(&uid2);
+    EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid2));
+}
+
+TEST(PDMUnlinkDevicesTest, NULLDevice1)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_3, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMUnlinkDevices(NULL, &uid));
+}
+
+TEST(PDMUnlinkDevicesTest, NULLDevice2)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_3, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMUnlinkDevices(&uid, NULL));
+}
+
+TEST(PDMUnlinkDevices, ValidCase)
+{
+    OicUuid_t uid1 = {{0,}};
+    memcpy(&uid1.id, ID_4, sizeof(uid1.id));
+    OicUuid_t uid2 = {{0,}};
+    memcpy(&uid2.id, ID_5, sizeof(uid2.id));
+    EXPECT_EQ(OC_STACK_OK, PDMUnlinkDevices(&uid1, &uid2));
+}
+
+
+TEST (PDMDeleteDevice, NULLDeviceID)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMDeleteDevice(NULL));
+}
+
+TEST (PDMDeleteDevice, ValidDeviceID)
+{
+
+    OicUuid_t uid = {{0,}};
+    uint8_t id[UUID_LENGTH] = {0,};
+    for (size_t i = 0 ; i < sizeof(id) ; i++)
+    {
+        int tem = rand() % 25;
+
+        id[i] = tem + 65;
+    }
+
+    memcpy(&uid.id, &id, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_OK, PDMDeleteDevice(&uid));
+}
+
+TEST(PDMGetOwnedDevices, ValidCase)
+{
+    OCUuidList_t *list = NULL;
+    size_t noOfDevcies = 0;
+    EXPECT_EQ(OC_STACK_OK, PDMGetOwnedDevices(&list, &noOfDevcies));
+}
+
+TEST(PDMGetLinkedDevices, NULLDeviceID)
+{
+    OCUuidList_t *list = NULL;
+    size_t noOfDevices = 0;
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMGetLinkedDevices(NULL, &list, &noOfDevices));
+}
+
+TEST(PDMGetLinkedDevices, ValidCase)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_1, sizeof(uid.id));
+    OCUuidList_t *list = NULL;
+    size_t noOfDevices = 0;
+    EXPECT_EQ(OC_STACK_OK, PDMGetLinkedDevices(&uid, &list, &noOfDevices));
+}
+
+TEST(PDMSetLinkStale, NULLDeviceID1)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_1, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetLinkStale(NULL, &uid));
+}
+
+TEST(PDMSetLinkStale, NULLDeviceID2)
+{
+    OicUuid_t uid = {{0,}};
+    memcpy(&uid.id, ID_1, sizeof(uid.id));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetLinkStale(&uid, NULL));
+}
+
+TEST(PDMSetLinkStale, ValidCase)
+{
+    OicUuid_t uid1 = {{0,}};
+    memcpy(&uid1.id, ID_6, sizeof(uid1.id));
+    OicUuid_t uid2 = {{0,}};
+    memcpy(&uid2.id, ID_1, sizeof(uid2.id));
+    EXPECT_EQ(OC_STACK_OK, PDMSetLinkStale(&uid1, &uid2));
+}
+
+TEST(PDMGetToBeUnlinkedDevices, ValidCase)
+{
+    OCPairList_t *list = NULL;
+    size_t noOfDevices = 0;
+    EXPECT_EQ(OC_STACK_OK, PDMGetToBeUnlinkedDevices(&list, &noOfDevices));
+}
+
+TEST(PDMClose, ValidCase)
+{
+   EXPECT_EQ(OC_STACK_OK, PDMClose());
+}
+
+TEST(PDMDestoryOicUuidLinkList, NULLParam)
+{
+   EXPECT_EQ(OC_STACK_OK, PDMDestoryOicUuidLinkList(NULL));
+}
+
+TEST(PDMDestoryStaleLinkList, NULLParam)
+{
+   EXPECT_EQ(OC_STACK_OK, PDMDestoryOicUuidLinkList(NULL));
+}
index 839fd73..6603fbe 100644 (file)
@@ -633,6 +633,10 @@ typedef enum
     /** Request is not authorized by Resource Server. */
     OC_STACK_UNAUTHORIZED_REQ,
 
+    /** Error code from PDM */
+    OC_STACK_DUPLICATE_UUID,
+    OC_STACK_INCONSISTENT_DB,
+
     /** Insert all new error codes here!.*/
     #ifdef WITH_PRESENCE
     OC_STACK_PRESENCE_STOPPED = 128,
index b7b0a62..eeaecd5 100644 (file)
@@ -105,6 +105,8 @@ namespace OC
         static const char INVALID_ATTRIBUTE[]          = "Invalid Attribute: ";
         static const char INVALID_DEVICE_INFO[]        = "Invalid Device Information";
         static const char UNAUTHORIZED_REQUEST[]       = "Unauthorized Request";
+        static const char DUPLICATE_UUID[]             = "Duplicate UUID in DB";
+        static const char INCONSISTENT_DB[]            = "Data in provisioning DB is inconsistent";
 
     }
 
index 76893f1..8d4b584 100644 (file)
@@ -97,6 +97,10 @@ std::string OC::OCException::reason(const OCStackResult sr)
             return OC::Exception::INVALID_REPRESENTATION;
         case OC_STACK_UNAUTHORIZED_REQ:
             return OC::Exception::UNAUTHORIZED_REQUEST;
+        case OC_STACK_DUPLICATE_UUID:
+            return OC::Exception::DUPLICATE_UUID;
+        case OC_STACK_INCONSISTENT_DB:
+            return OC::Exception::INCONSISTENT_DB;
     }
 
     return OC::Exception::UNKNOWN_ERROR;
index 0c71f02..80e67b9 100644 (file)
@@ -67,7 +67,9 @@ namespace OC
                 OC_STACK_PRESENCE_STOPPED,
                 OC_STACK_PRESENCE_TIMEOUT,
                 OC_STACK_PRESENCE_DO_NOT_HANDLE,
-                OC_STACK_ERROR
+                OC_STACK_ERROR,
+                OC_STACK_DUPLICATE_UUID,
+                OC_STACK_INCONSISTENT_DB
             };
 
             std::string resultMessages[]=
@@ -106,7 +108,9 @@ namespace OC
                 OC::Exception::PRESENCE_STOPPED,
                 OC::Exception::PRESENCE_TIMEOUT,
                 OC::Exception::PRESENCE_NOT_HANDLED,
-                OC::Exception::GENERAL_FAULT
+                OC::Exception::GENERAL_FAULT,
+                OC::Exception::DUPLICATE_UUID,
+                OC::Exception::INCONSISTENT_DB
             };
             TEST(OCExceptionTest, ReasonCodeMatches)
             {