Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / service / notification-manager / NotificationManager / src / hosting.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
21 // Hosting Header
22 #include "hosting.h"
23 #include "virtualResource.h"
24
25 // External Lib
26 #include "cJSON.h"
27
28 /*
29  * internal function & static variable
30  */
31 ///////////////////////////////////////////////////////////////////////////////////////////////////
32 static MirrorResourceList *s_mirrorResourceList = NULL;
33 static RequestHandleList *s_requestHandleList = NULL;
34
35 #define OIC_COORDINATING_FLAG "/hosting"
36 #define OIC_STRING_MAX_VALUE 100
37
38 #define OC_DEFAULT_ADDRESS               "224.0.1.187"
39 #define OC_WELL_KNOWN_COORDINATING_QUERY "coap://224.0.1.187:5683/oc/core?rt=Resource.Hosting"
40 #define OC_COORDINATING_QUERY            "/oc/core?rt=Resource.Hosting"
41 #define DEFAULT_CONTEXT_VALUE 0x99
42
43 /*
44  * Presence Func for hosting
45  */
46
47 /**
48  *
49  * request presence for coordinating
50  *
51  * @param[in] originResourceAddr - pointer of address string of original resource
52  *
53  * @return
54  *     OC_STACK_OK
55  *     OC_STACK_ERROR
56  */
57 OCStackResult requestPresence(char *originResourceAddr);
58
59 /**
60  *
61  * callback function that call when response of presence request received
62  *
63  * @param[in] originResourceAddr - pointer of address string of original resource
64  *
65  * @return
66  *     OC_STACK_OK
67  *     OC_STACK_ERROR
68  */
69 OCStackApplicationResult requestPresenceCB(void *context, OCDoHandle handle,
70         OCClientResponse *clientResponse);
71
72 /**
73  *
74  * build mirror resource list by clientResponse
75  *
76  * @param[in] handle - not using...
77  * @param[in] clientResponse - client response that mirror resources are stored
78  *
79  * @return
80  *     pointer of result MirrorResourceList
81  */
82 MirrorResourceList *buildMirrorResourceList(OCDoHandle handle, OCClientResponse *clientResponse);
83
84 /**
85  *
86  * build mirror resource by JSON payload
87  *
88  * @param[in] ocArray_sub - pointer of json payload string
89  *
90  * @return
91  *     pointer of result MirrorResource
92  */
93 MirrorResource *buildMirrorResource(cJSON *ocArray_sub);
94
95 /**
96  *
97  * This method is used when setting queryUri, registering callback function and starting OCDoResource() Function in order to find Coordinatee Candidate
98  *
99  * @brief discover coordinatee candidate
100  *
101  * @return
102  *     OC_STACK_OK               - no errors
103  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
104  *     OC_STACK_INVALID_METHOD   - invalid resource method
105  *     OC_STACK_INVALID_URI      - invalid required or reference URI
106  *     OC_STACK_INVALID_QUERY    - number of resource types specified for filtering presence
107  *                                 notifications exceeds @ref MAX_PRESENCE_FILTERS.
108  *     OC_STACK_ERROR            - otherwise error(initialized value)
109  */
110 int requestCoordinateeCandidateDiscovery(char *address);
111
112 /**
113  *
114  * This method is used to add a coordinator resource callback method in mirrorResourceList when host resource discovered.
115  *
116  * @param[in] context
117  *              Context for callback method
118  * @param[in] handle
119  *              Handle to an @ref OCDoResource invocation.
120  * @param[in] clientResponse
121  *              Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
122  *
123  * @brief callback for receiving response of discoverCoordinateeCandidate()
124  *
125  * @return
126  *     PRINT("Callback Context for DISCOVER query recvd successfully")      - context is DEFAULT_CONTEXT_VALUE
127  *     call the buildMirrorResource() method                                    - clientResponse is not NULL && clientResponse->result is OC_STACK_OK
128  *     OC_STACK_KEEP_TRANSACTION                                                - otherwise case
129  */
130 OCStackApplicationResult requestCoordinateeCandidateDiscoveryCB(void *context, OCDoHandle handle,
131         OCClientResponse *clientResponse);
132
133 /**
134  *
135  * This method is used when setting queryUri, registering callback function and starting OCDoResource() Function in order to request resource coordination
136  *
137  * @brief
138  *
139  * @param[in] mirrorResource
140  *          mirrorResource for using in order to request resource coordination
141  *
142  * @return
143  *     OC_STACK_OK               - no errors
144  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
145  *     OC_STACK_INVALID_METHOD   - invalid resource method
146  *     OC_STACK_INVALID_URI      - invalid required or reference URI
147  *     OC_STACK_INVALID_QUERY    - number of resource types specified for filtering presence
148  *                                 notifications exceeds @ref MAX_PRESENCE_FILTERS.
149  *     OC_STACK_ERROR            - otherwise error(initialized value)
150  */
151 OCStackResult requestResourceObservation(MirrorResource *mirrorResource);
152
153 /**
154  *
155  * This method is used to handle callback of requestCoordination method.
156  *
157  * @param[in] context
158  *              Context for callback method
159  * @param[in] handle
160  *              Handle to update mirror resource and check errorResponse
161  * @param[in] clientResponse
162  *              Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
163  *
164  * @brief callback when receiving response of coordinating requestion.
165  *
166  * @todo diverge return value
167  *
168  * @return
169  *
170  *     OC_STACK_KEEP_TRANSACTION                                            - otherwise case
171  */
172 OCStackApplicationResult requestResourceObservationCB(void *context, OCDoHandle handle,
173         OCClientResponse *clientResponse);
174
175 /**
176  *
177  * This method is used to check resource validation and delete resource if it is not exist(not alive).
178  *
179  * @brief check mirror resource is alive
180  *
181  * @param[in] requestHandle
182  *              Handle to check mirror resource
183  *
184  * @return
185  *
186  *     OC_STACK_DELETE_TRANSACTION                                              - otherwise case
187  */
188 OCStackApplicationResult checkResourceValidation(OCDoHandle requestHandle);
189
190 /**
191  *
192  * register Mirror resource in the base resource list
193  *
194  * @param[in] requestHandle
195  *              Handle to check mirror resource
196  *
197  * @return
198  *     OC_STACK_OK
199  *     OC_STACK_ERROR
200  */
201 OCStackResult registerMirrorResource(MirrorResource *node);
202
203 /**
204  *
205  * update resource
206  *
207  * @param[in] sourceHandle - handle of source resource
208  * @param[in] payload - pointer of json payload string that update items stored
209  *
210  * @return
211  *     pointer of mirror resource. return NULL if there is any error.
212  */
213 MirrorResource *updateMirrorResource(OCDoHandle sourceHandle, const char *payload);
214
215 /**
216  *
217  * build response payload
218  *
219  * @param[in] ehRequest - pointer of handler of entity handler request that to be responded
220  *
221  * @return
222  *     OC_STACK_OK
223  *     OC_STACK_ERROR
224  */
225 char *buildResponsePayload (OCEntityHandlerRequest *ehRequest);
226
227 /**
228  *
229  * handle "Get" request
230  *
231  * @param[in] ehRequest - pointer of handler of entity handler request
232  * @param[out] payload - pointer of payload to be responded
233  * @param[in] maxPayloadSize - size of payload
234  *
235  * @return
236  *     OC_EH_OK - success to copy response payload
237  *     OC_EH_ERROR - error to copy response payload
238  */
239 OCEntityHandlerResult handleGetRequest (OCEntityHandlerRequest *ehRequest,
240                                         char *payload, uint16_t maxPayloadSize);
241
242 /**
243  *
244  * handle request for non-existing resource
245  *
246  * @param[in] ehRequest - pointer of handler of entity handler request
247  * @param[out] payload - pointer of payload to be responded
248  * @param[in] maxPayloadSize - size of payload
249  *
250  * @return
251  *     OC_EH_RESOURCE_DELETED - resource deleted
252  */
253 OCEntityHandlerResult handleNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest,
254         char *payload, uint16_t maxPayloadSize);
255
256 /**
257  *
258  * callback function that called when source resource changed
259  *
260  * @param[in] flag - entity handler flag
261  * @param[in] entityHandlerRequest - pointer of entity handler request
262  *
263  * @return
264  *     OC_EH_OK
265  *     OC_EH_ERROR
266  */
267 OCEntityHandlerResult resourceEntityHandlerCB (OCEntityHandlerFlag flag,
268         OCEntityHandlerRequest *entityHandlerRequest);
269
270 /**
271  *
272  * request that address is alive
273  *
274  * @param[in] address - pointer of address string
275  *
276  * @return
277  *     OC_STACK_OK
278  *     OC_STACK_ERROR
279  */
280 OCStackResult requestIsAlive(const char *address);
281
282 /**
283  *
284  * get string value of OCStackResult code
285  *
286  * @param[in] result - OCStringResult code
287  *
288  * @return
289  *     pointer of result string value
290  */
291 const char *getResultString(OCStackResult result);
292
293 OCStackResult requestQuery(RequestHandle *request, OCMethod method,
294                            const char *queryAddress, const char *queryUri);
295 OCStackApplicationResult requestQueryCB(void *context, OCDoHandle handle,
296                                         OCClientResponse *clientResponse);
297 OCEntityHandlerResponse buildEntityHandlerResponse(OCEntityHandlerRequest *entityHandlerRequest,
298         const char *clientPayload);
299 OCEntityHandlerResult handleRequestPayload (OCEntityHandlerRequest *entityHandlerRequest,
300         char *payload, uint16_t maxPayloadSize);
301
302 /*
303  * for Lite Device Side
304  */
305
306 /**
307  *
308  * register resource as coordinatable
309  *
310  * @param[in] handle - resource handle
311  * @param[in] resourceTypeName - resource type name
312  * @param[in] resourceInterfaceName - resource interface name
313  * @param[in] resourceUri - resource URI
314  * @param[in] entityHandler - entity handler
315  * @param[in] resourceProperties - resource properties
316  *
317  * @return
318  *     pointer of result string value
319  */
320 OCStackResult registerResourceAsCoordinatable(OCResourceHandle *handle,
321         const char *resourceTypeName, const char *resourceInterfaceName,
322         const char *resourceUri, OCEntityHandler entityHandler, uint8_t resourceProperties);
323
324 OCStackResult registerResourceAsCoordinatable(OCResourceHandle *handle,
325         const char *resourceTypeName,
326         const char *resourceInterfaceName,
327         const char *resourceUri,
328         OCEntityHandler entityHandler,
329         uint8_t resourceProperties)
330 {
331     OCStackResult ret = OC_STACK_OK;
332     size_t coordinateUriLen = sizeof(char) * (strlen(resourceUri) +
333             strlen(OIC_COORDINATING_FLAG) + 1);
334     char *coordinatingURI = (char *)malloc(coordinateUriLen);
335     if(coordinatingURI == NULL)
336     {
337         OC_LOG_V(DEBUG, HOSTING_TAG, "memory alloc fail : coordinatingURI");
338         return OC_STACK_NO_MEMORY;
339     }
340
341     snprintf(coordinatingURI, coordinateUriLen,"%s%s", resourceUri, OIC_COORDINATING_FLAG);
342
343     OC_LOG_V(DEBUG, HOSTING_TAG, "requiredUri+coordinatingFlag = %s", coordinatingURI);
344
345     ret = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
346             coordinatingURI, entityHandler, resourceProperties);
347     free(coordinatingURI);
348     return ret;
349 }
350
351 /*
352  *  for Hosting Device Side
353  */
354 OCStackResult OICStartCoordinate()
355 {
356     OCStackResult ret = OC_STACK_ERROR;
357     if (OCInit((char *) NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
358     {
359         OC_LOG(ERROR, HOSTING_TAG, PCF("OCStack init ERROR"));
360     }
361     else
362     {
363         s_mirrorResourceList = createMirrorResourceList();
364         s_requestHandleList = createRequestHandleList();
365         ret = requestPresence(OC_MULTICAST_PREFIX);
366     }
367
368     return ret;
369 }
370
371 OCStackResult OICStopCoordinate()
372 {
373     OCStackResult result = OC_STACK_ERROR;
374
375     if (OCStop() == OC_STACK_OK)
376     {
377         OC_LOG_V(DEBUG, HOSTING_TAG, "OCStack Stop OK");
378     }
379
380     result = destroyMirrorResourceList(s_mirrorResourceList);
381     s_mirrorResourceList = NULL;
382     if(result != OC_STACK_OK)
383     {
384         return OC_STACK_ERROR;
385     }
386
387     return result;
388 }
389
390 int requestCoordinateeCandidateDiscovery(char *sourceResourceAddress)
391 {
392     OCStackResult result;
393     OCCallbackData cbData;
394     OCDoHandle handle;
395
396     /* Start a discovery query*/
397     char queryUri[OIC_STRING_MAX_VALUE] = { '\0' };
398     if (sourceResourceAddress == NULL)
399     {
400         strncpy(queryUri, OC_WELL_KNOWN_COORDINATING_QUERY, sizeof(queryUri));
401     }
402     else
403     {
404         snprintf(queryUri, sizeof(queryUri), "coap://%s%s",
405                 sourceResourceAddress , OC_COORDINATING_QUERY);
406     }
407
408     cbData.cb = requestCoordinateeCandidateDiscoveryCB;
409     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
410     cbData.cd = NULL;
411
412     result = OCDoResource(&handle, OC_REST_GET, queryUri, OIC_COORDINATING_FLAG, 0,
413             OC_TRANSPORT, OC_LOW_QOS, &cbData, NULL, 0);
414     if (result != OC_STACK_OK)
415     {
416         OC_LOG_V(DEBUG, HOSTING_TAG, "OCStack resource error");
417     }
418     else
419     {
420         OC_LOG_V(DEBUG, HOSTING_TAG, "Host Resource Finding...");
421     }
422     return result;
423 }
424
425 OCStackResult requestPresence(char *sourceResourceAddress)
426 {
427     OCStackResult result = OC_STACK_ERROR;
428     OCCallbackData cbData;
429     OCDoHandle handle;
430
431     if (sourceResourceAddress == NULL)
432     {
433         OC_LOG_V(DEBUG, HOSTING_TAG, "SourceResourceAddress is not available.");
434         return result;
435     }
436
437     cbData.cb = requestPresenceCB;
438     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
439     cbData.cd = NULL;
440
441     char queryUri[OIC_STRING_MAX_VALUE] = { '\0' };
442     snprintf(queryUri, sizeof(queryUri), "coap://%s%s", sourceResourceAddress , OC_PRESENCE_URI);
443     OC_LOG_V(DEBUG, HOSTING_TAG, "initializePresenceForCoordinating Query : %s", queryUri);
444
445     result = OCDoResource(&handle, OC_REST_PRESENCE, queryUri, 0, 0,
446             OC_TRANSPORT, OC_LOW_QOS, &cbData, NULL, 0);
447
448     if (result != OC_STACK_OK)
449     {
450         OC_LOG_V(DEBUG, HOSTING_TAG, "initializePresenceForCoordinating error");
451         result = OC_STACK_ERROR;
452     }
453     else
454     {
455         OC_LOG_V(DEBUG, HOSTING_TAG, "Success initializePresenceForCoordinating");
456     }
457
458     return result;
459 }
460
461 OCStackApplicationResult requestPresenceCB(void *context, OCDoHandle handle,
462         OCClientResponse *clientResponse)
463 {
464     uint8_t remoteIpAddress[4];
465     uint16_t remotePortNumber;
466     char address[OIC_STRING_MAX_VALUE] = { '\0' };
467
468     if (context == (void *) DEFAULT_CONTEXT_VALUE)
469     {
470         OC_LOG_V(DEBUG, HOSTING_TAG, "\tCallback Context for presence CB recv successfully");
471     }
472     if (clientResponse)
473     {
474         OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddress,
475                             remoteIpAddress + 1, remoteIpAddress + 2, remoteIpAddress + 3);
476         OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNumber);
477         OC_LOG_V(DEBUG, HOSTING_TAG, "\tStackResult: %s",  getResultString(clientResponse->result));
478         OC_LOG_V(DEBUG, HOSTING_TAG, "\tStackResult: %d",  clientResponse->result);
479         OC_LOG_V(DEBUG, HOSTING_TAG,
480                  "\tPresence Device =============> Presence %s @ %d.%d.%d.%d:%d",
481                  clientResponse->resJSONPayload, remoteIpAddress[0], remoteIpAddress[1],
482                  remoteIpAddress[2], remoteIpAddress[3], remotePortNumber);
483
484         snprintf(address, sizeof(address), "%d.%d.%d.%d:%d", remoteIpAddress[0], remoteIpAddress[1],
485                 remoteIpAddress[2], remoteIpAddress[3], remotePortNumber);
486         if (clientResponse->result == OC_STACK_OK)
487         {
488             requestCoordinateeCandidateDiscovery(address);
489         }
490         if (clientResponse->result == OC_STACK_PRESENCE_STOPPED
491             || clientResponse->result == OC_STACK_PRESENCE_TIMEOUT
492             || clientResponse->result == OC_STACK_PRESENCE_DO_NOT_HANDLE)
493         {
494             requestIsAlive(address);
495         }
496
497     }
498     return OC_STACK_KEEP_TRANSACTION;
499 }
500
501 OCStackApplicationResult requestCoordinateeCandidateDiscoveryCB(void *ctx, OCDoHandle handle,
502         OCClientResponse *clientResponse)
503 {
504     OC_LOG(DEBUG, HOSTING_TAG, "Found Host Resource");
505     OCStackResult ret = OC_STACK_DELETE_TRANSACTION;
506
507     if (ctx == (void *) DEFAULT_CONTEXT_VALUE)
508     {
509         OC_LOG(DEBUG, HOSTING_TAG, "Callback Context for DISCOVER query recvd successfully");
510     }
511     if (clientResponse && clientResponse->result == OC_STACK_OK)
512     {
513         MirrorResourceList *vList = buildMirrorResourceList(handle, clientResponse);
514         if (vList != NULL)
515         {
516
517             if (vList->headerNode == NULL)
518             {
519                 OC_LOG(DEBUG, HOSTING_TAG, "This Discover Response is empty");
520                 destroyMirrorResourceList(vList);
521                 return ret;
522             }
523
524             // register All of VirtualResource
525             while (vList->headerNode)
526             {
527                 MirrorResource *mirrorResource = vList->headerNode;
528                 ret = ejectMirrorResource(vList, mirrorResource);
529                 mirrorResource->next = NULL;
530                 OC_LOG_V(DEBUG, HOSTING_TAG,
531                         "register virtual resource uri : %s", mirrorResource->uri);
532                 if (ret != OC_STACK_OK)
533                 {
534                     continue;
535                 }
536
537                 ret = registerMirrorResource(mirrorResource);
538                 if (ret != OC_STACK_OK)
539                 {
540                     continue;
541                 }
542
543                 ret = insertMirrorResource(s_mirrorResourceList, mirrorResource);
544                 if (ret != OC_STACK_OK)
545                 {
546                     OCDeleteResource(mirrorResource->resourceHandle[OIC_MIRROR_HANDLE]);
547                     continue;
548                 }
549                 printMirrorResourceList(s_mirrorResourceList);
550
551                 ret = requestResourceObservation(mirrorResource);
552                 if (ret != OC_STACK_OK)
553                 {
554                     OCDeleteResource(mirrorResource->resourceHandle[OIC_MIRROR_HANDLE]);
555                     deleteMirrorResourceFromList(s_mirrorResourceList, mirrorResource);
556                     continue;
557                 }
558             }
559             destroyMirrorResourceList(vList);
560             if (ret != OC_STACK_OK)
561             {
562                 return ret;
563             }
564         }
565         ret = OC_STACK_KEEP_TRANSACTION;
566     }
567     return ret;
568 }
569
570 MirrorResourceList *buildMirrorResourceList(OCDoHandle handle, OCClientResponse *clientResponse)
571 {
572
573     cJSON *discoveryJson = cJSON_CreateObject();
574     discoveryJson = cJSON_Parse((char *)clientResponse->resJSONPayload);
575
576     cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, "oc");
577     char *ocArray_str = cJSON_PrintUnformatted(ocArray);
578
579     if ( strstr(ocArray_str, "[{}") == ocArray_str )
580     {
581         OC_LOG_V(DEBUG, HOSTING_TAG, "invalid payload : %s", ocArray_str);
582         cJSON_Delete(discoveryJson);
583         return NULL;
584     }
585
586     MirrorResourceList *retList = createMirrorResourceList();
587
588     uint8_t remoteIpAddr[4];
589     uint16_t remotePortNum;
590
591     OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
592                         remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
593     OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNum);
594
595     char sourceaddr[OIC_STRING_MAX_VALUE] = {'\0'};
596     snprintf(sourceaddr, sizeof(sourceaddr), "%d.%d.%d.%d:%d", remoteIpAddr[0], remoteIpAddr[1],
597             remoteIpAddr[2], remoteIpAddr[3], remotePortNum);
598
599     OC_LOG_V(DEBUG, HOSTING_TAG, "Host Device =============> Discovered %s @ %s",
600              clientResponse->resJSONPayload, sourceaddr);
601
602     int arraySize = cJSON_GetArraySize(ocArray);
603     for (int i = 0; i < arraySize; ++i)
604     {
605         cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, i);
606         MirrorResource *mirrorResource = buildMirrorResource(ocArray_sub);
607
608         if (mirrorResource == NULL)
609         {
610             continue;
611         }
612         mirrorResource->address[OIC_SOURCE_ADDRESS] =
613                 (char *)malloc(sizeof(char) * OIC_STRING_MAX_VALUE);
614         if(mirrorResource->address[OIC_SOURCE_ADDRESS] == NULL)
615         {
616             OC_LOG_V(DEBUG, HOSTING_TAG, "memory alloc fail : mirrorResource address_source");
617             destroyMirrorResource(mirrorResource);
618             continue;
619         }
620         snprintf(mirrorResource->address[OIC_SOURCE_ADDRESS],
621                 sizeof(char) * OIC_STRING_MAX_VALUE, "%s", sourceaddr);
622
623         mirrorResource->address[OIC_MIRROR_ADDRESS] =
624                 (char *)malloc(sizeof(char) * OIC_STRING_MAX_VALUE);
625         if(mirrorResource->address[OIC_MIRROR_ADDRESS] == NULL)
626         {
627             OC_LOG_V(DEBUG, HOSTING_TAG, "memory alloc fail : mirrorResource address_mirror");
628             destroyMirrorResource(mirrorResource);
629             continue;
630         }
631         snprintf(mirrorResource->address[OIC_MIRROR_ADDRESS],
632                 sizeof(char) * OIC_STRING_MAX_VALUE, "0.0.0.0:00");
633
634         if (OC_STACK_OK != insertMirrorResource(retList, mirrorResource))
635         {
636             OC_LOG_V(DEBUG, HOSTING_TAG, "buildVirtualResourceList : insert resource fail");
637             destroyMirrorResource(mirrorResource);
638         }
639     }
640
641     cJSON_Delete(discoveryJson);
642     return retList;
643 }
644
645 MirrorResource *buildMirrorResource(cJSON *ocArray_sub)
646 {
647     MirrorResource *mirrorResource = NULL;
648     const char *curValuestring = cJSON_GetObjectItem(ocArray_sub, "href")->valuestring;
649
650     if ( strstr(curValuestring, OIC_COORDINATING_FLAG) )
651     {
652         mirrorResource = createMirrorResource();
653         if(mirrorResource == NULL)
654         {
655             OC_LOG_V(DEBUG, HOSTING_TAG, "memory alloc fail for mirrorResource");
656             goto RET_ERROR;
657         }
658
659         mirrorResource->uri = (char *)malloc(sizeof(char) * OIC_STRING_MAX_VALUE);
660         if(mirrorResource->uri == NULL)
661         {
662             OC_LOG_V(DEBUG, HOSTING_TAG, "memory alloc fail for mirrorResource uri");
663             goto RET_ERROR;
664         }
665         strncpy(mirrorResource->uri, curValuestring, strlen(curValuestring) - strlen(OIC_COORDINATING_FLAG));
666         mirrorResource->uri[strlen(curValuestring) - strlen(OIC_COORDINATING_FLAG)] = '\0';
667         OC_LOG_V(DEBUG, HOSTING_TAG, "VirtualResource URI : %s", mirrorResource->uri);
668
669         cJSON *inArray_sub = cJSON_GetObjectItem(ocArray_sub, "prop");
670
671         cJSON *tmpJSON = NULL;
672         int sizetemp = 0;
673
674         tmpJSON = cJSON_GetObjectItem(inArray_sub, "rt");
675         sizetemp = cJSON_GetArraySize(tmpJSON);
676         mirrorResource->prop.countResourceType = sizetemp;
677         mirrorResource->prop.resourceType = (char **)malloc(sizeof(char *)*sizetemp);
678         if (mirrorResource->prop.resourceType == NULL)
679         {
680             OC_LOG_V(DEBUG, HOSTING_TAG,
681                     "memory alloc fail for mirrorResource number of resourceType");
682             goto RET_ERROR;
683         }
684         else
685         {
686             for (int k = 0; k < sizetemp; ++k)
687             {
688                 mirrorResource->prop.resourceType[k] =
689                         (char *)malloc(sizeof(char) * OIC_STRING_MAX_VALUE);
690                 if (mirrorResource->prop.resourceType[k] == NULL)
691                 {
692                     OC_LOG_V(DEBUG, HOSTING_TAG,
693                             "memory alloc fail for mirrorResource resourceType[n]");
694                     goto RET_ERROR;
695                 }
696                 memset(mirrorResource->prop.resourceType[k], '\0', OIC_STRING_MAX_VALUE);
697                 strncpy(mirrorResource->prop.resourceType[k],
698                         cJSON_GetArrayItem(tmpJSON, k)->valuestring,
699                         sizeof(char) * OIC_STRING_MAX_VALUE);
700             }
701         }
702
703         tmpJSON = cJSON_GetObjectItem(inArray_sub, "if");
704         sizetemp = cJSON_GetArraySize(tmpJSON);
705         mirrorResource->prop.countInterface = sizetemp;
706         mirrorResource->prop.resourceInterfaceName = (char **)malloc(sizeof(char *)*sizetemp);
707         if (mirrorResource->prop.resourceInterfaceName == NULL)
708         {
709             OC_LOG_V(DEBUG, HOSTING_TAG,
710                     "memory alloc fail for mirrorResource number of resourceInterfaceName");
711             goto RET_ERROR;
712         }
713
714         for (int k = 0; k < sizetemp; ++k)
715         {
716             mirrorResource->prop.resourceInterfaceName[k] =
717                     (char *)malloc(sizeof(char) * OIC_STRING_MAX_VALUE);
718             if (mirrorResource->prop.resourceInterfaceName[k] == NULL)
719             {
720                 OC_LOG_V(DEBUG, HOSTING_TAG,
721                         "memory alloc fail for mirrorResource resourceInterfaceName[n]");
722                 goto RET_ERROR;
723             }
724
725             memset(mirrorResource->prop.resourceInterfaceName[k], '\0', OIC_STRING_MAX_VALUE);
726             strncpy(mirrorResource->prop.resourceInterfaceName[k],
727                     cJSON_GetArrayItem(tmpJSON, k)->valuestring,
728                     sizeof(char) * OIC_STRING_MAX_VALUE);
729         }
730     }
731
732     return mirrorResource;
733
734 RET_ERROR:
735     destroyMirrorResource(mirrorResource);
736     return NULL;
737 }
738
739 OCStackResult registerMirrorResource(MirrorResource *mirrorResource)
740 {
741     OCStackResult result = OC_STACK_ERROR;
742
743     MirrorResource *foundMirrorResource = findMirrorResourceUsingAddressAndURI(s_mirrorResourceList,
744                                           mirrorResource->address[OIC_MIRROR_ADDRESS], OIC_MIRROR_ADDRESS, mirrorResource->uri);
745     if (foundMirrorResource != NULL)
746     {
747         OC_LOG_V(DEBUG, HOSTING_TAG, "Already registered resource");
748         goto RETURN_ERR;
749     }
750
751     result = OCCreateResource(&(mirrorResource->resourceHandle[OIC_MIRROR_HANDLE]),
752                               mirrorResource->prop.resourceType[0],
753                               mirrorResource->prop.resourceInterfaceName[0],
754                               mirrorResource->uri,
755                               resourceEntityHandlerCB,
756                               OC_DISCOVERABLE | OC_OBSERVABLE);
757
758     OC_LOG_V(DEBUG, HOSTING_TAG, "created mirror resource Handle : %u",mirrorResource->resourceHandle[OIC_MIRROR_HANDLE]);
759
760     if (result != OC_STACK_OK)
761     {
762         OC_LOG_V(DEBUG, HOSTING_TAG, "error return = %s", getResultString(result));
763         mirrorResource->next = NULL;
764         destroyMirrorResource(mirrorResource);
765         return result;
766     }
767
768     if (mirrorResource->prop.countResourceType > 1)
769     {
770         int i = 0;
771         for (i = 1; i < mirrorResource->prop.countResourceType; ++i)
772         {
773             result = OCBindResourceTypeToResource(
774                              mirrorResource->resourceHandle[OIC_MIRROR_HANDLE],
775                              mirrorResource->prop.resourceType[i]);
776             if (result != OC_STACK_OK)
777             {
778                 OC_LOG_V(DEBUG, HOSTING_TAG, "Virtual Resource Registration Fail : BindResourceType");
779                 goto RETURN_ERR;
780             }
781         }
782     }
783
784     if (mirrorResource->prop.countInterface > 1)
785     {
786         int i = 0;
787         for (i = 1; i < mirrorResource->prop.countInterface; ++i)
788         {
789             result = OCBindResourceInterfaceToResource(
790                          mirrorResource->resourceHandle[OIC_MIRROR_HANDLE],
791                          mirrorResource->prop.resourceInterfaceName[i]);
792             if (result != OC_STACK_OK)
793             {
794                 OC_LOG_V(DEBUG, HOSTING_TAG,
795                         "Virtual Resource Registration Fail : BindResourceInterfaceName");
796                 goto RETURN_ERR;
797             }
798         }
799     }
800
801     OC_LOG_V(DEBUG, HOSTING_TAG, "Mirror Resource Registration Success");
802     OC_LOG_V(DEBUG, HOSTING_TAG, "Mirror Resource uri : %s", mirrorResource->uri);
803     OC_LOG_V(DEBUG, HOSTING_TAG, "Mirror Resource source address : %s",
804              mirrorResource->address[OIC_SOURCE_ADDRESS]);
805     OC_LOG_V(DEBUG, HOSTING_TAG, "Mirror Resource virtual address : %s",
806              mirrorResource->address[OIC_MIRROR_ADDRESS]);
807     return result;
808
809 RETURN_ERR:
810     OCDeleteResource(mirrorResource->resourceHandle[OIC_MIRROR_HANDLE]);
811     mirrorResource->next = NULL;
812     destroyMirrorResource(mirrorResource);
813
814     return result;
815 }
816
817 OCStackResult requestResourceObservation(MirrorResource *mirrorResource)
818 {
819     OCStackResult result;
820     OCCallbackData cbData;
821
822     cbData.cb = requestResourceObservationCB;
823     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
824     cbData.cd = NULL;
825
826     char query[OIC_STRING_MAX_VALUE] = {'\0'};
827     snprintf(query, sizeof(query), "coap://%s%s%s", mirrorResource->address[OIC_SOURCE_ADDRESS], mirrorResource->uri,
828             OIC_COORDINATING_FLAG);
829
830     result = OCDoResource(&mirrorResource->resourceHandle[OIC_REQUEST_HANDLE], OC_REST_OBSERVE, query,
831                           0, NULL, OC_TRANSPORT,
832                           OC_HIGH_QOS, &cbData, NULL, 0);
833
834     if (result != OC_STACK_OK)
835     {
836         OC_LOG_V(DEBUG, HOSTING_TAG, "OCDoResource returns error %s with method %d",
837                  getResultString(result), OC_REST_OBSERVE);
838     }
839
840     return result;
841 }
842
843 OCStackApplicationResult requestResourceObservationCB(void *context, OCDoHandle handle,
844         OCClientResponse *clientResponse)
845 {
846     OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
847
848     if (context == (void *)DEFAULT_CONTEXT_VALUE)
849     {
850         OC_LOG_V(DEBUG, HOSTING_TAG, "Callback Context for OBS query recvd successfully");
851     }
852
853     if (clientResponse && clientResponse->result != OC_STACK_OK)
854     {
855         OC_LOG_V(DEBUG, HOSTING_TAG, "observeCB result error = %s",
856                  getResultString(clientResponse->result));
857         return checkResourceValidation(handle);
858     }
859
860     if (clientResponse && clientResponse->result == OC_STACK_OK)
861     {
862         OC_LOG_V(DEBUG, HOSTING_TAG,
863                  "<=============Callback Context for OBSERVE notification recvd successfully");
864         OC_LOG_V(DEBUG, HOSTING_TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
865         OC_LOG_V(DEBUG, HOSTING_TAG, "JSON = %s =============> Obs Response",
866                  clientResponse->resJSONPayload);
867
868         MirrorResource *foundMirrorResource = updateMirrorResource(handle, clientResponse->resJSONPayload);
869         if (foundMirrorResource == NULL)
870         {
871             OC_LOG_V(DEBUG, HOSTING_TAG, "Cannot found Mirror Resource : Fail");
872             return ret;
873         }
874
875         if ( OC_STACK_OK != OCNotifyAllObservers(foundMirrorResource->resourceHandle[OIC_MIRROR_HANDLE],
876                 OC_HIGH_QOS) )
877         {
878             OC_LOG_V(DEBUG, HOSTING_TAG, "Notify Mirror Resource's Subscriber : Fail");
879         }
880         else
881         {
882             OC_LOG_V(DEBUG, HOSTING_TAG, "Notify Mirror Resource's Subscriber : Success");
883         }
884
885         if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
886         {
887             OC_LOG_V(DEBUG, HOSTING_TAG, "This also serves as a registration confirmation");
888         }
889         else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
890         {
891             OC_LOG_V(DEBUG, HOSTING_TAG, "This also serves as a deregistration confirmation");
892             return ret;
893         }
894         else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
895         {
896             OC_LOG_V(DEBUG, HOSTING_TAG, "This also tells you that registration/deregistration failed");
897             return ret;
898         }
899         ret = OC_STACK_KEEP_TRANSACTION;
900     }
901     return ret;
902 }
903
904 OCStackApplicationResult checkResourceValidation(OCDoHandle handle)
905 {
906     OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
907
908     RequestHandle *foundRequestHandle = findRequestHandle(s_requestHandleList, handle,
909                                         OIC_REQUEST_BY_COORDINATOR);
910
911     if (foundRequestHandle == NULL)
912     {
913         OC_LOG_V(DEBUG, HOSTING_TAG, "Not found any request.");
914         return ret;
915     }
916
917     if (foundRequestHandle->isAliveCheck)
918     {
919         OC_LOG_V(DEBUG, HOSTING_TAG, "This response is Alive Check : Expired resource");
920         OCDeleteResource(foundRequestHandle->requestHandle[OIC_REQUEST_BY_CLIENT]);
921     }
922     deleteRequestHandleFromList(s_requestHandleList, foundRequestHandle);
923     return ret;
924 }
925
926 MirrorResource *updateMirrorResource(OCDoHandle handle, const char *payload)
927 {
928     MirrorResource *foundMirrorResource = findMirrorResourceUsingHandle(
929             s_mirrorResourceList, handle, OIC_REQUEST_HANDLE);
930
931     if (!foundMirrorResource)
932     {
933         // TODO
934         OC_LOG_V(DEBUG, HOSTING_TAG, "Cannot found Mirror Resource. In updateMirrorResource");
935         return NULL;
936     }
937
938     cJSON *repData = NULL;
939     cJSON *observeJson = cJSON_Parse(payload);
940
941     if (observeJson)
942     {
943         cJSON *ocArray = cJSON_GetObjectItem(observeJson, "oc");
944         cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
945         cJSON *tempData = cJSON_GetObjectItem(ocArray_sub, "rep");
946         char *temp = cJSON_PrintUnformatted(tempData);
947
948         repData = cJSON_Parse(temp);
949         if (temp != NULL)
950         {
951             free(temp);
952         }
953         cJSON_Delete(observeJson);
954     }
955     else
956     {
957         OC_LOG_V(DEBUG, HOSTING_TAG, "Mirror resource payload is not correct");
958         return NULL;
959     }
960
961     if (foundMirrorResource->rep)
962     {
963         cJSON_Delete(foundMirrorResource->rep);
964         foundMirrorResource->rep = NULL;
965     }
966     foundMirrorResource->rep = repData;
967
968     cJSON *json = cJSON_CreateObject();
969
970     char nodeData[OIC_STRING_MAX_VALUE] = {'\0'};
971     snprintf(nodeData, sizeof(nodeData), "%s", foundMirrorResource->uri);
972     cJSON_AddStringToObject(json, "href", nodeData);
973
974     cJSON *nodeRep = cJSON_Parse(cJSON_PrintUnformatted(foundMirrorResource->rep));
975     cJSON_AddItemToObject(json, "rep", nodeRep);
976     OC_LOG_V(DEBUG, HOSTING_TAG, "It will notify resource : %s", cJSON_PrintUnformatted(json));
977
978     cJSON_Delete(json);
979
980     return foundMirrorResource;
981 }
982
983 char *buildResponsePayload (OCEntityHandlerRequest *entityHandlerRequest)
984 {
985     MirrorResource *mirrorResource = findMirrorResourceUsingHandle(s_mirrorResourceList,
986                                      entityHandlerRequest->resource, OIC_MIRROR_HANDLE);
987     if (!mirrorResource)
988     {
989         OC_LOG_V(DEBUG, HOSTING_TAG, "Cannot found Mirror Resource. In buildResponsePayload()");
990         OC_LOG_V(DEBUG, HOSTING_TAG, "Mirror Resource's Handle : %x.", entityHandlerRequest->resource);
991         return NULL;
992     }
993
994     if (entityHandlerRequest->method == OC_REST_PUT)
995     {
996         OC_LOG_V(DEBUG, HOSTING_TAG, "oc_rest_put");
997         if (mirrorResource->rep)
998         {
999             cJSON_Delete(mirrorResource->rep);
1000             mirrorResource->rep = NULL;
1001         }
1002         mirrorResource->rep = cJSON_CreateObject();
1003         mirrorResource->rep = cJSON_Parse(entityHandlerRequest->reqJSONPayload);
1004     }
1005
1006     OC_LOG_V(DEBUG, HOSTING_TAG, "node's uri : %s", mirrorResource->uri);
1007     OC_LOG_V(DEBUG, HOSTING_TAG, "node's source address : %s", mirrorResource->address[0]);
1008     OC_LOG_V(DEBUG, HOSTING_TAG, "node's mirror address : %s", mirrorResource->address[1]);
1009     OC_LOG_V(DEBUG, HOSTING_TAG, "node's rep : %s", cJSON_PrintUnformatted(mirrorResource->rep));
1010
1011     cJSON *jsonObject = cJSON_CreateObject();
1012
1013     char uriString[OIC_STRING_MAX_VALUE] = {'\0'};
1014     snprintf(uriString, sizeof(uriString), "%s", mirrorResource->uri);
1015     cJSON_AddStringToObject(jsonObject, "href", uriString);
1016
1017     cJSON *itemRep = cJSON_Parse(cJSON_PrintUnformatted(mirrorResource->rep));
1018     cJSON_AddItemToObject(jsonObject, "rep", itemRep);
1019     OC_LOG_V(DEBUG, HOSTING_TAG, "Will response resource : %s", cJSON_PrintUnformatted(jsonObject));
1020
1021     char *jsonResponse = cJSON_Print(jsonObject);
1022     cJSON_Delete(jsonObject);
1023
1024     return jsonResponse;
1025 }
1026
1027 OCEntityHandlerResult
1028 resourceEntityHandlerCB (OCEntityHandlerFlag entifyHandlerFlag,
1029                          OCEntityHandlerRequest *entityHandlerRequest)
1030 {
1031     OC_LOG_V(DEBUG, HOSTING_TAG, "Inside device default entity handler - flags: 0x%x",
1032              entifyHandlerFlag);
1033
1034     OCEntityHandlerResult entityHandlerResult = OC_EH_OK;
1035     OCEntityHandlerResponse entityHandlerResponse;
1036     char payload[MAX_RESPONSE_LENGTH] = {0};
1037
1038     // Validate pointer
1039     if (!entityHandlerRequest)
1040     {
1041         OC_LOG_V(DEBUG, HOSTING_TAG, "Invalid request pointer");
1042         return OC_EH_ERROR;
1043     }
1044
1045     // Initialize certain response fields
1046     entityHandlerResponse.numSendVendorSpecificHeaderOptions = 0;
1047     memset(entityHandlerResponse.sendVendorSpecificHeaderOptions, 0,
1048            sizeof entityHandlerResponse.sendVendorSpecificHeaderOptions);
1049     memset(entityHandlerResponse.resourceUri, 0, sizeof entityHandlerResponse.resourceUri);
1050
1051     if (entifyHandlerFlag & OC_REQUEST_FLAG)
1052     {
1053         OC_LOG_V(DEBUG, HOSTING_TAG, "Flag includes OC_REQUEST_FLAG");
1054         if (entityHandlerRequest->resource == NULL)
1055         {
1056             OC_LOG_V(DEBUG, HOSTING_TAG, "Received request from client to a non-existing resource");
1057             entityHandlerResult = handleNonExistingResourceRequest(entityHandlerRequest, payload,
1058                                   sizeof(payload) - 1);
1059         }
1060         else if (OC_REST_GET == entityHandlerRequest->method)
1061         {
1062             OC_LOG_V(DEBUG, HOSTING_TAG, "Received OC_REST_GET from client");
1063             entityHandlerResult = handleGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
1064         }
1065         else if (OC_REST_PUT == entityHandlerRequest->method ||
1066                  OC_REST_DELETE == entityHandlerRequest->method )
1067         {
1068             OC_LOG_V(DEBUG, HOSTING_TAG, "Received OC_REST_PUT/DELETE from client");
1069
1070             RequestHandle *request = createRequestHandle();
1071
1072             request->requestHandle[OIC_REQUEST_BY_CLIENT] = entityHandlerRequest;
1073             request->resourceHandle = entityHandlerRequest->resource;
1074             request->method = entityHandlerRequest->method;
1075             request->entityRequestHandle = entityHandlerRequest->requestHandle;
1076
1077             OCStackResult result = insertRequestHandle(s_requestHandleList, request);
1078             if (result != OC_STACK_OK)
1079             {
1080                 OC_LOG_V(DEBUG, HOSTING_TAG, "Insert request list : fail2(%d)", result);
1081                 return result;
1082             }
1083
1084             MirrorResource *mirrorResource = findMirrorResourceUsingHandle(s_mirrorResourceList,
1085                                              entityHandlerRequest->resource, OIC_MIRROR_HANDLE);
1086             if (mirrorResource == NULL)
1087             {
1088                 OC_LOG_V(DEBUG, HOSTING_TAG, "Not found requested resource");
1089                 return OC_EH_ERROR;
1090             }
1091
1092             result = requestQuery(request,
1093                     entityHandlerRequest->method, mirrorResource->address[OIC_SOURCE_ADDRESS],
1094                     mirrorResource->uri);
1095             if (result != OC_STACK_OK)
1096             {
1097                 OC_LOG_V(DEBUG, HOSTING_TAG, "Request query failed");
1098                 deleteRequestHandleFromList(s_requestHandleList, request);
1099             }
1100             return OC_EH_OK;
1101         }
1102         else
1103         {
1104             OC_LOG_V(DEBUG, HOSTING_TAG, "Received unsupported method %d from client",
1105                      entityHandlerRequest->method);
1106             entityHandlerResult = OC_EH_ERROR;
1107         }
1108
1109         // If the result isn't an error or forbidden, send response
1110         if (!((entityHandlerResult == OC_EH_ERROR) || (entityHandlerResult == OC_EH_FORBIDDEN)))
1111         {
1112             // Format the response.  Note this requires some info about the request
1113             entityHandlerResponse.requestHandle = entityHandlerRequest->requestHandle;
1114             entityHandlerResponse.resourceHandle = entityHandlerRequest->resource;
1115             entityHandlerResponse.ehResult = entityHandlerResult;
1116             entityHandlerResponse.payload = (char *)payload;
1117             entityHandlerResponse.payloadSize = strlen(payload);
1118             // Indicate that response is NOT in a persistent buffer
1119             entityHandlerResponse.persistentBufferFlag = 0;
1120
1121             // Handle vendor specific options
1122             if (entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
1123                 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
1124             {
1125                 OC_LOG_V(DEBUG, HOSTING_TAG, "Received vendor specific options");
1126                 OCHeaderOption *receivedVenderSpecificHeaderOptions =
1127                     entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
1128                 for ( int i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
1129                 {
1130                     if (((OCHeaderOption)receivedVenderSpecificHeaderOptions[i]).protocolID == OC_COAP_ID)
1131                     {
1132                         OC_LOG_V(DEBUG, HOSTING_TAG, "Received option with OC_COAP_ID and ID %u with",
1133                                  ((OCHeaderOption)receivedVenderSpecificHeaderOptions[i]).optionID );
1134                     }
1135                 }
1136                 OCHeaderOption *sendVenderSpecificHeaderOptions =
1137                     entityHandlerResponse.sendVendorSpecificHeaderOptions;
1138                 uint8_t option2[] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
1139                 uint8_t option3[] = {31, 32, 33, 34, 35, 36, 37, 38, 39, 40};
1140                 sendVenderSpecificHeaderOptions[0].protocolID = OC_COAP_ID;
1141                 sendVenderSpecificHeaderOptions[0].optionID = 2248;
1142                 memcpy(sendVenderSpecificHeaderOptions[0].optionData, option2, sizeof(option2));
1143                 sendVenderSpecificHeaderOptions[0].optionLength = 10;
1144                 sendVenderSpecificHeaderOptions[1].protocolID = OC_COAP_ID;
1145                 sendVenderSpecificHeaderOptions[1].optionID = 2600;
1146                 memcpy(sendVenderSpecificHeaderOptions[1].optionData, option3, sizeof(option3));
1147                 sendVenderSpecificHeaderOptions[1].optionLength = 10;
1148                 entityHandlerResponse.numSendVendorSpecificHeaderOptions = 2;
1149             }
1150
1151             // Send the response
1152             if (OCDoResponse(&entityHandlerResponse) != OC_STACK_OK)
1153             {
1154                 OC_LOG(ERROR, HOSTING_TAG, "Error sending response");
1155                 entityHandlerResult = OC_EH_ERROR;
1156             }
1157         }
1158     }
1159     if (entifyHandlerFlag & OC_OBSERVE_FLAG)
1160     {
1161         OC_LOG_V(DEBUG, HOSTING_TAG, "Flag includes OC_OBSERVE_FLAG");
1162         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
1163         {
1164             OC_LOG_V(DEBUG, HOSTING_TAG, "Received OC_OBSERVE_REGISTER from client");
1165         }
1166         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
1167         {
1168             OC_LOG_V(DEBUG, HOSTING_TAG, "Received OC_OBSERVE_DEREGISTER from client");
1169         }
1170     }
1171
1172     return entityHandlerResult;
1173 }
1174 OCEntityHandlerResult
1175 handleGetRequest (OCEntityHandlerRequest *entityHandlerRequest,
1176         char *payload, uint16_t maxPayloadSize)
1177 {
1178     OC_LOG_V(DEBUG, HOSTING_TAG, "ProcessGetRequest in....");
1179
1180     OCEntityHandlerResult entityHandlerResult = OC_EH_ERROR;
1181     char *responsePayload = buildResponsePayload(entityHandlerRequest);
1182     if(!responsePayload)
1183     {
1184         return entityHandlerResult;
1185     }
1186
1187     if (maxPayloadSize > strlen ((char *)responsePayload))
1188     {
1189         strncpy(payload, responsePayload, strlen((char *)responsePayload));
1190         entityHandlerResult = OC_EH_OK;
1191     }
1192     else
1193     {
1194         OC_LOG_V(DEBUG, HOSTING_TAG, "Response buffer: %d bytes is too small", maxPayloadSize);
1195     }
1196
1197     free(responsePayload);
1198
1199     return entityHandlerResult;
1200 }
1201 OCEntityHandlerResult
1202 handleNonExistingResourceRequest(OCEntityHandlerRequest *entityHandlerRequest,
1203         char *payload, uint16_t maxPayloadSize)
1204 {
1205     OC_LOG_V(INFO, HOSTING_TAG, "Executing %s ", __func__);
1206
1207     char responsePayload[OIC_STRING_MAX_VALUE] = {'\0'};
1208     strncpy(responsePayload, "{App determines payload: The resource does not exist.}",
1209             sizeof(responsePayload));
1210
1211     if ( (entityHandlerRequest != NULL) &&
1212          (maxPayloadSize > strlen ((char *)responsePayload)) )
1213     {
1214         strncpy((char *)payload, responsePayload, strlen((char *)responsePayload));
1215     }
1216     else
1217     {
1218         OC_LOG_V (INFO, HOSTING_TAG, "Response buffer: %d bytes is too small",
1219                   maxPayloadSize);
1220     }
1221
1222     return OC_EH_RESOURCE_DELETED;
1223 }
1224
1225 OCStackResult requestIsAlive(const char *address)
1226 {
1227     MirrorResourceList *requestMirrorResourceList = findMirrorResourceListUsingAddress(
1228                 s_mirrorResourceList, address, OIC_SOURCE_ADDRESS);
1229
1230     if (requestMirrorResourceList == NULL)
1231     {
1232         OC_LOG_V(DEBUG, HOSTING_TAG, "Cannot found any mirror resource1");
1233         return OC_STACK_ERROR;
1234     }
1235
1236     if (requestMirrorResourceList->headerNode == NULL)
1237     {
1238         OC_LOG_V(DEBUG, HOSTING_TAG, "Cannot found any mirror resource2");
1239         return OC_STACK_ERROR;
1240     }
1241
1242     MirrorResource *mirrorResource = requestMirrorResourceList->headerNode;
1243     while (mirrorResource)
1244     {
1245         RequestHandle *requestAlive = createRequestHandle();
1246         requestAlive->isAliveCheck = 1;
1247         requestAlive->requestHandle[OIC_REQUEST_BY_CLIENT] =
1248             mirrorResource->resourceHandle[OIC_MIRROR_HANDLE];
1249
1250         OCStackResult result = insertRequestHandle(s_requestHandleList, requestAlive);
1251         if (result != OC_STACK_OK)
1252         {
1253             OC_LOG_V(DEBUG, HOSTING_TAG, "Insert request list : fail3");
1254             destroyRequestHandle(requestAlive);
1255             mirrorResource = mirrorResource->next;
1256             continue;
1257         }
1258
1259         result = requestQuery(requestAlive, OC_REST_GET, address, mirrorResource->uri);
1260         if (result != OC_STACK_OK)
1261         {
1262             deleteRequestHandleFromList(s_requestHandleList, requestAlive);
1263         }
1264         mirrorResource = mirrorResource->next;
1265     }
1266     destroyMirrorResourceList(requestMirrorResourceList);
1267
1268     return OC_STACK_OK;
1269 }
1270
1271 const char *getResultString(OCStackResult result)
1272 {
1273     switch (result)
1274     {
1275         case OC_STACK_OK:
1276             return "OC_STACK_OK";
1277         case OC_STACK_RESOURCE_CREATED:
1278             return "OC_STACK_RESOURCE_CREATED";
1279         case OC_STACK_RESOURCE_DELETED:
1280             return "OC_STACK_RESOURCE_DELETED";
1281         case OC_STACK_INVALID_URI:
1282             return "OC_STACK_INVALID_URI";
1283         case OC_STACK_INVALID_QUERY:
1284             return "OC_STACK_INVALID_QUERY";
1285         case OC_STACK_INVALID_IP:
1286             return "OC_STACK_INVALID_IP";
1287         case OC_STACK_INVALID_PORT:
1288             return "OC_STACK_INVALID_PORT";
1289         case OC_STACK_INVALID_CALLBACK:
1290             return "OC_STACK_INVALID_CALLBACK";
1291         case OC_STACK_INVALID_METHOD:
1292             return "OC_STACK_INVALID_METHOD";
1293         case OC_STACK_NO_MEMORY:
1294             return "OC_STACK_NO_MEMORY";
1295         case OC_STACK_COMM_ERROR:
1296             return "OC_STACK_COMM_ERROR";
1297         case OC_STACK_INVALID_PARAM:
1298             return "OC_STACK_INVALID_PARAM";
1299         case OC_STACK_NOTIMPL:
1300             return "OC_STACK_NOTIMPL";
1301         case OC_STACK_NO_RESOURCE:
1302             return "OC_STACK_NO_RESOURCE";
1303         case OC_STACK_RESOURCE_ERROR:
1304             return "OC_STACK_RESOURCE_ERROR";
1305         case OC_STACK_SLOW_RESOURCE:
1306             return "OC_STACK_SLOW_RESOURCE";
1307         case OC_STACK_NO_OBSERVERS:
1308             return "OC_STACK_NO_OBSERVERS";
1309         case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
1310             return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
1311         case OC_STACK_PRESENCE_STOPPED:
1312             return "OC_STACK_PRESENCE_STOPPED";
1313         case OC_STACK_PRESENCE_TIMEOUT:
1314             return "OC_STACK_PRESENCE_TIMEOUT";
1315         case OC_STACK_PRESENCE_DO_NOT_HANDLE:
1316             return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
1317         case OC_STACK_ERROR:
1318             return "OC_STACK_ERROR";
1319         default:
1320             return "UNKNOWN";
1321     }
1322 }
1323
1324 void getJsonArrayPair(cJSON *tempData)
1325 {
1326     int countofrep = cJSON_GetArraySize(tempData);
1327     OC_LOG_V(DEBUG, HOSTING_TAG,
1328              "//////////////////////////////////////////////////////////////////////////");
1329     OC_LOG_V(DEBUG, HOSTING_TAG, "//Test");
1330     OC_LOG_V(DEBUG, HOSTING_TAG, "rep Size : %d", countofrep);
1331
1332     for (int i = 0; i < countofrep; ++i)
1333     {
1334         cJSON *arrayJSON = cJSON_GetArrayItem(tempData, i);
1335         OC_LOG_V(DEBUG, HOSTING_TAG, "rep#%d's name : %s", i, arrayJSON->string);
1336
1337         switch (arrayJSON->type)
1338         {
1339             case cJSON_False:
1340             case cJSON_True:
1341                 OC_LOG_V(DEBUG, HOSTING_TAG, "rep#%d's value : %d", i, arrayJSON->valueint);
1342                 break;
1343             case cJSON_Number:
1344                 OC_LOG_V(DEBUG, HOSTING_TAG, "rep#%d's value : %f", i, arrayJSON->valuedouble);
1345                 break;
1346             case cJSON_String:
1347                 OC_LOG_V(DEBUG, HOSTING_TAG, "rep#%d's value : %s", i, arrayJSON->valuestring);
1348                 break;
1349             case cJSON_NULL:
1350             default:
1351                 OC_LOG_V(DEBUG, HOSTING_TAG, "rep#%d's value : NULL", i);
1352                 break;
1353         }
1354     }
1355     OC_LOG_V(DEBUG, HOSTING_TAG,
1356              "//////////////////////////////////////////////////////////////////////////");
1357 }
1358
1359 OCStackResult requestQuery(RequestHandle *request, OCMethod method,
1360                            const char *queryAddress, const char *queryUri)
1361 {
1362
1363     OCStackResult result = OC_STACK_ERROR;
1364     OCCallbackData cbData;
1365
1366     /* Start a discovery query*/
1367     char queryFullUri[OIC_STRING_MAX_VALUE] = {'\0'};
1368     if (queryAddress == NULL)
1369     {
1370         return result;
1371     }
1372     else
1373     {
1374         snprintf(queryFullUri, sizeof(queryFullUri) ,"coap://%s%s%s", queryAddress , queryUri, OIC_COORDINATING_FLAG);
1375     }
1376
1377     cbData.cb = requestQueryCB;
1378     cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
1379     cbData.cd = NULL;
1380
1381     if(method == OC_REST_PUT)
1382     {
1383         char payload[OIC_STRING_MAX_VALUE] = {'\0'};
1384         snprintf(payload , sizeof(payload), "%s" ,
1385          ((OCEntityHandlerRequest*)request->requestHandle[OIC_REQUEST_BY_CLIENT])->reqJSONPayload);
1386
1387         result = OCDoResource(&request->requestHandle[OIC_REQUEST_BY_COORDINATOR],
1388                 method, queryFullUri, NULL, payload, OC_TRANSPORT, OC_LOW_QOS, &cbData, NULL, 0);
1389     }
1390     else
1391     {
1392         result = OCDoResource(&request->requestHandle[OIC_REQUEST_BY_COORDINATOR],
1393                 method, queryFullUri, NULL, 0, OC_TRANSPORT, OC_LOW_QOS, &cbData, NULL, 0);
1394     }
1395
1396     if (result != OC_STACK_OK)
1397     {
1398         OC_LOG_V(DEBUG, HOSTING_TAG, "OCStack resource error");
1399     }
1400
1401     return result;
1402 }
1403
1404 OCStackApplicationResult requestQueryCB(void *context, OCDoHandle handle,
1405                                         OCClientResponse *clientResponse)
1406 {
1407     OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
1408
1409     if (context == (void *) DEFAULT_CONTEXT_VALUE)
1410     {
1411         OC_LOG_V(DEBUG, HOSTING_TAG, "Callback Context for Request query recvd successfully");
1412     }
1413
1414     if (clientResponse && clientResponse->result != OC_STACK_OK && clientResponse->result != OC_STACK_RESOURCE_DELETED)
1415     {
1416         OC_LOG_V(DEBUG, HOSTING_TAG, "requestQueryCB result error = %s",
1417                  getResultString(clientResponse->result));
1418         return checkResourceValidation(handle);
1419     }
1420
1421     if (clientResponse && (clientResponse->result == OC_STACK_OK || clientResponse->result == OC_STACK_RESOURCE_DELETED))
1422     {
1423         RequestHandle *request = findRequestHandle(s_requestHandleList, handle, OIC_REQUEST_BY_COORDINATOR);
1424         if (request == NULL)
1425         {
1426             OC_LOG_V(DEBUG, HOSTING_TAG, "Not found Any request");
1427             return ret;
1428         }
1429         if (request->isAliveCheck == 1)
1430         {
1431             OC_LOG_V(DEBUG, HOSTING_TAG, "This response is Alive Check : Keep resource");
1432         }
1433         else
1434         {
1435             OC_LOG_V(DEBUG, HOSTING_TAG, "requestCB's payload: %s", clientResponse->resJSONPayload);
1436             OCEntityHandlerRequest *entityHandler = (OCEntityHandlerRequest *)(
1437                     request->requestHandle[OIC_REQUEST_BY_CLIENT]);
1438             OC_LOG_V(DEBUG, HOSTING_TAG, "requested resource handle : %u", entityHandler->resource
1439                     );
1440
1441             entityHandler->resource = request->resourceHandle;
1442             entityHandler->method = request->method;
1443             entityHandler->requestHandle = request->entityRequestHandle;
1444
1445             OCEntityHandlerResponse response = buildEntityHandlerResponse(
1446                                                    entityHandler, clientResponse->resJSONPayload);
1447             if (OCDoResponse(&response) != OC_STACK_OK)
1448             {
1449                 OC_LOG_V(DEBUG, HOSTING_TAG, "Error sending response");
1450                 deleteRequestHandleFromList(s_requestHandleList, request);
1451                 return ret;
1452             }
1453             if (entityHandler->method == OC_REST_DELETE)
1454             {
1455                 OCDeleteResource(entityHandler->resource);
1456             }
1457         }
1458         deleteRequestHandleFromList(s_requestHandleList, request);
1459         ret = OC_STACK_KEEP_TRANSACTION;
1460     }
1461
1462     return ret;
1463 }
1464
1465 OCEntityHandlerResponse buildEntityHandlerResponse(OCEntityHandlerRequest *entityHandlerRequest,
1466         const char *clientPayload)
1467 {
1468     OC_LOG_V(DEBUG, HOSTING_TAG, "enter buildEntityHandlerResponse");
1469     OCEntityHandlerResponse response;
1470     memset(&response, 0, sizeof(response));
1471     OCEntityHandlerResult entityHandlerResult = OC_EH_OK;
1472     char payload[MAX_RESPONSE_LENGTH] = {'\0'};
1473
1474     // Initialize certain response fields
1475     response.numSendVendorSpecificHeaderOptions = 0;
1476     memset(response.sendVendorSpecificHeaderOptions, 0,
1477            sizeof response.sendVendorSpecificHeaderOptions);
1478     memset(response.resourceUri, 0, sizeof response.resourceUri);
1479
1480     char *temp = NULL;
1481     if(entityHandlerRequest->method == OC_REST_PUT)
1482     {
1483         cJSON *observeJson = cJSON_CreateObject();
1484         observeJson = cJSON_Parse(clientPayload);
1485
1486         cJSON *ocArray = cJSON_GetObjectItem(observeJson, "oc");
1487         cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
1488
1489         cJSON *tempData = cJSON_GetObjectItem(ocArray_sub, "rep");
1490         temp = cJSON_PrintUnformatted(tempData);
1491
1492         cJSON_Delete(observeJson);
1493
1494         entityHandlerRequest->reqJSONPayload = temp;
1495     }
1496     entityHandlerResult = handleRequestPayload(entityHandlerRequest, payload, sizeof(payload) - 1);
1497
1498     // Format the response.  Note this requires some info about the request
1499     response.requestHandle = entityHandlerRequest->requestHandle;
1500     response.resourceHandle = entityHandlerRequest->resource;
1501     response.ehResult = entityHandlerResult;
1502
1503     response.payload = (char *)payload;
1504     response.payloadSize = strlen(payload);
1505     // Indicate that response is NOT in a persistent buffer
1506     response.persistentBufferFlag = 0;
1507
1508     if(entityHandlerRequest->method == OC_REST_PUT){
1509         if(temp){
1510             free(temp);
1511         }
1512     }
1513
1514     return response;
1515 }
1516
1517 OCEntityHandlerResult handleRequestPayload (OCEntityHandlerRequest *entityHandlerRequest,
1518         char *payload, uint16_t maxPayloadSize)
1519 {
1520     OC_LOG_V(DEBUG, HOSTING_TAG, "enter handleRequestPayload");
1521     OCEntityHandlerResult entityHandlerResult = OC_EH_ERROR;
1522
1523     if (entityHandlerRequest->method == OC_REST_DELETE)
1524     {
1525         memset(payload, '\0', sizeof(char) * (maxPayloadSize + 1));
1526         OC_LOG_V(DEBUG, HOSTING_TAG, "DELETE");
1527         return OC_EH_RESOURCE_DELETED;
1528     }
1529
1530     char *responsePayload = buildResponsePayload(entityHandlerRequest);
1531     if(!responsePayload)
1532     {
1533         return entityHandlerResult;
1534     }
1535
1536     if (maxPayloadSize > strlen ((char *)responsePayload))
1537     {
1538         strncpy(payload, responsePayload, strlen ((char *)responsePayload));
1539         entityHandlerResult = OC_EH_OK;
1540     }
1541     else
1542     {
1543         OC_LOG_V(DEBUG, HOSTING_TAG, "Response buffer: %d bytes is too small", maxPayloadSize);
1544         entityHandlerResult = OC_EH_ERROR;
1545     }
1546
1547     free(responsePayload);
1548
1549     return entityHandlerResult;
1550 }