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 #define RD_PATH "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 static void errorCallback(void *arg, int errCode, const char *errMsg)
72 OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
75 static OCStackResult initializeDatabase(const char *path)
77 if (SQLITE_OK == sqlite3_config(SQLITE_CONFIG_LOG, errorCallback))
79 OIC_LOG_V(INFO, TAG, "SQLite debugging log initialized.");
82 sqlite3_open_v2(!path ? RD_PATH : path, &gRDDB, SQLITE_OPEN_READONLY, NULL);
85 return OC_STACK_ERROR;
90 static OCStackResult appendStringLL(OCStringLL **type, const unsigned char *value)
92 OCStringLL *temp= (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
95 return OC_STACK_NO_MEMORY;
97 temp->value = OICStrdup((char *)value);
100 return OC_STACK_NO_MEMORY;
110 OCStringLL *tmp = *type;
111 for (; tmp->next; tmp = tmp->next);
117 /* stmt is of form "SELECT * FROM RD_DEVICE_LINK_LIST ..." */
118 static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayload *discPayload)
120 int res = sqlite3_step(stmt);
121 if (SQLITE_ROW != res)
123 return OC_STACK_NO_RESOURCE;
125 OCStackResult result = OC_STACK_OK;
126 OCResourcePayload *resourcePayload = NULL;
127 while (SQLITE_ROW == res)
129 resourcePayload = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
130 if (!resourcePayload)
132 result = OC_STACK_NO_MEMORY;
136 int id = sqlite3_column_int(stmt, ins_index);
137 const unsigned char *uri = sqlite3_column_text(stmt, uri_index);
138 int bitmap = sqlite3_column_int(stmt, p_index);
139 int deviceId = sqlite3_column_int(stmt, d_index);
140 OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
141 resourcePayload->uri = OICStrdup((char *)uri);
142 if (!resourcePayload->uri)
144 result = OC_STACK_NO_MEMORY;
148 sqlite3_stmt *stmtRT = 0;
149 const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
150 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, strlen(rt) + 1, &stmtRT, NULL));
151 VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
152 while (SQLITE_ROW == sqlite3_step(stmtRT))
154 const unsigned char *rt1 = sqlite3_column_text(stmtRT, rt_value_index);
155 result = appendStringLL(&resourcePayload->types, rt1);
156 if (OC_STACK_OK != result)
161 VERIFY_SQLITE(sqlite3_finalize(stmtRT));
163 sqlite3_stmt *stmtIF = 0;
164 const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
165 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, strlen(itf) + 1, &stmtIF, NULL));
166 VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
167 while (SQLITE_ROW == sqlite3_step(stmtIF))
169 const unsigned char *itf = sqlite3_column_text(stmtIF, if_value_index);
170 result = appendStringLL(&resourcePayload->interfaces, itf);
171 if (OC_STACK_OK != result)
176 VERIFY_SQLITE(sqlite3_finalize(stmtIF));
178 resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
179 resourcePayload->secure = (bitmap & OC_SECURE) != 0;
181 const char *address = "SELECT di, address FROM RD_DEVICE_LIST "
182 "INNER JOIN RD_DEVICE_LINK_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID "
183 "WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=?";
184 const uint8_t di_index = 0;
185 const uint8_t address_index = 1;
187 sqlite3_stmt *stmt1 = 0;
188 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, strlen(address) + 1, &stmt1, NULL));
189 VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
191 res = sqlite3_step(stmt1);
192 if (SQLITE_ROW == res || SQLITE_DONE == res)
194 const unsigned char *di = sqlite3_column_text(stmt1, di_index);
195 const unsigned char *address = sqlite3_column_text(stmt1, address_index);
196 OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
197 discPayload->baseURI = OICStrdup((char *)address);
198 if (!discPayload->baseURI)
200 result = OC_STACK_NO_MEMORY;
203 discPayload->sid = OICStrdup((char *)di);
204 if (!discPayload->sid)
206 result = OC_STACK_NO_MEMORY;
210 VERIFY_SQLITE(sqlite3_finalize(stmt1));
211 OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
212 res = sqlite3_step(stmt);
215 if (OC_STACK_OK != result)
217 OCDiscoveryResourceDestroy(resourcePayload);
222 static OCStackResult CheckResources(const char *interfaceType, const char *resourceType,
223 OCDiscoveryPayload *discPayload)
225 if (initializeDatabase(NULL) != OC_STACK_OK)
227 return OC_STACK_INTERNAL_SERVER_ERROR;
229 if (!interfaceType && !resourceType)
231 return OC_STACK_INVALID_QUERY;
233 if (!discPayload || !discPayload->sid)
235 return OC_STACK_INTERNAL_SERVER_ERROR;
238 OCStackResult result = OC_STACK_OK;
239 sqlite3_stmt *stmt = 0;
242 if (!interfaceType || 0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
244 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
245 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
246 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
247 "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2";
248 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
249 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
251 VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
255 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
256 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
257 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
258 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
259 "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2 AND RD_LINK_IF.if LIKE ?3";
260 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
261 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
263 VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
264 VERIFY_SQLITE(sqlite3_bind_text(stmt, 3, interfaceType, strlen(interfaceType), SQLITE_STATIC));
266 result = ResourcePayloadCreate(stmt, discPayload);
268 else if (interfaceType)
270 if (0 == strcmp(interfaceType, OC_RSRVD_INTERFACE_LL))
272 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
273 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
274 "WHERE RD_DEVICE_LIST.di LIKE ?1";
275 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
276 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
281 const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
282 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
283 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
284 "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_IF.if LIKE ?2";
285 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
286 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
288 VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, interfaceType, strlen(interfaceType), SQLITE_STATIC));
290 result = ResourcePayloadCreate(stmt, discPayload);
294 VERIFY_SQLITE(sqlite3_finalize(stmt));
299 OCStackResult OCRDDatabaseDiscoveryPayloadCreate(const char *interfaceType,
300 const char *resourceType,
301 OCDiscoveryPayload **payload)
303 OCStackResult result = OC_STACK_NO_RESOURCE;
304 OCDiscoveryPayload *head = NULL;
305 OCDiscoveryPayload **tail = &head;
310 * This is an error of the caller, return here instead of touching the
311 * caller provided payload.
313 OIC_LOG_V(ERROR, TAG, "Payload is already allocated");
314 return OC_STACK_INTERNAL_SERVER_ERROR;
316 if (initializeDatabase(NULL) != OC_STACK_OK)
321 const char *serverID = OCGetServerInstanceIDString();
322 sqlite3_stmt *stmt = 0;
323 const char *input = "SELECT di FROM RD_DEVICE_LIST";
324 const uint8_t di_index = 0;
325 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
326 while (SQLITE_ROW == sqlite3_step(stmt))
328 const unsigned char *di = sqlite3_column_text(stmt, di_index);
329 if (0 == strcmp((const char *)di, serverID))
333 *tail = OCDiscoveryPayloadCreate();
334 VERIFY_PARAM_NON_NULL(TAG, *tail, "Failed creating discovery payload.");
335 (*tail)->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
336 VERIFY_PARAM_NON_NULL(TAG, (*tail)->sid, "Failed adding device id to discovery payload.");
337 memcpy((*tail)->sid, di, UUID_STRING_SIZE);
338 result = CheckResources(interfaceType, resourceType, *tail);
339 if (OC_STACK_OK == result)
341 tail = &(*tail)->next;
345 OCPayloadDestroy((OCPayload *) *tail);
349 VERIFY_SQLITE(sqlite3_finalize(stmt));
353 OCPayloadDestroy((OCPayload *) *tail);
355 return OC_STACK_INTERNAL_SERVER_ERROR;