Added connectivity files for full code review
[platform/upstream/iotivity.git] / resource / csdk / stack / src / oicgroup.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 #define _POSIX_C_SOURCE 200112L
22 #include <string.h>
23
24 #include "cJSON.h"
25 #include "ocmalloc.h"
26 #include "oicgroup.h"
27 #include "ocresource.h"
28 #include "occollection.h"
29 #include "logger.h"
30
31 #define TAG PCF("OICGROUP")
32
33 #define DESC_DELIMITER          "\""
34 #define ACTION_DELIMITER        "*"
35 #define ATTR_DELIMITER          "|"
36 #define ATTR_ASSIGN             "="
37
38 typedef struct aggregatehandleinfo
39 {
40     OCServerRequest *ehRequest;
41     OCDoHandle required;
42     OCResource *collResource;
43
44     struct aggregatehandleinfo *next;
45 } ClientRequstInfo;
46
47 // unsigned int nHandleIdx = 0;
48 // ClientRequstInfo g_AggregateResponseHandle[10];
49
50 ClientRequstInfo *clientRequstList = NULL;
51
52 void AddClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* add)
53 {
54     ClientRequstInfo *tmp = NULL;
55
56     if (*head != NULL)
57     {
58         tmp = *head;
59
60         while (tmp->next)
61         {
62             tmp = tmp->next;
63         }
64         tmp->next = add;
65     }
66     else
67     {
68         *head = add;
69     }
70 }
71
72 ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle)
73 {
74     ClientRequstInfo *tmp = NULL;
75
76     tmp = head;
77
78     if (tmp)
79     {
80         while (tmp)
81         {
82 //            printf("%p :: %p\n", tmp->required, handle);
83             if (tmp->required == handle)
84             {
85                 break;
86             }
87
88             tmp = tmp->next;
89         }
90
91         return tmp;
92     }
93     return NULL;
94 }
95
96 void RemoveClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* del)
97 {
98     ClientRequstInfo *tmp = NULL;
99
100     if (*head == del)
101     {
102         *head = (*head)->next;
103     }
104     else
105     {
106         tmp = *head;
107         while (tmp->next && (tmp->next != del))
108         {
109             tmp = tmp->next;
110         }
111         if (tmp->next)
112         {
113             tmp->next = del->next;
114         }
115     }
116 }
117
118
119
120 void AddCapability(OCCapability** head, OCCapability* node)
121 {
122     OCCapability *pointer = *head;
123     if (NULL == pointer)
124     {
125         *head = node;
126     }
127     else
128     {
129         while (pointer->next != NULL)
130         {
131             pointer = pointer->next;
132         }
133
134         pointer->next = node;
135     }
136 }
137
138 void AddAction(OCAction** head, OCAction* node)
139 {
140     OCAction *pointer = *head;
141     if (NULL == pointer)
142     {
143         *head = node;
144     }
145     else
146     {
147
148         while (pointer->next != NULL)
149         {
150             pointer = pointer->next;
151         }
152
153         pointer->next = node;
154     }
155 }
156
157 void AddActionSet(OCActionSet **head, OCActionSet* node)
158 {
159     OCActionSet *pointer = *head;
160     if (NULL == pointer)
161     {
162         *head = node;
163     }
164     else
165     {
166
167         while (pointer->next != NULL)
168         {
169             pointer = pointer->next;
170         }
171
172         pointer->next = node;
173     }
174 }
175
176 void DeleteCapability(OCCapability *del)
177 {
178     free(del->capability);
179     del->capability = NULL;
180     free(del->status);
181     del->status = NULL;
182 }
183
184 void DeleteAction(OCAction** action)
185 {
186     OCCapability* pointer = (*action)->head;
187     OCCapability* pDel = NULL;
188
189     while (pointer)
190     {
191         pDel = pointer;
192         pointer = pointer->next;
193
194         DeleteCapability(pDel);
195         pDel->next = NULL;
196     }
197     OCFree((*action)->resourceUri);
198     (*action)->resourceUri = NULL;
199     (*action)->next = NULL;
200 }
201
202 void DeleteActionSet(OCActionSet** actionset)
203 {
204     OCAction* pointer = (*actionset)->head;
205     OCAction* pDel = NULL;
206
207     while (pointer)
208     {
209         pDel = pointer;
210         pointer = pointer->next;
211
212         DeleteAction(&pDel);
213         pDel->next = NULL;
214     }
215
216     OCFree((*actionset)->actionsetName);
217     (*actionset)->head = NULL;
218 }
219
220 OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName)
221 {
222     if (*resource != NULL)
223     {
224         OCActionSet *pointer = NULL;
225         OCActionSet *pDel = NULL;
226
227         pointer = (*resource)->actionsetHead;
228
229         if (pointer == NULL)
230         {
231             return OC_STACK_ERROR;
232         }
233         else
234         {
235             if (strcmp(pointer->actionsetName, actionsetName) == 0)
236             {
237                 if (pointer->next != NULL)
238                     (*resource)->actionsetHead = pointer->next;
239                 else
240                     (*resource)->actionsetHead = NULL;
241                 DeleteActionSet(&pointer);
242             }
243             else if (pointer->next != NULL)
244             {
245                 while (pointer)
246                 {
247                     if (pointer->next != NULL)
248                     {
249                         if (strcmp(pointer->next->actionsetName, actionsetName) == 0)
250                         {
251                             pDel = pointer->next;
252                             pointer->next = pointer->next->next;
253
254                             DeleteActionSet(&pDel);
255                         }
256                     }
257                     pointer = pointer->next;
258                 }
259             }
260
261             return OC_STACK_OK;
262         }
263
264     }
265     return OC_STACK_ERROR;
266 }
267
268 OCStackResult DeleteActionSets(OCResource** resource)
269 {
270     OCActionSet *pointer = (*resource)->actionsetHead;
271     OCActionSet *pDel = pointer;
272
273     while (pointer)
274     {
275         pDel = pointer;
276         pointer = pointer->next;
277
278         DeleteActionSet(&pDel);
279         pDel->next = NULL;
280     }
281
282     (*resource)->actionsetHead = NULL;
283     return OC_STACK_OK;
284 }
285
286 OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSet** actionset)
287 {
288     OCActionSet *pointer = head;
289
290     while (pointer)
291     {
292         if (strcmp(pointer->actionsetName, actionName) == 0)
293         {
294             *actionset = pointer;
295             return OC_STACK_OK;
296         }
297
298         pointer = pointer->next;
299     }
300
301     return OC_STACK_ERROR;
302
303 }
304
305
306 #define OIC_ACTION_PREFIX               "{\"oc\":[{\"rep\":{"
307 #define VARIFY_POINTER_NULL(pointer, result, toExit) \
308     if(pointer == NULL) \
309     {\
310         result = OC_STACK_NO_MEMORY;\
311         goto toExit;\
312     }
313 #define VARIFY_PARAM_NULL(pointer, result, toExit) \
314     if(pointer == NULL)\
315     {\
316         result = OC_STACK_INVALID_PARAM;\
317         goto exit;\
318     }
319
320 OCStackResult ExtractKeyValueFromRequest(char *request, char **key, char **value)
321 {
322     OCStackResult result = OC_STACK_OK;
323     size_t length = 0;
324
325     char* pRequest = (char *)request + strlen(OIC_ACTION_PREFIX);
326     char* iterToken, *iterTokenPtr;
327
328     iterToken = (char *) strtok_r(pRequest, ":", &iterTokenPtr);
329     length = strlen(iterToken) + 1;
330
331     *key = (char *)OCMalloc(length);
332     VARIFY_POINTER_NULL(*key, result, exit);
333
334     strncpy(*key, iterToken + 1, length);
335     ((*key)[ (( length - 1 ) - 2) ]) = '\0';
336
337     iterToken = (char *) strtok_r(NULL, "}", &iterTokenPtr);
338     length = strlen(iterToken) + 1;
339
340     *value = (char *)OCMalloc(length);
341     VARIFY_POINTER_NULL(*key, result, exit);
342
343     strncpy(*value, iterToken + 1, length);
344     ((*value)[ (( length - 1 ) - 2) ]) = '\0';
345 exit:
346     if(result != OC_STACK_OK)
347     {
348         OCFree(*key);
349         OCFree(*value);
350         *key = NULL;
351         *value = NULL;
352     }
353
354     return result;
355 }
356
357 OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
358 {
359     OCStackResult result = OC_STACK_OK;
360
361     char *iterToken = NULL, *iterTokenPtr = NULL;
362     char *descIterToken = NULL, *descIterTokenPtr = NULL;
363     char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
364     char *desc = NULL, *attr = NULL;
365     char *key = NULL, *value = NULL;
366
367     OCAction *action = NULL;
368     OCCapability *capa = NULL;
369
370     OC_LOG(INFO, TAG, PCF("Build ActionSet Instance."));
371
372     *set = (OCActionSet*) OCMalloc(sizeof(OCActionSet));
373     VARIFY_POINTER_NULL(*set, result, exit)
374
375     iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
376
377     memset(*set, 0, sizeof(OCActionSet));
378     (*set)->actionsetName = (char *)OCMalloc(sizeof(OCActionSet));
379     VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
380     VARIFY_PARAM_NULL(iterToken, result, exit)
381     strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
382
383     OC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
384
385     iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
386     while(iterToken)
387     {
388         desc = (char *)OCMalloc(strlen(iterToken) + 1);
389         strncpy(desc, iterToken, strlen(iterToken) + 1);
390         descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER, &descIterTokenPtr);
391         while(descIterToken)
392         {
393             attr = (char *)OCMalloc(strlen(descIterToken) + 1);
394             strncpy(attr, descIterToken, strlen(descIterToken) + 1);
395
396             attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN, &attrIterTokenPtr);
397             key = (char *)OCMalloc(strlen(attrIterToken) + 1);
398             VARIFY_POINTER_NULL(key, result, exit)
399
400             VARIFY_PARAM_NULL(attrIterToken, result, exit)
401             strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
402             attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN, &attrIterTokenPtr);
403
404             value = (char *)OCMalloc(strlen(attrIterToken) + 1);
405             VARIFY_POINTER_NULL(value, result, exit)
406             VARIFY_PARAM_NULL(attrIterToken, result, exit)
407             strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
408
409             if(strcmp(key, "uri") == 0)
410             {
411                 OC_LOG(INFO, TAG, PCF("Build OCAction Instance."));
412
413                 action = (OCAction*)OCMalloc(sizeof(OCAction));
414                 VARIFY_POINTER_NULL(action, result, exit)
415                 memset(action, 0, sizeof(OCAction));
416                 action->resourceUri = (char *)OCMalloc(strlen(value) + 1);
417                 VARIFY_POINTER_NULL(action->resourceUri, result, exit)
418                 VARIFY_PARAM_NULL(value, result, exit)
419                 strncpy(action->resourceUri, value, strlen(value) + 1);
420             }
421             else
422             {
423                 if( (key != NULL) && (value != NULL))
424                 {
425                     OC_LOG(INFO, TAG, PCF("Build OCCapability Instance."));
426                     capa = (OCCapability*)OCMalloc(sizeof(OCCapability));
427                     VARIFY_POINTER_NULL(capa, result, exit)
428                     memset(capa, 0, sizeof(OCCapability));
429                     capa->capability = (char *)OCMalloc(strlen(key) + 1);
430                     capa->status = (char *)OCMalloc(strlen(value) + 1);
431
432                     strncpy(capa->capability, key, strlen(key) + 1);
433                     strncpy(capa->status, value, strlen(value) + 1);
434
435                     VARIFY_POINTER_NULL(action, result, exit)
436
437                     AddCapability(&action->head, capa);
438                 }
439             }
440
441             OCFree(key);
442             OCFree(value);
443             OCFree(attr);
444
445             descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &descIterTokenPtr);
446         }
447
448         AddAction(&(*set)->head, action);
449         iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
450         OCFree(desc);
451     }
452
453     return OC_STACK_OK;
454 exit:
455     OCFree(attr);
456     OCFree(desc);
457     OCFree(capa);
458     OCFree(action);
459     OCFree(*set);
460     *set = NULL;
461     return result;
462 }
463
464 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
465 {
466     char temp[1024] = { 0 };
467     int remaining = 1023;
468
469     // OCActionSet *as = resource->actionsetHead;
470     // while(as != NULL)
471     // {
472     // printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName);
473     OCAction *action = actionset->head;
474
475     if (remaining >= strlen(actionset->actionsetName) + 1)
476     {
477         strcat(temp, actionset->actionsetName);
478         remaining -= strlen(actionset->actionsetName);
479         strcat(temp, "*");
480         remaining--;
481     }
482     else
483     {
484         return OC_STACK_ERROR;
485     }
486
487     while (action != NULL)
488     {
489         printf("\tURI :: %s\n", action->resourceUri);
490         strcat(temp, "uri=");
491         remaining -= strlen("uri=");
492         strcat(temp, action->resourceUri);
493         remaining -= strlen(action->resourceUri);
494         strcat(temp, "|");
495         remaining--;
496
497         OCCapability *capas = action->head;
498         while (capas != NULL)
499         {
500             printf("\t\t%s = %s\n", capas->capability, capas->status);
501             strcat(temp, capas->capability);
502             remaining -= strlen(capas->capability);
503             strcat(temp, "=");
504             remaining--;
505             strcat(temp, capas->status);
506             remaining -= strlen(capas->capability);
507
508             capas = capas->next;
509             if (capas != NULL)
510             {
511                 strcat(temp, "|");
512             }
513         }
514
515         action = action->next;
516         if (action != NULL)
517         {
518             strcat(temp, "*");
519             remaining--;
520         }
521     }
522     //     as = as->next;
523     // }
524
525     *desc = (char *) OCMalloc(1024 - remaining);
526     strcpy(*desc, temp);
527     // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining);
528
529     return OC_STACK_OK;
530 }
531
532 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
533         OCClientResponse* clientResponse)
534 {
535     printf("\n\n\tcallback is called\n\n");
536
537     ClientRequstInfo *info = GetClientRequestInfo(clientRequstList, handle);
538
539     if (info)
540     {
541         int idx;
542
543         unsigned char *responseJson;
544         responseJson = (unsigned char *) OCMalloc(
545                 (unsigned int) (strlen((char *) clientResponse->resJSONPayload) + 1));
546
547         // We need the body of response.
548         // Copy the body from the response
549         strcpy((char *) responseJson, ((char *) clientResponse->resJSONPayload
550                 + OC_JSON_PREFIX_LEN));
551         idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
552         // And insert NULL at the end of body.
553         (responseJson[idx]) = 0;
554
555         OCEntityHandlerResponse response = { 0 };
556         response.ehResult = OC_EH_OK;
557         response.payload = responseJson;
558         response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
559         response.persistentBufferFlag = 0;
560         response.requestHandle = (OCRequestHandle) info->ehRequest;
561         response.resourceHandle = (OCResourceHandle) info->collResource;
562
563         OCDoResponse(&response);
564
565         RemoveClientRequestInfo(&clientRequstList, info);
566         OCFree(responseJson);
567     }
568
569     // g_AggregateResponseHandle
570
571     return OC_STACK_KEEP_TRANSACTION;
572 }
573
574 void ActionSetCD(void *context)
575 {
576     // printf("\n\t\tCD is called\n");
577
578     // free( context );
579 }
580
581 OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16_t *remaining)
582 {
583     OCStackResult ret = OC_STACK_ERROR;
584     cJSON *json;
585     cJSON *body;
586
587     char *jsonStr;
588     uint16_t jsonLen;
589
590     OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
591     json = cJSON_CreateObject();
592
593     cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
594
595     OCCapability* pointerCapa = action->head;
596     while (pointerCapa)
597     {
598         cJSON_AddStringToObject(body, pointerCapa->capability, pointerCapa->status);
599         pointerCapa = pointerCapa->next;
600     }
601
602     jsonStr = cJSON_PrintUnformatted(json);
603
604     jsonLen = strlen(jsonStr);
605     if (jsonLen < *remaining)
606     {
607         strcat((char*) bufferPtr, jsonStr);
608         *remaining -= jsonLen;
609         bufferPtr += jsonLen;
610         ret = OC_STACK_OK;
611     }
612
613     cJSON_Delete(json);
614     free(jsonStr);
615
616     return ret;
617 }
618
619 unsigned int GetNumOfTargetResource(OCAction *actionset)
620 {
621     int numOfREsource = 0;
622
623     OCAction *pointerAction = actionset;
624
625     while (pointerAction != NULL)
626     {
627         numOfREsource++;
628         pointerAction = pointerAction->next;
629     }
630
631     return numOfREsource;
632 }
633
634 OCStackResult SendAction(OCDoHandle *handle, const char *targetUri, const unsigned char *action)
635 {
636     OCCallbackData cbdata = { 0 };
637     cbdata.cb = &ActionSetCB;
638     cbdata.cd = &ActionSetCD;
639     cbdata.context = (void *) 0x99;
640
641     return OCDoResource(handle, OC_REST_PUT, targetUri,
642     //temp->rsrcType->resourcetypename,
643             NULL, (char *) action, OC_WIFI, OC_NA_QOS, &cbdata, NULL, 0);
644 }
645
646 OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
647         OCResource *resource, OCEntityHandlerRequest *ehRequest)
648 {
649     OCStackResult stackRet = OC_STACK_ERROR;
650
651     OC_LOG(INFO, TAG, PCF("Group Action is requested."));
652     // if (stackRet == OC_STACK_OK)
653     {
654         char *doWhat = NULL;
655         char *details = NULL;
656
657         size_t bufferLength = 0;
658         unsigned char buffer[MAX_RESPONSE_LENGTH] = { 0 };
659         unsigned char *bufferPtr = NULL;
660
661         bufferPtr = buffer;
662
663         OCResource * collResource = (OCResource *) ehRequest->resource;
664
665         char *jsonResponse;
666
667         ExtractKeyValueFromRequest((char *)ehRequest->reqJSONPayload, &doWhat, &details);
668
669         cJSON *json;
670         cJSON *format;
671
672
673         if (method == OC_REST_PUT)
674         {
675             json = cJSON_CreateObject();
676             cJSON_AddStringToObject(json, "href", resource->uri);
677             cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
678
679             OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
680
681             if(strcmp(doWhat, "ActionSet") == 0)
682             {
683                 OCActionSet *actionSet;
684                 BuildActionSetFromString(&actionSet, details);
685
686                 if(actionSet != NULL)
687                 {
688                     AddActionSet(&resource->actionsetHead, actionSet);
689                     stackRet = OC_STACK_OK;
690                 }
691                 else
692                 {
693                     stackRet = OC_STACK_ERROR;
694                 }
695
696             }
697             else if (strcmp(doWhat, "DelActionSet") == 0)
698             {
699                 if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
700                 {
701                     stackRet = OC_STACK_OK;
702                 }
703                 else
704                 {
705                     stackRet = OC_STACK_ERROR;
706                 }
707             }
708
709             jsonResponse = cJSON_Print(json);
710             cJSON_Delete(json);
711
712             strcat((char *) bufferPtr, jsonResponse);
713
714             bufferLength = strlen((const char *) buffer);
715             if (bufferLength > 0)
716             {
717                 OCEntityHandlerResponse response = { 0 };
718                 response.ehResult = OC_EH_OK;
719                 response.payload = buffer;
720                 response.payloadSize = bufferLength + 1;
721                 response.persistentBufferFlag = 0;
722                 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
723                 response.resourceHandle = (OCResourceHandle) collResource;
724                 stackRet = OCDoResponse(&response);
725             }
726
727             stackRet = OC_STACK_OK;
728         }
729
730         if (method == OC_REST_POST)
731         {
732             OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
733
734             OCActionSet *actionset = NULL;
735
736             json = cJSON_CreateObject();
737             cJSON_AddStringToObject(json, "href", resource->uri);
738
739             if (strcmp(doWhat, "DoAction") == 0)
740             {
741                 if (GetActionSet(details, resource->actionsetHead, &actionset) != OC_STACK_OK)
742                 {
743                     OC_LOG(INFO, TAG, PCF("ERROR"));
744                     stackRet = OC_STACK_ERROR;
745                 }
746
747                 if (actionset == NULL)
748                 {
749                     OC_LOG(INFO, TAG, PCF("ERROR"));
750                     stackRet = OC_STACK_ERROR;
751                 }
752                 else
753                 {
754
755                     OCAction *pointerAction = actionset->head;
756
757                     unsigned int num = GetNumOfTargetResource(pointerAction);
758
759                     ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
760                             HandleAggregateResponse;
761                     ((OCServerRequest *) ehRequest->requestHandle)->numResponses = num + 1;
762
763                     while (pointerAction != NULL)
764                     {
765                         unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
766                         unsigned char* actionDescPtr = actionDesc;
767                         uint16_t remaining = MAX_RESPONSE_LENGTH;
768
769                         strncpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX,
770                             strlen((const char *) OC_JSON_PREFIX) + 1);
771                         BuildActionJSON(pointerAction, actionDescPtr, &remaining);
772                         strncat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX,
773                             strlen((const char *) OC_JSON_SUFFIX));
774
775                         ClientRequstInfo *info = (ClientRequstInfo *) OCMalloc(
776                                 sizeof(ClientRequstInfo));
777                         memset(info, 0, sizeof(ClientRequstInfo));
778
779                         info->collResource = resource;
780                         info->ehRequest = (OCServerRequest *) ehRequest->requestHandle;
781
782                         SendAction(&info->required, pointerAction->resourceUri, actionDescPtr);
783
784                         AddClientRequestInfo(&clientRequstList, info);
785
786                         pointerAction = pointerAction->next;
787                     }
788
789
790                     stackRet = OC_STACK_OK;
791                 }
792             }
793             else if (strcmp(doWhat, "GetActionSet") == 0)
794             {
795                 char *plainText = NULL;
796                 OCActionSet *actionset = NULL;
797
798                 cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
799                 GetActionSet(details, resource->actionsetHead, &actionset);
800                 if (actionset != NULL)
801                 {
802                     BuildStringFromActionSet(actionset, &plainText);
803
804                     if (plainText != NULL)
805                     {
806                         cJSON_AddStringToObject(format, "ActionSet", plainText);
807                     }
808
809                     stackRet = OC_STACK_OK;
810                 }
811             }
812
813             jsonResponse = cJSON_Print(json);
814             cJSON_Delete(json);
815
816             strcat((char *) bufferPtr, jsonResponse);
817
818             bufferLength = strlen((const char *) buffer);
819             if (bufferLength > 0)
820             {
821                 OCEntityHandlerResponse response =
822                 { 0 };
823                 response.ehResult = OC_EH_OK;
824                 response.payload = buffer;
825                 response.payloadSize = bufferLength + 1;
826                 response.persistentBufferFlag = 0;
827                 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
828                 response.resourceHandle = (OCResourceHandle) collResource;
829                 stackRet = OCDoResponse(&response);
830             }
831         }
832
833         OCFree(doWhat);
834         OCFree(details);
835     }
836
837     return stackRet;
838 }