replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / stack / src / oicresourcedirectory.c
1 //******************************************************************
2 //
3 // Copyright 2016 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 a
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 <stdlib.h>
22 #include <string.h>
23
24 #ifdef RD_SERVER
25 #include "sqlite3.h"
26 #endif
27
28 #include "octypes.h"
29 #include "ocstack.h"
30 #include "logger.h"
31 #include "ocpayload.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34
35 #define TAG "OIC_RI_RESOURCEDIRECTORY"
36
37 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
38              TAG, #arg " is NULL"); return (retVal); } }
39
40 #ifdef RD_SERVER
41
42 #define RD_PATH "RD.db"
43
44 static sqlite3 *gRDDB = NULL;
45
46 static const uint8_t uri_index = 2;
47 static const uint8_t p_index = 5;
48 static const uint8_t mt_index = 7;
49 static const uint8_t d_index = 8;
50
51 static const uint8_t rt_value_index = 1;
52 static const uint8_t rt_link_id_index = 2;
53
54 static const uint8_t if_value_index = 1;
55 static const uint8_t if_link_id_index = 2;
56
57 #define VERIFY_SQLITE(arg) \
58 if (SQLITE_OK != (arg)) \
59 { \
60     OIC_LOG_V(ERROR, TAG, "Error in " #arg ", Error Message: %s",  sqlite3_errmsg(gRDDB)); \
61     sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL); \
62     return OC_STACK_ERROR; \
63 }
64
65 static void errorCallback(void *arg, int errCode, const char *errMsg)
66 {
67     OC_UNUSED(arg);
68     OC_UNUSED(errCode);
69     OC_UNUSED(errMsg);
70     OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
71 }
72
73 static OCStackResult initializeDatabase(const char *path)
74 {
75     if (SQLITE_OK == sqlite3_config(SQLITE_CONFIG_LOG, errorCallback))
76     {
77         OIC_LOG_V(INFO, TAG, "SQLite debugging log initialized.");
78     }
79
80     sqlite3_open_v2(!path ? RD_PATH : path, &gRDDB, SQLITE_OPEN_READONLY, NULL);
81     if (!gRDDB)
82     {
83         return OC_STACK_ERROR;
84     }
85     return OC_STACK_OK;
86 }
87
88 static OCStackResult appendStringLL(OCStringLL **type, const unsigned char *value)
89 {
90     OCStringLL *temp= (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
91     if (!temp)
92     {
93         return OC_STACK_NO_MEMORY;
94     }
95     temp->value = OICStrdup((char *)value);
96     if (!temp->value)
97     {
98         return OC_STACK_NO_MEMORY;
99     }
100     temp->next = NULL;
101
102     if (!*type)
103     {
104         *type = temp;
105     }
106     else
107     {
108         OCStringLL *tmp = *type;
109         for (; tmp->next; tmp = tmp->next);
110         tmp->next = temp;
111     }
112     return OC_STACK_OK;
113 }
114
115 OCStackResult OCRDDatabaseCheckResources(const char *interfaceType, const char *resourceType,
116     OCDiscoveryPayload *discPayload)
117 {
118     if (initializeDatabase(NULL) != OC_STACK_OK)
119     {
120         return OC_STACK_INTERNAL_SERVER_ERROR;
121     }
122     if (!interfaceType && !resourceType)
123     {
124         return OC_STACK_INVALID_QUERY;
125     }
126     OCResourcePayload *resourcePayload = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
127     if (!resourcePayload)
128     {
129         return OC_STACK_NO_MEMORY;
130     }
131
132     if (resourceType)
133     {
134         sqlite3_stmt *stmt = 0;
135         const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST INNER JOIN RD_LINK_RT ON " \
136         "RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID WHERE RD_LINK_RT.rt LIKE ? ";
137
138         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
139         VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, resourceType, strlen(resourceType) + 1, SQLITE_STATIC));
140
141         int res = sqlite3_step (stmt);
142         if (res == SQLITE_ROW || res == SQLITE_DONE)
143         {
144             int id = sqlite3_column_int(stmt, 0);
145             const unsigned char *uri = sqlite3_column_text(stmt, uri_index - 1);
146             int bitmap = sqlite3_column_int(stmt, p_index - 1);
147             int deviceId = sqlite3_column_int(stmt, d_index - 1);
148             OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
149             resourcePayload->uri = OICStrdup((char *)uri);
150             if (!resourcePayload->uri)
151             {
152                 OCDiscoveryResourceDestroy(resourcePayload);
153                 return OC_STACK_NO_MEMORY;
154             }
155             res = sqlite3_reset(stmt);
156             VERIFY_SQLITE(res);
157
158             sqlite3_stmt *stmtRT = 0;
159             const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
160             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, -1, &stmtRT, NULL));
161             VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
162             while (SQLITE_ROW == sqlite3_step(stmtRT))
163             {
164                 const unsigned char *rt1 = sqlite3_column_text(stmtRT, (rt_value_index - 1));
165                 appendStringLL(&resourcePayload->types, rt1);
166             }
167
168             sqlite3_stmt *stmtIF = 0;
169             const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
170             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, -1, &stmtIF, NULL));
171             VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
172             while (SQLITE_ROW == sqlite3_step(stmtIF))
173             {
174                 const unsigned char *itf = sqlite3_column_text(stmtIF, (if_value_index - 1));
175                 appendStringLL(&resourcePayload->interfaces, itf);
176             }
177
178             resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
179             resourcePayload->secure = (bitmap & OC_SECURE) != 0;
180
181             const char *address = "SELECT di, address FROM RD_DEVICE_LIST INNER JOIN RD_DEVICE_LINK_LIST ON " \
182             "RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=?";
183
184             sqlite3_stmt *stmt1 = 0;
185             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, -1, &stmt1, NULL));
186             VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
187             // TODO: Right now, we have a bug where discovery payload can only send one device information.
188             res = sqlite3_step(stmt1);
189             if (res == SQLITE_ROW || res == SQLITE_DONE)
190             {
191                 const unsigned char *di = sqlite3_column_text(stmt1, 0);
192                 const unsigned char *address = sqlite3_column_text(stmt1, 1);
193                 OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
194                 (discPayload)->baseURI = OICStrdup((char *)address);
195                 (discPayload)->sid = OICStrdup((char *)di);
196             }
197             OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
198         }
199     }
200     if (interfaceType)
201     {
202         sqlite3_stmt *stmt = 0;
203         const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST INNER JOIN RD_LINK_IF ON " \
204         "RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID WHERE RD_LINK_IF.if LIKE ? ";
205
206         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
207         VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, interfaceType, strlen(interfaceType) + 1, SQLITE_STATIC));
208
209         int res = sqlite3_step (stmt);
210         if (res == SQLITE_ROW || res == SQLITE_DONE)
211         {
212             int id = sqlite3_column_int(stmt, 0);
213             const unsigned char *uri = sqlite3_column_text(stmt, uri_index - 1);
214             int bitmap = sqlite3_column_int(stmt, p_index - 1);
215             int deviceId = sqlite3_column_int(stmt, d_index - 1);
216             OIC_LOG_V(DEBUG, TAG, " %s %d", uri, deviceId);
217             resourcePayload->uri = OICStrdup((char *)uri);
218             if (!resourcePayload->uri)
219             {
220                 OCDiscoveryResourceDestroy(resourcePayload);
221                 return OC_STACK_NO_MEMORY;
222             }
223             VERIFY_SQLITE(sqlite3_reset(stmt));
224
225             sqlite3_stmt *stmtRT = 0;
226             const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
227             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, -1, &stmtRT, NULL));
228             VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
229             while (SQLITE_ROW == sqlite3_step(stmtRT))
230             {
231                 const unsigned char *rt1 = sqlite3_column_text(stmtRT, (rt_value_index - 1));
232                 appendStringLL(&resourcePayload->types, rt1);
233             }
234
235             sqlite3_stmt *stmtIF = 0;
236             const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
237             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, -1, &stmtIF, NULL));
238             VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
239             while (SQLITE_ROW == sqlite3_step (stmtIF))
240             {
241                 const unsigned char *itf = sqlite3_column_text(stmtIF, (if_value_index - 1));
242                 appendStringLL(&resourcePayload->interfaces, itf);
243             }
244
245             resourcePayload->bitmap = bitmap & (OC_OBSERVABLE | OC_DISCOVERABLE);
246             resourcePayload->secure = ((bitmap & OC_SECURE) != 0);
247
248             const char *address = "SELECT di, address FROM RD_DEVICE_LIST INNER JOIN RD_DEVICE_LINK_LIST ON " \
249             "RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=?";
250
251             sqlite3_stmt *stmt1 = 0;
252             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, -1, &stmt1, NULL));
253             VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
254
255             res = sqlite3_step(stmt1);
256             if (res == SQLITE_ROW || res == SQLITE_DONE)
257             {
258                 const unsigned char *di = sqlite3_column_text(stmt1, 0);
259                 const unsigned char *address = sqlite3_column_text(stmt1, 1);
260                 OIC_LOG_V(DEBUG, TAG, " %s %s", di, address);
261                 (discPayload)->baseURI = OICStrdup((char *)address);
262                 (discPayload)->sid = OICStrdup((char *)di);
263             }
264             OCDiscoveryPayloadAddNewResource(discPayload, resourcePayload);
265         }
266     }
267     return OC_STACK_OK;
268 }
269 #endif