1 //******************************************************************
3 // Copyright 2015 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 at
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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include "rd_server.h"
22 #include "rd_database.h"
27 #include "payload_logging.h"
28 #include "ocpayload.h"
30 #include "oic_string.h"
32 #define TAG PCF("OIC_RD_SERVER")
36 // This is temporary hardcoded value for bias factor.
37 static const int OC_RD_DISC_SEL = 100;
39 static OCResourceHandle rdHandle;
41 static OCStackResult sendResponse(const OCEntityHandlerRequest *ehRequest, OCRepPayload *rdPayload,
42 OCEntityHandlerResult ehResult)
44 OCEntityHandlerResponse response = { 0 };
45 response.requestHandle = ehRequest->requestHandle;
46 response.resourceHandle = ehRequest->resource;
47 response.ehResult = ehResult;
48 response.payload = (OCPayload*)(rdPayload);
49 return OCDoResponse(&response);
53 * This internal method handles RD discovery request.
54 * Responds with the RD discovery payload message.
56 static OCEntityHandlerResult handleGetRequest(const OCEntityHandlerRequest *ehRequest)
60 OIC_LOG(DEBUG, TAG, "Invalid request pointer.");
64 OCEntityHandlerResult ehResult = OC_EH_OK;
65 OIC_LOG_V(DEBUG, TAG, "Received OC_REST_GET from client with query: %s.", ehRequest->query);
67 OCRepPayload *rdPayload = (OCRepPayload *)OCRepPayloadCreate();
70 return OC_STACK_NO_MEMORY;
73 const char *id = OCGetServerInstanceIDString();
76 OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, id);
78 OCRepPayloadSetPropInt(rdPayload, OC_RSRVD_RD_DISCOVERY_SEL, OC_RD_DISC_SEL);
80 OCRepPayloadAddResourceType(rdPayload, OC_RSRVD_RESOURCE_TYPE_RD);
81 OCRepPayloadAddResourceType(rdPayload, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
83 OCRepPayloadAddInterface(rdPayload, OC_RSRVD_INTERFACE_DEFAULT);
85 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
87 if (OC_STACK_OK != sendResponse(ehRequest, rdPayload, OC_EH_OK))
89 OIC_LOG(ERROR, TAG, "Sending response failed.");
90 ehResult = OC_EH_ERROR;
97 * This internal method handles RD publish request.
98 * Responds with the RD success message.
100 static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *ehRequest)
102 OCEntityHandlerResult ehResult = OC_EH_OK;
106 OIC_LOG(DEBUG, TAG, "Invalid request pointer");
110 OIC_LOG_V(DEBUG, TAG, "Received OC_REST_POST from client with query: %s.", ehRequest->query);
112 OCRepPayload *payload = (OCRepPayload *)ehRequest->payload;
113 OCRepPayload *resPayload = NULL;
116 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) payload);
117 if (OC_STACK_OK == OCRDDatabaseInit(NULL))
119 if (OC_STACK_OK == OCRDDatabaseStoreResources(payload, &ehRequest->devAddr))
121 OIC_LOG_V(DEBUG, TAG, "Stored resources.");
122 resPayload = payload;
127 resPayload = (OCRepPayload *)OCRepPayloadCreate();
128 ehResult = OC_EH_ERROR;
133 if (OC_STACK_OK != sendResponse(ehRequest, resPayload, ehResult))
135 OIC_LOG(ERROR, TAG, "Sending response failed.");
138 if (OC_EH_OK == ehResult)
140 OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_WELL_KNOWN_URI);
142 OCStackResult result = OCNotifyAllObservers(handle, OC_NA_QOS);
143 if (OC_STACK_NO_OBSERVERS != result && OC_STACK_OK != result)
145 OIC_LOG(ERROR, TAG, "Notifying observers failed.");
153 static OCEntityHandlerResult handleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
155 OCEntityHandlerResult ehResult = OC_EH_ERROR;
158 char *queryDup = NULL;
159 char *restOfQuery = NULL;
160 char *keyValuePair = NULL;
167 OIC_LOG(DEBUG, TAG, "Invalid request pointer");
171 OIC_LOG_V(DEBUG, TAG, "Received OC_REST_DELETE from client with query: %s.", ehRequest->query);
173 if (OC_STACK_OK != OCRDDatabaseInit(NULL))
178 #define OC_RSRVD_INS_KEY OC_RSRVD_INS OC_KEY_VALUE_DELIMITER /* "ins=" */
179 keyValuePair = strstr(ehRequest->query, OC_RSRVD_INS_KEY);
183 keyValuePair = strstr(keyValuePair + sizeof(OC_RSRVD_INS_KEY), OC_RSRVD_INS_KEY);
187 ins = OICMalloc(nIns * sizeof(uint8_t));
190 OIC_LOG_V(ERROR, TAG, "ins is NULL");
196 queryDup = OICStrdup(ehRequest->query);
197 if (NULL == queryDup)
199 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
202 keyValuePair = strtok_r(queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
205 key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
208 OIC_LOG_V(ERROR, TAG, "Invalid query parameter!");
211 else if (0 == strncasecmp(key, OC_RSRVD_DEVICE_ID, sizeof(OC_RSRVD_DEVICE_ID) - 1))
215 else if (0 == strncasecmp(key, OC_RSRVD_INS, sizeof(OC_RSRVD_INS) - 1))
218 long int i = strtol(value, &endptr, 0);
219 if ( '\0' != *endptr || i < 0 || i > UINT8_MAX)
221 OIC_LOG_V(ERROR, TAG, "Invalid ins query parameter: %s", value);
227 keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
231 OIC_LOG_V(ERROR, TAG, "Missing required di query parameter!");
235 if (OC_STACK_OK == OCRDDatabaseDeleteResources(di, ins, nIns))
237 OIC_LOG_V(DEBUG, TAG, "Deleted resource(s).");
241 if (OC_EH_OK == ehResult)
243 OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_WELL_KNOWN_URI);
245 OCStackResult result = OCNotifyAllObservers(handle, OC_NA_QOS);
246 if (OC_STACK_NO_OBSERVERS != result && OC_STACK_OK != result)
248 OIC_LOG(ERROR, TAG, "Notifying observers failed.");
255 if (OC_STACK_OK != sendResponse(ehRequest, NULL, ehResult))
257 OIC_LOG(ERROR, TAG, "Sending response failed.");
263 * This internal method is the entity handler for RD resources and
264 * will handle REST request (GET/PUT/POST/DEL) for them.
266 static OCEntityHandlerResult rdEntityHandler(OCEntityHandlerFlag flag,
267 OCEntityHandlerRequest *ehRequest, OC_ANNOTATE_UNUSED void *callbackParameter)
269 OCEntityHandlerResult ehRet = OC_EH_ERROR;
276 if (flag & OC_REQUEST_FLAG)
278 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG.");
279 switch (ehRequest->method)
282 case OC_REST_DISCOVER:
283 ehRet = handleGetRequest(ehRequest);
286 ehRet = handlePublishRequest(ehRequest);
289 ehRet = handleDeleteRequest(ehRequest);
292 case OC_REST_OBSERVE:
293 case OC_REST_OBSERVE_ALL:
294 case OC_REST_PRESENCE:
295 case OC_REST_NOMETHOD:
304 * Registers RD resource
306 OCStackResult OCRDStart()
308 OCStackResult result = OCCreateResource(&rdHandle,
309 OC_RSRVD_RESOURCE_TYPE_RD,
310 OC_RSRVD_INTERFACE_DEFAULT,
314 (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE));
316 if (OC_STACK_OK == result)
318 OIC_LOG(DEBUG, TAG, "Resource Directory resource created.");
322 OIC_LOG(ERROR, TAG, "Failed creating Resource Directory resource.");
325 result = OCBindResourceTypeToResource(rdHandle,
326 OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
327 if (OC_STACK_OK == result)
329 OIC_LOG(DEBUG, TAG, "Resource Directory resource Publish created.");
333 OIC_LOG(ERROR, TAG, "Failed creating Resource Directory Publish resource.");
340 * Stops resource directory server
342 OCStackResult OCRDStop()
346 OIC_LOG(ERROR, TAG, "Resource Directory resource handle is not initialized.");
347 return OC_STACK_NO_RESOURCE;
350 OCStackResult result = OCDeleteResource(rdHandle);
352 if (OC_STACK_OK == result)
354 OIC_LOG(DEBUG, TAG, "Resource Directory resource deleted.");
358 OIC_LOG(ERROR, TAG, "Resource Directory resource not deleted.");