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)
76 pthread_mutex_t g_scheduledResourceLock;
77 #define MUTEX_LOCK(ARG_NAME) { pthread_mutex_lock(ARG_NAME); }
78 #define MUTEX_UNLOCK(ARG_NAME) { pthread_mutex_unlock(ARG_NAME); }
79 #define MUTEX_INITIALIZE(ARG_NAME) { }
80 #define MUTEX_TERMINATE(ARG_NAME) { }
82 #elif defined(HAVE_WINDOWS_H)
85 CRITICAL_SECTION g_scheduledResourceLock;
86 bool g_initializedScheduledResourceLock = false;
87 #define MUTEX_LOCK(ARG_NAME) { EnterCriticalSection(ARG_NAME); }
88 #define MUTEX_UNLOCK(ARG_NAME) { LeaveCriticalSection(ARG_NAME); }
89 #define MUTEX_INITIALIZE(ARG_NAME) { assert(!g_initializedScheduledResourceLock); \
90 InitializeCriticalSection(ARG_NAME); \
91 g_initializedScheduledResourceLock = true; \
93 #define MUTEX_TERMINATE(ARG_NAME) { if (g_initializedScheduledResourceLock) \
95 DeleteCriticalSection(ARG_NAME); \
96 g_initializedScheduledResourceLock = false; \
100 #elif defined(WITH_ARDUINO)
102 #define MUTEX_LOCK(ARG_NAME) { }
103 #define MUTEX_UNLOCK(ARG_NAME) { }
104 #define MUTEX_INITIALIZE(ARG_NAME) { }
105 #define MUTEX_TERMINATE(ARG_NAME) { }
109 ERROR Need mutex implementation on this platform
115 NONE = 0, SCHEDULED, RECURSIVE
118 typedef struct scheduledresourceinfo
120 OCResource *resource;
121 OCActionSet *actionset;
125 OCServerRequest *ehRequest;
128 struct scheduledresourceinfo* next;
129 } ScheduledResourceInfo;
131 ScheduledResourceInfo *g_scheduleResourceList = NULL;
133 void AddScheduledResource(ScheduledResourceInfo **head,
134 ScheduledResourceInfo* add)
136 OIC_LOG(INFO, TAG, "AddScheduledResource Entering...");
138 MUTEX_LOCK(&g_scheduledResourceLock);
139 ScheduledResourceInfo *tmp = NULL;
155 MUTEX_UNLOCK(&g_scheduledResourceLock);
158 ScheduledResourceInfo* GetScheduledResource(ScheduledResourceInfo *head)
160 OIC_LOG(INFO, TAG, "GetScheduledResource Entering...");
162 MUTEX_LOCK(&g_scheduledResourceLock);
166 ScheduledResourceInfo *tmp = NULL;
169 #if !defined(WITH_ARDUINO)
180 diffTm = timespec_diff(tmp->time, t_now);
182 if (diffTm <= (time_t) 0)
184 OIC_LOG(INFO, TAG, "return Call INFO.");
194 MUTEX_UNLOCK(&g_scheduledResourceLock);
198 OIC_LOG(INFO, TAG, "Cannot Find Call Info.");
203 ScheduledResourceInfo* GetScheduledResourceByActionSetName(ScheduledResourceInfo *head, char *setName)
205 OIC_LOG(INFO, TAG, "GetScheduledResourceByActionSetName Entering...");
207 MUTEX_LOCK(&g_scheduledResourceLock);
209 ScheduledResourceInfo *tmp = NULL;
216 if (strcmp(tmp->actionset->actionsetName, setName) == 0)
218 OIC_LOG(INFO, TAG, "return Call INFO.");
227 MUTEX_UNLOCK(&g_scheduledResourceLock);
231 OIC_LOG(INFO, TAG, "Cannot Find Call Info.");
236 void RemoveScheduledResource(ScheduledResourceInfo **head,
237 ScheduledResourceInfo* del)
240 MUTEX_LOCK(&g_scheduledResourceLock);
242 OIC_LOG(INFO, TAG, "RemoveScheduledResource Entering...");
243 ScheduledResourceInfo *tmp = NULL;
248 MUTEX_UNLOCK(&g_scheduledResourceLock);
255 *head = (*head)->next;
260 while (tmp->next && (tmp->next != del))
266 tmp->next = del->next;
272 MUTEX_UNLOCK(&g_scheduledResourceLock);
275 typedef struct aggregatehandleinfo
277 OCServerRequest *ehRequest;
279 OCResource *collResource;
281 struct aggregatehandleinfo *next;
284 ClientRequestInfo *clientRequstList = NULL;
286 void AddClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* add)
288 ClientRequestInfo *tmp = NULL;
306 ClientRequestInfo* GetClientRequestInfo(ClientRequestInfo *head,
309 ClientRequestInfo *tmp = NULL;
317 if (tmp->required == handle)
330 void RemoveClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* del)
332 ClientRequestInfo *tmp = NULL;
339 *head = (*head)->next;
344 while (tmp->next && (tmp->next != del))
350 tmp->next = del->next;
355 void AddCapability(OCCapability** head, OCCapability* node)
357 OCCapability *pointer = *head;
364 while (pointer->next != NULL)
366 pointer = pointer->next;
369 pointer->next = node;
373 void AddAction(OCAction** head, OCAction* node)
375 OCAction *pointer = *head;
383 while (pointer->next != NULL)
385 pointer = pointer->next;
388 pointer->next = node;
392 OCStackResult AddActionSet(OCActionSet **head, OCActionSet* node)
394 OCActionSet *pointer = *head;
395 OCActionSet *prev = NULL;
398 return OC_STACK_ERROR;
407 while (pointer != NULL)
409 // check the uniqeness of actionsetname.
410 if (strcmp(pointer->actionsetName, node->actionsetName) == 0)
412 return OC_STACK_ERROR;
416 pointer = pointer->next;
425 void DeleteCapability(OCCapability *del)
427 OCFREE(del->capability)
428 del->capability = NULL;
434 void DeleteAction(OCAction** action)
436 OCCapability* pointer = (*action)->head;
437 OCCapability* pDel = NULL;
442 pointer = pointer->next;
444 DeleteCapability(pDel);
446 OCFREE((*action)->resourceUri)
447 (*action)->next = NULL;
451 void DeleteActionSet(OCActionSet** actionset)
453 OCAction* pointer = NULL;
454 OCAction* pDel = NULL;
456 if(*actionset == NULL)
459 pointer = (*actionset)->head;
464 pointer = pointer->next;
468 // (*actionset)->head = NULL;
469 OCFREE((*actionset)->actionsetName)
473 OCStackResult FindAndDeleteActionSet(OCResource **resource,
474 const char * actionsetName)
476 if (*resource != NULL)
478 OCActionSet *pointer = NULL;
479 OCActionSet *pDel = NULL;
481 pointer = (*resource)->actionsetHead;
485 return OC_STACK_ERROR;
489 if (strcmp(pointer->actionsetName, actionsetName) == 0)
491 if (pointer->next != NULL)
492 (*resource)->actionsetHead = pointer->next;
494 (*resource)->actionsetHead = NULL;
496 DeleteActionSet(&pointer);
498 else if (pointer->next != NULL)
502 if (pointer->next != NULL)
504 if (strcmp(pointer->next->actionsetName, actionsetName)
507 pDel = pointer->next;
508 pointer->next = pointer->next->next;
510 DeleteActionSet(&pDel);
513 pointer = pointer->next;
521 return OC_STACK_ERROR;
524 OCStackResult GetActionSet(const char *actionName, OCActionSet *head,
525 OCActionSet** actionset)
527 OCActionSet *pointer = head;
531 if (strcmp(pointer->actionsetName, actionName) == 0)
533 *actionset = pointer;
537 pointer = pointer->next;
540 return OC_STACK_ERROR;
544 OCStackResult ExtractKeyValueFromRequest(OCEntityHandlerRequest *ehRequest,
545 char **key, char **value)
547 OCStackResult result = OC_STACK_OK;
549 char *actionSetStr = NULL;
551 if( NULL == ehRequest->payload )
553 result = OC_STACK_ERROR;
559 input = (OCRepPayload*)(ehRequest->payload);
561 if(OCRepPayloadGetPropString(input, ACTIONSET, &actionSetStr))
563 *key = OICStrdup(ACTIONSET);
564 VARIFY_POINTER_NULL(*key, result, exit);
566 *value = OICStrdup(actionSetStr);
567 VARIFY_POINTER_NULL(*value, result, exit);
569 else if(OCRepPayloadGetPropString(input, DO_ACTION, &actionSetStr))
571 *key = OICStrdup(DO_ACTION);
572 VARIFY_POINTER_NULL(*key, result, exit);
574 *value = OICStrdup(actionSetStr);
575 VARIFY_POINTER_NULL(*value, result, exit);
577 else if(OCRepPayloadGetPropString(input, GET_ACTIONSET, &actionSetStr))
579 *key = OICStrdup(GET_ACTIONSET);
580 VARIFY_POINTER_NULL(*key, result, exit);
582 *value = OICStrdup(actionSetStr);
583 VARIFY_POINTER_NULL(*value, result, exit);
585 else if(OCRepPayloadGetPropString(input, DELETE_ACTIONSET, &actionSetStr))
587 *key = OICStrdup(DELETE_ACTIONSET);
588 VARIFY_POINTER_NULL(*key, result, exit);
590 *value = OICStrdup(actionSetStr);
591 VARIFY_POINTER_NULL(*value, result, exit);
593 else if(OCRepPayloadGetPropString(input, CANCEL_ACTIONSET, &actionSetStr))
595 *key = OICStrdup(CANCEL_ACTIONSET);
596 VARIFY_POINTER_NULL(*key, result, exit);
598 *value = OICStrdup(actionSetStr);
599 VARIFY_POINTER_NULL(*value, result, exit);
603 result = OC_STACK_ERROR;
607 if (result != OC_STACK_OK)
613 OCFREE(actionSetStr);
618 OCStackResult ExtractActionSetNameAndDelaytime(char *pChar, char **setName,
621 char *token = NULL, *tokenPtr = NULL;
622 OCStackResult result = OC_STACK_OK;
624 token = (char*) strtok_r(pChar, ACTION_DELIMITER, &tokenPtr);
625 VARIFY_POINTER_NULL(token, result, exit)
627 *setName = (char *) OICMalloc(strlen(token) + 1);
628 VARIFY_POINTER_NULL(*setName, result, exit)
629 VARIFY_PARAM_NULL(token, result, exit)
630 strncpy(*setName, token, strlen(token) + 1);
632 token = strtok_r(NULL, ACTION_DELIMITER, &tokenPtr);
633 VARIFY_POINTER_NULL(pa, result, exit)
634 VARIFY_PARAM_NULL(token, result, exit)
644 OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
646 OCStackResult result = OC_STACK_OK;
648 char *iterToken = NULL, *iterTokenPtr = NULL;
649 char *descIterToken = NULL, *descIterTokenPtr = NULL;
650 char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
651 char *desc = NULL, *attr = NULL;
652 char *key = NULL, *value = NULL;
654 OCAction *action = NULL;
655 OCCapability *capa = NULL;
657 OIC_LOG(INFO, TAG, "Build ActionSet Instance.");
659 *set = (OCActionSet*) OICMalloc(sizeof(OCActionSet));
660 VARIFY_POINTER_NULL(*set, result, exit)
662 iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
663 VARIFY_POINTER_NULL(iterToken, result, exit);
666 memset(*set, 0, sizeof(OCActionSet));
667 (*set)->actionsetName = (char *) OICMalloc(strlen(iterToken) + 1);
668 VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
669 VARIFY_PARAM_NULL(iterToken, result, exit)
670 strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
672 // Time info. for Scheduled/Recursive Group action.
673 // d is meant Day of the week.
674 // T is meant ActionType.
675 // yyyy-mm-dd hh:mm:ss d
676 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
677 VARIFY_PARAM_NULL(iterToken, result, exit)
678 #if !defined(WITH_ARDUINO)
679 if( 2 != sscanf(iterToken, "%ld %u", &(*set)->timesteps, &(*set)->type) )
681 // If the return value should be 2, the number of items in the argument. Otherwise, it fails.
686 OIC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
688 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
691 desc = (char *) OICMalloc(strlen(iterToken) + 1);
692 VARIFY_POINTER_NULL(desc, result, exit)
693 VARIFY_PARAM_NULL(desc, result, exit)
694 strncpy(desc, iterToken, strlen(iterToken) + 1);
695 descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER,
697 while (descIterToken)
699 attr = (char *) OICMalloc(strlen(descIterToken) + 1);
700 VARIFY_POINTER_NULL(attr, result, exit)
701 VARIFY_PARAM_NULL(descIterToken, result, exit)
702 strncpy(attr, descIterToken, strlen(descIterToken) + 1);
704 attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN,
706 VARIFY_POINTER_NULL(attrIterToken, result, exit);
708 key = (char *) OICMalloc(strlen(attrIterToken) + 1);
709 VARIFY_POINTER_NULL(key, result, exit)
710 VARIFY_PARAM_NULL(attrIterToken, result, exit)
711 strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
713 attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN,
715 VARIFY_POINTER_NULL(attrIterToken, result, exit);
716 value = (char *) OICMalloc(strlen(attrIterToken) + 1);
717 VARIFY_POINTER_NULL(value, result, exit)
718 VARIFY_PARAM_NULL(attrIterToken, result, exit)
719 strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
721 if (strcmp(key, "uri") == 0)
723 OIC_LOG(INFO, TAG, "Build OCAction Instance.");
725 action = (OCAction*) OICMalloc(sizeof(OCAction));
726 VARIFY_POINTER_NULL(action, result, exit)
727 memset(action, 0, sizeof(OCAction));
728 action->resourceUri = (char *) OICMalloc(strlen(value) + 1);
729 VARIFY_POINTER_NULL(action->resourceUri, result, exit)
730 VARIFY_PARAM_NULL(value, result, exit)
731 strncpy(action->resourceUri, value, strlen(value) + 1);
735 if ((key != NULL) && (value != NULL))
737 OIC_LOG(INFO, TAG, "Build OCCapability Instance.");
739 capa = (OCCapability*) OICMalloc(sizeof(OCCapability));
740 VARIFY_POINTER_NULL(capa, result, exit)
741 memset(capa, 0, sizeof(OCCapability));
743 capa->capability = (char *) OICMalloc(strlen(key) + 1);
744 VARIFY_POINTER_NULL(capa->capability, result, exit)
745 VARIFY_PARAM_NULL(key, result, exit)
746 strncpy(capa->capability, key, strlen(key) + 1);
748 capa->status = (char *) OICMalloc(strlen(value) + 1);
749 VARIFY_POINTER_NULL(capa->status, result, exit)
750 VARIFY_PARAM_NULL(value, result, exit)
751 strncpy(capa->status, value, strlen(value) + 1);
753 VARIFY_POINTER_NULL(action, result, exit)
755 AddCapability(&action->head, capa);
763 descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER,
767 AddAction(&(*set)->head, action);
768 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
786 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
788 // Can't use the macros here as they are hardcoded to 'exit' and will
789 // result in dereferencing a null pointer.
790 if (!actionset || !desc)
792 return OC_STACK_INVALID_PARAM;
794 char temp[1024] = { 0 };
795 size_t remaining = sizeof(temp) - 1;
796 OCStackResult res = OC_STACK_ERROR;
797 char* actionTypeStr = NULL;
799 OCAction *action = actionset->head;
801 if (remaining >= strlen(actionset->actionsetName) + 1)
803 strncat(temp, actionset->actionsetName, strlen(actionset->actionsetName));
804 remaining -= strlen(actionset->actionsetName);
805 strncat(temp, ACTION_DELIMITER, strlen(ACTION_DELIMITER));
810 res = OC_STACK_ERROR;
814 actionTypeStr = (char *)OICMalloc(1024);
815 if(actionTypeStr != NULL)
817 sprintf(actionTypeStr, "%ld %u", actionset->timesteps, actionset->type);
818 if(remaining >= strlen(actionTypeStr) + strlen(ACTION_DELIMITER) + 1)
820 strncat(temp, actionTypeStr, strlen(actionTypeStr));
821 remaining -= strlen(actionTypeStr);
822 strncat(temp, ACTION_DELIMITER, strlen(ACTION_DELIMITER));
823 remaining -= strlen(ACTION_DELIMITER);
824 OICFree(actionTypeStr);
828 OICFree(actionTypeStr);
829 res = OC_STACK_ERROR;
835 res = OC_STACK_ERROR;
839 while (action != NULL)
841 if (remaining < (strlen("uri=") + strlen(action->resourceUri) + 1))
843 res = OC_STACK_ERROR;
847 strcat(temp, "uri=");
848 remaining -= strlen("uri=");
849 strcat(temp, action->resourceUri);
850 remaining -= strlen(action->resourceUri);
854 OCCapability *capas = action->head;
855 while (capas != NULL)
857 if (remaining < (strlen(capas->capability)
858 + 1 + strlen(capas->status)))
860 res = OC_STACK_ERROR;
864 strcat(temp, capas->capability);
865 remaining -= strlen(capas->capability);
868 strcat(temp, capas->status);
869 remaining -= strlen(capas->status);
876 res = OC_STACK_ERROR;
884 action = action->next;
887 if (remaining < strlen(ACTION_DELIMITER))
889 res = OC_STACK_ERROR;
892 strcat(temp, ACTION_DELIMITER);
897 *desc = OICStrdup(temp);
898 VARIFY_POINTER_NULL(*desc, res, exit);
907 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
908 OCClientResponse* clientResponse)
911 (void)clientResponse;
912 OIC_LOG(INFO, TAG, "Entering ActionSetCB");
914 ClientRequestInfo *info = GetClientRequestInfo(clientRequstList, handle);
918 OCEntityHandlerResponse response = { 0 };
920 response.ehResult = OC_EH_OK;
922 if(NULL == clientResponse->payload)
924 OIC_LOG(ERROR, TAG, "Error sending response");
925 return OC_STACK_DELETE_TRANSACTION;
928 // Format the response. Note this requires some info about the request
929 response.requestHandle = info->ehRequest;
930 response.resourceHandle = info->collResource;
931 response.payload = clientResponse->payload;
932 response.numSendVendorSpecificHeaderOptions = 0;
933 memset(response.sendVendorSpecificHeaderOptions, 0,
934 sizeof response.sendVendorSpecificHeaderOptions);
935 memset(response.resourceUri, 0, sizeof response.resourceUri);
936 // Indicate that response is NOT in a persistent buffer
937 response.persistentBufferFlag = 0;
940 if (OCDoResponse(&response) != OC_STACK_OK)
942 OIC_LOG(ERROR, TAG, "Error sending response");
943 return OC_STACK_DELETE_TRANSACTION;
946 RemoveClientRequestInfo(&clientRequstList, info);
950 return OC_STACK_KEEP_TRANSACTION;
953 void ActionSetCD(void *context)
958 OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr,
961 OCStackResult ret = OC_STACK_ERROR;
968 OIC_LOG(INFO, TAG, "Entering BuildActionJSON");
969 json = cJSON_CreateObject();
971 cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
973 OCCapability* pointerCapa = action->head;
976 cJSON_AddStringToObject(body, pointerCapa->capability,
977 pointerCapa->status);
978 pointerCapa = pointerCapa->next;
981 jsonStr = cJSON_PrintUnformatted(json);
983 jsonLen = strlen(jsonStr);
984 if (jsonLen < *remaining)
986 strncat((char*) bufferPtr, jsonStr, jsonLen);
987 *remaining -= jsonLen;
988 bufferPtr += jsonLen;
998 OCPayload* BuildActionCBOR(OCAction* action)
1000 OCRepPayload* payload = OCRepPayloadCreate();
1004 OIC_LOG(INFO, TAG, "Failed to create put payload object");
1008 OCCapability* pointerCapa = action->head;
1011 OCRepPayloadSetPropString(payload, pointerCapa->capability, pointerCapa->status);
1012 pointerCapa = pointerCapa->next;
1015 return (OCPayload*) payload;
1018 unsigned int GetNumOfTargetResource(OCAction *actionset)
1020 int numOfResource = 0;
1022 OCAction *pointerAction = actionset;
1024 while (pointerAction != NULL)
1027 pointerAction = pointerAction->next;
1030 return numOfResource;
1033 OCStackResult SendAction(OCDoHandle *handle, OCServerRequest* requestHandle, const char *targetUri,
1037 OCCallbackData cbData;
1038 cbData.cb = &ActionSetCB;
1039 cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
1042 return OCDoResource(handle, OC_REST_PUT, targetUri, &requestHandle->devAddr,
1043 payload, CT_ADAPTER_IP, OC_NA_QOS, &cbData, NULL, 0);
1046 OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
1047 OCServerRequest* requestHandle)
1049 OCStackResult result = OC_STACK_ERROR;
1051 if( NULL == actionset->head)
1056 OCAction *pointerAction = actionset->head;
1058 while (pointerAction != NULL)
1061 payload = BuildActionCBOR(pointerAction);
1068 ClientRequestInfo *info = (ClientRequestInfo *) OICMalloc(
1069 sizeof(ClientRequestInfo));
1074 return OC_STACK_NO_MEMORY;
1077 memset(info, 0, sizeof(ClientRequestInfo));
1079 info->collResource = resource;
1080 info->ehRequest = requestHandle;
1082 result = SendAction(&info->required, info->ehRequest, pointerAction->resourceUri,
1085 if (result != OC_STACK_OK)
1091 AddClientRequestInfo(&clientRequstList, info);
1093 pointerAction = pointerAction->next;
1099 void DoScheduledGroupAction()
1101 OIC_LOG(INFO, TAG, "DoScheduledGroupAction Entering...");
1102 ScheduledResourceInfo* info = GetScheduledResource(g_scheduleResourceList);
1106 OIC_LOG(INFO, TAG, "Target resource is NULL");
1109 else if (info->resource == NULL)
1111 OIC_LOG(INFO, TAG, "Target resource is NULL");
1114 else if (info->actionset == NULL)
1116 OIC_LOG(INFO, TAG, "Target ActionSet is NULL");
1119 else if (info->ehRequest == NULL)
1121 OIC_LOG(INFO, TAG, "Target ActionSet is NULL");
1125 MUTEX_LOCK(&g_scheduledResourceLock);
1127 DoAction(info->resource, info->actionset, info->ehRequest);
1129 MUTEX_UNLOCK(&g_scheduledResourceLock);
1132 if (info->actionset->type == RECURSIVE)
1134 ScheduledResourceInfo *schedule;
1135 schedule = (ScheduledResourceInfo *) OICMalloc(
1136 sizeof(ScheduledResourceInfo));
1140 OIC_LOG(INFO, TAG, "Building New Call Info.");
1141 memset(schedule, 0, sizeof(ScheduledResourceInfo));
1143 if (info->actionset->timesteps > 0)
1145 MUTEX_LOCK(&g_scheduledResourceLock);
1146 schedule->resource = info->resource;
1147 schedule->actionset = info->actionset;
1148 schedule->ehRequest = info->ehRequest;
1150 schedule->time = registerTimer(info->actionset->timesteps,
1151 &schedule->timer_id,
1152 &DoScheduledGroupAction);
1154 OIC_LOG(INFO, TAG, "Reregistration.");
1155 MUTEX_UNLOCK(&g_scheduledResourceLock);
1156 AddScheduledResource(&g_scheduleResourceList, schedule);
1165 RemoveScheduledResource(&g_scheduleResourceList, info);
1172 OCStackResult BuildCollectionGroupActionCBORResponse(
1173 OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource,
1174 OCEntityHandlerRequest *ehRequest)
1176 OCStackResult stackRet = OC_STACK_ERROR;
1178 OIC_LOG(INFO, TAG, "Group Action is requested.");
1180 char *doWhat = NULL;
1181 char *details = NULL;
1183 stackRet = ExtractKeyValueFromRequest(ehRequest, &doWhat, &details);
1185 if(stackRet != OC_STACK_OK)
1187 OIC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
1191 stackRet = OC_STACK_ERROR;
1193 if (method == OC_REST_PUT)
1195 OIC_LOG(INFO, TAG, "Group Action[PUT].");
1197 if (strcmp(doWhat, ACTIONSET) == 0)
1199 OCActionSet *actionSet = NULL;
1200 stackRet = BuildActionSetFromString(&actionSet, details);
1202 if(stackRet == OC_STACK_OK)
1204 if (actionSet != NULL)
1206 stackRet = AddActionSet(&resource->actionsetHead,
1208 if (stackRet == OC_STACK_ERROR)
1210 if(actionSet != NULL)
1212 DeleteActionSet( &actionSet );
1214 OIC_LOG(INFO, TAG, "Duplicated ActionSet ");
1219 stackRet = OC_STACK_ERROR;
1225 stackRet = OC_STACK_ERROR;
1229 else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
1231 if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
1233 stackRet = OC_STACK_OK;
1237 stackRet = OC_STACK_ERROR;
1241 OCRepPayload* payload = OCRepPayloadCreate();
1245 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
1246 stackRet = OC_STACK_ERROR;
1250 OCEntityHandlerResponse response = { 0 };
1252 if(stackRet == OC_STACK_OK)
1253 response.ehResult = OC_EH_OK;
1255 response.ehResult = OC_EH_ERROR;
1257 // Format the response. Note this requires some info about the request
1258 response.requestHandle = ehRequest->requestHandle;
1259 response.resourceHandle = ehRequest->resource;
1260 response.payload = (OCPayload*) payload;
1261 response.numSendVendorSpecificHeaderOptions = 0;
1262 memset(response.sendVendorSpecificHeaderOptions, 0,
1263 sizeof response.sendVendorSpecificHeaderOptions);
1264 memset(response.resourceUri, 0, sizeof response. resourceUri);
1265 // Indicate that response is NOT in a persistent buffer
1266 response.persistentBufferFlag = 0;
1267 response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
1269 // Send the response
1270 if (OCDoResponse(&response) != OC_STACK_OK)
1272 OIC_LOG(ERROR, TAG, "Error sending response");
1273 stackRet = OC_STACK_ERROR;
1277 else if (method == OC_REST_POST)
1279 OCActionSet *actionset = NULL;
1281 OCRepPayload* payload = OCRepPayloadCreate();
1282 OCRepPayloadSetUri(payload, resource->uri);
1284 if ((strcmp(doWhat, DO_ACTION) == 0)
1285 || (strcmp(doWhat, "DoScheduledAction") == 0))
1287 char *pActionsetName = NULL;
1288 long int delay = -1;
1290 if (strcmp(doWhat, "DoScheduledAction") == 0)
1292 stackRet = ExtractActionSetNameAndDelaytime(details,
1293 &pActionsetName, &delay);
1296 details = pActionsetName;
1300 stackRet = OC_STACK_OK;
1303 if (stackRet == OC_STACK_OK)
1305 if (GetActionSet(details, resource->actionsetHead,
1306 &actionset) != OC_STACK_OK)
1308 OIC_LOG(INFO, TAG, "ERROR");
1309 stackRet = OC_STACK_ERROR;
1312 if (actionset == NULL)
1314 OIC_LOG(INFO, TAG, "Cannot Find ActionSet");
1315 stackRet = OC_STACK_ERROR;
1319 OIC_LOG(INFO, TAG, "Group Action[POST].");
1320 if (actionset->type == NONE)
1322 OIC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
1323 actionset->actionsetName);
1324 unsigned int num = GetNumOfTargetResource(
1327 ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
1328 HandleAggregateResponse;
1329 ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
1332 DoAction(resource, actionset,
1333 (OCServerRequest*) ehRequest->requestHandle);
1334 stackRet = OC_STACK_OK;
1338 OIC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
1339 actionset->actionsetName);
1342 (delay == -1 ? actionset->timesteps : delay);
1344 ScheduledResourceInfo *schedule;
1345 schedule = (ScheduledResourceInfo *) OICMalloc(
1346 sizeof(ScheduledResourceInfo));
1350 OIC_LOG(INFO, TAG, "Building New Call Info.");
1352 sizeof(ScheduledResourceInfo));
1353 MUTEX_LOCK(&g_scheduledResourceLock);
1354 schedule->resource = resource;
1355 schedule->actionset = actionset;
1356 schedule->ehRequest =
1357 (OCServerRequest*) ehRequest->requestHandle;
1358 MUTEX_UNLOCK(&g_scheduledResourceLock);
1361 OIC_LOG_V(INFO, TAG, "delay_time is %ld seconds.",
1362 actionset->timesteps);
1363 MUTEX_LOCK(&g_scheduledResourceLock);
1364 schedule->time = registerTimer(delay,
1365 &schedule->timer_id,
1366 &DoScheduledGroupAction);
1367 MUTEX_UNLOCK(&g_scheduledResourceLock);
1368 AddScheduledResource(&g_scheduleResourceList,
1370 stackRet = OC_STACK_OK;
1374 stackRet = OC_STACK_ERROR;
1381 else if (strcmp(doWhat, "CancelAction") == 0)
1383 ScheduledResourceInfo *info =
1384 GetScheduledResourceByActionSetName(g_scheduleResourceList, details);
1388 MUTEX_LOCK(&g_scheduledResourceLock);
1389 unregisterTimer(info->timer_id);
1390 MUTEX_UNLOCK(&g_scheduledResourceLock);
1392 RemoveScheduledResource(&g_scheduleResourceList, info);
1393 stackRet = OC_STACK_OK;
1397 stackRet = OC_STACK_ERROR;
1401 else if (strcmp(doWhat, GET_ACTIONSET) == 0)
1403 char *plainText = NULL;
1404 OCActionSet *actionset = NULL;
1406 GetActionSet(details, resource->actionsetHead, &actionset);
1407 if (actionset != NULL)
1409 BuildStringFromActionSet(actionset, &plainText);
1411 if (plainText != NULL)
1413 OCRepPayloadSetPropString(payload, ACTIONSET, plainText);
1416 stackRet = OC_STACK_OK;
1422 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
1423 stackRet = OC_STACK_ERROR;
1427 OCEntityHandlerResponse response = { 0 };
1428 if(stackRet == OC_STACK_OK)
1429 response.ehResult = OC_EH_OK;
1431 response.ehResult = OC_EH_ERROR;
1433 // Format the response. Note this requires some info about the request
1434 response.requestHandle = ehRequest->requestHandle;
1435 response.resourceHandle = ehRequest->resource;
1436 response.payload = (OCPayload*) payload;
1437 response.numSendVendorSpecificHeaderOptions = 0;
1438 memset(response.sendVendorSpecificHeaderOptions, 0,
1439 sizeof response.sendVendorSpecificHeaderOptions);
1440 memset(response.resourceUri, 0, sizeof response.resourceUri);
1441 // Indicate that response is NOT in a persistent buffer
1442 response.persistentBufferFlag = 0;
1443 response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
1445 // Send the response
1446 if (OCDoResponse(&response) != OC_STACK_OK)
1448 OIC_LOG(ERROR, TAG, "Error sending response");
1449 stackRet = OC_STACK_ERROR;
1462 OCStackResult InitializeScheduleResourceList()
1464 MUTEX_INITIALIZE(&g_scheduledResourceLock);
1466 g_scheduleResourceList = NULL;
1470 void TerminateScheduleResourceList()
1472 assert(g_scheduleResourceList == NULL);
1474 MUTEX_TERMINATE(&g_scheduledResourceLock);