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"
31 #define TAG PCF("OICGROUP")
33 #define DESC_DELIMITER "\""
34 #define ACTION_DELIMITER "*"
35 #define ATTR_DELIMITER "|"
36 #define ATTR_ASSIGN "="
38 typedef struct aggregatehandleinfo
40 OCServerRequest *ehRequest;
42 OCResource *collResource;
44 struct aggregatehandleinfo *next;
47 // unsigned int nHandleIdx = 0;
48 // ClientRequstInfo g_AggregateResponseHandle[10];
50 ClientRequstInfo *clientRequstList = NULL;
52 void AddClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* add)
54 ClientRequstInfo *tmp = NULL;
72 ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle)
74 ClientRequstInfo *tmp = NULL;
82 // printf("%p :: %p\n", tmp->required, handle);
83 if (tmp->required == handle)
96 void RemoveClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* del)
98 ClientRequstInfo *tmp = NULL;
102 *head = (*head)->next;
107 while (tmp->next && (tmp->next != del))
113 tmp->next = del->next;
120 void AddCapability(OCCapability** head, OCCapability* node)
122 OCCapability *pointer = *head;
129 while (pointer->next != NULL)
131 pointer = pointer->next;
134 pointer->next = node;
138 void AddAction(OCAction** head, OCAction* node)
140 OCAction *pointer = *head;
148 while (pointer->next != NULL)
150 pointer = pointer->next;
153 pointer->next = node;
157 void AddActionSet(OCActionSet **head, OCActionSet* node)
159 OCActionSet *pointer = *head;
167 while (pointer->next != NULL)
169 pointer = pointer->next;
172 pointer->next = node;
176 void DeleteCapability(OCCapability *del)
178 free(del->capability);
179 del->capability = NULL;
184 void DeleteAction(OCAction** action)
186 OCCapability* pointer = (*action)->head;
187 OCCapability* pDel = NULL;
192 pointer = pointer->next;
194 DeleteCapability(pDel);
197 OCFree((*action)->resourceUri);
198 (*action)->resourceUri = NULL;
199 (*action)->next = NULL;
202 void DeleteActionSet(OCActionSet** actionset)
204 OCAction* pointer = (*actionset)->head;
205 OCAction* pDel = NULL;
210 pointer = pointer->next;
216 OCFree((*actionset)->actionsetName);
217 (*actionset)->head = NULL;
220 OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName)
222 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;
241 DeleteActionSet(&pointer);
243 else if (pointer->next != NULL)
247 if (pointer->next != NULL)
249 if (strcmp(pointer->next->actionsetName, actionsetName) == 0)
251 pDel = pointer->next;
252 pointer->next = pointer->next->next;
254 DeleteActionSet(&pDel);
257 pointer = pointer->next;
265 return OC_STACK_ERROR;
268 OCStackResult DeleteActionSets(OCResource** resource)
270 OCActionSet *pointer = (*resource)->actionsetHead;
271 OCActionSet *pDel = pointer;
276 pointer = pointer->next;
278 DeleteActionSet(&pDel);
282 (*resource)->actionsetHead = NULL;
286 OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSet** actionset)
288 OCActionSet *pointer = head;
292 if (strcmp(pointer->actionsetName, actionName) == 0)
294 *actionset = pointer;
298 pointer = pointer->next;
301 return OC_STACK_ERROR;
306 #define OIC_ACTION_PREFIX "{\"oc\":[{\"rep\":{"
307 #define VARIFY_POINTER_NULL(pointer, result, toExit) \
308 if(pointer == NULL) \
310 result = OC_STACK_NO_MEMORY;\
313 #define VARIFY_PARAM_NULL(pointer, result, toExit) \
316 result = OC_STACK_INVALID_PARAM;\
320 OCStackResult ExtractKeyValueFromRequest(char *request, char **key, char **value)
322 OCStackResult result = OC_STACK_OK;
325 char* pRequest = (char *)request + strlen(OIC_ACTION_PREFIX);
326 char* iterToken, *iterTokenPtr;
328 iterToken = (char *) strtok_r(pRequest, ":", &iterTokenPtr);
329 length = strlen(iterToken) + 1;
331 *key = (char *)OCMalloc(length);
332 VARIFY_POINTER_NULL(*key, result, exit);
334 strncpy(*key, iterToken + 1, length);
335 ((*key)[ (( length - 1 ) - 2) ]) = '\0';
337 iterToken = (char *) strtok_r(NULL, "}", &iterTokenPtr);
338 length = strlen(iterToken) + 1;
340 *value = (char *)OCMalloc(length);
341 VARIFY_POINTER_NULL(*key, result, exit);
343 strncpy(*value, iterToken + 1, length);
344 ((*value)[ (( length - 1 ) - 2) ]) = '\0';
346 if(result != OC_STACK_OK)
357 OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
359 OCStackResult result = OC_STACK_OK;
361 char *iterToken = NULL, *iterTokenPtr = NULL;
362 char *descIterToken = NULL, *descIterTokenPtr = NULL;
363 char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
364 char *desc = NULL, *attr = NULL;
365 char *key = NULL, *value = NULL;
367 OCAction *action = NULL;
368 OCCapability *capa = NULL;
370 OC_LOG(INFO, TAG, PCF("Build ActionSet Instance."));
372 *set = (OCActionSet*) OCMalloc(sizeof(OCActionSet));
373 VARIFY_POINTER_NULL(*set, result, exit)
375 iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
377 memset(*set, 0, sizeof(OCActionSet));
378 (*set)->actionsetName = (char *)OCMalloc(sizeof(OCActionSet));
379 VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
380 VARIFY_PARAM_NULL(iterToken, result, exit)
381 strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
383 OC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
385 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
388 desc = (char *)OCMalloc(strlen(iterToken) + 1);
389 strncpy(desc, iterToken, strlen(iterToken) + 1);
390 descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER, &descIterTokenPtr);
393 attr = (char *)OCMalloc(strlen(descIterToken) + 1);
394 strncpy(attr, descIterToken, strlen(descIterToken) + 1);
396 attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN, &attrIterTokenPtr);
397 key = (char *)OCMalloc(strlen(attrIterToken) + 1);
398 VARIFY_POINTER_NULL(key, result, exit)
400 VARIFY_PARAM_NULL(attrIterToken, result, exit)
401 strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
402 attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN, &attrIterTokenPtr);
404 value = (char *)OCMalloc(strlen(attrIterToken) + 1);
405 VARIFY_POINTER_NULL(value, result, exit)
406 VARIFY_PARAM_NULL(attrIterToken, result, exit)
407 strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
409 if(strcmp(key, "uri") == 0)
411 OC_LOG(INFO, TAG, PCF("Build OCAction Instance."));
413 action = (OCAction*)OCMalloc(sizeof(OCAction));
414 VARIFY_POINTER_NULL(action, result, exit)
415 memset(action, 0, sizeof(OCAction));
416 action->resourceUri = (char *)OCMalloc(strlen(value) + 1);
417 VARIFY_POINTER_NULL(action->resourceUri, result, exit)
418 VARIFY_PARAM_NULL(value, result, exit)
419 strncpy(action->resourceUri, value, strlen(value) + 1);
423 if( (key != NULL) && (value != NULL))
425 OC_LOG(INFO, TAG, PCF("Build OCCapability Instance."));
426 capa = (OCCapability*)OCMalloc(sizeof(OCCapability));
427 VARIFY_POINTER_NULL(capa, result, exit)
428 memset(capa, 0, sizeof(OCCapability));
429 capa->capability = (char *)OCMalloc(strlen(key) + 1);
430 capa->status = (char *)OCMalloc(strlen(value) + 1);
432 strncpy(capa->capability, key, strlen(key) + 1);
433 strncpy(capa->status, value, strlen(value) + 1);
435 VARIFY_POINTER_NULL(action, result, exit)
437 AddCapability(&action->head, capa);
445 descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &descIterTokenPtr);
448 AddAction(&(*set)->head, action);
449 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
464 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
466 char temp[1024] = { 0 };
467 int remaining = 1023;
469 // OCActionSet *as = resource->actionsetHead;
472 // printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName);
473 OCAction *action = actionset->head;
475 if (remaining >= strlen(actionset->actionsetName) + 1)
477 strcat(temp, actionset->actionsetName);
478 remaining -= strlen(actionset->actionsetName);
484 return OC_STACK_ERROR;
487 while (action != NULL)
489 printf("\tURI :: %s\n", action->resourceUri);
490 strcat(temp, "uri=");
491 remaining -= strlen("uri=");
492 strcat(temp, action->resourceUri);
493 remaining -= strlen(action->resourceUri);
497 OCCapability *capas = action->head;
498 while (capas != NULL)
500 printf("\t\t%s = %s\n", capas->capability, capas->status);
501 strcat(temp, capas->capability);
502 remaining -= strlen(capas->capability);
505 strcat(temp, capas->status);
506 remaining -= strlen(capas->capability);
515 action = action->next;
525 *desc = (char *) OCMalloc(1024 - remaining);
527 // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining);
532 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
533 OCClientResponse* clientResponse)
535 printf("\n\n\tcallback is called\n\n");
537 ClientRequstInfo *info = GetClientRequestInfo(clientRequstList, handle);
543 unsigned char *responseJson;
544 responseJson = (unsigned char *) OCMalloc(
545 (unsigned int) (strlen((char *) clientResponse->resJSONPayload) + 1));
547 // We need the body of response.
548 // Copy the body from the response
549 strcpy((char *) responseJson, ((char *) clientResponse->resJSONPayload
550 + OC_JSON_PREFIX_LEN));
551 idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
552 // And insert NULL at the end of body.
553 (responseJson[idx]) = 0;
555 OCEntityHandlerResponse response = { 0 };
556 response.ehResult = OC_EH_OK;
557 response.payload = responseJson;
558 response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
559 response.persistentBufferFlag = 0;
560 response.requestHandle = (OCRequestHandle) info->ehRequest;
561 response.resourceHandle = (OCResourceHandle) info->collResource;
563 OCDoResponse(&response);
565 RemoveClientRequestInfo(&clientRequstList, info);
566 OCFree(responseJson);
569 // g_AggregateResponseHandle
571 return OC_STACK_KEEP_TRANSACTION;
574 void ActionSetCD(void *context)
576 // printf("\n\t\tCD is called\n");
581 OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16_t *remaining)
583 OCStackResult ret = OC_STACK_ERROR;
590 OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
591 json = cJSON_CreateObject();
593 cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
595 OCCapability* pointerCapa = action->head;
598 cJSON_AddStringToObject(body, pointerCapa->capability, pointerCapa->status);
599 pointerCapa = pointerCapa->next;
602 jsonStr = cJSON_PrintUnformatted(json);
604 jsonLen = strlen(jsonStr);
605 if (jsonLen < *remaining)
607 strcat((char*) bufferPtr, jsonStr);
608 *remaining -= jsonLen;
609 bufferPtr += jsonLen;
619 unsigned int GetNumOfTargetResource(OCAction *actionset)
621 int numOfREsource = 0;
623 OCAction *pointerAction = actionset;
625 while (pointerAction != NULL)
628 pointerAction = pointerAction->next;
631 return numOfREsource;
634 OCStackResult SendAction(OCDoHandle *handle, const char *targetUri, const unsigned char *action)
636 OCCallbackData cbdata = { 0 };
637 cbdata.cb = &ActionSetCB;
638 cbdata.cd = &ActionSetCD;
639 cbdata.context = (void *) 0x99;
641 return OCDoResource(handle, OC_REST_PUT, targetUri,
642 //temp->rsrcType->resourcetypename,
643 NULL, (char *) action, OC_WIFI, OC_NA_QOS, &cbdata, NULL, 0);
646 OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
647 OCResource *resource, OCEntityHandlerRequest *ehRequest)
649 OCStackResult stackRet = OC_STACK_ERROR;
651 OC_LOG(INFO, TAG, PCF("Group Action is requested."));
652 // if (stackRet == OC_STACK_OK)
655 char *details = NULL;
657 size_t bufferLength = 0;
658 unsigned char buffer[MAX_RESPONSE_LENGTH] = { 0 };
659 unsigned char *bufferPtr = NULL;
663 OCResource * collResource = (OCResource *) ehRequest->resource;
667 ExtractKeyValueFromRequest((char *)ehRequest->reqJSONPayload, &doWhat, &details);
673 if (method == OC_REST_PUT)
675 json = cJSON_CreateObject();
676 cJSON_AddStringToObject(json, "href", resource->uri);
677 cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
679 OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
681 if(strcmp(doWhat, "ActionSet") == 0)
683 OCActionSet *actionSet;
684 BuildActionSetFromString(&actionSet, details);
686 if(actionSet != NULL)
688 AddActionSet(&resource->actionsetHead, actionSet);
689 stackRet = OC_STACK_OK;
693 stackRet = OC_STACK_ERROR;
697 else if (strcmp(doWhat, "DelActionSet") == 0)
699 if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
701 stackRet = OC_STACK_OK;
705 stackRet = OC_STACK_ERROR;
709 jsonResponse = cJSON_Print(json);
712 strcat((char *) bufferPtr, jsonResponse);
714 bufferLength = strlen((const char *) buffer);
715 if (bufferLength > 0)
717 OCEntityHandlerResponse response = { 0 };
718 response.ehResult = OC_EH_OK;
719 response.payload = buffer;
720 response.payloadSize = bufferLength + 1;
721 response.persistentBufferFlag = 0;
722 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
723 response.resourceHandle = (OCResourceHandle) collResource;
724 stackRet = OCDoResponse(&response);
727 stackRet = OC_STACK_OK;
730 if (method == OC_REST_POST)
732 OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
734 OCActionSet *actionset = NULL;
736 json = cJSON_CreateObject();
737 cJSON_AddStringToObject(json, "href", resource->uri);
739 if (strcmp(doWhat, "DoAction") == 0)
741 if (GetActionSet(details, resource->actionsetHead, &actionset) != OC_STACK_OK)
743 OC_LOG(INFO, TAG, PCF("ERROR"));
744 stackRet = OC_STACK_ERROR;
747 if (actionset == NULL)
749 OC_LOG(INFO, TAG, PCF("ERROR"));
750 stackRet = OC_STACK_ERROR;
755 OCAction *pointerAction = actionset->head;
757 unsigned int num = GetNumOfTargetResource(pointerAction);
759 ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
760 HandleAggregateResponse;
761 ((OCServerRequest *) ehRequest->requestHandle)->numResponses = num + 1;
763 while (pointerAction != NULL)
765 unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
766 unsigned char* actionDescPtr = actionDesc;
767 uint16_t remaining = MAX_RESPONSE_LENGTH;
769 strncpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX,
770 strlen((const char *) OC_JSON_PREFIX) + 1);
771 BuildActionJSON(pointerAction, actionDescPtr, &remaining);
772 strncat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX,
773 strlen((const char *) OC_JSON_SUFFIX));
775 ClientRequstInfo *info = (ClientRequstInfo *) OCMalloc(
776 sizeof(ClientRequstInfo));
777 memset(info, 0, sizeof(ClientRequstInfo));
779 info->collResource = resource;
780 info->ehRequest = (OCServerRequest *) ehRequest->requestHandle;
782 SendAction(&info->required, pointerAction->resourceUri, actionDescPtr);
784 AddClientRequestInfo(&clientRequstList, info);
786 pointerAction = pointerAction->next;
790 stackRet = OC_STACK_OK;
793 else if (strcmp(doWhat, "GetActionSet") == 0)
795 char *plainText = NULL;
796 OCActionSet *actionset = NULL;
798 cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
799 GetActionSet(details, resource->actionsetHead, &actionset);
800 if (actionset != NULL)
802 BuildStringFromActionSet(actionset, &plainText);
804 if (plainText != NULL)
806 cJSON_AddStringToObject(format, "ActionSet", plainText);
809 stackRet = OC_STACK_OK;
813 jsonResponse = cJSON_Print(json);
816 strcat((char *) bufferPtr, jsonResponse);
818 bufferLength = strlen((const char *) buffer);
819 if (bufferLength > 0)
821 OCEntityHandlerResponse response =
823 response.ehResult = OC_EH_OK;
824 response.payload = buffer;
825 response.payloadSize = bufferLength + 1;
826 response.persistentBufferFlag = 0;
827 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
828 response.resourceHandle = (OCResourceHandle) collResource;
829 stackRet = OCDoResponse(&response);