Fixed Tizen build error with SECURED=1
[platform/upstream/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
26 #include "sqlite3.h"
27 #include "logger.h"
28 #include "oic_malloc.h"
29 #include "provisioningdatabasemanager.h"
30 #include "pmutility.h"
31 #include "oic_string.h"
32 #include "utlist.h"
33
34
35 #define DB_FILE "PDM.db"
36
37 #define TAG "PDM"
38
39 #define PDM_STALE_STATE 1
40 #define PDM_ACTIVE_STATE 0
41
42 #define PDM_FIRST_INDEX 0
43 #define PDM_SECOND_INDEX 1
44
45 #define PDM_BIND_INDEX_FIRST 1
46 #define PDM_BIND_INDEX_SECOND 2
47 #define PDM_BIND_INDEX_THIRD 3
48
49 #define PDM_CREATE_T_DEVICE_LIST "create table T_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT,\
50                                   UUID BLOB NOT NULL UNIQUE);"
51
52 #define PDM_CREATE_T_DEVICE_LINK  "create table T_DEVICE_LINK_STATE(ID INT NOT NULL, ID2 INT NOT \
53                                    NULL,STATE INT NOT NULL, PRIMARY KEY (ID, ID2));"
54 /**
55  * Macro to verify sqlite success.
56  * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
57  */
58 #define PDM_VERIFY_SQLITE_OK(tag, arg, logLevel, retValue) do{ if (SQLITE_OK != (arg)) \
59             { OC_LOG_V((logLevel), tag, "Error in " #arg ", Error Message: %s", \
60                sqlite3_errmsg(g_db)); return retValue; }}while(0)
61
62 #define PDM_SQLITE_TRANSACTION_BEGIN "BEGIN TRANSACTION;"
63 #define PDM_SQLITE_TRANSACTION_COMMIT "COMMIT;"
64 #define PDM_SQLITE_TRANSACTION_ROLLBACK "ROLLBACK;"
65 #define PDM_SQLITE_GET_STALE_INFO "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE STATE = ?"
66 #define PDM_SQLITE_INSERT_T_DEVICE_LIST "INSERT INTO T_DEVICE_LIST VALUES(?,?)"
67 #define PDM_SQLITE_GET_ID "SELECT ID FROM T_DEVICE_LIST WHERE UUID like ?"
68 #define PDM_SQLITE_INSERT_LINK_DATA "INSERT INTO T_DEVICE_LINK_STATE VALUES(?,?,?)"
69 #define PDM_SQLITE_DELETE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? and ID2 = ?"
70 #define PDM_SQLITE_DELETE_DEVICE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
71 #define PDM_SQLITE_DELETE_DEVICE "DELETE FROM T_DEVICE_LIST  WHERE ID = ?"
72 #define PDM_SQLITE_UPDATE_LINK "UPDATE T_DEVICE_LINK_STATE SET STATE = ?  WHERE ID = ? and ID2 = ?"
73 #define PDM_SQLITE_LIST_ALL_UUID "SELECT UUID FROM T_DEVICE_LIST"
74 #define PDM_SQLITE_GET_UUID "SELECT UUID FROM T_DEVICE_LIST WHERE ID = ?"
75 #define PDM_SQLITE_GET_LINKED_DEVICES "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
76
77 #define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
78   { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
79
80 #define CHECK_PDM_INIT(tag) do{if(true != gInit)\
81   { OC_LOG(ERROR, (tag), "PDB is not initialized"); \
82     return OC_STACK_PDM_IS_NOT_INITIALIZED; }}while(0)
83
84 static sqlite3 *g_db = NULL;
85 static bool gInit = false;  /* Only if we can open sqlite db successfully, gInit is true. */
86
87 /**
88  * function to create DB in case DB doesn't exists
89  */
90 static OCStackResult createDB(const char* path)
91 {
92
93     int result = 0;
94     result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
95     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
96
97     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
98     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
99
100     OC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
101     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
102     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
103
104     OC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
105     gInit = true;
106     return OC_STACK_OK;
107 }
108
109
110 /**
111  * Function to begin any transaction
112  */
113 static OCStackResult begin()
114 {
115     int res = 0;
116     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
117     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
118     return OC_STACK_OK;
119 }
120
121 /**
122  * Function to commit any transaction
123  */
124 static OCStackResult commit()
125 {
126     int res = 0;
127     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
128     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
129     return OC_STACK_OK;
130 }
131
132 /**
133  * Function to rollback any transaction
134  */
135 static OCStackResult rollback()
136 {
137     int res = 0;
138     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
139     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
140     return OC_STACK_OK;
141 }
142
143 /**
144  * Error log callback called by SQLite stack in case of error
145  */
146 void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
147 {
148     (void) pArg;
149     (void) iErrCode;
150     (void) zMsg;
151     OC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
152 }
153
154 OCStackResult PDMInit(const char *path)
155 {
156     int rc;
157     const char *dbPath = NULL;
158     if (SQLITE_OK !=  sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
159     {
160         OC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
161     }
162
163     if (NULL == path || !*path)
164     {
165         dbPath = DB_FILE;
166     }
167     else
168     {
169         dbPath = path;
170     }
171     rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
172     if (SQLITE_OK != rc)
173     {
174         OC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
175         return createDB(dbPath);
176     }
177     gInit = true;
178     return OC_STACK_OK;
179 }
180
181
182 OCStackResult PDMAddDevice(const OicUuid_t *UUID)
183 {
184     CHECK_PDM_INIT(TAG);
185     if (NULL == UUID)
186     {
187         return OC_STACK_INVALID_PARAM;
188     }
189
190     sqlite3_stmt *stmt = 0;
191     int res =0;
192     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
193                               strlen(PDM_SQLITE_INSERT_T_DEVICE_LIST) + 1, &stmt, NULL);
194     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
195
196     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
197     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
198
199     res = sqlite3_step(stmt);
200     if (SQLITE_DONE != res)
201     {
202         if (SQLITE_CONSTRAINT == res)
203         {
204             //new OCStack result code
205             OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
206             sqlite3_finalize(stmt);
207             return OC_STACK_DUPLICATE_UUID;
208         }
209         OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
210         sqlite3_finalize(stmt);
211         return OC_STACK_ERROR;
212     }
213     sqlite3_finalize(stmt);
214     return OC_STACK_OK;
215 }
216
217 /**
218  *function to get Id for given UUID
219  */
220 static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
221 {
222     sqlite3_stmt *stmt = 0;
223     int res = 0;
224     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
225     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
226
227     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
228     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
229
230     OC_LOG(DEBUG, TAG, "Binding Done");
231     while (SQLITE_ROW == sqlite3_step(stmt))
232     {
233         int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
234         OC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
235         *id = tempId;
236         sqlite3_finalize(stmt);
237         return OC_STACK_OK;
238     }
239     sqlite3_finalize(stmt);
240     return OC_STACK_INVALID_PARAM;
241 }
242
243 /**
244  * Function to check duplication of device's Device ID.
245  */
246 OCStackResult PDMIsDuplicateDevice(const OicUuid_t* UUID, bool *result)
247 {
248
249     CHECK_PDM_INIT(TAG);
250     if (NULL == UUID || NULL == result)
251     {
252         OC_LOG(ERROR, TAG, "UUID or result is NULL");
253         return OC_STACK_INVALID_PARAM;
254     }
255     sqlite3_stmt *stmt = 0;
256     int res = 0;
257     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
258     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
259
260     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
261     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
262
263     OC_LOG(DEBUG, TAG, "Binding Done");
264     bool retValue = false;
265     while(SQLITE_ROW == sqlite3_step(stmt))
266     {
267         OC_LOG(INFO, TAG, "Duplicated UUID");
268         retValue = true;
269     }
270
271     sqlite3_finalize(stmt);
272     *result = retValue;
273     return OC_STACK_OK;
274 }
275
276 /**
277  * Function to add link in sqlite
278  */
279 static OCStackResult addlink(int id1, int id2)
280 {
281     sqlite3_stmt *stmt = 0;
282     int res = 0;
283     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_LINK_DATA,
284                               strlen(PDM_SQLITE_INSERT_LINK_DATA) + 1, &stmt, NULL);
285     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
286
287     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
288     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
289
290     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
291     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
292
293     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
294     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
295
296     if (sqlite3_step(stmt) != SQLITE_DONE)
297     {
298         OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
299         sqlite3_finalize(stmt);
300         return OC_STACK_ERROR;
301     }
302     sqlite3_finalize(stmt);
303     return OC_STACK_OK;
304 }
305
306 OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
307 {
308     CHECK_PDM_INIT(TAG);
309     if (NULL == UUID1 || NULL == UUID2)
310     {
311         OC_LOG(ERROR, TAG, "Invalid PARAM");
312         return  OC_STACK_INVALID_PARAM;
313     }
314     int id1 = 0;
315     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
316     {
317         OC_LOG(ERROR, TAG, "Requested value not found");
318         return OC_STACK_INVALID_PARAM;
319     }
320     int id2 = 0;
321     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
322     {
323         OC_LOG(ERROR, TAG, "Requested value not found");
324         return OC_STACK_INVALID_PARAM;
325     }
326     ASCENDING_ORDER(id1, id2);
327     return addlink(id1, id2);
328 }
329
330 /**
331  * Function to remove created link
332  */
333 static OCStackResult removeLink(int id1, int id2)
334 {
335     int res = 0;
336     sqlite3_stmt *stmt = 0;
337     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_LINK, strlen(PDM_SQLITE_DELETE_LINK) + 1, &stmt, NULL);
338     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
339
340     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
341     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
342
343     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
344     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
345
346     if (SQLITE_DONE != sqlite3_step(stmt))
347     {
348         OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
349         sqlite3_finalize(stmt);
350         return OC_STACK_ERROR;
351     }
352     sqlite3_finalize(stmt);
353     return OC_STACK_OK;
354 }
355
356 OCStackResult PDMUnlinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
357 {
358     CHECK_PDM_INIT(TAG);
359     if (NULL == UUID1 || NULL == UUID2)
360     {
361         OC_LOG(ERROR, TAG, "Invalid PARAM");
362         return  OC_STACK_INVALID_PARAM;
363     }
364
365     int id1 = 0;
366     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
367     {
368         OC_LOG(ERROR, TAG, "Requested value not found");
369         return OC_STACK_INVALID_PARAM;
370     }
371
372     int id2 = 0;
373     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
374     {
375         OC_LOG(ERROR, TAG, "Requested value not found");
376         return OC_STACK_INVALID_PARAM;
377     }
378     ASCENDING_ORDER(id1, id2);
379     return removeLink(id1, id2);
380 }
381
382 static OCStackResult removeFromDeviceList(int id)
383 {
384     sqlite3_stmt *stmt = 0;
385     int res = 0;
386     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_DEVICE,
387                               strlen(PDM_SQLITE_DELETE_DEVICE) + 1, &stmt, NULL);
388     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
389
390     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
391     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
392
393     if (sqlite3_step(stmt) != SQLITE_DONE)
394     {
395         OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
396         sqlite3_finalize(stmt);
397         return OC_STACK_ERROR;
398     }
399     sqlite3_finalize(stmt);
400     return OC_STACK_OK;
401 }
402
403 OCStackResult PDMDeleteDevice(const OicUuid_t *UUID)
404 {
405     CHECK_PDM_INIT(TAG);
406     if (NULL == UUID)
407     {
408         return OC_STACK_INVALID_PARAM;
409     }
410     int id = 0;
411     if (OC_STACK_OK != getIdForUUID(UUID, &id))
412     {
413         OC_LOG(ERROR, TAG, "Requested value not found");
414         return OC_STACK_INVALID_PARAM;
415     }
416     begin();
417     if(OC_STACK_OK != removeFromDeviceList(id))
418     {
419         rollback();
420         OC_LOG(ERROR, TAG, "Requested value not found");
421         return OC_STACK_ERROR;
422     }
423     commit();
424     return OC_STACK_OK;
425 }
426
427
428 static OCStackResult updateLinkState(int id1, int id2, int state)
429 {
430     sqlite3_stmt *stmt = 0;
431     int res = 0 ;
432     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK,
433                               strlen(PDM_SQLITE_UPDATE_LINK) + 1, &stmt, NULL);
434     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
435
436     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
437     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
438
439     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id1);
440     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
441
442     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, id2);
443     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
444
445     if (SQLITE_DONE != sqlite3_step(stmt))
446     {
447         OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
448         sqlite3_finalize(stmt);
449         return OC_STACK_ERROR;
450     }
451     sqlite3_finalize(stmt);
452     return OC_STACK_OK;
453 }
454
455 OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2)
456 {
457     CHECK_PDM_INIT(TAG);
458     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2)
459     {
460         OC_LOG(ERROR, TAG, "Invalid PARAM");
461         return  OC_STACK_INVALID_PARAM;
462     }
463
464     int id1 = 0;
465     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
466     {
467         OC_LOG(ERROR, TAG, "Requested value not found");
468         return OC_STACK_INVALID_PARAM;
469     }
470
471     int id2 = 0;
472     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
473     {
474         OC_LOG(ERROR, TAG, "Requested value not found");
475         return OC_STACK_INVALID_PARAM;
476     }
477     ASCENDING_ORDER(id1, id2);
478     return updateLinkState(id1, id2, PDM_STALE_STATE);
479
480 }
481
482 OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
483 {
484     CHECK_PDM_INIT(TAG);
485     if (NULL != *uuidList)
486     {
487         OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
488         return OC_STACK_INVALID_PARAM;
489     }
490     sqlite3_stmt *stmt = 0;
491     int res = 0;
492     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_LIST_ALL_UUID,
493                               strlen(PDM_SQLITE_LIST_ALL_UUID) + 1, &stmt, NULL);
494     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
495
496     int counter  = 0;
497     while (SQLITE_ROW == sqlite3_step(stmt))
498     {
499
500         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
501         OicUuid_t *uid = (OicUuid_t *)ptr;
502         OCUuidList_t *temp = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
503         if (NULL == temp)
504         {
505             OC_LOG_V(ERROR, TAG, "Memory allocation problem");
506             sqlite3_finalize(stmt);
507             return OC_STACK_NO_MEMORY;
508         }
509         memcpy(&temp->dev.id, uid->id, UUID_LENGTH);
510         LL_PREPEND(*uuidList,temp);
511         ++counter;
512     }
513     *numOfDevices = counter;
514     sqlite3_finalize(stmt);
515     return OC_STACK_OK;
516 }
517
518 static OCStackResult getUUIDforId(int id, OicUuid_t *uid)
519 {
520     sqlite3_stmt *stmt = 0;
521     int res = 0;
522     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_UUID,
523                               strlen(PDM_SQLITE_GET_UUID) + 1, &stmt, NULL);
524     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
525
526     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
527     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
528
529     while (SQLITE_ROW == sqlite3_step(stmt))
530     {
531         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
532         memcpy(uid, ptr, sizeof(OicUuid_t));
533     }
534     sqlite3_finalize(stmt);
535     return OC_STACK_OK;
536 }
537
538 OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST, size_t *numOfDevices)
539 {
540     CHECK_PDM_INIT(TAG);
541     if (NULL != *UUIDLIST)
542     {
543         OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
544         return OC_STACK_INVALID_PARAM;
545     }
546     if (NULL == UUID)
547     {
548         return OC_STACK_INVALID_PARAM;
549     }
550     int id = 0;
551     if (OC_STACK_OK != getIdForUUID(UUID, &id))
552     {
553         OC_LOG(ERROR, TAG, "Requested value not found");
554         return OC_STACK_INVALID_PARAM;
555     }
556
557     sqlite3_stmt *stmt = 0;
558     int res = 0;
559     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
560                               strlen(PDM_SQLITE_GET_LINKED_DEVICES) + 1, &stmt, NULL);
561     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
562
563     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
564     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
565
566     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
567     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
568
569     int counter  = 0;
570     while (SQLITE_ROW == sqlite3_step(stmt))
571     {
572         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
573         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
574
575         OicUuid_t temp = {{0,}};
576         if (i1 != id)
577         {
578             getUUIDforId(i1, &temp);
579         }
580         if (i2 != id)
581         {
582             getUUIDforId(i2, &temp);
583         }
584
585         OCUuidList_t *tempNode = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
586         if (NULL == tempNode)
587         {
588             OC_LOG(ERROR, TAG, "No Memory");
589             sqlite3_finalize(stmt);
590             return OC_STACK_NO_MEMORY;
591         }
592         memcpy(&tempNode->dev.id, &temp.id, UUID_LENGTH);
593         LL_PREPEND(*UUIDLIST,tempNode);
594         ++counter;
595     }
596     *numOfDevices = counter;
597      sqlite3_finalize(stmt);
598      return OC_STACK_OK;
599 }
600
601 OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *numOfDevices)
602 {
603     CHECK_PDM_INIT(TAG);
604     if (NULL != *staleDevList)
605     {
606         OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
607         return OC_STACK_INVALID_PARAM;
608     }
609
610     sqlite3_stmt *stmt = 0;
611     int res = 0;
612     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_STALE_INFO,
613                               strlen(PDM_SQLITE_GET_STALE_INFO) + 1, &stmt, NULL);
614     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
615
616     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_STALE_STATE);
617     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
618
619     int counter  = 0;
620     while (SQLITE_ROW == sqlite3_step(stmt))
621     {
622         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
623         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
624         OicUuid_t temp1 = {{0,}};
625         OicUuid_t temp2 = {{0,}};;
626         getUUIDforId(i1, &temp1);
627         getUUIDforId(i2, &temp2);
628
629         OCPairList_t *tempNode = (OCPairList_t *) OICCalloc(1, sizeof(OCPairList_t));
630         if (NULL == tempNode)
631         {
632             OC_LOG(ERROR, TAG, "No Memory");
633             sqlite3_finalize(stmt);
634             return OC_STACK_NO_MEMORY;
635         }
636         memcpy(&tempNode->dev.id, &temp1.id, UUID_LENGTH);
637         memcpy(&tempNode->dev2.id, &temp2.id, UUID_LENGTH);
638         LL_PREPEND(*staleDevList, tempNode);
639         ++counter;
640     }
641     *numOfDevices = counter;
642     sqlite3_finalize(stmt);
643     return OC_STACK_OK;
644 }
645
646 OCStackResult PDMClose()
647 {
648     CHECK_PDM_INIT(TAG);
649     int res = 0;
650     res = sqlite3_close(g_db);
651     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
652     return OC_STACK_OK;
653 }
654
655 void PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
656 {
657     if(ptr)
658     {
659         OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
660         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
661         {
662             LL_DELETE(ptr, tmp1);
663             OICFree(tmp1);
664         }
665     }
666 }
667
668 void PDMDestoryStaleLinkList(OCPairList_t* ptr)
669 {
670     if(ptr)
671     {
672         OCPairList_t *tmp1 = NULL,*tmp2=NULL;
673         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
674         {
675             LL_DELETE(ptr, tmp1);
676             OICFree(tmp1);
677         }
678     }
679 }
680
681 OCStackResult PDMIsLinkExists(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2,
682                                bool* result)
683 {
684     CHECK_PDM_INIT(TAG);
685     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2 || NULL == result)
686     {
687         return OC_STACK_INVALID_PARAM;
688     }
689     int id1 = 0;
690     int id2 = 0;
691     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
692     {
693         OC_LOG(ERROR, TAG, "Requested value not found");
694         return OC_STACK_INVALID_PARAM;
695     }
696
697     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
698     {
699         OC_LOG(ERROR, TAG, "Requested value not found");
700         return OC_STACK_INVALID_PARAM;
701     }
702
703     ASCENDING_ORDER(id1, id2);
704
705     sqlite3_stmt *stmt = 0;
706     int res = 0;
707     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
708                               strlen(PDM_SQLITE_GET_LINKED_DEVICES) + 1, &stmt, NULL);
709     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
710
711     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
712     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
713
714     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
715     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
716
717     bool ret = false;
718     while(SQLITE_ROW == sqlite3_step(stmt))
719     {
720         OC_LOG(INFO, TAG, "Link already exists between devices");
721         ret = true;
722     }
723     sqlite3_finalize(stmt);
724     *result = ret;
725     return OC_STACK_OK;
726 }