IOT-1583: Removing /W3 warning from resource/csdk/security.
[iotivity.git] / resource / csdk / security / provisioning / src / provisioningdatabasemanager.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20
21 #include <stdio.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <limits.h>
26
27 #include "sqlite3.h"
28 #include "logger.h"
29 #include "oic_malloc.h"
30 #include "provisioningdatabasemanager.h"
31 #include "pmutility.h"
32 #include "oic_string.h"
33 #include "utlist.h"
34
35
36 #define DB_FILE "PDM.db"
37
38 #define TAG "OIC_PDM"
39
40 #define PDM_FIRST_INDEX 0
41 #define PDM_SECOND_INDEX 1
42
43 #define PDM_BIND_INDEX_FIRST 1
44 #define PDM_BIND_INDEX_SECOND 2
45 #define PDM_BIND_INDEX_THIRD 3
46
47 #define PDM_CREATE_T_DEVICE_LIST "create table T_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT,\
48                                   UUID BLOB NOT NULL UNIQUE, STATE INT NOT NULL);"
49
50 #define PDM_CREATE_T_DEVICE_LINK  "create table T_DEVICE_LINK_STATE(ID INT NOT NULL, ID2 INT NOT \
51                                    NULL,STATE INT NOT NULL, PRIMARY KEY (ID, ID2));"
52 /**
53  * Macro to verify sqlite success.
54  * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
55  */
56 #define PDM_VERIFY_SQLITE_OK(tag, arg, logLevel, retValue) do{ if (SQLITE_OK != (arg)) \
57             { OIC_LOG_V((logLevel), tag, "Error in " #arg ", Error Message: %s", \
58                sqlite3_errmsg(g_db)); return retValue; }}while(0)
59
60 #define PDM_SQLITE_TRANSACTION_BEGIN "BEGIN TRANSACTION;"
61 #define PDM_SQLITE_TRANSACTION_COMMIT "COMMIT;"
62 #define PDM_SQLITE_TRANSACTION_ROLLBACK "ROLLBACK;"
63
64 #ifdef __GNUC__
65 #if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 6))
66 #define static_assert(value, message) _Static_assert((value) ? 1 : 0, message)
67 #else
68 #define static_assert(value, message)
69 #endif
70 #endif
71 #define PDM_VERIFY_STATEMENT_SIZE(stmt) \
72     static_assert(sizeof(stmt) < INT_MAX, #stmt " must be shorter than INT_MAX.")
73
74 #define PDM_SQLITE_GET_STALE_INFO "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE STATE = ?"
75 #define PDM_SQLITE_GET_STALE_INFO_SIZE (int)sizeof(PDM_SQLITE_GET_STALE_INFO)
76 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_GET_STALE_INFO);
77
78 #define PDM_SQLITE_INSERT_T_DEVICE_LIST "INSERT INTO T_DEVICE_LIST VALUES(?,?,?)"
79 #define PDM_SQLITE_INSERT_T_DEVICE_LIST_SIZE (int)sizeof(PDM_SQLITE_INSERT_T_DEVICE_LIST)
80 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_INSERT_T_DEVICE_LIST);
81
82 #define PDM_SQLITE_GET_ID "SELECT ID FROM T_DEVICE_LIST WHERE UUID like ?"
83 #define PDM_SQLITE_GET_ID_SIZE (int)sizeof(PDM_SQLITE_GET_ID)
84 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_GET_ID);
85
86 #define PDM_SQLITE_INSERT_LINK_DATA "INSERT INTO T_DEVICE_LINK_STATE VALUES(?,?,?)"
87 #define PDM_SQLITE_INSERT_LINK_DATA_SIZE (int)sizeof(PDM_SQLITE_INSERT_LINK_DATA)
88 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_INSERT_LINK_DATA);
89
90 #define PDM_SQLITE_DELETE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? and ID2 = ?"
91 #define PDM_SQLITE_DELETE_LINK_SIZE (int)sizeof(PDM_SQLITE_DELETE_LINK)
92 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_DELETE_LINK);
93
94 #define PDM_SQLITE_DELETE_DEVICE "DELETE FROM T_DEVICE_LIST  WHERE ID = ?"
95 #define PDM_SQLITE_DELETE_DEVICE_SIZE (int)sizeof(PDM_SQLITE_DELETE_DEVICE)
96 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_DELETE_DEVICE);
97
98 #define PDM_SQLITE_UPDATE_LINK "UPDATE T_DEVICE_LINK_STATE SET STATE = ?  WHERE ID = ? and ID2 = ?"
99 #define PDM_SQLITE_UPDATE_LINK_SIZE (int)sizeof(PDM_SQLITE_UPDATE_LINK)
100 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_UPDATE_LINK);
101
102 #define PDM_SQLITE_LIST_ALL_UUID "SELECT UUID FROM T_DEVICE_LIST WHERE STATE = 0"
103 #define PDM_SQLITE_LIST_ALL_UUID_SIZE (int)sizeof(PDM_SQLITE_LIST_ALL_UUID)
104 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_LIST_ALL_UUID);
105
106 #define PDM_SQLITE_GET_UUID "SELECT UUID,STATE FROM T_DEVICE_LIST WHERE ID = ?"
107 #define PDM_SQLITE_GET_UUID_SIZE (int)sizeof(PDM_SQLITE_GET_UUID)
108 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_GET_UUID);
109
110 #define PDM_SQLITE_GET_LINKED_DEVICES "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE \
111                                            (ID = ? or ID2 = ?) and state = 0"
112 #define PDM_SQLITE_GET_LINKED_DEVICES_SIZE (int)sizeof(PDM_SQLITE_GET_LINKED_DEVICES)
113 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_GET_LINKED_DEVICES);
114
115 #define PDM_SQLITE_GET_DEVICE_LINKS "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE \
116                                           ID = ? and ID2 = ? and state = 0"
117 #define PDM_SQLITE_GET_DEVICE_LINKS_SIZE (int)sizeof(PDM_SQLITE_GET_DEVICE_LINKS)
118 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_GET_DEVICE_LINKS);
119
120 #define PDM_SQLITE_UPDATE_DEVICE "UPDATE T_DEVICE_LIST SET STATE = ?  WHERE UUID like ?"
121 #define PDM_SQLITE_UPDATE_DEVICE_SIZE (int)sizeof(PDM_SQLITE_UPDATE_DEVICE)
122 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_UPDATE_DEVICE);
123
124 #define PDM_SQLITE_GET_DEVICE_STATUS "SELECT STATE FROM T_DEVICE_LIST WHERE UUID like ?"
125 #define PDM_SQLITE_GET_DEVICE_STATUS_SIZE (int)sizeof(PDM_SQLITE_GET_DEVICE_STATUS)
126 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_GET_DEVICE_STATUS);
127
128 #define PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE "UPDATE T_DEVICE_LINK_STATE SET STATE = 1\
129                                                           WHERE ID = ? or ID2 = ?"
130 #define PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE_SIZE (int)sizeof(PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE)
131 PDM_VERIFY_STATEMENT_SIZE(PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE);
132
133
134 #define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
135   { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
136
137 #define CHECK_PDM_INIT(tag) do{if(true != gInit)\
138   { OIC_LOG(ERROR, (tag), "PDB is not initialized"); \
139     return OC_STACK_PDM_IS_NOT_INITIALIZED; }}while(0)
140
141 static sqlite3 *g_db = NULL;
142 static bool gInit = false;  /* Only if we can open sqlite db successfully, gInit is true. */
143
144 /**
145  * function to create DB in case DB doesn't exists
146  */
147 static OCStackResult createDB(const char* path)
148 {
149
150     int result = 0;
151     result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
152     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
153
154     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
155     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
156
157     OIC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
158     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
159     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
160
161     OIC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
162     gInit = true;
163     return OC_STACK_OK;
164 }
165
166
167 /**
168  * Function to begin any transaction
169  */
170 static OCStackResult begin()
171 {
172     int res = 0;
173     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
174     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
175     return OC_STACK_OK;
176 }
177
178 /**
179  * Function to commit any transaction
180  */
181 static OCStackResult commit()
182 {
183     int res = 0;
184     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
185     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
186     return OC_STACK_OK;
187 }
188
189 /**
190  * Function to rollback any transaction
191  */
192 static OCStackResult rollback()
193 {
194     int res = 0;
195     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
196     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
197     return OC_STACK_OK;
198 }
199
200 /**
201  * Error log callback called by SQLite stack in case of error
202  */
203 void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
204 {
205     (void) pArg;
206     (void) iErrCode;
207     (void) zMsg;
208     OIC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
209 }
210
211 OCStackResult PDMInit(const char *path)
212 {
213     int rc;
214     const char *dbPath = NULL;
215     if (SQLITE_OK !=  sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
216     {
217         OIC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
218     }
219
220     if (NULL == path || !*path)
221     {
222         dbPath = DB_FILE;
223     }
224     else
225     {
226         dbPath = path;
227     }
228     rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
229     if (SQLITE_OK != rc)
230     {
231         OIC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
232         return createDB(dbPath);
233     }
234     gInit = true;
235     return OC_STACK_OK;
236 }
237
238
239 OCStackResult PDMAddDevice(const OicUuid_t *UUID)
240 {
241     CHECK_PDM_INIT(TAG);
242     if (NULL == UUID)
243     {
244         return OC_STACK_INVALID_PARAM;
245     }
246
247     sqlite3_stmt *stmt = 0;
248     int res =0;
249     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
250                               PDM_SQLITE_INSERT_T_DEVICE_LIST_SIZE, &stmt, NULL);
251     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
252
253     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
254     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
255
256     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_DEVICE_INIT);
257     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
258
259     res = sqlite3_step(stmt);
260     if (SQLITE_DONE != res)
261     {
262         if (SQLITE_CONSTRAINT == res)
263         {
264             //new OCStack result code
265             OIC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
266             sqlite3_finalize(stmt);
267             return OC_STACK_DUPLICATE_UUID;
268         }
269         OIC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
270         sqlite3_finalize(stmt);
271         return OC_STACK_ERROR;
272     }
273     sqlite3_finalize(stmt);
274     return OC_STACK_OK;
275 }
276
277 /**
278  *function to get Id for given UUID
279  */
280 static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
281 {
282     sqlite3_stmt *stmt = 0;
283     int res = 0;
284     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, PDM_SQLITE_GET_ID_SIZE,
285                              &stmt, NULL);
286     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
287
288     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
289     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
290
291     OIC_LOG(DEBUG, TAG, "Binding Done");
292     while (SQLITE_ROW == sqlite3_step(stmt))
293     {
294         int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
295         OIC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
296         *id = tempId;
297         sqlite3_finalize(stmt);
298         return OC_STACK_OK;
299     }
300     sqlite3_finalize(stmt);
301     return OC_STACK_INVALID_PARAM;
302 }
303
304 /**
305  * Function to check duplication of device's Device ID.
306  */
307 OCStackResult PDMIsDuplicateDevice(const OicUuid_t* UUID, bool *result)
308 {
309
310     CHECK_PDM_INIT(TAG);
311     if (NULL == UUID || NULL == result)
312     {
313         OIC_LOG(ERROR, TAG, "UUID or result is NULL");
314         return OC_STACK_INVALID_PARAM;
315     }
316     sqlite3_stmt *stmt = 0;
317     int res = 0;
318     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, PDM_SQLITE_GET_ID_SIZE,
319                              &stmt, NULL);
320     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
321
322     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
323     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
324
325     OIC_LOG(DEBUG, TAG, "Binding Done");
326     bool retValue = false;
327     while(SQLITE_ROW == sqlite3_step(stmt))
328     {
329         OIC_LOG(INFO, TAG, "Duplicated UUID");
330         retValue = true;
331     }
332
333     sqlite3_finalize(stmt);
334     *result = retValue;
335     return OC_STACK_OK;
336 }
337
338 /**
339  * Function to add link in sqlite
340  */
341 static OCStackResult addlink(int id1, int id2)
342 {
343     sqlite3_stmt *stmt = 0;
344     int res = 0;
345     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_LINK_DATA,
346                               PDM_SQLITE_INSERT_LINK_DATA_SIZE, &stmt, NULL);
347     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
348
349     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
350     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
351
352     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
353     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
354
355     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_DEVICE_ACTIVE);
356     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
357
358     if (sqlite3_step(stmt) != SQLITE_DONE)
359     {
360         OIC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
361         sqlite3_finalize(stmt);
362         return OC_STACK_ERROR;
363     }
364     sqlite3_finalize(stmt);
365     return OC_STACK_OK;
366 }
367
368 OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
369 {
370     CHECK_PDM_INIT(TAG);
371     if (NULL == UUID1 || NULL == UUID2)
372     {
373         OIC_LOG(ERROR, TAG, "Invalid PARAM");
374         return  OC_STACK_INVALID_PARAM;
375     }
376
377     PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
378     if (OC_STACK_OK != PDMGetDeviceState(UUID1, &state))
379     {
380         OIC_LOG(ERROR, TAG, "Internal error occured");
381         return OC_STACK_ERROR;
382     }
383     if (PDM_DEVICE_ACTIVE != state)
384     {
385         OIC_LOG_V(ERROR, TAG, "UUID1: Device state is not active : %d", state);
386         return OC_STACK_INVALID_PARAM;
387     }
388
389     state = PDM_DEVICE_UNKNOWN;
390     if (OC_STACK_OK != PDMGetDeviceState(UUID2, &state))
391     {
392         OIC_LOG(ERROR, TAG, "Internal error occured");
393         return OC_STACK_ERROR;
394     }
395     if (PDM_DEVICE_ACTIVE != state)
396     {
397         OIC_LOG_V(ERROR, TAG, "UUID2: Device state is not active : %d", state);
398         return OC_STACK_INVALID_PARAM;
399     }
400
401     int id1 = 0;
402     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
403     {
404         OIC_LOG(ERROR, TAG, "Requested value not found");
405         return OC_STACK_INVALID_PARAM;
406     }
407     int id2 = 0;
408     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
409     {
410         OIC_LOG(ERROR, TAG, "Requested value not found");
411         return OC_STACK_INVALID_PARAM;
412     }
413
414     ASCENDING_ORDER(id1, id2);
415     return addlink(id1, id2);
416 }
417
418 /**
419  * Function to remove created link
420  */
421 static OCStackResult removeLink(int id1, int id2)
422 {
423     int res = 0;
424     sqlite3_stmt *stmt = 0;
425     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_LINK,
426                              PDM_SQLITE_DELETE_LINK_SIZE, &stmt, NULL);
427     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
428
429     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
430     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
431
432     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
433     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
434
435     if (SQLITE_DONE != sqlite3_step(stmt))
436     {
437         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
438         sqlite3_finalize(stmt);
439         return OC_STACK_ERROR;
440     }
441     sqlite3_finalize(stmt);
442     return OC_STACK_OK;
443 }
444
445 OCStackResult PDMUnlinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
446 {
447     CHECK_PDM_INIT(TAG);
448     if (NULL == UUID1 || NULL == UUID2)
449     {
450         OIC_LOG(ERROR, TAG, "Invalid PARAM");
451         return  OC_STACK_INVALID_PARAM;
452     }
453
454     int id1 = 0;
455     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
456     {
457         OIC_LOG(ERROR, TAG, "Requested value not found");
458         return OC_STACK_INVALID_PARAM;
459     }
460
461     int id2 = 0;
462     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
463     {
464         OIC_LOG(ERROR, TAG, "Requested value not found");
465         return OC_STACK_INVALID_PARAM;
466     }
467     ASCENDING_ORDER(id1, id2);
468     return removeLink(id1, id2);
469 }
470
471 static OCStackResult removeFromDeviceList(int id)
472 {
473     sqlite3_stmt *stmt = 0;
474     int res = 0;
475     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_DEVICE,
476                               PDM_SQLITE_DELETE_DEVICE_SIZE, &stmt, NULL);
477     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
478
479     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
480     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
481
482     if (sqlite3_step(stmt) != SQLITE_DONE)
483     {
484         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
485         sqlite3_finalize(stmt);
486         return OC_STACK_ERROR;
487     }
488     sqlite3_finalize(stmt);
489     return OC_STACK_OK;
490 }
491
492 OCStackResult PDMDeleteDevice(const OicUuid_t *UUID)
493 {
494     CHECK_PDM_INIT(TAG);
495     if (NULL == UUID)
496     {
497         return OC_STACK_INVALID_PARAM;
498     }
499     int id = 0;
500     if (OC_STACK_OK != getIdForUUID(UUID, &id))
501     {
502         OIC_LOG(ERROR, TAG, "Requested value not found");
503         return OC_STACK_INVALID_PARAM;
504     }
505     begin();
506     if(OC_STACK_OK != removeFromDeviceList(id))
507     {
508         rollback();
509         OIC_LOG(ERROR, TAG, "Requested value not found");
510         return OC_STACK_ERROR;
511     }
512     commit();
513     return OC_STACK_OK;
514 }
515
516
517 static OCStackResult updateLinkState(int id1, int id2, int state)
518 {
519     sqlite3_stmt *stmt = 0;
520     int res = 0 ;
521     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK,
522                               PDM_SQLITE_UPDATE_LINK_SIZE, &stmt, NULL);
523     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
524
525     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
526     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
527
528     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id1);
529     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
530
531     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, id2);
532     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
533
534     if (SQLITE_DONE != sqlite3_step(stmt))
535     {
536         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
537         sqlite3_finalize(stmt);
538         return OC_STACK_ERROR;
539     }
540     sqlite3_finalize(stmt);
541     return OC_STACK_OK;
542 }
543
544 OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2)
545 {
546     CHECK_PDM_INIT(TAG);
547     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2)
548     {
549         OIC_LOG(ERROR, TAG, "Invalid PARAM");
550         return  OC_STACK_INVALID_PARAM;
551     }
552
553     int id1 = 0;
554     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
555     {
556         OIC_LOG(ERROR, TAG, "Requested value not found");
557         return OC_STACK_INVALID_PARAM;
558     }
559
560     int id2 = 0;
561     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
562     {
563         OIC_LOG(ERROR, TAG, "Requested value not found");
564         return OC_STACK_INVALID_PARAM;
565     }
566     ASCENDING_ORDER(id1, id2);
567     return updateLinkState(id1, id2, PDM_DEVICE_STALE);
568 }
569
570 OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
571 {
572     CHECK_PDM_INIT(TAG);
573     if (NULL != *uuidList)
574     {
575         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
576         return OC_STACK_INVALID_PARAM;
577     }
578     sqlite3_stmt *stmt = 0;
579     int res = 0;
580     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_LIST_ALL_UUID,
581                               PDM_SQLITE_LIST_ALL_UUID_SIZE, &stmt, NULL);
582     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
583
584     size_t counter  = 0;
585     while (SQLITE_ROW == sqlite3_step(stmt))
586     {
587         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
588         OicUuid_t *uid = (OicUuid_t *)ptr;
589         OCUuidList_t *temp = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
590         if (NULL == temp)
591         {
592             OIC_LOG_V(ERROR, TAG, "Memory allocation problem");
593             sqlite3_finalize(stmt);
594             return OC_STACK_NO_MEMORY;
595         }
596         memcpy(&temp->dev.id, uid->id, UUID_LENGTH);
597         LL_PREPEND(*uuidList,temp);
598         ++counter;
599     }
600     *numOfDevices = counter;
601     sqlite3_finalize(stmt);
602     return OC_STACK_OK;
603 }
604
605 static OCStackResult getUUIDforId(int id, OicUuid_t *uid, bool *result)
606 {
607     sqlite3_stmt *stmt = 0;
608     int res = 0;
609     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_UUID,
610                               PDM_SQLITE_GET_UUID_SIZE, &stmt, NULL);
611     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
612
613     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
614     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
615
616     while (SQLITE_ROW == sqlite3_step(stmt))
617     {
618         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
619         memcpy(uid, ptr, sizeof(OicUuid_t));
620
621         int temp = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
622         if(PDM_DEVICE_STALE == temp)
623         {
624             if(result)
625             {
626                 *result = true;
627             }
628         }
629         else
630         {
631             if(result)
632             {
633                 *result = false;
634             }
635         }
636         sqlite3_finalize(stmt);
637         return OC_STACK_OK;
638     }
639     sqlite3_finalize(stmt);
640     return OC_STACK_INVALID_PARAM;
641 }
642
643 OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST, size_t *numOfDevices)
644 {
645     CHECK_PDM_INIT(TAG);
646     if (NULL == UUID || NULL == numOfDevices || !UUIDLIST)
647     {
648         return OC_STACK_INVALID_PARAM;
649     }
650     if (NULL != *UUIDLIST )
651     {
652         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
653         return OC_STACK_INVALID_PARAM;
654     }
655     PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
656     OCStackResult ret = PDMGetDeviceState(UUID, &state);
657     if (OC_STACK_OK != ret)
658     {
659         OIC_LOG(ERROR, TAG, "Internal error occured");
660         return OC_STACK_ERROR;
661     }
662     if (PDM_DEVICE_ACTIVE != state)
663     {
664         OIC_LOG_V(ERROR, TAG, "Device state is not active : %d", state);
665         return OC_STACK_INVALID_PARAM;
666     }
667     int id = 0;
668     if (OC_STACK_OK != getIdForUUID(UUID, &id))
669     {
670         OIC_LOG(ERROR, TAG, "Requested value not found");
671         return OC_STACK_INVALID_PARAM;
672     }
673
674
675     sqlite3_stmt *stmt = 0;
676     int res = 0;
677     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
678                               PDM_SQLITE_GET_LINKED_DEVICES_SIZE, &stmt, NULL);
679     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
680
681     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
682     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
683
684     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
685     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
686
687     size_t counter  = 0;
688     while (SQLITE_ROW == sqlite3_step(stmt))
689     {
690         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
691         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
692
693         OicUuid_t temp = {{0,}};
694         if (i1 != id)
695         {
696             getUUIDforId(i1, &temp, NULL);
697         }
698         if (i2 != id)
699         {
700             getUUIDforId(i2, &temp, NULL);
701         }
702
703         OCUuidList_t *tempNode = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
704         if (NULL == tempNode)
705         {
706             OIC_LOG(ERROR, TAG, "No Memory");
707             sqlite3_finalize(stmt);
708             return OC_STACK_NO_MEMORY;
709         }
710         memcpy(&tempNode->dev.id, &temp.id, UUID_LENGTH);
711         LL_PREPEND(*UUIDLIST,tempNode);
712         ++counter;
713     }
714     *numOfDevices = counter;
715      sqlite3_finalize(stmt);
716      return OC_STACK_OK;
717 }
718
719 OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *numOfDevices)
720 {
721     CHECK_PDM_INIT(TAG);
722     if (NULL != *staleDevList)
723     {
724         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
725         return OC_STACK_INVALID_PARAM;
726     }
727
728     sqlite3_stmt *stmt = 0;
729     int res = 0;
730     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_STALE_INFO,
731                               PDM_SQLITE_GET_STALE_INFO_SIZE, &stmt, NULL);
732     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
733
734     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_DEVICE_STALE);
735     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
736
737     size_t counter  = 0;
738     while (SQLITE_ROW == sqlite3_step(stmt))
739     {
740         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
741         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
742         OicUuid_t temp1 = {{0,}};
743         OicUuid_t temp2 = {{0,}};;
744         getUUIDforId(i1, &temp1, NULL);
745         getUUIDforId(i2, &temp2, NULL);
746
747         OCPairList_t *tempNode = (OCPairList_t *) OICCalloc(1, sizeof(OCPairList_t));
748         if (NULL == tempNode)
749         {
750             OIC_LOG(ERROR, TAG, "No Memory");
751             sqlite3_finalize(stmt);
752             return OC_STACK_NO_MEMORY;
753         }
754         memcpy(&tempNode->dev.id, &temp1.id, UUID_LENGTH);
755         memcpy(&tempNode->dev2.id, &temp2.id, UUID_LENGTH);
756         LL_PREPEND(*staleDevList, tempNode);
757         ++counter;
758     }
759     *numOfDevices = counter;
760     sqlite3_finalize(stmt);
761     return OC_STACK_OK;
762 }
763
764 OCStackResult PDMClose()
765 {
766     CHECK_PDM_INIT(TAG);
767     int res = 0;
768     res = sqlite3_close(g_db);
769     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
770     return OC_STACK_OK;
771 }
772
773 void PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
774 {
775     if(ptr)
776     {
777         OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
778         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
779         {
780             LL_DELETE(ptr, tmp1);
781             OICFree(tmp1);
782         }
783     }
784 }
785
786 void PDMDestoryStaleLinkList(OCPairList_t* ptr)
787 {
788     if(ptr)
789     {
790         OCPairList_t *tmp1 = NULL,*tmp2=NULL;
791         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
792         {
793             LL_DELETE(ptr, tmp1);
794             OICFree(tmp1);
795         }
796     }
797 }
798
799 OCStackResult PDMIsLinkExists(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2,
800                                bool* result)
801 {
802     CHECK_PDM_INIT(TAG);
803     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2 || NULL == result)
804     {
805         return OC_STACK_INVALID_PARAM;
806     }
807     int id1 = 0;
808     int id2 = 0;
809     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
810     {
811         OIC_LOG(ERROR, TAG, "Requested value not found");
812         return OC_STACK_INVALID_PARAM;
813     }
814
815     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
816     {
817         OIC_LOG(ERROR, TAG, "Requested value not found");
818         return OC_STACK_INVALID_PARAM;
819     }
820
821     PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
822     if (OC_STACK_OK != PDMGetDeviceState(uuidOfDevice1, &state))
823     {
824         OIC_LOG(ERROR, TAG, "uuidOfDevice1:Internal error occured");
825         return OC_STACK_ERROR;
826     }
827     if (PDM_DEVICE_ACTIVE != state)
828     {
829         OIC_LOG_V(ERROR, TAG, "uuidOfDevice1:Device state is not active : %d", state);
830         return OC_STACK_INVALID_PARAM;
831     }
832
833     state = PDM_DEVICE_UNKNOWN;
834     if (OC_STACK_OK != PDMGetDeviceState(uuidOfDevice2, &state))
835     {
836         OIC_LOG(ERROR, TAG, "uuidOfDevice2:Internal error occured");
837         return OC_STACK_ERROR;
838     }
839     if (PDM_DEVICE_ACTIVE != state)
840     {
841         OIC_LOG_V(ERROR, TAG, "uuidOfDevice2:Device state is not active : %d", state);
842         return OC_STACK_INVALID_PARAM;
843     }
844
845     ASCENDING_ORDER(id1, id2);
846
847     sqlite3_stmt *stmt = 0;
848     int res = 0;
849     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_LINKS,
850                               PDM_SQLITE_GET_DEVICE_LINKS_SIZE, &stmt, NULL);
851     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
852
853     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
854     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
855
856     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
857     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
858
859     bool ret = false;
860     while(SQLITE_ROW == sqlite3_step(stmt))
861     {
862         OIC_LOG(INFO, TAG, "Link already exists between devices");
863         ret = true;
864     }
865     sqlite3_finalize(stmt);
866     *result = ret;
867     return OC_STACK_OK;
868 }
869
870 static OCStackResult updateDeviceState(const OicUuid_t *uuid, PdmDeviceState_t state)
871 {
872     sqlite3_stmt *stmt = 0;
873     int res = 0 ;
874     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_DEVICE,
875                               PDM_SQLITE_UPDATE_DEVICE_SIZE, &stmt, NULL);
876     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
877
878     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
879     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
880
881     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, uuid, UUID_LENGTH, SQLITE_STATIC);
882     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
883
884     if (SQLITE_DONE != sqlite3_step(stmt))
885     {
886         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
887         sqlite3_finalize(stmt);
888         return OC_STACK_ERROR;
889     }
890     sqlite3_finalize(stmt);
891     return OC_STACK_OK;
892 }
893
894 static OCStackResult updateLinkForStaleDevice(const OicUuid_t *devUuid)
895 {
896     sqlite3_stmt *stmt = 0;
897     int res = 0 ;
898
899     int id = 0;
900     if (OC_STACK_OK != getIdForUUID(devUuid, &id))
901     {
902         OIC_LOG(ERROR, TAG, "Requested value not found");
903         return OC_STACK_INVALID_PARAM;
904     }
905
906     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE,
907                               PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE_SIZE,
908                                &stmt, NULL);
909     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
910
911     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
912     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
913
914     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
915     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
916
917     if (SQLITE_DONE != sqlite3_step(stmt))
918     {
919         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
920         sqlite3_finalize(stmt);
921         return OC_STACK_ERROR;
922     }
923     sqlite3_finalize(stmt);
924     return OC_STACK_OK;
925 }
926
927 OCStackResult PDMSetDeviceState(const OicUuid_t* uuid, PdmDeviceState_t state)
928 {
929     OCStackResult res = OC_STACK_ERROR;
930
931     CHECK_PDM_INIT(TAG);
932     if (NULL == uuid)
933     {
934         OIC_LOG(ERROR, TAG, "Invalid PARAM");
935         return  OC_STACK_INVALID_PARAM;
936     }
937     begin();
938
939     if(PDM_DEVICE_STALE == state)
940     {
941         res = updateLinkForStaleDevice(uuid);
942         if (OC_STACK_OK != res)
943         {
944             rollback();
945             OIC_LOG(ERROR, TAG, "unable to update links");
946             return res;
947         }
948     }
949
950     res = updateDeviceState(uuid, state);
951     if (OC_STACK_OK != res)
952     {
953         rollback();
954         OIC_LOG(ERROR, TAG, "unable to update device state");
955         return res;
956     }
957     commit();
958     return OC_STACK_OK;
959 }
960
961 OCStackResult PDMGetDeviceState(const OicUuid_t *uuid, PdmDeviceState_t* result)
962 {
963     if (NULL == uuid || NULL == result)
964     {
965         OIC_LOG(ERROR, TAG, "UUID or result is NULL");
966         return OC_STACK_INVALID_PARAM;
967     }
968
969     sqlite3_stmt *stmt = 0;
970     int res = 0;
971     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_STATUS, PDM_SQLITE_GET_DEVICE_STATUS_SIZE,
972                               &stmt, NULL);
973     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
974
975     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, uuid, UUID_LENGTH, SQLITE_STATIC);
976     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
977
978     *result = PDM_DEVICE_UNKNOWN;
979     while(SQLITE_ROW == sqlite3_step(stmt))
980     {
981         int tempStaleStateFromDb = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
982         OIC_LOG_V(DEBUG, TAG, "Device state is %d", tempStaleStateFromDb);
983         *result = (PdmDeviceState_t)tempStaleStateFromDb;
984     }
985     sqlite3_finalize(stmt);
986     return OC_STACK_OK;
987 }
988