1 //******************************************************************
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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 a
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
32 #include "ocpayload.h"
33 #include "oic_malloc.h"
34 #include "oic_string.h"
36 #define TAG "OIC_RI_RESOURCEDIRECTORY"
38 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
39 TAG, #arg " is NULL"); return (retVal); } }
43 static const char *gRDPath = "RD.db";
45 static sqlite3 *gRDDB = NULL;
47 /* Column indices of RD_DEVICE_LINK_LIST table */
48 static const uint8_t ins_index = 0;
49 static const uint8_t uri_index = 1;
50 static const uint8_t p_index = 4;
51 static const uint8_t d_index = 7;
53 /* Column indices of RD_LINK_RT table */
54 static const uint8_t rt_value_index = 0;
56 /* Column indices of RD_LINK_IF table */
57 static const uint8_t if_value_index = 0;
59 #define VERIFY_SQLITE(arg) \
60 if (SQLITE_OK != (arg)) \
62 OIC_LOG_V(ERROR, TAG, "Error in " #arg ", Error Message: %s", sqlite3_errmsg(gRDDB)); \
63 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL); \
64 return OC_STACK_ERROR; \
67 OCStackResult OCRDDatabaseSetStorageFilename(const char *filename)
71 OIC_LOG(ERROR, TAG, "The persistent storage filename is invalid");
72 return OC_STACK_INVALID_PARAM;
78 const char *OCRDDatabaseGetStorageFilename()
83 static void errorCallback(void *arg, int errCode, const char *errMsg)
88 OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
91 static OCStackResult initializeDatabase()
93 if (SQLITE_OK == sqlite3_config(SQLITE_CONFIG_LOG, errorCallback))
95 OIC_LOG_V(INFO, TAG, "SQLite debugging log initialized.");
98 sqlite3_open_v2(OCRDDatabaseGetStorageFilename(), &gRDDB, SQLITE_OPEN_READONLY, NULL);
101 return OC_STACK_ERROR;
106 static OCStackResult appendStringLL(OCStringLL **type, const unsigned char *value)
108 OCStringLL *temp= (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
111 return OC_STACK_NO_MEMORY;
113 temp->value = OICStrdup((char *)value);
116 return OC_STACK_NO_MEMORY;
126 OCStringLL *tmp = *type;
127 for (; tmp->next; tmp = tmp->next);
133 /* stmt is of form "SELECT * FROM RD_DEVICE_LINK_LIST ..." */
134 static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayload *discPayload)
136 int res = sqlite3_step(stmt);
137 if (SQLITE_ROW != res)
139 return OC_STACK_NO_RESOURCE;
141 OCStackResult result = OC_STACK_OK;
142 OCResourcePayload *resourcePayload = NULL;
143 while (SQLITE_ROW == res)
145 resourcePayload = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
146 if (!resourcePayload)
148 result = OC_STACK_NO_MEMORY;
152 int id = sqlite3_column_int(stmt, ins_index);
153 const unsigned char *uri = sqlite3_column_text(stmt, uri_index);
154 int bitmap = sqlite3_column_int(stmt, p_index);
155 int deviceId = sqlite3_column_int(stmt, d_index);
156 OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
157 resourcePayload->uri = OICStrdup((char *)uri);
158 if (!resourcePayload->uri)
160 result = OC_STACK_NO_MEMORY;
164 sqlite3_stmt *stmtRT = 0;
165 const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
166 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, strlen(rt) + 1, &stmtRT, NULL));
167 VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
168 while (SQLITE_ROW == sqlite3_step(stmtRT))
170 const unsigned char *rt1 = sqlite3_column_text(stmtRT, rt_value_index);
171 result = appendStringLL(&resourcePayload->types, rt1);
172 if (OC_STACK_OK != result)
177 VERIFY_SQLITE(sqlite3_finalize(stmtRT));
179 sqlite3_stmt *stmtIF = 0;
180 const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
181 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, strlen(itf) + 1, &stmtIF, NULL));
182 VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
183 while (SQLITE_ROW == sqlite3_step(stmtIF))
185 const unsigned char *itf = sqlite3_column_text(stmtIF, if_value_index);
186 result = appendStringLL(&resourcePayload->interfaces, itf);
187 if (OC_STACK_OK != result)
192 VERIFY_SQLITE(sqlite3_finalize(stmtIF));
194 resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
195 resourcePayload->secure = (bitmap & OC_SECURE) != 0;
197 const char *address = "SELECT di, address FROM RD_DEVICE_LIST "
198 "INNER JOIN RD_DEVICE_LINK_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID "
199 "WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=?";
200 const uint8_t di_index = 0;
201 const uint8_t address_index = 1;
203 sqlite3_stmt *stmt1 = 0;
204 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, strlen(address) + 1, &stmt1, NULL));
205 VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
207 res = sqlite3_step(stmt1);
208 if (SQLITE_ROW == res || SQLITE_DONE == res)
210 const unsigned char *di = sqlite3_column_text(stmt1, di_index);
211 const unsigned char *address = sqlite3_column_text(stmt1, address_index);
212 OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
213 discPayload->baseURI = OICStrdup((char *)address);
214 if (!discPayload->baseURI)
216 result = OC_STACK_NO_MEMORY;
219 discPayload->sid = OICStrdup((char *)di);
220 if (!discPayload->sid)
222 result = OC_STACK_NO_MEMORY;
226 VERIFY_SQLITE(sqlite3_finalize(stmt1));
227 OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
228 res = sqlite3_step(stmt);
231 if (OC_STACK_OK != result)
233 OCDiscoveryResourceDestroy(resourcePayload);
238 static OCStackResult CheckResources(const char *interfaceType, const char *resourceType,
239 OCDiscoveryPayload *discPayload)
241 if (initializeDatabase() != OC_STACK_OK)
243 return OC_STACK_INTERNAL_SERVER_ERROR;
245 if (!interfaceType && !resourceType)
247 return OC_STACK_INVALID_QUERY;
249 if (!discPayload || !discPayload->sid)
251 return OC_STACK_INTERNAL_SERVER_ERROR;
254 OCStackResult result = OC_STACK_OK;
255 sqlite3_stmt *stmt = 0;
258 if (!interfaceType || 0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
260 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
261 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
262 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
263 "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2";
264 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
265 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
267 VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
271 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
272 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
273 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
274 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
275 "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2 AND RD_LINK_IF.if LIKE ?3";
276 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
277 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
279 VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
280 VERIFY_SQLITE(sqlite3_bind_text(stmt, 3, interfaceType, strlen(interfaceType), SQLITE_STATIC));
282 result = ResourcePayloadCreate(stmt, discPayload);
284 else if (interfaceType)
286 if (0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
288 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
289 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
290 "WHERE RD_DEVICE_LIST.di LIKE ?1";
291 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
292 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
297 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
298 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
299 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
300 "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_IF.if LIKE ?2";
301 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
302 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
304 VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, interfaceType, strlen(interfaceType), SQLITE_STATIC));
306 result = ResourcePayloadCreate(stmt, discPayload);
310 VERIFY_SQLITE(sqlite3_finalize(stmt));
315 OCStackResult OCRDDatabaseDiscoveryPayloadCreate(const char *interfaceType,
316 const char *resourceType,
317 OCDiscoveryPayload **payload)
319 OCStackResult result = OC_STACK_NO_RESOURCE;
320 OCDiscoveryPayload *head = NULL;
321 OCDiscoveryPayload **tail = &head;
326 * This is an error of the caller, return here instead of touching the
327 * caller provided payload.
329 OIC_LOG_V(ERROR, TAG, "Payload is already allocated");
330 return OC_STACK_INTERNAL_SERVER_ERROR;
332 if (initializeDatabase() != OC_STACK_OK)
337 const char *serverID = OCGetServerInstanceIDString();
338 sqlite3_stmt *stmt = 0;
339 const char *input = "SELECT di FROM RD_DEVICE_LIST";
340 const uint8_t di_index = 0;
341 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
342 while (SQLITE_ROW == sqlite3_step(stmt))
344 const unsigned char *di = sqlite3_column_text(stmt, di_index);
345 if (0 == strcmp((const char *)di, serverID))
349 *tail = OCDiscoveryPayloadCreate();
350 VERIFY_PARAM_NON_NULL(TAG, *tail, "Failed creating discovery payload.");
351 (*tail)->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
352 VERIFY_PARAM_NON_NULL(TAG, (*tail)->sid, "Failed adding device id to discovery payload.");
353 memcpy((*tail)->sid, di, UUID_STRING_SIZE);
354 result = CheckResources(interfaceType, resourceType, *tail);
355 if (OC_STACK_OK == result)
357 tail = &(*tail)->next;
361 OCPayloadDestroy((OCPayload *) *tail);
365 VERIFY_SQLITE(sqlite3_finalize(stmt));
369 OCPayloadDestroy((OCPayload *) *tail);
371 return OC_STACK_INTERNAL_SERVER_ERROR;