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