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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
33 #include "ocpayload.h"
34 #include "oic_malloc.h"
35 #include "oic_string.h"
37 #define TAG "OIC_RI_RESOURCEDIRECTORY"
39 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
40 TAG, #arg " is NULL"); return (retVal); } }
44 static const char *gRDPath = "RD.db";
46 static sqlite3 *gRDDB = NULL;
48 /* Column indices of RD_DEVICE_LINK_LIST table */
49 static const uint8_t ins_index = 0;
50 static const uint8_t uri_index = 1;
51 static const uint8_t p_index = 4;
52 static const uint8_t d_index = 7;
54 /* Column indices of RD_LINK_RT table */
55 static const uint8_t rt_value_index = 0;
57 /* Column indices of RD_LINK_IF table */
58 static const uint8_t if_value_index = 0;
60 #define VERIFY_SQLITE(arg) \
61 if (SQLITE_OK != (arg)) \
63 OIC_LOG_V(ERROR, TAG, "Error in " #arg ", Error Message: %s", sqlite3_errmsg(gRDDB)); \
64 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL); \
65 return OC_STACK_ERROR; \
68 OCStackResult OCRDDatabaseSetStorageFilename(const char *filename)
72 OIC_LOG(ERROR, TAG, "The persistent storage filename is invalid");
73 return OC_STACK_INVALID_PARAM;
79 const char *OCRDDatabaseGetStorageFilename()
84 static void errorCallback(void *arg, int errCode, const char *errMsg)
89 OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
92 static OCStackResult initializeDatabase()
94 if (SQLITE_OK == sqlite3_config(SQLITE_CONFIG_LOG, errorCallback))
96 OIC_LOG_V(INFO, TAG, "SQLite debugging log initialized.");
99 sqlite3_open_v2(OCRDDatabaseGetStorageFilename(), &gRDDB, SQLITE_OPEN_READONLY, NULL);
102 return OC_STACK_ERROR;
107 static OCStackResult appendStringLL(OCStringLL **type, const unsigned char *value)
109 OCStringLL *temp= (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
112 return OC_STACK_NO_MEMORY;
114 temp->value = OICStrdup((char *)value);
117 return OC_STACK_NO_MEMORY;
127 OCStringLL *tmp = *type;
128 for (; tmp->next; tmp = tmp->next);
134 /* stmt is of form "SELECT * FROM RD_DEVICE_LINK_LIST ..." */
135 static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayload *discPayload)
137 int res = sqlite3_step(stmt);
138 if (SQLITE_ROW != res)
140 return OC_STACK_NO_RESOURCE;
142 OCStackResult result = OC_STACK_OK;
143 OCResourcePayload *resourcePayload = NULL;
144 while (SQLITE_ROW == res)
146 resourcePayload = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
147 if (!resourcePayload)
149 result = OC_STACK_NO_MEMORY;
153 sqlite3_int64 id = sqlite3_column_int64(stmt, ins_index);
154 const unsigned char *uri = sqlite3_column_text(stmt, uri_index);
155 sqlite3_int64 bitmap = sqlite3_column_int64(stmt, p_index);
156 sqlite3_int64 deviceId = sqlite3_column_int64(stmt, d_index);
157 OIC_LOG_V(DEBUG, TAG, " %s %" PRId64, uri, deviceId);
158 resourcePayload->uri = OICStrdup((char *)uri);
159 if (!resourcePayload->uri)
161 result = OC_STACK_NO_MEMORY;
165 sqlite3_stmt *stmtRT = 0;
166 const char rt[] = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=@id";
167 int rtSize = (int)sizeof(rt);
169 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, rtSize, &stmtRT, NULL));
170 VERIFY_SQLITE(sqlite3_bind_int64(stmtRT, sqlite3_bind_parameter_index(stmtRT, "@id"), id));
171 while (SQLITE_ROW == sqlite3_step(stmtRT))
173 const unsigned char *rt1 = sqlite3_column_text(stmtRT, rt_value_index);
174 result = appendStringLL(&resourcePayload->types, rt1);
175 if (OC_STACK_OK != result)
180 VERIFY_SQLITE(sqlite3_finalize(stmtRT));
182 sqlite3_stmt *stmtIF = 0;
183 const char itf[] = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=@id";
184 int itfSize = (int)sizeof(itf);
186 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, itfSize, &stmtIF, NULL));
187 VERIFY_SQLITE(sqlite3_bind_int64(stmtIF, sqlite3_bind_parameter_index(stmtIF, "@id"), id));
188 while (SQLITE_ROW == sqlite3_step(stmtIF))
190 const unsigned char *itf = sqlite3_column_text(stmtIF, if_value_index);
191 result = appendStringLL(&resourcePayload->interfaces, itf);
192 if (OC_STACK_OK != result)
197 VERIFY_SQLITE(sqlite3_finalize(stmtIF));
199 resourcePayload->bitmap = (uint8_t)(bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE));
200 resourcePayload->secure = ((bitmap & OC_SECURE) != 0);
202 const char address[] = "SELECT di, address FROM RD_DEVICE_LIST "
203 "INNER JOIN RD_DEVICE_LINK_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID "
204 "WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=@deviceId";
205 int addressSize = (int)sizeof(address);
207 const uint8_t di_index = 0;
208 const uint8_t address_index = 1;
210 sqlite3_stmt *stmt1 = 0;
211 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, addressSize, &stmt1, NULL));
212 VERIFY_SQLITE(sqlite3_bind_int64(stmt1, sqlite3_bind_parameter_index(stmt1, "@deviceId"), deviceId));
214 res = sqlite3_step(stmt1);
215 if (SQLITE_ROW == res || SQLITE_DONE == res)
217 const unsigned char *di = sqlite3_column_text(stmt1, di_index);
218 const unsigned char *address = sqlite3_column_text(stmt1, address_index);
219 OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
220 discPayload->baseURI = OICStrdup((char *)address);
221 if (!discPayload->baseURI)
223 result = OC_STACK_NO_MEMORY;
226 discPayload->sid = OICStrdup((char *)di);
227 if (!discPayload->sid)
229 result = OC_STACK_NO_MEMORY;
233 VERIFY_SQLITE(sqlite3_finalize(stmt1));
234 OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
235 res = sqlite3_step(stmt);
238 if (OC_STACK_OK != result)
240 OCDiscoveryResourceDestroy(resourcePayload);
245 static OCStackResult CheckResources(const char *interfaceType, const char *resourceType,
246 OCDiscoveryPayload *discPayload)
248 if (initializeDatabase() != OC_STACK_OK)
250 return OC_STACK_INTERNAL_SERVER_ERROR;
252 if (!interfaceType && !resourceType)
254 return OC_STACK_INVALID_QUERY;
256 if (!discPayload || !discPayload->sid)
258 return OC_STACK_INTERNAL_SERVER_ERROR;
261 size_t sidLength = strlen(discPayload->sid);
262 size_t resourceTypeLength = resourceType ? strlen(resourceType) : 0;
263 size_t interfaceTypeLength = interfaceType ? strlen(interfaceType) : 0;
265 if ((sidLength > INT_MAX) ||
266 (resourceTypeLength > INT_MAX) ||
267 (interfaceTypeLength > INT_MAX))
269 return OC_STACK_INVALID_QUERY;
272 OCStackResult result = OC_STACK_OK;
273 sqlite3_stmt *stmt = 0;
276 if (!interfaceType || 0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
278 const char input[] = "SELECT * FROM RD_DEVICE_LINK_LIST "
279 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
280 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
281 "WHERE RD_DEVICE_LIST.di LIKE @di AND RD_LINK_RT.rt LIKE @resourceType";
282 int inputSize = (int)sizeof(input);
284 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
285 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
286 discPayload->sid, (int)sidLength, SQLITE_STATIC));
287 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@resourceType"),
288 resourceType, (int)resourceTypeLength, SQLITE_STATIC));
292 const char input[] = "SELECT * FROM RD_DEVICE_LINK_LIST "
293 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
294 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
295 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
296 "WHERE RD_DEVICE_LIST.di LIKE @di "
297 "AND RD_LINK_RT.rt LIKE @resourceType "
298 "AND RD_LINK_IF.if LIKE @interfaceType";
299 int inputSize = (int)sizeof(input);
301 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
302 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
303 discPayload->sid, (int)sidLength, SQLITE_STATIC));
304 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@resourceType"),
305 resourceType, (int)resourceTypeLength, SQLITE_STATIC));
306 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@interfaceType"),
307 interfaceType, (int)interfaceTypeLength, SQLITE_STATIC));
309 result = ResourcePayloadCreate(stmt, discPayload);
311 else if (interfaceType)
313 if (0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
315 const char input[] = "SELECT * FROM RD_DEVICE_LINK_LIST "
316 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
317 "WHERE RD_DEVICE_LIST.di LIKE @di";
318 int inputSize = (int)sizeof(input);
320 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
321 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
322 discPayload->sid, (int)sidLength, SQLITE_STATIC));
326 const char input[] = "SELECT * FROM RD_DEVICE_LINK_LIST "
327 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
328 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
329 "WHERE RD_DEVICE_LIST.di LIKE @di AND RD_LINK_IF.if LIKE @interfaceType";
330 int inputSize = (int)sizeof(input);
332 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
333 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
334 discPayload->sid, (int)sidLength, SQLITE_STATIC));
335 VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@interfaceType"),
336 interfaceType, (int)interfaceTypeLength, SQLITE_STATIC));
338 result = ResourcePayloadCreate(stmt, discPayload);
342 VERIFY_SQLITE(sqlite3_finalize(stmt));
347 OCStackResult OCRDDatabaseDiscoveryPayloadCreate(const char *interfaceType,
348 const char *resourceType,
349 OCDiscoveryPayload **payload)
351 OCStackResult result = OC_STACK_NO_RESOURCE;
352 OCDiscoveryPayload *head = NULL;
353 OCDiscoveryPayload **tail = &head;
358 * This is an error of the caller, return here instead of touching the
359 * caller provided payload.
361 OIC_LOG_V(ERROR, TAG, "Payload is already allocated");
362 return OC_STACK_INTERNAL_SERVER_ERROR;
364 if (initializeDatabase() != OC_STACK_OK)
369 const char *serverID = OCGetServerInstanceIDString();
370 sqlite3_stmt *stmt = 0;
371 const char input[] = "SELECT di FROM RD_DEVICE_LIST";
372 int inputSize = (int)sizeof(input);
373 const uint8_t di_index = 0;
374 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
375 while (SQLITE_ROW == sqlite3_step(stmt))
377 const unsigned char *di = sqlite3_column_text(stmt, di_index);
378 if (0 == strcmp((const char *)di, serverID))
382 *tail = OCDiscoveryPayloadCreate();
383 VERIFY_PARAM_NON_NULL(TAG, *tail, "Failed creating discovery payload.");
384 (*tail)->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
385 VERIFY_PARAM_NON_NULL(TAG, (*tail)->sid, "Failed adding device id to discovery payload.");
386 memcpy((*tail)->sid, di, UUID_STRING_SIZE);
387 result = CheckResources(interfaceType, resourceType, *tail);
388 if (OC_STACK_OK == result)
390 tail = &(*tail)->next;
394 OCPayloadDestroy((OCPayload *) *tail);
398 VERIFY_SQLITE(sqlite3_finalize(stmt));
402 OCPayloadDestroy((OCPayload *) *tail);
404 return OC_STACK_INTERNAL_SERVER_ERROR;