Imported Upstream version 0.9.2
[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
23 #include <string.h>
24
25 #include "oicgroup.h"
26 #include "cJSON.h"
27 #include "oic_malloc.h"
28 #include "occollection.h"
29 #include "logger.h"
30 #include "timer.h"
31
32 #ifndef WITH_ARDUINO
33 #include <pthread.h>
34 #endif
35
36 #define TAG PCF("OICGROUP")
37
38 #define DESC_DELIMITER          "\""
39 #define ACTION_DELIMITER        "*"
40 #define ATTR_DELIMITER          "|"
41 #define ATTR_ASSIGN             "="
42
43 // Definitions for operations related to actions
44 #define DO_ACTION               "DoAction"
45 #define GET_ACTIONSET           "GetActionSet"
46 #define ACTIONSET               "ActionSet"
47 #define DELETE_ACTIONSET        "DelActionSet"
48
49 #define OIC_ACTION_PREFIX               "{\"oic\":[{\"rep\":{"
50 #define VARIFY_POINTER_NULL(pointer, result, toExit) \
51     if(pointer == NULL) \
52     {\
53         result = OC_STACK_NO_MEMORY;\
54         goto toExit;\
55     }
56 #define VARIFY_PARAM_NULL(pointer, result, toExit) \
57     if(pointer == NULL)\
58     {\
59         result = OC_STACK_INVALID_PARAM;\
60         goto exit;\
61     }
62
63 #define OCFREE(pointer) \
64     { \
65         OICFree(pointer); \
66         pointer = NULL; \
67     }
68
69 #ifndef WITH_ARDUINO
70 pthread_mutex_t lock;
71 #endif
72
73 enum ACTION_TYPE
74 {
75     NONE = 0, SCHEDULED, RECURSIVE
76 };
77
78 typedef struct scheduledresourceinfo
79 {
80     OCResource *resource;
81     OCActionSet *actionset;
82
83     int timer_id;
84
85     OCServerRequest *ehRequest;
86
87     time_t time;
88     struct scheduledresourceinfo* next;
89 } ScheduledResourceInfo;
90
91 ScheduledResourceInfo *scheduleResourceList = NULL;
92
93 void AddScheduledResource(ScheduledResourceInfo **head,
94         ScheduledResourceInfo* add)
95 {
96     OC_LOG(INFO, TAG, PCF("AddScheduledResource Entering..."));
97
98 #ifndef WITH_ARDUINO
99     pthread_mutex_lock(&lock);
100 #endif
101     ScheduledResourceInfo *tmp = NULL;
102
103     if (*head != NULL)
104     {
105         tmp = *head;
106
107         while (tmp->next)
108         {
109             tmp = tmp->next;
110         }
111         tmp->next = add;
112     }
113     else
114     {
115         *head = add;
116     }
117 #ifndef WITH_ARDUINO
118     pthread_mutex_unlock(&lock);
119 #endif
120 }
121
122 ScheduledResourceInfo* GetScheduledResource(ScheduledResourceInfo *head)
123 {
124     OC_LOG(INFO, TAG, PCF("GetScheduledResource Entering..."));
125
126 #ifndef WITH_ARDUINO
127     pthread_mutex_lock(&lock);
128 #endif
129
130     time_t t_now;
131
132     ScheduledResourceInfo *tmp = NULL;
133     tmp = head;
134
135 #ifndef WITH_ARDUINO
136     time(&t_now);
137 #else
138     t_now = now();
139 #endif
140
141     if (tmp)
142     {
143         while (tmp)
144         {
145             time_t diffTm = 0;
146 #ifndef WITH_ARDUINO
147             diffTm = timespec_diff(tmp->time, t_now);
148 #else
149             diffTm = timespec_diff(tmp->time, t_now);
150 #endif
151
152             if (diffTm <= (time_t) 0)
153             {
154                 OC_LOG(INFO, TAG, PCF("return Call INFO."));
155                 goto exit;
156             }
157
158             tmp = tmp->next;
159         }
160     }
161
162     exit:
163 #ifndef WITH_ARDUINO
164     pthread_mutex_unlock(&lock);
165 #endif
166     if (tmp == NULL)
167     {
168         OC_LOG(INFO, TAG, PCF("Cannot Find Call Info."));
169     }
170     return tmp;
171 }
172
173 ScheduledResourceInfo* GetScheduledResourceByActionSetName(ScheduledResourceInfo *head, char *setName)
174 {
175     OC_LOG(INFO, TAG, PCF("GetScheduledResourceByActionSetName Entering..."));
176
177 #ifndef WITH_ARDUINO
178     pthread_mutex_lock(&lock);
179 #endif
180     ScheduledResourceInfo *tmp = NULL;
181     tmp = head;
182
183     if (tmp)
184     {
185         while (tmp)
186         {
187             if (strcmp(tmp->actionset->actionsetName, setName) == 0)
188             {
189                 OC_LOG(INFO, TAG, PCF("return Call INFO."));
190                 goto exit;
191             }
192             tmp = tmp->next;
193         }
194     }
195
196 exit:
197 #ifndef WITH_ARDUINO
198     pthread_mutex_unlock(&lock);
199 #endif
200     if (tmp == NULL)
201     {
202         OC_LOG(INFO, TAG, PCF("Cannot Find Call Info."));
203     }
204     return tmp;
205 }
206
207 void RemoveScheduledResource(ScheduledResourceInfo **head,
208         ScheduledResourceInfo* del)
209 {
210 #ifndef WITH_ARDUINO
211     pthread_mutex_lock(&lock);
212 #endif
213     OC_LOG(INFO, TAG, PCF("RemoveScheduledResource Entering..."));
214     ScheduledResourceInfo *tmp = NULL;
215
216     if (del == NULL)
217     {
218         return;
219     }
220
221     if (*head == del)
222     {
223         *head = (*head)->next;
224     }
225     else
226     {
227         tmp = *head;
228         while (tmp->next && (tmp->next != del))
229         {
230             tmp = tmp->next;
231         }
232         if (tmp->next)
233         {
234             tmp->next = del->next;
235         }
236     }
237
238     OCFREE(del)
239 #ifndef WITH_ARDUINO
240     pthread_mutex_unlock(&lock);
241 #endif
242 }
243
244 typedef struct aggregatehandleinfo
245 {
246     OCServerRequest *ehRequest;
247     OCDoHandle required;
248     OCResource *collResource;
249
250     struct aggregatehandleinfo *next;
251 } ClientRequestInfo;
252
253 ClientRequestInfo *clientRequstList = NULL;
254
255 void AddClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* add)
256 {
257     ClientRequestInfo *tmp = NULL;
258
259     if (*head != NULL)
260     {
261         tmp = *head;
262
263         while (tmp->next)
264         {
265             tmp = tmp->next;
266         }
267         tmp->next = add;
268     }
269     else
270     {
271         *head = add;
272     }
273 }
274
275 ClientRequestInfo* GetClientRequestInfo(ClientRequestInfo *head,
276         OCDoHandle handle)
277 {
278     ClientRequestInfo *tmp = NULL;
279
280     tmp = head;
281
282     if (tmp)
283     {
284         while (tmp)
285         {
286             if (tmp->required == handle)
287             {
288                 break;
289             }
290
291             tmp = tmp->next;
292         }
293
294         return tmp;
295     }
296     return NULL;
297 }
298
299 void RemoveClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* del)
300 {
301     ClientRequestInfo *tmp = NULL;
302
303     if (del == NULL)
304         return;
305
306     if (*head == del)
307     {
308         *head = (*head)->next;
309     }
310     else
311     {
312         tmp = *head;
313         while (tmp->next && (tmp->next != del))
314         {
315             tmp = tmp->next;
316         }
317         if (tmp->next)
318         {
319             tmp->next = del->next;
320         }
321     }
322 }
323
324 void AddCapability(OCCapability** head, OCCapability* node)
325 {
326     OCCapability *pointer = *head;
327     if (NULL == pointer)
328     {
329         *head = node;
330     }
331     else
332     {
333         while (pointer->next != NULL)
334         {
335             pointer = pointer->next;
336         }
337
338         pointer->next = node;
339     }
340 }
341
342 void AddAction(OCAction** head, OCAction* node)
343 {
344     OCAction *pointer = *head;
345     if (NULL == pointer)
346     {
347         *head = node;
348     }
349     else
350     {
351
352         while (pointer->next != NULL)
353         {
354             pointer = pointer->next;
355         }
356
357         pointer->next = node;
358     }
359 }
360
361 OCStackResult AddActionSet(OCActionSet **head, OCActionSet* node)
362 {
363     OCActionSet *pointer = *head;
364     OCActionSet *prev = NULL;
365     if(node == NULL)
366     {
367         return OC_STACK_ERROR;
368     }
369     if (NULL == pointer)
370     {
371         *head = node;
372     }
373     else
374     {
375         prev = pointer;
376         while (pointer != NULL)
377         {
378             // check the uniqeness of actionsetname.
379             if (strcmp(pointer->actionsetName, node->actionsetName) == 0)
380             {
381                 return OC_STACK_ERROR;
382             }
383
384             prev = pointer;
385             pointer = pointer->next;
386         }
387
388         prev->next = node;
389     }
390
391     return OC_STACK_OK;
392 }
393
394 void DeleteCapability(OCCapability *del)
395 {
396     OCFREE(del->capability)
397     del->capability = NULL;
398     OCFREE(del->status)
399     del->status = NULL;
400     OCFREE(del)
401 }
402
403 void DeleteAction(OCAction** action)
404 {
405     OCCapability* pointer = (*action)->head;
406     OCCapability* pDel = NULL;
407
408     while (pointer)
409     {
410         pDel = pointer;
411         pointer = pointer->next;
412
413         DeleteCapability(pDel);
414     }
415     OCFREE((*action)->resourceUri)
416     (*action)->next = NULL;
417     OCFREE(*action)
418 }
419
420 void DeleteActionSet(OCActionSet** actionset)
421 {
422     if(*actionset == NULL)
423         return;
424
425     OCAction* pointer = (*actionset)->head;
426     OCAction* pDel = NULL;
427
428     while (pointer)
429     {
430         pDel = pointer;
431         pointer = pointer->next;
432
433         DeleteAction(&pDel);
434     }
435     //    (*actionset)->head = NULL;
436     OCFREE((*actionset)->actionsetName)
437     OCFREE(*actionset)
438 }
439
440 OCStackResult FindAndDeleteActionSet(OCResource **resource,
441         const char * actionsetName)
442 {
443     if (*resource != NULL)
444     {
445         OCActionSet *pointer = NULL;
446         OCActionSet *pDel = NULL;
447
448         pointer = (*resource)->actionsetHead;
449
450         if (pointer == NULL)
451         {
452             return OC_STACK_ERROR;
453         }
454         else
455         {
456             if (strcmp(pointer->actionsetName, actionsetName) == 0)
457             {
458                 if (pointer->next != NULL)
459                     (*resource)->actionsetHead = pointer->next;
460                 else
461                     (*resource)->actionsetHead = NULL;
462
463                 DeleteActionSet(&pointer);
464             }
465             else if (pointer->next != NULL)
466             {
467                 while (pointer)
468                 {
469                     if (pointer->next != NULL)
470                     {
471                         if (strcmp(pointer->next->actionsetName, actionsetName)
472                                 == 0)
473                         {
474                             pDel = pointer->next;
475                             pointer->next = pointer->next->next;
476
477                             DeleteActionSet(&pDel);
478                         }
479                     }
480                     pointer = pointer->next;
481                 }
482             }
483
484             return OC_STACK_OK;
485         }
486
487     }
488     return OC_STACK_ERROR;
489 }
490
491 OCStackResult DeleteActionSets(OCResource** resource)
492 {
493     OCActionSet *pointer = (*resource)->actionsetHead;
494     OCActionSet *pDel = pointer;
495
496     while (pointer)
497     {
498         pDel = pointer;
499         pointer = pointer->next;
500
501         DeleteActionSet(&pDel);
502         pDel->next = NULL;
503     }
504
505     (*resource)->actionsetHead = NULL;
506     return OC_STACK_OK;
507 }
508
509 OCStackResult GetActionSet(const char *actionName, OCActionSet *head,
510         OCActionSet** actionset)
511 {
512     OCActionSet *pointer = head;
513
514     while (pointer)
515     {
516         if (strcmp(pointer->actionsetName, actionName) == 0)
517         {
518             *actionset = pointer;
519             return OC_STACK_OK;
520         }
521
522         pointer = pointer->next;
523     }
524
525     return OC_STACK_ERROR;
526
527 }
528
529 OCStackResult ExtractKeyValueFromRequest(char *request, char **key,
530         char **value)
531 {
532     OCStackResult result = OC_STACK_OK;
533     size_t length = 0;
534
535     char* pRequest = (char *) request + strlen(OIC_ACTION_PREFIX);
536     char* iterToken, *iterTokenPtr;
537
538     iterToken = (char *) strtok_r(pRequest, ":", &iterTokenPtr);
539     VARIFY_POINTER_NULL(iterToken, result, exit);
540     length = strlen(iterToken) + 1;
541
542     *key = (char *) OICMalloc(length);
543     VARIFY_POINTER_NULL(*key, result, exit)
544
545     strncpy(*key, iterToken + 1, length);
546     ((*key)[((length - 1) - 2)]) = '\0';
547
548     iterToken = (char *) strtok_r(NULL, "}", &iterTokenPtr);
549     VARIFY_POINTER_NULL(iterToken, result, exit);
550     length = strlen(iterToken) + 1;
551
552     *value = (char *) OICMalloc(length);
553     VARIFY_POINTER_NULL(*value, result, exit)
554
555     strncpy(*value, iterToken + 1, length);
556     ((*value)[((length - 1) - 2)]) = '\0';
557
558 exit:
559     if (result != OC_STACK_OK)
560     {
561         OCFREE(*key)
562         OCFREE(*value)
563     }
564
565     return result;
566 }
567
568 OCStackResult ExtractActionSetNameAndDelaytime(char *pChar, char **setName,
569         long int *pa)
570 {
571     char *token, *tokenPtr;
572     OCStackResult result = OC_STACK_OK;
573
574     token = (char*) strtok_r(pChar, ACTION_DELIMITER, &tokenPtr);
575     *setName = (char *) OICMalloc(strlen(token) + 1);
576     VARIFY_POINTER_NULL(*setName, result, exit)
577     VARIFY_PARAM_NULL(token, result, exit)
578     strncpy(*setName, token, strlen(token) + 1);
579
580     token = strtok_r(NULL, ACTION_DELIMITER, &tokenPtr);
581     VARIFY_POINTER_NULL(pa, result, exit)
582     VARIFY_PARAM_NULL(token, result, exit)
583     *pa = atoi(token);
584
585     return OC_STACK_OK;
586
587 exit:
588     OCFREE(*setName);
589     return result;
590 }
591
592 OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
593 {
594     OCStackResult result = OC_STACK_OK;
595
596     char *iterToken = NULL, *iterTokenPtr = NULL;
597     char *descIterToken = NULL, *descIterTokenPtr = NULL;
598     char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
599     char *desc = NULL, *attr = NULL;
600     char *key = NULL, *value = NULL;
601
602     OCAction *action = NULL;
603     OCCapability *capa = NULL;
604
605     OC_LOG(INFO, TAG, PCF("Build ActionSet Instance."));
606
607     *set = (OCActionSet*) OICMalloc(sizeof(OCActionSet));
608     VARIFY_POINTER_NULL(*set, result, exit)
609
610     iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
611
612     // ActionSet Name
613     memset(*set, 0, sizeof(OCActionSet));
614     (*set)->actionsetName = (char *) OICMalloc(strlen(iterToken) + 1);
615     VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
616     VARIFY_PARAM_NULL(iterToken, result, exit)
617     strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
618
619     // Time info. for Scheduled/Recursive Group action.
620     // d is meant Day of the week.
621     // T is meant ActionType.
622     // yyyy-mm-dd hh:mm:ss d
623     iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
624     VARIFY_PARAM_NULL(iterToken, result, exit)
625 #ifndef WITH_ARDUINO
626     sscanf(iterToken, "%ld %d", &(*set)->timesteps, &(*set)->type);
627 #endif
628
629     OC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
630
631     iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
632     while (iterToken)
633     {
634         desc = (char *) OICMalloc(strlen(iterToken) + 1);
635         VARIFY_POINTER_NULL(desc, result, exit)
636         VARIFY_PARAM_NULL(desc, result, exit)
637         strncpy(desc, iterToken, strlen(iterToken) + 1);
638         descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER,
639                 &descIterTokenPtr);
640         while (descIterToken)
641         {
642             attr = (char *) OICMalloc(strlen(descIterToken) + 1);
643             VARIFY_POINTER_NULL(attr, result, exit)
644             VARIFY_PARAM_NULL(descIterToken, result, exit)
645             strncpy(attr, descIterToken, strlen(descIterToken) + 1);
646
647             attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN,
648                     &attrIterTokenPtr);
649             key = (char *) OICMalloc(strlen(attrIterToken) + 1);
650             VARIFY_POINTER_NULL(key, result, exit)
651             VARIFY_PARAM_NULL(attrIterToken, result, exit)
652             strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
653
654             attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN,
655                     &attrIterTokenPtr);
656             value = (char *) OICMalloc(strlen(attrIterToken) + 1);
657             VARIFY_POINTER_NULL(value, result, exit)
658             VARIFY_PARAM_NULL(attrIterToken, result, exit)
659             strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
660
661             if (strcmp(key, "uri") == 0)
662             {
663                 OC_LOG(INFO, TAG, PCF("Build OCAction Instance."));
664
665                 action = (OCAction*) OICMalloc(sizeof(OCAction));
666                 VARIFY_POINTER_NULL(action, result, exit)
667                 memset(action, 0, sizeof(OCAction));
668                 action->resourceUri = (char *) OICMalloc(strlen(value) + 1);
669                 VARIFY_POINTER_NULL(action->resourceUri, result, exit)
670                 VARIFY_PARAM_NULL(value, result, exit)
671                 strncpy(action->resourceUri, value, strlen(value) + 1);
672             }
673             else
674             {
675                 if ((key != NULL) && (value != NULL))
676                 {
677                     OC_LOG(INFO, TAG, PCF("Build OCCapability Instance."));
678
679                     capa = (OCCapability*) OICMalloc(sizeof(OCCapability));
680                     VARIFY_POINTER_NULL(capa, result, exit)
681                     memset(capa, 0, sizeof(OCCapability));
682
683                     capa->capability = (char *) OICMalloc(strlen(key) + 1);
684                     VARIFY_POINTER_NULL(capa->capability, result, exit)
685                     VARIFY_PARAM_NULL(key, result, exit)
686                     strncpy(capa->capability, key, strlen(key) + 1);
687
688                     capa->status = (char *) OICMalloc(strlen(value) + 1);
689                     VARIFY_POINTER_NULL(capa->status, result, exit)
690                     VARIFY_PARAM_NULL(value, result, exit)
691                     strncpy(capa->status, value, strlen(value) + 1);
692
693                     VARIFY_POINTER_NULL(action, result, exit)
694
695                     AddCapability(&action->head, capa);
696                 }
697             }
698
699             OCFREE(key)
700             OCFREE(value)
701             OCFREE(attr)
702
703             descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER,
704                     &descIterTokenPtr);
705         }
706
707         AddAction(&(*set)->head, action);
708         iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
709         OCFREE(desc);
710     }
711
712     return OC_STACK_OK;
713 exit:
714     OCFREE(attr)
715     OCFREE(desc)
716     OCFREE(capa)
717     OCFREE(action)
718     OCFREE(*set)
719     OCFREE(key)
720     OCFREE(value)
721     OCFREE(attr)
722
723     return result;
724 }
725
726 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
727 {
728     char temp[1024] = { 0 };
729     int remaining = 1023;
730     OCStackResult res = OC_STACK_ERROR;
731
732     OCAction *action = actionset->head;
733
734     if (remaining >= strlen(actionset->actionsetName) + 1)
735     {
736         strcat(temp, actionset->actionsetName);
737         remaining -= strlen(actionset->actionsetName);
738         strcat(temp, ACTION_DELIMITER);
739         remaining--;
740     }
741     else
742     {
743         res = OC_STACK_ERROR;
744         goto exit;
745     }
746
747     while (action != NULL)
748     {
749         strcat(temp, "uri=");
750         remaining -= strlen("uri=");
751         strcat(temp, action->resourceUri);
752         remaining -= strlen(action->resourceUri);
753         strcat(temp, "|");
754         remaining--;
755
756         OCCapability *capas = action->head;
757         while (capas != NULL)
758         {
759             strcat(temp, capas->capability);
760             remaining -= strlen(capas->capability);
761             strcat(temp, "=");
762             remaining--;
763             strcat(temp, capas->status);
764             remaining -= strlen(capas->capability);
765
766             capas = capas->next;
767             if (capas != NULL)
768             {
769                 strcat(temp, "|");
770             }
771         }
772
773         action = action->next;
774         if (action != NULL)
775         {
776             strcat(temp, ACTION_DELIMITER);
777             remaining--;
778         }
779     }
780
781     *desc = (char *) OICMalloc(1024 - remaining);
782     VARIFY_POINTER_NULL(*desc, res, exit);
783     strcpy(*desc, temp);
784
785     return OC_STACK_OK;
786
787 exit:
788     OCFREE(*desc);
789     return res;
790
791 }
792
793 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
794         OCClientResponse* clientResponse)
795 {
796     OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
797
798     ClientRequestInfo *info = GetClientRequestInfo(clientRequstList, handle);
799
800     if (info)
801     {
802         int idx;
803
804         unsigned char *responseJson = NULL;
805         // TODO: Figure out what this does, change implementation
806         //responseJson = (unsigned char *) OICMalloc(
807         //        (unsigned int) (strlen((char *) clientResponse->resJSONPayload)
808         //                + 1));
809
810         if( responseJson == NULL )
811             return OC_STACK_DELETE_TRANSACTION;
812
813         // We need the body of response.
814         // Copy the body from the response
815         // TODO: Taken out
816         //strcpy((char *) responseJson,
817         //        ((char *) clientResponse->resJSONPayload + OC_JSON_PREFIX_LEN));
818         //idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
819         // And insert NULL at the end of body.
820         (responseJson[idx]) = 0;
821
822         OCEntityHandlerResponse response = { 0 };
823         response.ehResult = OC_EH_OK;
824         // TODO: Removing payload size, waht goes here?
825         // response.payload = (char*)responseJson;
826         //response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
827         response.persistentBufferFlag = 0;
828         response.requestHandle = (OCRequestHandle) info->ehRequest;
829         response.resourceHandle = (OCResourceHandle) info->collResource;
830
831         OCDoResponse(&response);
832
833         RemoveClientRequestInfo(&clientRequstList, info);
834         OCFREE(info)
835         OCFREE(responseJson)
836     }
837
838     return OC_STACK_KEEP_TRANSACTION;
839 }
840
841 void ActionSetCD(void *context)
842 {
843 }
844
845 OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr,
846         uint16_t *remaining)
847 {
848     OCStackResult ret = OC_STACK_ERROR;
849     cJSON *json;
850     cJSON *body;
851
852     char *jsonStr;
853     uint16_t jsonLen;
854
855     OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
856     json = cJSON_CreateObject();
857
858     cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
859
860     OCCapability* pointerCapa = action->head;
861     while (pointerCapa)
862     {
863         cJSON_AddStringToObject(body, pointerCapa->capability,
864                 pointerCapa->status);
865         pointerCapa = pointerCapa->next;
866     }
867
868     jsonStr = cJSON_PrintUnformatted(json);
869
870     jsonLen = strlen(jsonStr);
871     if (jsonLen < *remaining)
872     {
873         strcat((char*) bufferPtr, jsonStr);
874         *remaining -= jsonLen;
875         bufferPtr += jsonLen;
876         ret = OC_STACK_OK;
877     }
878
879     cJSON_Delete(json);
880     free(jsonStr);
881
882     return ret;
883 }
884
885 unsigned int GetNumOfTargetResource(OCAction *actionset)
886 {
887     int numOfResource = 0;
888
889     OCAction *pointerAction = actionset;
890
891     while (pointerAction != NULL)
892     {
893         numOfResource++;
894         pointerAction = pointerAction->next;
895     }
896
897     return numOfResource;
898 }
899
900
901 #define DEFAULT_CONTEXT_VALUE 0x99
902
903 OCStackResult SendAction(OCDoHandle *handle, const char *targetUri,
904         const unsigned char *action)
905 {
906     OCCallbackData cbdata;
907     cbdata.cb = &ActionSetCB;
908     cbdata.cd = NULL;
909     cbdata.context = (void*)DEFAULT_CONTEXT_VALUE;
910
911     // TODO: disabled since this is no longer compatible
912     return OC_STACK_NOTIMPL;
913     //return OCDoResource(handle, OC_REST_PUT, targetUri,
914     //        NULL, (char *) action, CT_ADAPTER_IP, OC_NA_QOS, &cbdata, NULL, 0);
915 }
916
917 OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
918         OCServerRequest* requestHandle)
919 {
920     OCStackResult result = OC_STACK_ERROR;
921     OCAction *pointerAction = actionset->head;
922
923     while (pointerAction != NULL)
924     {
925         unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
926         unsigned char* actionDescPtr = actionDesc;
927         uint16_t remaining = MAX_RESPONSE_LENGTH;
928
929         strncpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX,
930                 strlen((const char *) OC_JSON_PREFIX) + 1);
931         BuildActionJSON(pointerAction, actionDescPtr, &remaining);
932         strncat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX,
933                 strlen((const char *) OC_JSON_SUFFIX));
934
935         ClientRequestInfo *info = (ClientRequestInfo *) OICMalloc(
936                 sizeof(ClientRequestInfo));
937
938         if( info == NULL )
939             return OC_STACK_NO_MEMORY;
940
941         memset(info, 0, sizeof(ClientRequestInfo));
942
943         info->collResource = resource;
944         info->ehRequest = requestHandle;
945
946         result = SendAction(&info->required, pointerAction->resourceUri,
947                 actionDescPtr);
948         if (result != OC_STACK_OK)
949         {
950             OICFree(info);
951             return result;
952         }
953
954         AddClientRequestInfo(&clientRequstList, info);
955
956         pointerAction = pointerAction->next;
957     }
958
959     return result;
960 }
961
962 void DoScheduledGroupAction()
963 {
964     OC_LOG(INFO, TAG, PCF("DoScheduledGroupAction Entering..."));
965     ScheduledResourceInfo* info = GetScheduledResource(scheduleResourceList);
966
967     if (info == NULL)
968     {
969         OC_LOG(INFO, TAG, PCF("Target resource is NULL"));
970         goto exit;
971     }
972     else if (info->resource == NULL)
973     {
974         OC_LOG(INFO, TAG, PCF("Target resource is NULL"));
975         goto exit;
976     }
977     else if (info->actionset == NULL)
978     {
979         OC_LOG(INFO, TAG, PCF("Target ActionSet is NULL"));
980         goto exit;
981     }
982     else if (info->ehRequest == NULL)
983     {
984         OC_LOG(INFO, TAG, PCF("Target ActionSet is NULL"));
985         goto exit;
986     }
987 #ifndef WITH_ARDUINO
988     pthread_mutex_lock(&lock);
989 #endif
990     DoAction(info->resource, info->actionset, info->ehRequest);
991 #ifndef WITH_ARDUINO
992     pthread_mutex_unlock(&lock);
993 #endif
994
995     if (info->actionset->type == RECURSIVE)
996     {
997         ScheduledResourceInfo *schedule;
998         schedule = (ScheduledResourceInfo *) OICMalloc(
999                 sizeof(ScheduledResourceInfo));
1000
1001         if (schedule)
1002         {
1003             OC_LOG(INFO, TAG, PCF("Building New Call Info."));
1004             memset(schedule, 0, sizeof(ScheduledResourceInfo));
1005
1006             if (info->actionset->timesteps > 0)
1007             {
1008 #ifndef WITH_ARDUINO
1009                 pthread_mutex_lock(&lock);
1010 #endif
1011                 schedule->resource = info->resource;
1012                 schedule->actionset = info->actionset;
1013                 schedule->ehRequest = info->ehRequest;
1014
1015                 schedule->time = registerTimer(info->actionset->timesteps,
1016                         &schedule->timer_id,
1017                         &DoScheduledGroupAction);
1018
1019                 OC_LOG(INFO, TAG, PCF("Reregisteration."));
1020 #ifndef WITH_ARDUINO
1021                 pthread_mutex_unlock(&lock);
1022 #endif
1023                 AddScheduledResource(&scheduleResourceList, schedule);
1024             }
1025         }
1026     }
1027
1028     RemoveScheduledResource(&scheduleResourceList, info);
1029
1030     exit:
1031
1032     return;
1033 }
1034
1035 OCStackResult BuildCollectionGroupActionJSONResponse(
1036         OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource,
1037         OCEntityHandlerRequest *ehRequest)
1038 {
1039     OCStackResult stackRet = OC_STACK_ERROR;
1040
1041     OC_LOG(INFO, TAG, PCF("Group Action is requested."));
1042     // if (stackRet == OC_STACK_OK)
1043     {
1044         char *doWhat = NULL;
1045         char *details = NULL;
1046
1047         size_t bufferLength = 0;
1048         unsigned char buffer[MAX_RESPONSE_LENGTH] = { 0 };
1049         unsigned char *bufferPtr = NULL;
1050
1051         bufferPtr = buffer;
1052
1053         OCResource * collResource = (OCResource *) ehRequest->resource;
1054
1055         char *jsonResponse;
1056
1057         stackRet = OC_STACK_NOTIMPL;
1058         // TODO: Fix?
1059         //stackRet = ExtractKeyValueFromRequest((char *) ehRequest->reqJSONPayload,
1060         //        &doWhat, &details);
1061
1062         if(stackRet != OC_STACK_OK)
1063         {
1064             OC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
1065             return stackRet;
1066         }
1067
1068         stackRet = OC_STACK_ERROR;
1069
1070         cJSON *json;
1071         cJSON *format;
1072
1073         if (method == OC_REST_PUT)
1074         {
1075             json = cJSON_CreateObject();
1076             cJSON_AddStringToObject(json, "href", resource->uri);
1077             cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
1078
1079             OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
1080
1081             if (strcmp(doWhat, ACTIONSET) == 0)
1082             {
1083                 OCActionSet *actionSet = NULL;
1084                 stackRet = BuildActionSetFromString(&actionSet, details);
1085
1086                 if(stackRet == OC_STACK_OK)
1087                 {
1088                     if (actionSet != NULL)
1089                     {
1090                         stackRet = AddActionSet(&resource->actionsetHead,
1091                                 actionSet);
1092                         if (stackRet == OC_STACK_ERROR)
1093                         {
1094                             if(actionSet != NULL)
1095                             {
1096                                 DeleteActionSet( &actionSet );
1097                             }
1098                             OC_LOG(INFO, TAG, PCF("Duplicated ActionSet "));
1099                         }
1100                     }
1101                 }
1102                 else
1103                 {
1104                     stackRet = OC_STACK_ERROR;
1105                 }
1106
1107             }
1108             else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
1109             {
1110                 if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
1111                 {
1112                     stackRet = OC_STACK_OK;
1113                 }
1114                 else
1115                 {
1116                     stackRet = OC_STACK_ERROR;
1117                 }
1118             }
1119
1120             jsonResponse = cJSON_Print(json);
1121             cJSON_Delete(json);
1122
1123             strcat((char *) bufferPtr, jsonResponse);
1124
1125             bufferLength = strlen((const char *) buffer);
1126             if (bufferLength > 0)
1127             {
1128                 OCEntityHandlerResponse response = { 0 };
1129                 if(stackRet == OC_STACK_OK)
1130                     response.ehResult = OC_EH_OK;
1131                 else
1132                     response.ehResult = OC_EH_ERROR;
1133                 // TODO: Fix
1134                 //response.payload = (char*)buffer;
1135                 //response.payloadSize = bufferLength + 1;
1136                 response.persistentBufferFlag = 0;
1137                 response.requestHandle =
1138                         (OCRequestHandle) ehRequest->requestHandle;
1139                 response.resourceHandle = (OCResourceHandle) collResource;
1140                 stackRet = OCDoResponse(&response);
1141             }
1142         }
1143
1144         if (method == OC_REST_POST)
1145         {
1146             OCActionSet *actionset = NULL;
1147
1148             json = cJSON_CreateObject();
1149             cJSON_AddStringToObject(json, "href", resource->uri);
1150
1151             if ((strcmp(doWhat, DO_ACTION) == 0)
1152                     || (strcmp(doWhat, "DoScheduledAction") == 0))
1153             {
1154                 char *pActionsetName = NULL;
1155                 long int delay = -1;
1156
1157                 if (strcmp(doWhat, "DoScheduledAction") == 0)
1158                 {
1159                     stackRet = ExtractActionSetNameAndDelaytime(details,
1160                             &pActionsetName, &delay);
1161
1162                     OCFREE(details)
1163                     details = pActionsetName;
1164                 }
1165                 else
1166                 {
1167                     stackRet = OC_STACK_OK;
1168                 }
1169
1170                 if (stackRet == OC_STACK_OK)
1171                 {
1172                     if (GetActionSet(details, resource->actionsetHead,
1173                             &actionset) != OC_STACK_OK)
1174                     {
1175                         OC_LOG(INFO, TAG, PCF("ERROR"));
1176                         stackRet = OC_STACK_ERROR;
1177                     }
1178
1179                     if (actionset == NULL)
1180                     {
1181                         OC_LOG(INFO, TAG, PCF("Cannot Find ActionSet"));
1182                         stackRet = OC_STACK_ERROR;
1183                     }
1184                     else
1185                     {
1186                         OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
1187                         if (actionset->type == NONE)
1188                         {
1189                             OC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
1190                                     actionset->actionsetName);
1191                             unsigned int num = GetNumOfTargetResource(
1192                                     actionset->head);
1193
1194                             ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
1195                                     HandleAggregateResponse;
1196                             ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
1197                                     num + 1;
1198
1199                             DoAction(resource, actionset,
1200                                     (OCServerRequest*) ehRequest->requestHandle);
1201                             stackRet = OC_STACK_OK;
1202                         }
1203                         else
1204                         {
1205                             OC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
1206                                     actionset->actionsetName);
1207
1208                             delay =
1209                                     (delay == -1 ? actionset->timesteps : delay);
1210
1211                             ScheduledResourceInfo *schedule;
1212                             schedule = (ScheduledResourceInfo *) OICMalloc(
1213                                     sizeof(ScheduledResourceInfo));
1214
1215                             if (schedule)
1216                             {
1217                                 OC_LOG(INFO, TAG, PCF("Building New Call Info."));
1218                                 memset(schedule, 0,
1219                                         sizeof(ScheduledResourceInfo));
1220
1221                                 schedule->resource = resource;
1222                                 schedule->actionset = actionset;
1223                                 schedule->ehRequest =
1224                                         (OCServerRequest*) ehRequest->requestHandle;
1225
1226                                 if (delay > 0)
1227                                 {
1228                                     OC_LOG_V(INFO, TAG, "delay_time is %lf seconds.",
1229                                             actionset->timesteps);
1230
1231                                     schedule->time = registerTimer(delay,
1232                                             &schedule->timer_id,
1233                                             &DoScheduledGroupAction);
1234
1235                                     AddScheduledResource(&scheduleResourceList,
1236                                             schedule);
1237                                     stackRet = OC_STACK_OK;
1238                                 }
1239                                 else
1240                                 {
1241                                     stackRet = OC_STACK_ERROR;
1242                                 }
1243                             }
1244                         }
1245                     }
1246                 }
1247             }
1248             else if (strcmp(doWhat, "CancelAction") == 0)
1249             {
1250                 ScheduledResourceInfo *info =
1251                         GetScheduledResourceByActionSetName(scheduleResourceList, details);
1252
1253                 if(info != NULL)
1254                 {
1255                     unregisterTimer(info->timer_id);
1256
1257                     RemoveScheduledResource(&scheduleResourceList, info);
1258                     stackRet = OC_STACK_OK;
1259                 }
1260                 else
1261                 {
1262                     stackRet = OC_STACK_ERROR;
1263                 }
1264             }
1265
1266             else if (strcmp(doWhat, GET_ACTIONSET) == 0)
1267             {
1268                 char *plainText = NULL;
1269                 OCActionSet *actionset = NULL;
1270
1271                 cJSON_AddItemToObject(json, "rep", format =
1272                         cJSON_CreateObject());
1273                 GetActionSet(details, resource->actionsetHead, &actionset);
1274                 if (actionset != NULL)
1275                 {
1276                     BuildStringFromActionSet(actionset, &plainText);
1277
1278                     if (plainText != NULL)
1279                     {
1280                         cJSON_AddStringToObject(format, ACTIONSET, plainText);
1281                     }
1282                     OICFree(plainText);
1283                     stackRet = OC_STACK_OK;
1284                 }
1285             }
1286
1287
1288             jsonResponse = cJSON_Print(json);
1289             cJSON_Delete(json);
1290
1291             strcat((char *) bufferPtr, jsonResponse);
1292
1293             bufferLength = strlen((const char *) buffer);
1294             if (bufferLength > 0)
1295             {
1296                 OCEntityHandlerResponse response = { 0 };
1297                 if(stackRet == OC_STACK_OK)
1298                     response.ehResult = OC_EH_OK;
1299                 else
1300                     response.ehResult = OC_EH_ERROR;
1301                 // TODO: Implement
1302                 //response.payload = (char *)buffer;
1303                 //response.payloadSize = bufferLength + 1;
1304                 response.persistentBufferFlag = 0;
1305                 response.requestHandle =
1306                         (OCRequestHandle) ehRequest->requestHandle;
1307                 response.resourceHandle = (OCResourceHandle) collResource;
1308                 stackRet = OCDoResponse(&response);
1309             }
1310         }
1311
1312         OCFREE(doWhat)
1313         OCFREE(details)
1314     }
1315
1316     return stackRet;
1317 }