1 //******************************************************************
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #define _POSIX_C_SOURCE 200112L
23 #include "iotivity_config.h"
30 #include "ocpayload.h"
31 #include "oic_malloc.h"
32 #include "oic_string.h"
33 #include "occollection.h"
37 #define TAG "OIC_RI_GROUP"
39 #define DESC_DELIMITER "\""
40 #define ACTION_DELIMITER "*"
41 #define ATTR_DELIMITER "|"
42 #define ATTR_ASSIGN "="
44 // Definitions for operations related to actions
45 #define DO_ACTION "DoAction"
46 #define GET_ACTIONSET "GetActionSet"
47 #define ACTIONSET "ActionSet"
48 #define CANCEL_ACTIONSET "CancelAction"
49 #define DELETE_ACTIONSET "DelActionSet"
51 #define DEFAULT_CONTEXT_VALUE 0x99
53 #define VARIFY_POINTER_NULL(pointer, result, toExit) \
56 result = OC_STACK_NO_MEMORY;\
59 #define VARIFY_PARAM_NULL(pointer, result, toExit) \
62 result = OC_STACK_INVALID_PARAM;\
66 #define OCFREE(pointer) \
72 // Mutex implementation macros
73 #if defined(HAVE_PTHREAD_H)
77 #define MUTEX_LOCK(ARG_NAME) { pthread_mutex_lock(ARG_NAME); }
78 #define MUTEX_UNLOCK(ARG_NAME) { pthread_mutex_unlock(ARG_NAME); }
80 #elif defined(HAVE_WINDOWS_H)
83 CRITICAL_SECTION lock;
84 #define MUTEX_LOCK(ARG_NAME) { EnterCriticalSection(ARG_NAME); }
85 #define MUTEX_UNLOCK(ARG_NAME) { LeaveCriticalSection(ARG_NAME); }
87 #elif defined(WITH_ARDUINO)
89 #define MUTEX_LOCK(ARG_NAME) { }
90 #define MUTEX_UNLOCK(ARG_NAME) { }
94 ERROR Need mutex implementation on this platform
100 NONE = 0, SCHEDULED, RECURSIVE
103 typedef struct scheduledresourceinfo
105 OCResource *resource;
106 OCActionSet *actionset;
110 OCServerRequest *ehRequest;
113 struct scheduledresourceinfo* next;
114 } ScheduledResourceInfo;
116 ScheduledResourceInfo *scheduleResourceList = NULL;
118 void AddScheduledResource(ScheduledResourceInfo **head,
119 ScheduledResourceInfo* add)
121 OIC_LOG(INFO, TAG, "AddScheduledResource Entering...");
124 ScheduledResourceInfo *tmp = NULL;
143 ScheduledResourceInfo* GetScheduledResource(ScheduledResourceInfo *head)
145 OIC_LOG(INFO, TAG, "GetScheduledResource Entering...");
151 ScheduledResourceInfo *tmp = NULL;
154 #if !defined(WITH_ARDUINO)
165 diffTm = timespec_diff(tmp->time, t_now);
167 if (diffTm <= (time_t) 0)
169 OIC_LOG(INFO, TAG, "return Call INFO.");
183 OIC_LOG(INFO, TAG, "Cannot Find Call Info.");
188 ScheduledResourceInfo* GetScheduledResourceByActionSetName(ScheduledResourceInfo *head, char *setName)
190 OIC_LOG(INFO, TAG, "GetScheduledResourceByActionSetName Entering...");
194 ScheduledResourceInfo *tmp = NULL;
201 if (strcmp(tmp->actionset->actionsetName, setName) == 0)
203 OIC_LOG(INFO, TAG, "return Call INFO.");
216 OIC_LOG(INFO, TAG, "Cannot Find Call Info.");
221 void RemoveScheduledResource(ScheduledResourceInfo **head,
222 ScheduledResourceInfo* del)
227 OIC_LOG(INFO, TAG, "RemoveScheduledResource Entering...");
228 ScheduledResourceInfo *tmp = NULL;
240 *head = (*head)->next;
245 while (tmp->next && (tmp->next != del))
251 tmp->next = del->next;
261 typedef struct aggregatehandleinfo
263 OCServerRequest *ehRequest;
265 OCResource *collResource;
267 struct aggregatehandleinfo *next;
270 ClientRequestInfo *clientRequstList = NULL;
272 void AddClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* add)
274 ClientRequestInfo *tmp = NULL;
292 ClientRequestInfo* GetClientRequestInfo(ClientRequestInfo *head,
295 ClientRequestInfo *tmp = NULL;
303 if (tmp->required == handle)
316 void RemoveClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* del)
318 ClientRequestInfo *tmp = NULL;
325 *head = (*head)->next;
330 while (tmp->next && (tmp->next != del))
336 tmp->next = del->next;
341 void AddCapability(OCCapability** head, OCCapability* node)
343 OCCapability *pointer = *head;
350 while (pointer->next != NULL)
352 pointer = pointer->next;
355 pointer->next = node;
359 void AddAction(OCAction** head, OCAction* node)
361 OCAction *pointer = *head;
369 while (pointer->next != NULL)
371 pointer = pointer->next;
374 pointer->next = node;
378 OCStackResult AddActionSet(OCActionSet **head, OCActionSet* node)
380 OCActionSet *pointer = *head;
381 OCActionSet *prev = NULL;
384 return OC_STACK_ERROR;
393 while (pointer != NULL)
395 // check the uniqeness of actionsetname.
396 if (strcmp(pointer->actionsetName, node->actionsetName) == 0)
398 return OC_STACK_ERROR;
402 pointer = pointer->next;
411 void DeleteCapability(OCCapability *del)
413 OCFREE(del->capability)
414 del->capability = NULL;
420 void DeleteAction(OCAction** action)
422 OCCapability* pointer = (*action)->head;
423 OCCapability* pDel = NULL;
428 pointer = pointer->next;
430 DeleteCapability(pDel);
432 OCFREE((*action)->resourceUri)
433 (*action)->next = NULL;
437 void DeleteActionSet(OCActionSet** actionset)
439 OCAction* pointer = NULL;
440 OCAction* pDel = NULL;
442 if(*actionset == NULL)
445 pointer = (*actionset)->head;
450 pointer = pointer->next;
454 // (*actionset)->head = NULL;
455 OCFREE((*actionset)->actionsetName)
459 OCStackResult FindAndDeleteActionSet(OCResource **resource,
460 const char * actionsetName)
462 if (*resource != NULL)
464 OCActionSet *pointer = NULL;
465 OCActionSet *pDel = NULL;
467 pointer = (*resource)->actionsetHead;
471 return OC_STACK_ERROR;
475 if (strcmp(pointer->actionsetName, actionsetName) == 0)
477 if (pointer->next != NULL)
478 (*resource)->actionsetHead = pointer->next;
480 (*resource)->actionsetHead = NULL;
482 DeleteActionSet(&pointer);
484 else if (pointer->next != NULL)
488 if (pointer->next != NULL)
490 if (strcmp(pointer->next->actionsetName, actionsetName)
493 pDel = pointer->next;
494 pointer->next = pointer->next->next;
496 DeleteActionSet(&pDel);
499 pointer = pointer->next;
507 return OC_STACK_ERROR;
510 OCStackResult GetActionSet(const char *actionName, OCActionSet *head,
511 OCActionSet** actionset)
513 OCActionSet *pointer = head;
517 if (strcmp(pointer->actionsetName, actionName) == 0)
519 *actionset = pointer;
523 pointer = pointer->next;
526 return OC_STACK_ERROR;
530 OCStackResult ExtractKeyValueFromRequest(OCEntityHandlerRequest *ehRequest,
531 char **key, char **value)
533 OCStackResult result = OC_STACK_OK;
535 char *actionSetStr = NULL;
537 if( NULL == ehRequest->payload )
539 result = OC_STACK_ERROR;
545 input = (OCRepPayload*)(ehRequest->payload);
547 if(OCRepPayloadGetPropString(input, ACTIONSET, &actionSetStr))
549 *key = OICStrdup(ACTIONSET);
550 VARIFY_POINTER_NULL(*key, result, exit);
552 *value = OICStrdup(actionSetStr);
553 VARIFY_POINTER_NULL(*value, result, exit);
555 else if(OCRepPayloadGetPropString(input, DO_ACTION, &actionSetStr))
557 *key = OICStrdup(DO_ACTION);
558 VARIFY_POINTER_NULL(*key, result, exit);
560 *value = OICStrdup(actionSetStr);
561 VARIFY_POINTER_NULL(*value, result, exit);
563 else if(OCRepPayloadGetPropString(input, GET_ACTIONSET, &actionSetStr))
565 *key = OICStrdup(GET_ACTIONSET);
566 VARIFY_POINTER_NULL(*key, result, exit);
568 *value = OICStrdup(actionSetStr);
569 VARIFY_POINTER_NULL(*value, result, exit);
571 else if(OCRepPayloadGetPropString(input, DELETE_ACTIONSET, &actionSetStr))
573 *key = OICStrdup(DELETE_ACTIONSET);
574 VARIFY_POINTER_NULL(*key, result, exit);
576 *value = OICStrdup(actionSetStr);
577 VARIFY_POINTER_NULL(*value, result, exit);
579 else if(OCRepPayloadGetPropString(input, CANCEL_ACTIONSET, &actionSetStr))
581 *key = OICStrdup(CANCEL_ACTIONSET);
582 VARIFY_POINTER_NULL(*key, result, exit);
584 *value = OICStrdup(actionSetStr);
585 VARIFY_POINTER_NULL(*value, result, exit);
589 result = OC_STACK_ERROR;
593 if (result != OC_STACK_OK)
599 OCFREE(actionSetStr);
604 OCStackResult ExtractActionSetNameAndDelaytime(char *pChar, char **setName,
607 char *token = NULL, *tokenPtr = NULL;
608 OCStackResult result = OC_STACK_OK;
610 token = (char*) strtok_r(pChar, ACTION_DELIMITER, &tokenPtr);
611 VARIFY_POINTER_NULL(token, result, exit)
613 *setName = (char *) OICMalloc(strlen(token) + 1);
614 VARIFY_POINTER_NULL(*setName, result, exit)
615 VARIFY_PARAM_NULL(token, result, exit)
616 strncpy(*setName, token, strlen(token) + 1);
618 token = strtok_r(NULL, ACTION_DELIMITER, &tokenPtr);
619 VARIFY_POINTER_NULL(pa, result, exit)
620 VARIFY_PARAM_NULL(token, result, exit)
630 OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
632 OCStackResult result = OC_STACK_OK;
634 char *iterToken = NULL, *iterTokenPtr = NULL;
635 char *descIterToken = NULL, *descIterTokenPtr = NULL;
636 char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
637 char *desc = NULL, *attr = NULL;
638 char *key = NULL, *value = NULL;
640 OCAction *action = NULL;
641 OCCapability *capa = NULL;
643 OIC_LOG(INFO, TAG, "Build ActionSet Instance.");
645 *set = (OCActionSet*) OICMalloc(sizeof(OCActionSet));
646 VARIFY_POINTER_NULL(*set, result, exit)
648 iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
649 VARIFY_POINTER_NULL(iterToken, result, exit);
652 memset(*set, 0, sizeof(OCActionSet));
653 (*set)->actionsetName = (char *) OICMalloc(strlen(iterToken) + 1);
654 VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
655 VARIFY_PARAM_NULL(iterToken, result, exit)
656 strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
658 // Time info. for Scheduled/Recursive Group action.
659 // d is meant Day of the week.
660 // T is meant ActionType.
661 // yyyy-mm-dd hh:mm:ss d
662 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
663 VARIFY_PARAM_NULL(iterToken, result, exit)
664 #if !defined(WITH_ARDUINO)
665 if( 2 != sscanf(iterToken, "%ld %u", &(*set)->timesteps, &(*set)->type) )
667 // If the return value should be 2, the number of items in the argument. Otherwise, it fails.
672 OIC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
674 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
677 desc = (char *) OICMalloc(strlen(iterToken) + 1);
678 VARIFY_POINTER_NULL(desc, result, exit)
679 VARIFY_PARAM_NULL(desc, result, exit)
680 strncpy(desc, iterToken, strlen(iterToken) + 1);
681 descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER,
683 while (descIterToken)
685 attr = (char *) OICMalloc(strlen(descIterToken) + 1);
686 VARIFY_POINTER_NULL(attr, result, exit)
687 VARIFY_PARAM_NULL(descIterToken, result, exit)
688 strncpy(attr, descIterToken, strlen(descIterToken) + 1);
690 attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN,
692 VARIFY_POINTER_NULL(attrIterToken, result, exit);
694 key = (char *) OICMalloc(strlen(attrIterToken) + 1);
695 VARIFY_POINTER_NULL(key, result, exit)
696 VARIFY_PARAM_NULL(attrIterToken, result, exit)
697 strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
699 attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN,
701 VARIFY_POINTER_NULL(attrIterToken, result, exit);
702 value = (char *) OICMalloc(strlen(attrIterToken) + 1);
703 VARIFY_POINTER_NULL(value, result, exit)
704 VARIFY_PARAM_NULL(attrIterToken, result, exit)
705 strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
707 if (strcmp(key, "uri") == 0)
709 OIC_LOG(INFO, TAG, "Build OCAction Instance.");
711 action = (OCAction*) OICMalloc(sizeof(OCAction));
712 VARIFY_POINTER_NULL(action, result, exit)
713 memset(action, 0, sizeof(OCAction));
714 action->resourceUri = (char *) OICMalloc(strlen(value) + 1);
715 VARIFY_POINTER_NULL(action->resourceUri, result, exit)
716 VARIFY_PARAM_NULL(value, result, exit)
717 strncpy(action->resourceUri, value, strlen(value) + 1);
721 if ((key != NULL) && (value != NULL))
723 OIC_LOG(INFO, TAG, "Build OCCapability Instance.");
725 capa = (OCCapability*) OICMalloc(sizeof(OCCapability));
726 VARIFY_POINTER_NULL(capa, result, exit)
727 memset(capa, 0, sizeof(OCCapability));
729 capa->capability = (char *) OICMalloc(strlen(key) + 1);
730 VARIFY_POINTER_NULL(capa->capability, result, exit)
731 VARIFY_PARAM_NULL(key, result, exit)
732 strncpy(capa->capability, key, strlen(key) + 1);
734 capa->status = (char *) OICMalloc(strlen(value) + 1);
735 VARIFY_POINTER_NULL(capa->status, result, exit)
736 VARIFY_PARAM_NULL(value, result, exit)
737 strncpy(capa->status, value, strlen(value) + 1);
739 VARIFY_POINTER_NULL(action, result, exit)
741 AddCapability(&action->head, capa);
749 descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER,
753 AddAction(&(*set)->head, action);
754 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
772 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
774 // Can't use the macros here as they are hardcoded to 'exit' and will
775 // result in dereferencing a null pointer.
776 if (!actionset || !desc)
778 return OC_STACK_INVALID_PARAM;
780 char temp[1024] = { 0 };
781 size_t remaining = sizeof(temp) - 1;
782 OCStackResult res = OC_STACK_ERROR;
783 char* actionTypeStr = NULL;
785 OCAction *action = actionset->head;
787 if (remaining >= strlen(actionset->actionsetName) + 1)
789 strncat(temp, actionset->actionsetName, strlen(actionset->actionsetName));
790 remaining -= strlen(actionset->actionsetName);
791 strncat(temp, ACTION_DELIMITER, strlen(ACTION_DELIMITER));
796 res = OC_STACK_ERROR;
800 actionTypeStr = (char *)malloc(1024);
801 if(actionTypeStr != NULL)
803 sprintf(actionTypeStr, "%ld %u", actionset->timesteps, actionset->type);
804 if(remaining >= strlen(actionTypeStr) + strlen(ACTION_DELIMITER) + 1)
806 strncat(temp, actionTypeStr, strlen(actionTypeStr));
807 remaining -= strlen(actionTypeStr);
808 strncat(temp, ACTION_DELIMITER, strlen(ACTION_DELIMITER));
809 remaining -= strlen(ACTION_DELIMITER);
815 res = OC_STACK_ERROR;
821 res = OC_STACK_ERROR;
825 while (action != NULL)
827 if (remaining < (strlen("uri=") + strlen(action->resourceUri) + 1))
829 res = OC_STACK_ERROR;
833 strcat(temp, "uri=");
834 remaining -= strlen("uri=");
835 strcat(temp, action->resourceUri);
836 remaining -= strlen(action->resourceUri);
840 OCCapability *capas = action->head;
841 while (capas != NULL)
843 if (remaining < (strlen(capas->capability)
844 + 1 + strlen(capas->status)))
846 res = OC_STACK_ERROR;
850 strcat(temp, capas->capability);
851 remaining -= strlen(capas->capability);
854 strcat(temp, capas->status);
855 remaining -= strlen(capas->status);
862 res = OC_STACK_ERROR;
870 action = action->next;
873 if (remaining < strlen(ACTION_DELIMITER))
875 res = OC_STACK_ERROR;
878 strcat(temp, ACTION_DELIMITER);
883 *desc = OICStrdup(temp);
884 VARIFY_POINTER_NULL(*desc, res, exit);
893 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
894 OCClientResponse* clientResponse)
897 (void)clientResponse;
898 OIC_LOG(INFO, TAG, "Entering ActionSetCB");
900 ClientRequestInfo *info = GetClientRequestInfo(clientRequstList, handle);
904 OCEntityHandlerResponse response = { 0 };
906 response.ehResult = OC_EH_OK;
908 if(NULL == clientResponse->payload)
910 OIC_LOG(ERROR, TAG, "Error sending response");
911 return OC_STACK_DELETE_TRANSACTION;
914 // Format the response. Note this requires some info about the request
915 response.requestHandle = info->ehRequest;
916 response.resourceHandle = info->collResource;
917 response.payload = clientResponse->payload;
918 response.numSendVendorSpecificHeaderOptions = 0;
919 memset(response.sendVendorSpecificHeaderOptions, 0,
920 sizeof response.sendVendorSpecificHeaderOptions);
921 memset(response.resourceUri, 0, sizeof response.resourceUri);
922 // Indicate that response is NOT in a persistent buffer
923 response.persistentBufferFlag = 0;
926 if (OCDoResponse(&response) != OC_STACK_OK)
928 OIC_LOG(ERROR, TAG, "Error sending response");
929 return OC_STACK_DELETE_TRANSACTION;
932 RemoveClientRequestInfo(&clientRequstList, info);
936 return OC_STACK_KEEP_TRANSACTION;
939 void ActionSetCD(void *context)
944 OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr,
947 OCStackResult ret = OC_STACK_ERROR;
954 OIC_LOG(INFO, TAG, "Entering BuildActionJSON");
955 json = cJSON_CreateObject();
957 cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
959 OCCapability* pointerCapa = action->head;
962 cJSON_AddStringToObject(body, pointerCapa->capability,
963 pointerCapa->status);
964 pointerCapa = pointerCapa->next;
967 jsonStr = cJSON_PrintUnformatted(json);
969 jsonLen = strlen(jsonStr);
970 if (jsonLen < *remaining)
972 strncat((char*) bufferPtr, jsonStr, jsonLen);
973 *remaining -= jsonLen;
974 bufferPtr += jsonLen;
984 OCPayload* BuildActionCBOR(OCAction* action)
986 OCRepPayload* payload = OCRepPayloadCreate();
990 OIC_LOG(INFO, TAG, "Failed to create put payload object");
994 OCCapability* pointerCapa = action->head;
997 OCRepPayloadSetPropString(payload, pointerCapa->capability, pointerCapa->status);
998 pointerCapa = pointerCapa->next;
1001 return (OCPayload*) payload;
1004 unsigned int GetNumOfTargetResource(OCAction *actionset)
1006 int numOfResource = 0;
1008 OCAction *pointerAction = actionset;
1010 while (pointerAction != NULL)
1013 pointerAction = pointerAction->next;
1016 return numOfResource;
1019 OCStackResult SendAction(OCDoHandle *handle, OCServerRequest* requestHandle, const char *targetUri,
1023 OCCallbackData cbData;
1024 cbData.cb = &ActionSetCB;
1025 cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
1028 return OCDoResource(handle, OC_REST_PUT, targetUri, &requestHandle->devAddr,
1029 payload, CT_ADAPTER_IP, OC_NA_QOS, &cbData, NULL, 0);
1032 OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
1033 OCServerRequest* requestHandle)
1035 OCStackResult result = OC_STACK_ERROR;
1037 if( NULL == actionset->head)
1042 OCAction *pointerAction = actionset->head;
1044 while (pointerAction != NULL)
1047 payload = BuildActionCBOR(pointerAction);
1054 ClientRequestInfo *info = (ClientRequestInfo *) OICMalloc(
1055 sizeof(ClientRequestInfo));
1060 return OC_STACK_NO_MEMORY;
1063 memset(info, 0, sizeof(ClientRequestInfo));
1065 info->collResource = resource;
1066 info->ehRequest = requestHandle;
1068 result = SendAction(&info->required, info->ehRequest, pointerAction->resourceUri,
1071 if (result != OC_STACK_OK)
1077 AddClientRequestInfo(&clientRequstList, info);
1079 pointerAction = pointerAction->next;
1085 void DoScheduledGroupAction()
1087 OIC_LOG(INFO, TAG, "DoScheduledGroupAction Entering...");
1088 ScheduledResourceInfo* info = GetScheduledResource(scheduleResourceList);
1092 OIC_LOG(INFO, TAG, "Target resource is NULL");
1095 else if (info->resource == NULL)
1097 OIC_LOG(INFO, TAG, "Target resource is NULL");
1100 else if (info->actionset == NULL)
1102 OIC_LOG(INFO, TAG, "Target ActionSet is NULL");
1105 else if (info->ehRequest == NULL)
1107 OIC_LOG(INFO, TAG, "Target ActionSet is NULL");
1113 DoAction(info->resource, info->actionset, info->ehRequest);
1115 MUTEX_UNLOCK(&lock);
1118 if (info->actionset->type == RECURSIVE)
1120 ScheduledResourceInfo *schedule;
1121 schedule = (ScheduledResourceInfo *) OICMalloc(
1122 sizeof(ScheduledResourceInfo));
1126 OIC_LOG(INFO, TAG, "Building New Call Info.");
1127 memset(schedule, 0, sizeof(ScheduledResourceInfo));
1129 if (info->actionset->timesteps > 0)
1132 schedule->resource = info->resource;
1133 schedule->actionset = info->actionset;
1134 schedule->ehRequest = info->ehRequest;
1136 schedule->time = registerTimer(info->actionset->timesteps,
1137 &schedule->timer_id,
1138 &DoScheduledGroupAction);
1140 OIC_LOG(INFO, TAG, "Reregisteration.");
1141 MUTEX_UNLOCK(&lock);
1142 AddScheduledResource(&scheduleResourceList, schedule);
1151 RemoveScheduledResource(&scheduleResourceList, info);
1158 OCStackResult BuildCollectionGroupActionCBORResponse(
1159 OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource,
1160 OCEntityHandlerRequest *ehRequest)
1162 OCStackResult stackRet = OC_STACK_ERROR;
1164 OIC_LOG(INFO, TAG, "Group Action is requested.");
1166 char *doWhat = NULL;
1167 char *details = NULL;
1170 static bool initializedCriticalSection = false;
1172 if(false == initializedCriticalSection) {
1173 /** @todo Find a way to DeleteCriticalSection somewhere. */
1174 InitializeCriticalSection(&lock);
1175 initializedCriticalSection = true;
1179 stackRet = ExtractKeyValueFromRequest(ehRequest, &doWhat, &details);
1181 if(stackRet != OC_STACK_OK)
1183 OIC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
1187 stackRet = OC_STACK_ERROR;
1189 if (method == OC_REST_PUT)
1191 OIC_LOG(INFO, TAG, "Group Action[PUT].");
1193 if (strcmp(doWhat, ACTIONSET) == 0)
1195 OCActionSet *actionSet = NULL;
1196 stackRet = BuildActionSetFromString(&actionSet, details);
1198 if(stackRet == OC_STACK_OK)
1200 if (actionSet != NULL)
1202 stackRet = AddActionSet(&resource->actionsetHead,
1204 if (stackRet == OC_STACK_ERROR)
1206 if(actionSet != NULL)
1208 DeleteActionSet( &actionSet );
1210 OIC_LOG(INFO, TAG, "Duplicated ActionSet ");
1215 stackRet = OC_STACK_ERROR;
1221 stackRet = OC_STACK_ERROR;
1225 else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
1227 if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
1229 stackRet = OC_STACK_OK;
1233 stackRet = OC_STACK_ERROR;
1237 OCRepPayload* payload = OCRepPayloadCreate();
1241 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
1242 stackRet = OC_STACK_ERROR;
1246 OCEntityHandlerResponse response = { 0 };
1248 if(stackRet == OC_STACK_OK)
1249 response.ehResult = OC_EH_OK;
1251 response.ehResult = OC_EH_ERROR;
1253 // Format the response. Note this requires some info about the request
1254 response.requestHandle = ehRequest->requestHandle;
1255 response.resourceHandle = ehRequest->resource;
1256 response.payload = (OCPayload*) payload;
1257 response.numSendVendorSpecificHeaderOptions = 0;
1258 memset(response.sendVendorSpecificHeaderOptions, 0,
1259 sizeof response.sendVendorSpecificHeaderOptions);
1260 memset(response.resourceUri, 0, sizeof response. resourceUri);
1261 // Indicate that response is NOT in a persistent buffer
1262 response.persistentBufferFlag = 0;
1263 response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
1265 // Send the response
1266 if (OCDoResponse(&response) != OC_STACK_OK)
1268 OIC_LOG(ERROR, TAG, "Error sending response");
1269 stackRet = OC_STACK_ERROR;
1273 else if (method == OC_REST_POST)
1275 OCActionSet *actionset = NULL;
1277 OCRepPayload* payload = OCRepPayloadCreate();
1278 OCRepPayloadSetUri(payload, resource->uri);
1280 if ((strcmp(doWhat, DO_ACTION) == 0)
1281 || (strcmp(doWhat, "DoScheduledAction") == 0))
1283 char *pActionsetName = NULL;
1284 long int delay = -1;
1286 if (strcmp(doWhat, "DoScheduledAction") == 0)
1288 stackRet = ExtractActionSetNameAndDelaytime(details,
1289 &pActionsetName, &delay);
1292 details = pActionsetName;
1296 stackRet = OC_STACK_OK;
1299 if (stackRet == OC_STACK_OK)
1301 if (GetActionSet(details, resource->actionsetHead,
1302 &actionset) != OC_STACK_OK)
1304 OIC_LOG(INFO, TAG, "ERROR");
1305 stackRet = OC_STACK_ERROR;
1308 if (actionset == NULL)
1310 OIC_LOG(INFO, TAG, "Cannot Find ActionSet");
1311 stackRet = OC_STACK_ERROR;
1315 OIC_LOG(INFO, TAG, "Group Action[POST].");
1316 if (actionset->type == NONE)
1318 OIC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
1319 actionset->actionsetName);
1320 unsigned int num = GetNumOfTargetResource(
1323 ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
1324 HandleAggregateResponse;
1325 ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
1328 DoAction(resource, actionset,
1329 (OCServerRequest*) ehRequest->requestHandle);
1330 stackRet = OC_STACK_OK;
1334 OIC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
1335 actionset->actionsetName);
1338 (delay == -1 ? actionset->timesteps : delay);
1340 ScheduledResourceInfo *schedule;
1341 schedule = (ScheduledResourceInfo *) OICMalloc(
1342 sizeof(ScheduledResourceInfo));
1346 OIC_LOG(INFO, TAG, "Building New Call Info.");
1348 sizeof(ScheduledResourceInfo));
1350 schedule->resource = resource;
1351 schedule->actionset = actionset;
1352 schedule->ehRequest =
1353 (OCServerRequest*) ehRequest->requestHandle;
1354 MUTEX_UNLOCK(&lock);
1357 OIC_LOG_V(INFO, TAG, "delay_time is %ld seconds.",
1358 actionset->timesteps);
1360 schedule->time = registerTimer(delay,
1361 &schedule->timer_id,
1362 &DoScheduledGroupAction);
1363 MUTEX_UNLOCK(&lock);
1364 AddScheduledResource(&scheduleResourceList,
1366 stackRet = OC_STACK_OK;
1370 stackRet = OC_STACK_ERROR;
1377 else if (strcmp(doWhat, "CancelAction") == 0)
1379 ScheduledResourceInfo *info =
1380 GetScheduledResourceByActionSetName(scheduleResourceList, details);
1384 unregisterTimer(info->timer_id);
1386 RemoveScheduledResource(&scheduleResourceList, info);
1387 stackRet = OC_STACK_OK;
1391 stackRet = OC_STACK_ERROR;
1395 else if (strcmp(doWhat, GET_ACTIONSET) == 0)
1397 char *plainText = NULL;
1398 OCActionSet *actionset = NULL;
1400 GetActionSet(details, resource->actionsetHead, &actionset);
1401 if (actionset != NULL)
1403 BuildStringFromActionSet(actionset, &plainText);
1405 if (plainText != NULL)
1407 OCRepPayloadSetPropString(payload, ACTIONSET, plainText);
1410 stackRet = OC_STACK_OK;
1416 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
1417 stackRet = OC_STACK_ERROR;
1421 OCEntityHandlerResponse response = { 0 };
1422 if(stackRet == OC_STACK_OK)
1423 response.ehResult = OC_EH_OK;
1425 response.ehResult = OC_EH_ERROR;
1427 // Format the response. Note this requires some info about the request
1428 response.requestHandle = ehRequest->requestHandle;
1429 response.resourceHandle = ehRequest->resource;
1430 response.payload = (OCPayload*) payload;
1431 response.numSendVendorSpecificHeaderOptions = 0;
1432 memset(response.sendVendorSpecificHeaderOptions, 0,
1433 sizeof response.sendVendorSpecificHeaderOptions);
1434 memset(response.resourceUri, 0, sizeof response.resourceUri);
1435 // Indicate that response is NOT in a persistent buffer
1436 response.persistentBufferFlag = 0;
1437 response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
1439 // Send the response
1440 if (OCDoResponse(&response) != OC_STACK_OK)
1442 OIC_LOG(ERROR, TAG, "Error sending response");
1443 stackRet = OC_STACK_ERROR;