cb243e486b988eb907829d6d6792cfa88261efa2
[platform/upstream/iotivity.git] / resource / csdk / resource-directory / src / rd_server.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 #include "rd_server.h"
21
22 #include "rd_database.h"
23
24 #include <string.h>
25 #include "payload_logging.h"
26 #include "ocpayload.h"
27 #include "octypes.h"
28 #include "oic_string.h"
29
30 #define TAG PCF("OIC_RD_SERVER")
31
32 #ifdef RD_SERVER
33
34 // This is temporary hardcoded value for bias factor.
35 static const int OC_RD_DISC_SEL = 100;
36
37 static OCResourceHandle rdHandle;
38
39 static OCStackResult sendResponse(const OCEntityHandlerRequest *ehRequest, OCRepPayload *rdPayload,
40     OCEntityHandlerResult ehResult)
41 {
42     OCEntityHandlerResponse response = { 0 };
43     response.requestHandle = ehRequest->requestHandle;
44     response.resourceHandle = ehRequest->resource;
45     response.ehResult = ehResult;
46     response.payload = (OCPayload*)(rdPayload);
47     return OCDoResponse(&response);
48 }
49
50 /**
51  * This internal method handles RD discovery request.
52  * Responds with the RD discovery payload message.
53  */
54 static OCEntityHandlerResult handleGetRequest(const OCEntityHandlerRequest *ehRequest)
55 {
56     if (!ehRequest)
57     {
58         OIC_LOG(DEBUG, TAG, "Invalid request pointer.");
59         return OC_EH_ERROR;
60     }
61
62     OCEntityHandlerResult ehResult = OC_EH_OK;
63     OIC_LOG_V(DEBUG, TAG, "Received OC_REST_GET from client with query: %s.", ehRequest->query);
64
65     OCRepPayload *rdPayload =  (OCRepPayload *)OCRepPayloadCreate();
66     if (!rdPayload)
67     {
68         return OC_STACK_NO_MEMORY;
69     }
70
71     const char *id = OCGetServerInstanceIDString();
72     if (id)
73     {
74         OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, id);
75     }
76     OCRepPayloadSetPropInt(rdPayload, OC_RSRVD_RD_DISCOVERY_SEL, OC_RD_DISC_SEL);
77
78     OCRepPayloadAddResourceType(rdPayload, OC_RSRVD_RESOURCE_TYPE_RD);
79     OCRepPayloadAddResourceType(rdPayload, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
80
81     OCRepPayloadAddInterface(rdPayload, OC_RSRVD_INTERFACE_DEFAULT);
82
83     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
84
85     if (sendResponse(ehRequest, rdPayload, OC_EH_OK) != OC_STACK_OK)
86     {
87         OIC_LOG(ERROR, TAG, "Sending response failed.");
88         ehResult = OC_EH_ERROR;
89     }
90
91     return ehResult;
92 }
93
94 /**
95  * This internal method handles RD publish request.
96  * Responds with the RD success message.
97  */
98 static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *ehRequest)
99 {
100     OCEntityHandlerResult ehResult = OC_EH_OK;
101
102     if (!ehRequest)
103     {
104         OIC_LOG(DEBUG, TAG, "Invalid request pointer");
105         return OC_EH_ERROR;
106     }
107
108     OIC_LOG_V(DEBUG, TAG, "Received OC_REST_POST from client with query: %s.", ehRequest->query);
109
110     OCRepPayload *payload = (OCRepPayload *)ehRequest->payload;
111     OCRepPayload *resPayload = NULL;
112     if (payload)
113     {
114         OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) payload);
115         if (OCRDDatabaseInit(NULL) == OC_STACK_OK)
116         {
117             if (OCRDDatabaseStoreResources(payload, &ehRequest->devAddr) == OC_STACK_OK)
118             {
119                 OIC_LOG_V(DEBUG, TAG, "Stored resources.");
120                 resPayload = payload;
121                 ehResult = OC_EH_OK;
122             }
123             else
124             {
125                 resPayload = (OCRepPayload *)OCRepPayloadCreate();
126                 ehResult = OC_EH_ERROR;
127             }
128         }
129
130         // Send Response
131         if (sendResponse(ehRequest, resPayload, ehResult) != OC_STACK_OK)
132         {
133             OIC_LOG(ERROR, TAG, "Sending response failed.");
134         }
135     }
136
137     return ehResult;
138 }
139
140 static OCEntityHandlerResult handleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
141 {
142     OCEntityHandlerResult ehResult = OC_EH_ERROR;
143     char *key = NULL;
144     char *value = NULL;
145     char *queryDup = NULL;
146     char *restOfQuery = NULL;
147     char *keyValuePair = NULL;
148     char *di = NULL;
149     size_t nIns = 0;
150     uint8_t *ins = NULL;
151
152     if (!ehRequest)
153     {
154         OIC_LOG(DEBUG, TAG, "Invalid request pointer");
155         return OC_EH_ERROR;
156     }
157
158     OIC_LOG_V(DEBUG, TAG, "Received OC_REST_DELETE from client with query: %s.", ehRequest->query);
159
160     if (OCRDDatabaseInit(NULL) != OC_STACK_OK)
161     {
162         goto exit;
163     }
164
165 #define OC_RSRVD_INS_KEY OC_RSRVD_INS OC_KEY_VALUE_DELIMITER /* "ins=" */
166     keyValuePair = strstr(ehRequest->query, OC_RSRVD_INS_KEY);
167     while (keyValuePair)
168     {
169         ++nIns;
170         keyValuePair = strstr(keyValuePair + sizeof(OC_RSRVD_INS_KEY), OC_RSRVD_INS_KEY);
171     }
172     if (nIns)
173     {
174         ins = OICMalloc(nIns * sizeof(uint8_t));
175         if (!ins)
176         {
177             OIC_LOG_V(ERROR, TAG, "ins is NULL");
178             goto exit;
179         }
180     }
181
182     nIns = 0;
183     queryDup = OICStrdup(ehRequest->query);
184     if (NULL == queryDup)
185     {
186         OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
187         goto exit;
188     }
189     keyValuePair = strtok_r(queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
190     while (keyValuePair)
191     {
192         key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
193         if (!key || !value)
194         {
195             OIC_LOG_V(ERROR, TAG, "Invalid query parameter!");
196             goto exit;
197         }
198         else if (strncasecmp(key, OC_RSRVD_DEVICE_ID, sizeof(OC_RSRVD_DEVICE_ID) - 1) == 0)
199         {
200             di = value;
201         }
202         else if (strncasecmp(key, OC_RSRVD_INS, sizeof(OC_RSRVD_INS) - 1) == 0)
203         {
204             char *endptr = NULL;
205             long int i = strtol(value, &endptr, 0);
206             if (*endptr != '\0' || i < 0 || i > UINT8_MAX)
207             {
208                 OIC_LOG_V(ERROR, TAG, "Invalid ins query parameter: %s", value);
209                 goto exit;
210             }
211             ins[nIns++] = i;
212         }
213
214         keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
215     }
216     if (!di)
217     {
218         OIC_LOG_V(ERROR, TAG, "Missing required di query parameter!");
219         goto exit;
220     }
221
222     if (OCRDDatabaseDeleteResources(di, ins, nIns) == OC_STACK_OK)
223     {
224         OIC_LOG_V(DEBUG, TAG, "Deleted resource(s).");
225         ehResult = OC_EH_OK;
226     }
227
228 exit:
229     OICFree(ins);
230     OICFree(queryDup);
231     if (sendResponse(ehRequest, NULL, ehResult) != OC_STACK_OK)
232     {
233         OIC_LOG(ERROR, TAG, "Sending response failed.");
234     }
235     return ehResult;
236 }
237
238 /*
239  * This internal method is the entity handler for RD resources and
240  * will handle REST request (GET/PUT/POST/DEL) for them.
241  */
242 static OCEntityHandlerResult rdEntityHandler(OCEntityHandlerFlag flag,
243         OCEntityHandlerRequest *ehRequest, OC_ANNOTATE_UNUSED void *callbackParameter)
244 {
245     OCEntityHandlerResult ehRet = OC_EH_ERROR;
246
247     if (!ehRequest)
248     {
249         return ehRet;
250     }
251
252     if (flag & OC_REQUEST_FLAG)
253     {
254         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG.");
255         switch (ehRequest->method)
256         {
257             case OC_REST_GET:
258             case OC_REST_DISCOVER:
259                 ehRet = handleGetRequest(ehRequest);
260                 break;
261             case OC_REST_POST:
262                 ehRet = handlePublishRequest(ehRequest);
263                 break;
264             case OC_REST_DELETE:
265                 ehRet = handleDeleteRequest(ehRequest);
266                 break;
267             case OC_REST_PUT:
268             case OC_REST_OBSERVE:
269             case OC_REST_OBSERVE_ALL:
270             case OC_REST_PRESENCE:
271             case OC_REST_NOMETHOD:
272                 break;
273         }
274     }
275
276     return ehRet;
277 }
278
279 /**
280  * Registers RD resource
281  */
282 OCStackResult OCRDStart()
283 {
284     OCStackResult result = OCCreateResource(&rdHandle,
285                                 OC_RSRVD_RESOURCE_TYPE_RD,
286                                 OC_RSRVD_INTERFACE_DEFAULT,
287                                 OC_RSRVD_RD_URI,
288                                 rdEntityHandler,
289                                 NULL,
290                                 (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE));
291
292     if (result == OC_STACK_OK)
293     {
294         OIC_LOG(DEBUG, TAG, "Resource Directory resource created.");
295     }
296     else
297     {
298         OIC_LOG(ERROR, TAG, "Failed creating Resource Directory resource.");
299         return result;
300     }
301     result = OCBindResourceTypeToResource(rdHandle,
302                     OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
303     if (result == OC_STACK_OK)
304     {
305         OIC_LOG(DEBUG, TAG, "Resource Directory resource Publish created.");
306     }
307     else
308     {
309         OIC_LOG(ERROR, TAG, "Failed creating Resource Directory Publish resource.");
310     }
311
312     return result;
313 }
314
315 /**
316  * Stops resource directory server
317  */
318 OCStackResult OCRDStop()
319 {
320     if (!rdHandle)
321     {
322         OIC_LOG(ERROR, TAG, "Resource Directory resource handle is not initialized.");
323         return OC_STACK_NO_RESOURCE;
324     }
325
326     OCStackResult result = OCDeleteResource(rdHandle);
327
328     if (result == OC_STACK_OK)
329     {
330       OIC_LOG(DEBUG, TAG, "Resource Directory resource deleted.");
331     }
332     else
333     {
334       OIC_LOG(ERROR, TAG, "Resource Directory resource not deleted.");
335     }
336
337     return result;
338 }
339
340 #endif