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
27 #include "ocresource.h"
28 #include "occollection.h"
30 #define TAG PCF("OICGROUP")
32 #define DESC_DELIMITER "\""
33 #define ACTION_DELIMITER "*"
34 #define ATTR_DELIMITER "|"
36 typedef struct aggregatehandleinfo
38 OCServerRequest *ehRequest;
40 OCResource *collResource;
42 struct aggregatehandleinfo *next;
45 // unsigned int nHandleIdx = 0;
46 // ClientRequstInfo g_AggregateResponseHandle[10];
48 ClientRequstInfo *clientRequstList = NULL;
50 void AddClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* add)
52 ClientRequstInfo *tmp = NULL;
70 ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle)
72 ClientRequstInfo *tmp = NULL;
80 // printf("%p :: %p\n", tmp->required, handle);
81 if (tmp->required == handle)
94 void RemoveClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* del)
96 ClientRequstInfo *tmp = NULL;
100 *head = (*head)->next;
105 while (tmp->next && (tmp->next != del))
111 tmp->next = del->next;
118 void AddCapability(OCCapability** head, OCCapability* node)
120 OCCapability *pointer = *head;
127 while (pointer->next != NULL)
129 pointer = pointer->next;
132 pointer->next = node;
136 void AddAction(OCAction** head, OCAction* node)
138 OCAction *pointer = *head;
146 while (pointer->next != NULL)
148 pointer = pointer->next;
151 pointer->next = node;
155 void AddActionSet(OCActionSet **head, OCActionSet* node)
157 OCActionSet *pointer = *head;
165 while (pointer->next != NULL)
167 pointer = pointer->next;
170 pointer->next = node;
174 void DeleteCapability(OCCapability *del)
176 free(del->capability);
177 del->capability = NULL;
182 void DeleteAction(OCAction** action)
184 OCCapability* pointer = (*action)->head;
185 OCCapability* pDel = NULL;
190 pointer = pointer->next;
192 DeleteCapability(pDel);
195 OCFree((*action)->resourceUri);
196 (*action)->resourceUri = NULL;
197 (*action)->next = NULL;
200 void DeleteActionSet(OCActionSet** actionset)
202 OCAction* pointer = (*actionset)->head;
203 OCAction* pDel = NULL;
208 pointer = pointer->next;
214 OCFree((*actionset)->actionsetName);
215 (*actionset)->head = NULL;
218 OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName)
221 if (*resource != NULL)
224 OCActionSet *pointer = NULL;
225 OCActionSet *pDel = NULL;
227 pointer = (*resource)->actionsetHead;
231 return OC_STACK_ERROR;
235 if (strcmp(pointer->actionsetName, actionsetName) == 0)
237 if (pointer->next != NULL)
238 (*resource)->actionsetHead = pointer->next;
240 (*resource)->actionsetHead = NULL;
242 DeleteActionSet(&pointer);
245 else if (pointer->next != NULL)
249 if (pointer->next != NULL)
251 if (strcmp(pointer->next->actionsetName, actionsetName) == 0)
253 pDel = pointer->next;
254 pointer->next = pointer->next->next;
256 DeleteActionSet(&pDel);
267 return OC_STACK_ERROR;
270 OCStackResult DeleteActionSets(OCResource** resource)
272 OCActionSet *pointer = (*resource)->actionsetHead;
273 OCActionSet *pDel = pointer;
278 pointer = pointer->next;
280 DeleteActionSet(&pDel);
284 (*resource)->actionsetHead = NULL;
288 OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSet** actionset)
290 OCActionSet *pointer = head;
294 if (strcmp(pointer->actionsetName, actionName) == 0)
296 *actionset = pointer;
300 pointer = pointer->next;
303 return OC_STACK_ERROR;
307 OCStackResult GetActionSetFromString(OCResource **resource, unsigned char *request, char** method,
308 char **actionsetName)
311 char *iterTokenPtr = NULL;
312 char *iterToken = NULL;
313 char *description = NULL;
314 char *iterDescPtr = NULL;
316 char *attributes = NULL;
317 char *iterAttrbutesPtr = NULL;
320 char *iterAttrPtr = NULL;
322 OCActionSet* actionset = NULL;
323 OCAction* action = NULL;
325 acitonRequest = (char *) OCMalloc(strlen((char *) request) + 1);
326 strncpy(acitonRequest, (char *) request, strlen((char *) request) + 1);
328 //printf("\t%s\n", acitonRequest);
329 if (acitonRequest != NULL)
331 iterToken = (char *) strtok_r(acitonRequest, DESC_DELIMITER, &iterTokenPtr);
333 while (iterToken != NULL)
335 if (strcmp(iterToken, "ActionSet") == 0)
336 { // if iterToken is ActionSet, will be created and added a new action set.
338 *method = (char *) OCMalloc(strlen(iterToken) + 1);
339 strncpy(*method, iterToken, strlen(iterToken) + 1);
341 //GetActionName(iterToken, &actionsetName);
342 // printf("%s\n", iterToken, &iterTokenPtr);
343 iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'.
344 // printf("%s\n", iterToken);
345 iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description.
346 // printf("%s\n", iterToken);
348 // printf("DESC :: %s\n", iterToken);
349 description = (char *) OCMalloc(strlen(iterToken) + 1);
350 strncpy(description, iterToken, strlen(iterToken) + 1);
351 // printf("DESC Copied :: %s\n", description);
353 // Find the action name from description.
355 iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr);
356 //while(iterToken != NULL)
357 if (iterToken != NULL)
359 if (*actionsetName != NULL)
361 // printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken);
362 return OC_STACK_ERROR; // ERROR OCCURED.
367 // printf("ACTION SET NAME :: %s\n", iterToken);
368 *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
370 strncpy(*actionsetName, iterToken, strlen(iterToken) + 1);
371 // printf("ACTION SET NAME :: %s\n", *actionsetName);
375 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
379 return OC_STACK_ERROR;
381 } // end Action Set Name.
383 // New ActionSet Add to OCResource's ActionSet list.
384 // 1. Allocate a new pointer for actionset.
385 actionset = (OCActionSet*) OCMalloc(sizeof(OCActionSet));
386 // 2. Initiate actionset.
387 memset(actionset, 0, sizeof(OCActionSet));
388 actionset->actionsetName = (char *) OCMalloc(strlen(*actionsetName) + 1);
389 strncpy(actionset->actionsetName, *actionsetName, strlen(*actionsetName) + 1);
390 // printf("ACTION SET NAME :: %s\n", actionset->actionsetName);
392 while (iterToken != NULL)
394 action = (OCAction *) OCMalloc(sizeof(OCAction));
395 memset(action, 0, sizeof(OCAction));
397 // printf("ATTR Copied :: %s\n", iterToken);
398 attributes = (char *) OCMalloc(strlen(iterToken) + 1);
399 strncpy(attributes, iterToken, strlen(iterToken) + 1);
400 // printf("ATTR Copied :: %s\n", attributes);
402 iterToken = (char *) strtok_r(attributes, ATTR_DELIMITER, &iterAttrbutesPtr);
403 while (iterToken != NULL)
405 attr = (char *) OCMalloc(strlen(iterToken) + 1);
406 strncpy(attr, iterToken, strlen(iterToken) + 1);
408 iterToken = (char *) strtok_r(attr, "=", &iterAttrPtr);
409 while (iterToken != NULL)
411 // Find the URI from description.
412 if (strcmp(iterToken, "uri") == 0)
414 iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
415 //printf("uri :: %s\n", iterToken);
416 action->resourceUri = (char *) OCMalloc(strlen(iterToken) + 1);
417 strncpy(action->resourceUri, iterToken, strlen(iterToken) + 1);
421 OCCapability* capa = (OCCapability*) OCMalloc(sizeof(OCCapability));
422 memset(capa, 0, sizeof(OCCapability));
423 //printf("%s :: ", iterToken);
424 capa->capability = (char *) OCMalloc(strlen(iterToken) + 1);
425 strncpy(capa->capability, iterToken, strlen(iterToken) + 1);
426 iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
427 //printf("%s\n", iterToken);
428 capa->status = (char *) OCMalloc(strlen(iterToken) + 1);
429 strncpy(capa->status, iterToken, strlen(iterToken) + 1);
431 AddCapability(&action->head, capa);
434 iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
437 iterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &iterAttrbutesPtr);
440 AddAction(&actionset->head, action);
442 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
445 // 3. Add the pointer OCResource's ActionSet list.
446 AddActionSet(&(*resource)->actionsetHead, actionset);
449 else if (strcmp(iterToken, "DoAction") == 0 || strcmp(iterToken, "DelActionSet") == 0
450 || strcmp(iterToken, "GetActionSet") == 0)
452 *method = (char *) OCMalloc(strlen(iterToken) + 1);
453 strncpy(*method, iterToken, strlen(iterToken) + 1);
455 iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'.
456 // printf("%s\n", iterToken);
457 iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description.
458 // printf("%s\n", iterToken);
460 description = (char *) OCMalloc(strlen(iterToken) + 1);
461 strncpy(description, iterToken, strlen(iterToken) + 1);
463 // Find the action name from description.
465 iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr);
466 if (iterToken != NULL)
468 if (*actionsetName != NULL)
470 // printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken);
471 return OC_STACK_ERROR; // ERROR OCCURED.
476 // printf("ACTION SET NAME :: %s\n", iterToken);
477 *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
479 strncpy(*actionsetName, iterToken, strlen(iterToken) + 1);
480 // printf("ACTION SET NAME :: %s\n", *actionsetName);
483 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
488 return OC_STACK_ERROR;
490 } // end Action Set Name.
494 iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr);
498 return OC_STACK_ERROR;
501 OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc)
505 int remaining = 1023;
507 // OCActionSet *as = resource->actionsetHead;
510 printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName);
511 OCAction *action = actionset->head;
513 if (remaining >= strlen(actionset->actionsetName) + 1)
515 strcat(temp, actionset->actionsetName);
516 remaining -= strlen(actionset->actionsetName);
522 return OC_STACK_ERROR;
525 while (action != NULL)
527 printf("\tURI :: %s\n", action->resourceUri);
528 strcat(temp, "uri=");
529 remaining -= strlen("uri=");
530 strcat(temp, action->resourceUri);
531 remaining -= strlen(action->resourceUri);
535 OCCapability *capas = action->head;
536 while (capas != NULL)
538 printf("\t\t%s = %s\n", capas->capability, capas->status);
539 strcat(temp, capas->capability);
540 remaining -= strlen(capas->capability);
543 strcat(temp, capas->status);
544 remaining -= strlen(capas->capability);
553 action = action->next;
563 *desc = (char *) OCMalloc(1024 - remaining);
565 // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining);
570 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
571 OCClientResponse* clientResponse)
573 printf("\n\n\tcallback is called\n\n");
575 ClientRequstInfo *info = GetClientRequestInfo(clientRequstList, handle);
581 unsigned char *responseJson;
582 responseJson = (unsigned char *) OCMalloc(
583 (unsigned int) (strlen((char *) clientResponse->resJSONPayload) + 1));
585 // We need the body of response.
586 // Copy the body from the response
587 strcpy((char *) responseJson, ((char *) clientResponse->resJSONPayload
588 + OC_JSON_PREFIX_LEN));
589 idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
590 // And insert NULL at the end of body.
591 (responseJson[idx]) = 0;
593 OCEntityHandlerResponse response = { 0 };
594 response.ehResult = OC_EH_OK;
595 response.payload = responseJson;
596 response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
597 response.persistentBufferFlag = 0;
598 response.requestHandle = (OCRequestHandle) info->ehRequest;
599 response.resourceHandle = (OCResourceHandle) info->collResource;
601 OCDoResponse(&response);
603 RemoveClientRequestInfo(&clientRequstList, info);
604 OCFree(responseJson);
607 // g_AggregateResponseHandle
609 return OC_STACK_KEEP_TRANSACTION;
612 void ActionSetCD(void *context)
614 // printf("\n\t\tCD is called\n");
619 OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16_t *remaining)
621 OCStackResult ret = OC_STACK_ERROR;
628 OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
629 json = cJSON_CreateObject();
631 cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
633 OCCapability* pointerCapa = action->head;
636 cJSON_AddStringToObject(body, pointerCapa->capability, pointerCapa->status);
637 pointerCapa = pointerCapa->next;
640 jsonStr = cJSON_PrintUnformatted(json);
642 jsonLen = strlen(jsonStr);
643 if (jsonLen < *remaining)
645 strcat((char*) bufferPtr, jsonStr);
646 *remaining -= jsonLen;
647 bufferPtr += jsonLen;
657 unsigned int GetNumOfTargetResource(OCAction *actionset)
659 int numOfREsource = 0;
661 OCAction *pointerAction = actionset;
663 while (pointerAction != NULL)
666 pointerAction = pointerAction->next;
669 return numOfREsource;
672 OCStackResult SendAction(OCDoHandle *handle, const char *targetUri, const unsigned char *action)
674 OCCallbackData cbdata =
676 cbdata.cb = &ActionSetCB;
677 cbdata.cd = &ActionSetCD;
678 cbdata.context = (void *) 0x99;
680 return OCDoResource(handle, OC_REST_PUT, targetUri,
681 //temp->rsrcType->resourcetypename,
682 NULL, (char *) action, OC_NA_QOS, &cbdata, NULL, 0);
685 OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
686 OCResource *resource, OCEntityHandlerRequest *ehRequest)
688 OCStackResult stackRet = OC_STACK_ERROR;
690 OC_LOG(INFO, TAG, PCF("Group Action is requested."));
691 // if (stackRet == OC_STACK_OK)
695 char *actionName = NULL;
697 size_t bufferLength = 0;
698 unsigned char buffer[MAX_RESPONSE_LENGTH] =
700 unsigned char *bufferPtr = NULL;
704 OCResource * collResource = (OCResource *) ehRequest->resource;
711 if (method == OC_REST_PUT)
713 json = cJSON_CreateObject();
714 cJSON_AddStringToObject(json, "href", resource->uri);
715 cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
717 OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
719 unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload;
720 GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName);
722 if (strcmp(doWhat, "DelActionSet") == 0)
724 if (FindAndDeleteActionSet(&resource, actionName) == OC_STACK_OK)
726 stackRet = OC_STACK_OK;
730 stackRet = OC_STACK_ERROR;
734 jsonResponse = cJSON_Print(json);
737 strcat((char *) bufferPtr, jsonResponse);
739 bufferLength = strlen((const char *) buffer);
740 if (bufferLength > 0)
742 OCEntityHandlerResponse response =
744 response.ehResult = OC_EH_OK;
745 response.payload = buffer;
746 response.payloadSize = bufferLength + 1;
747 response.persistentBufferFlag = 0;
748 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
749 response.resourceHandle = (OCResourceHandle) collResource;
750 stackRet = OCDoResponse(&response);
753 stackRet = OC_STACK_OK;
756 if (method == OC_REST_POST)
758 OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
760 OCActionSet *actionset = NULL;
761 unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload;
763 GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName);
765 json = cJSON_CreateObject();
766 cJSON_AddStringToObject(json, "href", resource->uri);
768 if (strcmp(doWhat, "DoAction") == 0)
770 if (GetActionSet(actionName, resource->actionsetHead, &actionset) != OC_STACK_OK)
772 OC_LOG(INFO, TAG, PCF("ERROR"));
773 stackRet = OC_STACK_ERROR;
776 if (actionset == NULL)
778 OC_LOG(INFO, TAG, PCF("ERROR"));
779 stackRet = OC_STACK_ERROR;
784 OCAction *pointerAction = actionset->head;
786 unsigned int num = GetNumOfTargetResource(pointerAction);
788 ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
789 HandleAggregateResponse;
790 ((OCServerRequest *) ehRequest->requestHandle)->numResponses = num + 1;
792 // printf("ActionSet Name :: %s\n", actionset->actionsetName);
793 while (pointerAction != NULL)
795 unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
796 unsigned char* actionDescPtr = actionDesc;
797 uint16_t remaining = MAX_RESPONSE_LENGTH;
799 strcpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX);
800 BuildActionJSON(pointerAction, actionDescPtr, &remaining);
801 strcat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX);
803 ClientRequstInfo *info = (ClientRequstInfo *) OCMalloc(
804 sizeof(ClientRequstInfo));
805 memset(info, 0, sizeof(ClientRequstInfo));
807 info->collResource = resource;
808 info->ehRequest = (OCServerRequest *) ehRequest->requestHandle;
810 SendAction(&info->required, pointerAction->resourceUri, actionDescPtr);
812 AddClientRequestInfo(&clientRequstList, info);
815 pointerAction = pointerAction->next;
819 stackRet = OC_STACK_OK;
822 else if (strcmp(doWhat, "GetActionSet") == 0)
824 char *plainText = NULL;
825 OCActionSet *actionset = NULL;
827 cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
828 GetActionSet(actionName, resource->actionsetHead, &actionset);
829 if (actionset != NULL)
831 GetStringFromActionSet(actionset, &plainText);
833 if (plainText != NULL)
835 cJSON_AddStringToObject(format, "ActionSet", plainText);
838 stackRet = OC_STACK_OK;
842 jsonResponse = cJSON_Print(json);
845 strcat((char *) bufferPtr, jsonResponse);
847 bufferLength = strlen((const char *) buffer);
848 if (bufferLength > 0)
850 OCEntityHandlerResponse response =
852 response.ehResult = OC_EH_OK;
853 response.payload = buffer;
854 response.payloadSize = bufferLength + 1;
855 response.persistentBufferFlag = 0;
856 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
857 response.resourceHandle = (OCResourceHandle) collResource;
858 stackRet = OCDoResponse(&response);