OCStackResult AddObserver (const char *resUri, const char *query, OCObservationId obsId, OCCoAPToken *token, OCDevAddr *addr, OCResource *resHandle, OCQualityOfService qos) { ResourceObserver *obsNode = NULL; obsNode = (ResourceObserver *) OCCalloc(1, sizeof(ResourceObserver)); if (obsNode) { obsNode->observeId = obsId; obsNode->resUri = (unsigned char *)OCMalloc(strlen(resUri)+1); VERIFY_NON_NULL (obsNode->resUri); memcpy (obsNode->resUri, resUri, strlen(resUri)+1); obsNode->qos = qos; if(query) { obsNode->query = (unsigned char *)OCMalloc(strlen(query)+1); VERIFY_NON_NULL (obsNode->query); memcpy (obsNode->query, query, strlen(query)+1); } obsNode->token.tokenLength = token->tokenLength; memcpy (obsNode->token.token, token->token, token->tokenLength); obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr)); VERIFY_NON_NULL (obsNode->addr); memcpy (obsNode->addr, addr, sizeof(OCDevAddr)); obsNode->resource = resHandle; LL_APPEND (serverObsList, obsNode); return OC_STACK_OK; } exit: if (obsNode) { OCFree(obsNode->resUri); OCFree(obsNode->query); OCFree(obsNode->addr); OCFree(obsNode); } return OC_STACK_NO_MEMORY; }
OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest) { OC_LOG(INFO, TAG, "Copying received request for slow response"); OCEntityHandlerRequest *request = (OCEntityHandlerRequest *)OCMalloc(sizeof(OCEntityHandlerRequest)); if (request) { // Do shallow copy memcpy(request, entityHandlerRequest, sizeof(OCEntityHandlerRequest)); // Do deep copy of query request->query = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->query) + 1); if (request->query) { strcpy((char *)request->query, (const char *)entityHandlerRequest->query); // Copy the request payload request->reqJSONPayload = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->reqJSONPayload) + 1); if (request->reqJSONPayload) { strcpy((char *)request->reqJSONPayload, (const char *)entityHandlerRequest->reqJSONPayload); // Ignore vendor specific header options for example request->numRcvdVendorSpecificHeaderOptions = 0; request->rcvdVendorSpecificHeaderOptions = NULL; } else { OCFree(request->query); OCFree(request); request = NULL; } } else { OCFree(request); request = NULL; } } if (request) { OC_LOG(INFO, TAG, "Copied client request"); } else { OC_LOG(ERROR, TAG, "Error copying client request"); } return request; }
OCStackResult ExtractKeyValueFromRequest(char *request, char **key, char **value) { OCStackResult result = OC_STACK_OK; size_t length = 0; char* pRequest = (char *)request + strlen(OIC_ACTION_PREFIX); char* iterToken, *iterTokenPtr; iterToken = (char *) strtok_r(pRequest, ":", &iterTokenPtr); length = strlen(iterToken) + 1; *key = (char *)OCMalloc(length); VARIFY_POINTER_NULL(*key, result, exit); strncpy(*key, iterToken + 1, length); ((*key)[ (( length - 1 ) - 2) ]) = '\0'; iterToken = (char *) strtok_r(NULL, "}", &iterTokenPtr); length = strlen(iterToken) + 1; *value = (char *)OCMalloc(length); VARIFY_POINTER_NULL(*key, result, exit); strncpy(*value, iterToken + 1, length); ((*value)[ (( length - 1 ) - 2) ]) = '\0'; exit: if(result != OC_STACK_OK) { OCFree(*key); OCFree(*value); *key = NULL; *value = NULL; } return result; }
void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo) { // CA layer interface publishes security data structures ONLY if // stack is compiled in SECURED mode CADtlsPskCredsBlob_t * caBlob = NULL; if(secConfigData && credInfo) { unsigned int i = 0; OCSecBlob * osb = (OCSecBlob*)secConfigData->blob; for ( ;(i<secConfigData->numBlob) && osb; i++) { if (osb->type == OC_BLOB_TYPE_PSK) { caBlob = (CADtlsPskCredsBlob_t *)OCCalloc(sizeof(CADtlsPskCredsBlob_t), 1); if (caBlob) { OCDtlsPskCredsBlob * ocBlob = (OCDtlsPskCredsBlob *)osb->val; memcpy(caBlob->identity, ocBlob->identity, sizeof(caBlob->identity)); caBlob->num = ocBlob->num; caBlob->creds = (OCDtlsPskCreds*) OCMalloc(caBlob->num * sizeof(OCDtlsPskCreds)); if (caBlob->creds) { memcpy(caBlob->creds, ocBlob->creds, caBlob->num * sizeof(OCDtlsPskCreds)); *credInfo = caBlob; // We copied the credential blob in the CA data structure. // Let's get out of here. return; } } break; } osb = config_data_next_blob(osb); } } // Clear memory if any memory allocation failed above if(caBlob) { OCFree(caBlob->creds); OCFree(caBlob); } }
OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle, OCClientResponse* clientResponse) { printf("\n\n\tcallback is called\n\n"); ClientRequstInfo *info = GetClientRequestInfo(clientRequstList, handle); if (info) { int idx; unsigned char *responseJson; responseJson = (unsigned char *) OCMalloc( (unsigned int) (strlen((char *) clientResponse->resJSONPayload) + 1)); // We need the body of response. // Copy the body from the response strcpy((char *) responseJson, ((char *) clientResponse->resJSONPayload + OC_JSON_PREFIX_LEN)); idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN; // And insert NULL at the end of body. (responseJson[idx]) = 0; OCEntityHandlerResponse response = { 0 }; response.ehResult = OC_EH_OK; response.payload = responseJson; response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1; response.persistentBufferFlag = 0; response.requestHandle = (OCRequestHandle) info->ehRequest; response.resourceHandle = (OCResourceHandle) info->collResource; OCDoResponse(&response); RemoveClientRequestInfo(&clientRequstList, info); OCFree(responseJson); } // g_AggregateResponseHandle return OC_STACK_KEEP_TRANSACTION; }
/** * Provides the Security configuration data to OC stack. * * @param cfgdata * binary blob containing credentials and other config data * @param len * length of binary blob * * @retval OC_STACK_OK for Success, otherwise some error value */ OCStackResult OCSecSetConfigData(const OCSecConfigData *cfgData, size_t len) { // Validate the data inside blob before consuming if (cfgData && ValidateSecConfigData(cfgData, len) == OC_STACK_OK) { // Remove existing blob DeinitOCSecurityInfo(); // Allocate storage for new blob secConfigData = (OCSecConfigData*)OCMalloc(len); if (secConfigData) { memcpy(secConfigData, cfgData, len); secConfigDataLen = len; return OC_STACK_OK; } return OC_STACK_NO_MEMORY; } return OC_STACK_INVALID_PARAM; }
//This function is called back by libcoap when a response is received static void HandleCoAPResponses(struct coap_context_t *ctx, const coap_queue_t * rcvdResponse) { OCResponse * response = NULL; OCCoAPToken rcvdToken; OCClientResponse clientResponse = {0}; ClientCB * cbNode = NULL; unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0}; uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION; uint32_t maxAge = 0; OCStackResult result = OC_STACK_ERROR; coap_pdu_t * sendPdu = NULL; coap_pdu_t * recvPdu = NULL; unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 }; uint8_t isObserveNotification = 0; #ifdef WITH_PRESENCE char * resourceTypeName = NULL; uint8_t remoteIpAddr[4]; uint16_t remotePortNu; unsigned char fullUri[MAX_URI_LENGTH] = { 0 }; uint8_t isPresenceNotification = 0; uint8_t isMulticastPresence = 0; uint32_t lowerBound; uint32_t higherBound; char * tok = NULL; #endif coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE}; coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE}; uint16_t rcvdSize2 = 0; VERIFY_NON_NULL(ctx); VERIFY_NON_NULL(rcvdResponse); recvPdu = rcvdResponse->pdu; result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge, &clientResponse.numRcvdVendorSpecificHeaderOptions, clientResponse.rcvdVendorSpecificHeaderOptions, &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes); VERIFY_SUCCESS(result, OC_STACK_OK); OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber); OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge); OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes); if(sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER) { isObserveNotification = 1; OC_LOG(INFO, TAG, PCF("Received an observe notification")); } #ifdef WITH_PRESENCE if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){ char* tokSavePtr; isPresenceNotification = 1; OC_LOG(INFO, TAG, PCF("Received a presence notification")); tok = strtok_r((char *)bufRes, "[:]}", &tokSavePtr); bufRes[strlen((char *)bufRes)] = ':'; tok = strtok_r(NULL, "[:]}", &tokSavePtr); bufRes[strlen((char *)bufRes)] = ':'; VERIFY_NON_NULL(tok); sequenceNumber = (uint32_t )atol(tok); OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber); tok = strtok_r(NULL, "[:]}", &tokSavePtr); VERIFY_NON_NULL(tok); maxAge = (uint32_t )atol(tok); OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge); tok = strtok_r(NULL, "[:]}", &tokSavePtr); if(tok) { bufRes[strlen((char *)bufRes)] = ':'; resourceTypeName = (char *)OCMalloc(strlen(tok)); if(!resourceTypeName) { goto exit; } strcpy(resourceTypeName, tok); OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", resourceTypeName); } bufRes[strlen((char *)bufRes)] = ']'; } #endif // fill OCCoAPToken structure RetrieveOCCoAPToken(recvPdu, &rcvdToken); OC_LOG_V(INFO, TAG,"Received a pdu with Token", rcvdToken.tokenLength); OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength); // fill OCClientResponse structure result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code), (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes); VERIFY_SUCCESS(result, OC_STACK_OK); cbNode = GetClientCB(&rcvdToken, NULL, NULL); #ifdef WITH_PRESENCE // Check if the application subscribed for presence if(!cbNode) { // get the address of the remote OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr, remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu); snprintf((char *)fullUri, sizeof(fullUri), "coap://%d.%d.%d.%d:%d%s", remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3], remotePortNu,rcvdUri); cbNode = GetClientCB(NULL, NULL, fullUri); } // Check if application subscribed for multicast presence if(!cbNode) { snprintf((char *)fullUri, sizeof(fullUri), "%s%s", OC_MULTICAST_IP, rcvdUri); cbNode = GetClientCB(NULL, NULL, fullUri); isMulticastPresence = 1; isPresenceNotification = 0; } #endif // fill OCResponse structure result = FormOCResponse(&response, cbNode, maxAge, &clientResponse); VERIFY_SUCCESS(result, OC_STACK_OK); if(cbNode) { if(!isObserveNotification) { #ifdef WITH_PRESENCE if(!isPresenceNotification) { #endif OC_LOG(INFO, TAG, PCF("Received a regular response")); if(recvPdu->hdr->type == COAP_MESSAGE_CON) { sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, recvPdu->hdr->id, NULL, NULL, NULL); VERIFY_NON_NULL(sendPdu); result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu, (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0)); } #ifdef WITH_PRESENCE } #endif } if(isObserveNotification) { OC_LOG(INFO, TAG, PCF("Received an observe notification")); if(recvPdu->hdr->type == COAP_MESSAGE_CON) { sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, recvPdu->hdr->id, NULL, NULL, NULL); VERIFY_NON_NULL(sendPdu); result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu, (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0)); } //TODO: check the standard for methods to detect wrap around condition if(cbNode->method == OC_REST_OBSERVE && (clientResponse.sequenceNumber <= cbNode->sequenceNumber || (clientResponse.sequenceNumber > cbNode->sequenceNumber && clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER)))) { OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \ Ignoring Incoming:%d Against Current:%d.", clientResponse.sequenceNumber, cbNode->sequenceNumber); goto exit; } if(clientResponse.sequenceNumber > cbNode->sequenceNumber){ cbNode->sequenceNumber = clientResponse.sequenceNumber; } } else { #ifdef WITH_PRESENCE if(isPresenceNotification)
OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource, OCEntityHandlerRequest *ehRequest) { OCStackResult stackRet = OC_STACK_ERROR; OC_LOG(INFO, TAG, PCF("Group Action is requested.")); // if (stackRet == OC_STACK_OK) { char *doWhat = NULL; char *details = NULL; size_t bufferLength = 0; unsigned char buffer[MAX_RESPONSE_LENGTH] = { 0 }; unsigned char *bufferPtr = NULL; bufferPtr = buffer; OCResource * collResource = (OCResource *) ehRequest->resource; char *jsonResponse; ExtractKeyValueFromRequest((char *)ehRequest->reqJSONPayload, &doWhat, &details); cJSON *json; cJSON *format; if (method == OC_REST_PUT) { json = cJSON_CreateObject(); cJSON_AddStringToObject(json, "href", resource->uri); cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject()); OC_LOG(INFO, TAG, PCF("Group Action[PUT].")); if(strcmp(doWhat, "ActionSet") == 0) { OCActionSet *actionSet; BuildActionSetFromString(&actionSet, details); if(actionSet != NULL) { AddActionSet(&resource->actionsetHead, actionSet); stackRet = OC_STACK_OK; } else { stackRet = OC_STACK_ERROR; } } else if (strcmp(doWhat, "DelActionSet") == 0) { if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK) { stackRet = OC_STACK_OK; } else { stackRet = OC_STACK_ERROR; } } jsonResponse = cJSON_Print(json); cJSON_Delete(json); strcat((char *) bufferPtr, jsonResponse); bufferLength = strlen((const char *) buffer); if (bufferLength > 0) { OCEntityHandlerResponse response = { 0 }; response.ehResult = OC_EH_OK; response.payload = buffer; response.payloadSize = bufferLength + 1; response.persistentBufferFlag = 0; response.requestHandle = (OCRequestHandle) ehRequest->requestHandle; response.resourceHandle = (OCResourceHandle) collResource; stackRet = OCDoResponse(&response); } stackRet = OC_STACK_OK; } if (method == OC_REST_POST) { OC_LOG(INFO, TAG, PCF("Group Action[POST].")); OCActionSet *actionset = NULL; json = cJSON_CreateObject(); cJSON_AddStringToObject(json, "href", resource->uri); if (strcmp(doWhat, "DoAction") == 0) { if (GetActionSet(details, resource->actionsetHead, &actionset) != OC_STACK_OK) { OC_LOG(INFO, TAG, PCF("ERROR")); stackRet = OC_STACK_ERROR; } if (actionset == NULL) { OC_LOG(INFO, TAG, PCF("ERROR")); stackRet = OC_STACK_ERROR; } else { OCAction *pointerAction = actionset->head; unsigned int num = GetNumOfTargetResource(pointerAction); ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse; ((OCServerRequest *) ehRequest->requestHandle)->numResponses = num + 1; while (pointerAction != NULL) { unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 }; unsigned char* actionDescPtr = actionDesc; uint16_t remaining = MAX_RESPONSE_LENGTH; strncpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX, strlen((const char *) OC_JSON_PREFIX) + 1); BuildActionJSON(pointerAction, actionDescPtr, &remaining); strncat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX, strlen((const char *) OC_JSON_SUFFIX)); ClientRequstInfo *info = (ClientRequstInfo *) OCMalloc( sizeof(ClientRequstInfo)); memset(info, 0, sizeof(ClientRequstInfo)); info->collResource = resource; info->ehRequest = (OCServerRequest *) ehRequest->requestHandle; SendAction(&info->required, pointerAction->resourceUri, actionDescPtr); AddClientRequestInfo(&clientRequstList, info); pointerAction = pointerAction->next; } stackRet = OC_STACK_OK; } } else if (strcmp(doWhat, "GetActionSet") == 0) { char *plainText = NULL; OCActionSet *actionset = NULL; cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject()); GetActionSet(details, resource->actionsetHead, &actionset); if (actionset != NULL) { BuildStringFromActionSet(actionset, &plainText); if (plainText != NULL) { cJSON_AddStringToObject(format, "ActionSet", plainText); } stackRet = OC_STACK_OK; } } jsonResponse = cJSON_Print(json); cJSON_Delete(json); strcat((char *) bufferPtr, jsonResponse); bufferLength = strlen((const char *) buffer); if (bufferLength > 0) { OCEntityHandlerResponse response = { 0 }; response.ehResult = OC_EH_OK; response.payload = buffer; response.payloadSize = bufferLength + 1; response.persistentBufferFlag = 0; response.requestHandle = (OCRequestHandle) ehRequest->requestHandle; response.resourceHandle = (OCResourceHandle) collResource; stackRet = OCDoResponse(&response); } } OCFree(doWhat); OCFree(details); } return stackRet; }
OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc) { char temp[1024] = { 0 }; int remaining = 1023; // OCActionSet *as = resource->actionsetHead; // while(as != NULL) // { // printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName); OCAction *action = actionset->head; if (remaining >= strlen(actionset->actionsetName) + 1) { strcat(temp, actionset->actionsetName); remaining -= strlen(actionset->actionsetName); strcat(temp, "*"); remaining--; } else { return OC_STACK_ERROR; } while (action != NULL) { printf("\tURI :: %s\n", action->resourceUri); strcat(temp, "uri="); remaining -= strlen("uri="); strcat(temp, action->resourceUri); remaining -= strlen(action->resourceUri); strcat(temp, "|"); remaining--; OCCapability *capas = action->head; while (capas != NULL) { printf("\t\t%s = %s\n", capas->capability, capas->status); strcat(temp, capas->capability); remaining -= strlen(capas->capability); strcat(temp, "="); remaining--; strcat(temp, capas->status); remaining -= strlen(capas->capability); capas = capas->next; if (capas != NULL) { strcat(temp, "|"); } } action = action->next; if (action != NULL) { strcat(temp, "*"); remaining--; } } // as = as->next; // } *desc = (char *) OCMalloc(1024 - remaining); strcpy(*desc, temp); // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining); return OC_STACK_OK; }
OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc) { OCStackResult result = OC_STACK_OK; char *iterToken = NULL, *iterTokenPtr = NULL; char *descIterToken = NULL, *descIterTokenPtr = NULL; char *attrIterToken = NULL, *attrIterTokenPtr = NULL; char *desc = NULL, *attr = NULL; char *key = NULL, *value = NULL; OCAction *action = NULL; OCCapability *capa = NULL; OC_LOG(INFO, TAG, PCF("Build ActionSet Instance.")); *set = (OCActionSet*) OCMalloc(sizeof(OCActionSet)); VARIFY_POINTER_NULL(*set, result, exit) iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr); memset(*set, 0, sizeof(OCActionSet)); (*set)->actionsetName = (char *)OCMalloc(sizeof(OCActionSet)); VARIFY_POINTER_NULL((*set)->actionsetName, result, exit) VARIFY_PARAM_NULL(iterToken, result, exit) strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1); OC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName); iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr); while(iterToken) { desc = (char *)OCMalloc(strlen(iterToken) + 1); strncpy(desc, iterToken, strlen(iterToken) + 1); descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER, &descIterTokenPtr); while(descIterToken) { attr = (char *)OCMalloc(strlen(descIterToken) + 1); strncpy(attr, descIterToken, strlen(descIterToken) + 1); attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN, &attrIterTokenPtr); key = (char *)OCMalloc(strlen(attrIterToken) + 1); VARIFY_POINTER_NULL(key, result, exit) VARIFY_PARAM_NULL(attrIterToken, result, exit) strncpy(key, attrIterToken, strlen(attrIterToken) + 1); attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN, &attrIterTokenPtr); value = (char *)OCMalloc(strlen(attrIterToken) + 1); VARIFY_POINTER_NULL(value, result, exit) VARIFY_PARAM_NULL(attrIterToken, result, exit) strncpy(value, attrIterToken, strlen(attrIterToken) + 1); if(strcmp(key, "uri") == 0) { OC_LOG(INFO, TAG, PCF("Build OCAction Instance.")); action = (OCAction*)OCMalloc(sizeof(OCAction)); VARIFY_POINTER_NULL(action, result, exit) memset(action, 0, sizeof(OCAction)); action->resourceUri = (char *)OCMalloc(strlen(value) + 1); VARIFY_POINTER_NULL(action->resourceUri, result, exit) VARIFY_PARAM_NULL(value, result, exit) strncpy(action->resourceUri, value, strlen(value) + 1); } else { if( (key != NULL) && (value != NULL)) { OC_LOG(INFO, TAG, PCF("Build OCCapability Instance.")); capa = (OCCapability*)OCMalloc(sizeof(OCCapability)); VARIFY_POINTER_NULL(capa, result, exit) memset(capa, 0, sizeof(OCCapability)); capa->capability = (char *)OCMalloc(strlen(key) + 1); capa->status = (char *)OCMalloc(strlen(value) + 1); strncpy(capa->capability, key, strlen(key) + 1); strncpy(capa->status, value, strlen(value) + 1); VARIFY_POINTER_NULL(action, result, exit) AddCapability(&action->head, capa); } } OCFree(key); OCFree(value); OCFree(attr); descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &descIterTokenPtr); } AddAction(&(*set)->head, action); iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr); OCFree(desc); } return OC_STACK_OK; exit: OCFree(attr); OCFree(desc); OCFree(capa); OCFree(action); OCFree(*set); *set = NULL; return result; }
OCStackResult SendListObserverNotification (OCResource * resource, OCObservationId *obsIdList, uint8_t numberOfIds, unsigned char *notificationJSONPayload, uint32_t maxAge, OCQualityOfService qos) { uint8_t numIds = numberOfIds; ResourceObserver *observation = NULL; uint8_t numSentNotification = 0; OCServerRequest * request = NULL; OCStackResult result = OC_STACK_ERROR; OCEntityHandlerResponse ehResponse = {0}; OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification")); while(numIds) { OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList); observation = NULL; observation = GetObserverUsingId (*obsIdList); if(observation) { // Found observation - verify if it matches the resource handle if (observation->resource == resource) { qos = DetermineObserverQoS(OC_REST_GET, observation, qos); result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET, 0, resource->sequenceNum, qos, observation->query, NULL, NULL, &observation->token, observation->addr, observation->resUri, 0); request->observeResult = OC_STACK_OK; if(request && result == OC_STACK_OK) { memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse)); ehResponse.ehResult = OC_EH_OK; ehResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH); if(!ehResponse.payload) { FindAndDeleteServerRequest(request); continue; } strcpy((char *)ehResponse.payload, (const char *)notificationJSONPayload); ehResponse.payloadSize = strlen((const char *)ehResponse.payload) + 1; ehResponse.persistentBufferFlag = 0; ehResponse.requestHandle = (OCRequestHandle) request; ehResponse.resourceHandle = (OCResourceHandle) resource; result = OCDoResponse(&ehResponse); if(result == OC_STACK_OK) { OCFree(ehResponse.payload); FindAndDeleteServerRequest(request); } } else { FindAndDeleteServerRequest(request); } numSentNotification++; } } obsIdList++; numIds--; } if(numSentNotification == numberOfIds) { return OC_STACK_OK; } else if(numSentNotification == 0) { return OC_STACK_NO_OBSERVERS; } else { //TODO: we need to signal that not every one in the // list got an update, should we also indicate who did not receive on? return OC_STACK_OK; } }