//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <stdlib.h>
+#include <string.h>
+
#include "ocstack.h"
-#include "logger.h"
#include "oic_malloc.h"
-#include "cJSON.h"
+#include "ocpayload.h"
+#include "payload_logging.h"
#include "resourcemanager.h"
#include "pstatresource.h"
#include "doxmresource.h"
#include "psinterface.h"
-#include "utlist.h"
-#include "base64.h"
#include "srmresourcestrings.h"
#include "srmutility.h"
-#include <stdlib.h>
-#include <string.h>
#define TAG "SRM-PSTAT"
+/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
+ * The value of payload size is increased until reaching below max cbor size. */
+static const uint8_t CBOR_SIZE = 255;
+
+// Max cbor size payload.
+static const uint16_t CBOR_MAX_SIZE = 4400;
+
+// PSTAT Map size - Number of mandatory items
+static const uint8_t PSTAT_MAP_SIZE = 7;
+
static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
static OicSecPstat_t gDefaultPstat =
{
}
}
-char * BinToPstatJSON(const OicSecPstat_t * pstat)
+OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size)
{
- if(NULL == pstat)
+ if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size)
{
- return NULL;
+ return OC_STACK_INVALID_PARAM;
}
- cJSON *jsonPstat = NULL;
- char *jsonStr = NULL;
- cJSON *jsonSmArray = NULL;
- char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] = {};
- uint32_t outLen = 0;
- B64Result b64Ret = B64_OK;
+ size_t cborLen = *size;
+ if (0 == cborLen)
+ {
+ cborLen = CBOR_SIZE;
+ }
- cJSON *jsonRoot = cJSON_CreateObject();
- VERIFY_NON_NULL(TAG, jsonRoot, INFO);
+ *payload = NULL;
+ *size = 0;
- cJSON_AddItemToObject(jsonRoot, OIC_JSON_PSTAT_NAME, jsonPstat=cJSON_CreateObject());
- cJSON_AddBoolToObject(jsonPstat, OIC_JSON_ISOP_NAME, pstat->isOp);
+ OCStackResult ret = OC_STACK_ERROR;
- b64Ret = b64Encode(pstat->deviceID.id,
- sizeof(pstat->deviceID.id), base64Buff, sizeof(base64Buff), &outLen);
- VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+ CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
+ CborEncoder pstatMap = { {.ptr = NULL }, .end = 0 };
+
+ CborError cborEncoderResult = CborNoError;
+
+ uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
+ VERIFY_NON_NULL(TAG, outPayload, ERROR);
+ cbor_encoder_init(&encoder, outPayload, cborLen, 0);
+
+ cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, PSTAT_MAP_SIZE);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME,
+ strlen(OIC_JSON_ISOP_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag.");
+ cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME,
+ strlen(OIC_JSON_DEVICE_ID_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
+ cborEncoderResult = cbor_encode_byte_string(&pstatMap, (uint8_t *)pstat->deviceID.id,
+ sizeof(pstat->deviceID.id));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_COMMIT_HASH_NAME,
+ strlen(OIC_JSON_COMMIT_HASH_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Commit Hash Tag.");
+ cborEncoderResult = cbor_encode_int(&pstatMap, pstat->commitHash);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Commit Hash Value.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME,
+ strlen(OIC_JSON_CM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag.");
+ cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME,
+ strlen(OIC_JSON_TM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag.");
+ cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME,
+ strlen(OIC_JSON_OM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag.");
+ cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value.");
+
+ cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME,
+ strlen(OIC_JSON_SM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag.");
+ {
+ CborEncoder sm = { {.ptr = NULL }, .end = 0 };
+ cborEncoderResult = cbor_encoder_create_array(&pstatMap, &sm, pstat->smLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Array.");
- cJSON_AddStringToObject(jsonPstat, OIC_JSON_DEVICE_ID_NAME, base64Buff);
- cJSON_AddNumberToObject(jsonPstat, OIC_JSON_COMMIT_HASH_NAME, pstat->commitHash);
- cJSON_AddNumberToObject(jsonPstat, OIC_JSON_CM_NAME, (int)pstat->cm);
- cJSON_AddNumberToObject(jsonPstat, OIC_JSON_TM_NAME, (int)pstat->tm);
- cJSON_AddNumberToObject(jsonPstat, OIC_JSON_OM_NAME, (int)pstat->om);
+ for (size_t i = 0; i < pstat->smLen; i++)
+ {
+ cborEncoderResult = cbor_encode_int(&sm, pstat->sm[i]);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Value in Array.");
+ }
+ cborEncoderResult = cbor_encoder_close_container(&pstatMap, &sm);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SM Array.");
+ }
+ cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map.");
+
+ *size = encoder.ptr - outPayload;
+ *payload = outPayload;
+ ret = OC_STACK_OK;
- cJSON_AddItemToObject(jsonPstat, OIC_JSON_SM_NAME, jsonSmArray = cJSON_CreateArray());
- VERIFY_NON_NULL(TAG, jsonSmArray, INFO);
- for (size_t i = 0; i < pstat->smLen; i++)
+exit:
+ if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
{
- cJSON_AddItemToArray(jsonSmArray, cJSON_CreateNumber((int )pstat->sm[i]));
+ // reallocate and try again!
+ OICFree(outPayload);
+ // Since the allocated initial memory failed, double the memory.
+ cborLen += encoder.ptr - encoder.end;
+ cborEncoderResult = CborNoError;
+ ret = PstatToCBORPayload(pstat, payload, &cborLen);
}
- jsonStr = cJSON_Print(jsonRoot);
-exit:
- if (jsonRoot)
+ if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
{
- cJSON_Delete(jsonRoot);
+ OICFree(outPayload);
+ outPayload = NULL;
+ *payload = NULL;
+ *size = 0;
+ ret = OC_STACK_ERROR;
}
- return jsonStr;
+
+ return ret;
}
-OicSecPstat_t * JSONToPstatBin(const char * jsonStr)
+OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size,
+ OicSecPstat_t **secPstat)
{
- if(NULL == jsonStr)
+ if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat)
{
- return NULL;
+ return OC_STACK_INVALID_PARAM;
}
OCStackResult ret = OC_STACK_ERROR;
+ *secPstat = NULL;
+
+ CborValue pstatCbor = { .parser = NULL };
+ CborParser parser = { .end = NULL };
+ CborError cborFindResult = CborNoError;
+ int cborLen = size;
+ if (0 == size)
+ {
+ cborLen = CBOR_SIZE;
+ }
+ cbor_parser_init(cborPayload, cborLen, 0, &parser, &pstatCbor);
+ CborValue pstatMap = { .parser = NULL } ;
OicSecPstat_t *pstat = NULL;
- cJSON *jsonPstat = NULL;
- cJSON *jsonObj = NULL;
-
- unsigned char base64Buff[sizeof(((OicUuid_t*) 0)->id)] = {};
- uint32_t outLen = 0;
- B64Result b64Ret = B64_OK;
-
- cJSON *jsonRoot = cJSON_Parse(jsonStr);
- VERIFY_NON_NULL(TAG, jsonRoot, INFO);
-
- jsonPstat = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PSTAT_NAME);
- VERIFY_NON_NULL(TAG, jsonPstat, INFO);
-
- pstat = (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t));
- VERIFY_NON_NULL(TAG, pstat, INFO);
- jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_ISOP_NAME);
- VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type) , ERROR);
- pstat->isOp = jsonObj->valueint;
-
- jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_DEVICE_ID_NAME);
- VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
- b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
- sizeof(base64Buff), &outLen);
- VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pstat->deviceID.id)), ERROR);
- memcpy(pstat->deviceID.id, base64Buff, outLen);
-
- jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME);
- VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
- pstat->commitHash = jsonObj->valueint;
-
- jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_CM_NAME);
- VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
- pstat->cm = (OicSecDpm_t)jsonObj->valueint;
-
- jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME);
- VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
- pstat->om = (OicSecDpom_t)jsonObj->valueint;
-
- jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_SM_NAME);
- VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- if (cJSON_Array == jsonObj->type)
+ char *name = NULL;
+ cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map.");
+
+ pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
+ VERIFY_NON_NULL(TAG, pstat, ERROR);
+
+ while (cbor_value_is_valid(&pstatMap))
{
- pstat->smLen = (size_t)cJSON_GetArraySize(jsonObj);
- size_t idxx = 0;
- VERIFY_SUCCESS(TAG, pstat->smLen != 0, ERROR);
- pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
- VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
- do
+ size_t len = 0;
+ cborFindResult = cbor_value_dup_text_string(&pstatMap, &name, &len, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
+ cborFindResult = cbor_value_advance(&pstatMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing PSTAT MAP.");
+
+ CborType type = cbor_value_get_type(&pstatMap);
+
+ if (0 == strcmp(OIC_JSON_ISOP_NAME, name))
+ {
+ cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ISOP Name.");
+ }
+
+ if (0 == strcmp(OIC_JSON_DEVICE_ID_NAME, name))
+ {
+ uint8_t *subjectId = NULL;
+ cborFindResult = cbor_value_dup_byte_string(&pstatMap, &subjectId, &len, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubjectId.");
+ memcpy(pstat->deviceID.id, subjectId, len);
+ OICFree(subjectId);
+ }
+
+ if (0 == strcmp(OIC_JSON_COMMIT_HASH_NAME, name))
+ {
+ cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->commitHash);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CommitHash.");
+ }
+
+ if (0 == strcmp(OIC_JSON_CM_NAME, name))
+ {
+ cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->cm);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM Name.");
+ }
+
+ if (0 == strcmp(OIC_JSON_OM_NAME, name))
+ {
+ cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->om);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM Name.");
+ }
+
+ if (0 == strcmp(OIC_JSON_SM_NAME, name))
+ {
+ CborValue sm = { .parser = NULL };
+
+ cborFindResult = cbor_value_get_array_length(&pstatMap, &pstat->smLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM Len Array.");
+ VERIFY_SUCCESS(TAG, pstat->smLen != 0, ERROR);
+
+ pstat->sm = (OicSecDpom_t *)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
+ VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
+
+ cborFindResult = cbor_value_enter_container(&pstatMap, &sm);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM Container.");
+
+ int i = 0;
+ while (cbor_value_is_valid(&sm))
+ {
+ cborFindResult = cbor_value_get_int(&sm, (int *)&pstat->sm[i++]);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM Value.");
+ cborFindResult = cbor_value_advance(&sm);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM Array.");
+ }
+ }
+ if (CborMapType != type && cbor_value_is_valid(&pstatMap))
{
- cJSON *jsonSm = cJSON_GetArrayItem(jsonObj, idxx);
- VERIFY_NON_NULL(TAG, jsonSm, ERROR);
- pstat->sm[idxx] = (OicSecDpom_t)jsonSm->valueint;
- }while ( ++idxx < pstat->smLen);
+ cborFindResult = cbor_value_advance(&pstatMap);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT MAP.");
+ }
+ OICFree(name);
+ name = NULL;
}
+
+ *secPstat = pstat;
ret = OC_STACK_OK;
exit:
- cJSON_Delete(jsonRoot);
- if (OC_STACK_OK != ret)
+ if (CborNoError != cborFindResult)
{
- OIC_LOG (ERROR, TAG, "JSONToPstatBin failed");
+ OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed");
DeletePstatBinData(pstat);
pstat = NULL;
+ ret = OC_STACK_ERROR;
}
- return pstat;
+ if (name)
+ {
+ OICFree(name);
+ }
+ return ret;
}
/**
* Function to update persistent storage
*/
-static bool UpdatePersistentStorage(OicSecPstat_t * pstat)
+static bool UpdatePersistentStorage(OicSecPstat_t *pstat)
{
bool bRet = false;
- if (pstat)
+ size_t size = 0;
+ uint8_t *cborPayload = NULL;
+ OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size);
+ if (OC_STACK_OK == ret)
{
- // Convert pstat data into JSON for update to persistent storage
- char *jsonStr = BinToPstatJSON(pstat);
- if (jsonStr)
+ if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
{
- cJSON *jsonPstat = cJSON_Parse(jsonStr);
- OICFree(jsonStr);
-
- if (jsonPstat &&
- (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_PSTAT_NAME, jsonPstat)))
- {
- bRet = true;
- }
- cJSON_Delete(jsonPstat);
+ bRet = true;
}
+ OICFree(cborPayload);
}
return bRet;
*/
static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
{
- OIC_LOG (INFO, TAG, "HandlePstatGetRequest processing GET request");
- // Convert ACL data into JSON for transmission
- char* jsonStr = BinToPstatJSON(gPstat);
+ OIC_LOG(INFO, TAG, "HandlePstatGetRequest processing GET request");
+
+ // Convert ACL data into CBOR for transmission
+ size_t size = 0;
+ uint8_t *payload = NULL;
+ OCStackResult res = PstatToCBORPayload(gPstat, &payload, &size);
- // A device should always have a default pstat. Therefore, jsonStr should never be NULL.
- OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+ // A device should always have a default pstat. Therefore, payload should never be NULL.
+ OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
// Send response payload to request originator
- SendSRMResponse(ehRequest, ehRet, jsonStr);
- OICFree(jsonStr);
+ SendSRMCBORResponse(ehRequest, ehRet, payload);
+ OICFree(payload);
return ehRet;
}
static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest *ehRequest)
{
OCEntityHandlerResult ehRet = OC_EH_ERROR;
- cJSON *postJson = NULL;
- OIC_LOG (INFO, TAG, "HandlePstatPutRequest processing PUT request");
+ OIC_LOG(INFO, TAG, "HandlePstatPutRequest processing PUT request");
+ OicSecPstat_t *pstat = NULL;
if (ehRequest->resource)
{
- postJson = cJSON_Parse(((OCSecurityPayload*)ehRequest->payload)->securityData);
- VERIFY_NON_NULL(TAG, postJson, INFO);
- cJSON *jsonPstat = cJSON_GetObjectItem(postJson, OIC_JSON_PSTAT_NAME);
- VERIFY_NON_NULL(TAG, jsonPstat, INFO);
- cJSON *commitHashJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME);
- uint16_t commitHash = 0;
- if (commitHashJson)
- {
- commitHash = commitHashJson->valueint;
- }
- cJSON *tmJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_TM_NAME);
- if (tmJson && gPstat)
+ uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;
+ VERIFY_NON_NULL(TAG, payload, ERROR);
+
+ OCStackResult ret = CBORPayloadToPstat(payload, CBOR_SIZE, &pstat);
+ OICFree(payload);
+ VERIFY_NON_NULL(TAG, pstat, ERROR);
+ if (OC_STACK_OK == ret)
{
- gPstat->tm = (OicSecDpm_t)tmJson->valueint;
- if(0 == tmJson->valueint && gPstat->commitHash == commitHash)
+ if (pstat->tm)
{
- gPstat->isOp = true;
- gPstat->cm = NORMAL;
- OIC_LOG (INFO, TAG, "CommitHash is valid and isOp is TRUE");
- }
- else
- {
- OIC_LOG (INFO, TAG, "CommitHash is not valid");
+ gPstat->tm = pstat->tm;
+ if(0 == pstat->tm && gPstat->commitHash == pstat->commitHash)
+ {
+ gPstat->isOp = true;
+ gPstat->cm = NORMAL;
+ OIC_LOG (INFO, TAG, "CommitHash is valid and isOp is TRUE");
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TAG, "CommitHash is not valid");
+ }
}
- }
- cJSON *omJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME);
- if (omJson && gPstat)
- {
- /*
- * Check if the operation mode is in the supported provisioning services
- * operation mode list.
- */
- for(size_t i=0; i< gPstat->smLen; i++)
+ if (pstat->om && gPstat)
{
- if(gPstat->sm[i] == (unsigned int)omJson->valueint)
+ /*
+ * Check if the operation mode is in the supported provisioning services
+ * operation mode list.
+ */
+ for(size_t i=0; i< gPstat->smLen; i++)
{
- gPstat->om = (OicSecDpom_t)omJson->valueint;
- break;
+ if(gPstat->sm[i] == pstat->om)
+ {
+ gPstat->om = pstat->om;
+ break;
+ }
}
}
+ // Convert pstat data into CBOR for update to persistent storage
+ if(UpdatePersistentStorage(gPstat))
+ {
+ ehRet = OC_EH_OK;
+ }
}
- // Convert pstat data into JSON for update to persistent storage
- if(UpdatePersistentStorage(gPstat))
- {
- ehRet = OC_EH_OK;
- }
+
+ OICFree(payload);
}
exit:
if(OC_EH_OK != ehRet)
}
//Send payload to request originator
- if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
+ if(OC_STACK_OK != SendSRMCBORResponse(ehRequest, ehRet, NULL))
{
OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
}
- cJSON_Delete(postJson);
+ DeletePstatBinData(pstat);
return ehRet;
}
// This method will handle REST request (GET/POST) for /oic/sec/pstat
if (flag & OC_REQUEST_FLAG)
{
- OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+ OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
switch (ehRequest->method)
{
case OC_REST_GET:
break;
default:
ehRet = OC_EH_ERROR;
- SendSRMResponse(ehRequest, ehRet, NULL);
+ SendSRMCBORResponse(ehRequest, ehRet, NULL);
break;
}
}
*/
OCStackResult CreatePstatResource()
{
- OCStackResult ret;
+ OCStackResult ret = OCCreateResource(&gPstatHandle,
+ OIC_RSRC_TYPE_SEC_PSTAT,
+ OIC_MI_DEF,
+ OIC_RSRC_PSTAT_URI,
+ PstatEntityHandler,
+ NULL,
+ OC_RES_PROP_NONE);
- ret = OCCreateResource(&gPstatHandle,
- OIC_RSRC_TYPE_SEC_PSTAT,
- OIC_MI_DEF,
- OIC_RSRC_PSTAT_URI,
- PstatEntityHandler,
- NULL,
- OC_RES_PROP_NONE);
-
- if (ret != OC_STACK_OK)
+ if (OC_STACK_OK != ret)
{
- OIC_LOG (FATAL, TAG, "Unable to instantiate pstat resource");
+ OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource");
DeInitPstatResource();
}
return ret;
}
/**
- * Post ACL hander update the commitHash during ACL provisioning.
- */
-void SetCommitHash(uint16_t commitHash)
-{
- gPstat->commitHash = commitHash;
-}
-
-/**
- * Get the default value
- * @retval the gDefaultPstat pointer
+ * Get the default value.
+ *
+ * @return the gDefaultPstat pointer.
*/
static OicSecPstat_t* GetPstatDefault()
{
return &gDefaultPstat;
}
-/**
- * Initialize pstat resource by loading data from persistent storage.
- *
- * @retval OC_STACK_OK for Success, otherwise some error value
- */
OCStackResult InitPstatResource()
{
OCStackResult ret = OC_STACK_ERROR;
// Read Pstat resource from PS
- char* jsonSVRDatabase = GetSVRDatabase();
- if (jsonSVRDatabase)
+ uint8_t *data = NULL;
+ size_t size = 0;
+ ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size);
+ // If database read failed
+ if (OC_STACK_OK != ret)
+ {
+ OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
+ }
+ if (data)
{
- // Convert JSON Pstat into binary format
- gPstat = JSONToPstatBin(jsonSVRDatabase);
+ // Read ACL resource from PS
+ ret = CBORPayloadToPstat(data, size, &gPstat);
}
/*
* If SVR database in persistent storage got corrupted or
* is not available for some reason, a default pstat is created
* which allows user to initiate pstat provisioning again.
*/
- if(!jsonSVRDatabase || !gPstat)
+ if ((OC_STACK_OK != ret) || !data || !gPstat)
{
gPstat = GetPstatDefault();
}
+ VERIFY_NON_NULL(TAG, gPstat, FATAL);
// Instantiate 'oic.sec.pstat'
ret = CreatePstatResource();
- OICFree(jsonSVRDatabase);
+exit:
+ OICFree(data);
+ if (OC_STACK_OK != ret)
+ {
+ DeInitPstatResource();
+ }
return ret;
}
return OCDeleteResource(gPstatHandle);
}
-
/**
* Function to restore pstat resurce to initial status.
* This function will use in case of error while ownership transfer
gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
}
- if(!UpdatePersistentStorage(gPstat))
+ if (!UpdatePersistentStorage(gPstat))
{
OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
}
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <unistd.h>
#include "gtest/gtest.h"
+
+#include "ocpayload.h"
#include "ocstack.h"
-#include "resourcemanager.h"
-#include "pstatresource.h"
#include "oic_malloc.h"
-#include "cJSON.h"
-#include "base64.h"
#include "cainterface.h"
+#include "resourcemanager.h"
#include "secureresourcemanager.h"
-#include "srmtestcommon.h"
-#include "ocpayload.h"
-#include <unistd.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-//Declare Provision status resource methods for testing
-OCStackResult CreatePstatResource();
-OCEntityHandlerResult PstatEntityHandler (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest * ehRequest);
-char * BinToPstatJSON(const OicSecPstat_t * pstat);
-OicSecPstat_t * JSONToPstatBin(const char * jsonStr);
-const char* UNIT_TEST_JSON_FILE_NAME = "oic_unittest.json";
-#ifdef __cplusplus
-}
-#endif
+#include "pstatresource.h"
+#include "security_internals.h"
-//InitPstatResource Tests
-TEST(InitPstatResourceTest, InitPstatResource)
+// InitPstatResource Tests
+TEST(PstatResourceTest, InitPstatResource)
{
- EXPECT_EQ(OC_STACK_INVALID_PARAM, InitPstatResource());
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, InitPstatResource());
}
-
-//DeInitPstatResource Tests
-TEST(DeInitPstatResourceTest, DeInitPstatResource)
+// DeInitPstatResource Tests
+TEST(PstatResourceTest, DeInitPstatResource)
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, DeInitPstatResource());
}
//CreatePstatResource Tests
-TEST(CreatePstatResourceTest, CreatePstatResource)
+TEST(PstatResourceTest, CreatePstatResource)
{
- EXPECT_EQ(OC_STACK_INVALID_PARAM, CreatePstatResource());
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, CreatePstatResource());
}
//PstatEntityHandler Tests
-TEST(PstatEntityHandlerTest, PstatEntityHandlerWithDummyRequest)
+TEST(PstatResourceTest, PstatEntityHandlerWithDummyRequest)
{
OCEntityHandlerRequest req;
EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
}
-TEST(PstatEntityHandlerTest, PstatEntityHandlerWithPostRequest)
+TEST(PstatResourceTest, PstatEntityHandlerWithPostRequest)
{
+ OicSecPstat_t *defaultPstat = (OicSecPstat_t *) OICCalloc(1, sizeof(*defaultPstat));
+ ASSERT_TRUE(defaultPstat != NULL);
+ defaultPstat->isOp = false;
+ uint8_t deviceId[] = {0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x69, 0x64, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x5a, 0x9f};
+ memcpy(defaultPstat->deviceID.id, deviceId, sizeof(deviceId));
+ EXPECT_EQ(sizeof(defaultPstat->deviceID.id), sizeof(deviceId));
+ defaultPstat->commitHash = 1234;
+ defaultPstat->cm = (OicSecDpm_t) 63;
+ defaultPstat->tm = (OicSecDpm_t) 48;
+ defaultPstat->om = (OicSecDpom_t) 0;
+ defaultPstat->smLen = 2;
+ defaultPstat->sm = (OicSecDpom_t *)OICCalloc(defaultPstat->smLen, sizeof(*defaultPstat->sm));
+ ASSERT_TRUE(defaultPstat->sm != NULL);
+ defaultPstat->sm[0] = (OicSecDpom_t) 3;
+ defaultPstat->sm[1] = (OicSecDpom_t) 1;
+ size_t size = 0;
+ uint8_t *cbor = NULL;
+ EXPECT_EQ(OC_STACK_OK, PstatToCBORPayload(defaultPstat, &cbor, &size));
+ DeletePstatBinData(defaultPstat);
+ ASSERT_TRUE(cbor != NULL);
+
OCEntityHandlerRequest req;
req.method = OC_REST_POST;
- req.payload = reinterpret_cast<OCPayload*>(
- OCSecurityPayloadCreate("{ \"pstat\": { \"tm\": 0, \"om\": 3 }}"));
+ req.payload = (OCPayload *) OCSecurityPayloadCBORCreate(cbor);
EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
OCPayloadDestroy(req.payload);
}
-TEST(PstatEntityHandlerTest, PstatEntityHandlerInvalidRequest)
+TEST(PstatResourceTest, PstatEntityHandlerInvalidRequest)
{
EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, NULL));
}
-//BinToJSON Tests
-TEST(BinToJSONTest, BinToNullJSON)
+TEST(PstatResourceTest, PstatToCBORPayloadNULL)
{
- char* value = BinToPstatJSON(NULL);
- EXPECT_TRUE(value == NULL);
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PstatToCBORPayload(NULL, NULL, 0));
+ // Case when cbor payload is NULL
+ OicSecPstat_t pstat;
+ size_t size = 10;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PstatToCBORPayload(&pstat, NULL, &size));
+ uint8_t *cborPayload = (uint8_t *) OICCalloc(1, size);
+ ASSERT_TRUE(NULL != cborPayload);
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PstatToCBORPayload(&pstat, &cborPayload, &size));
+ OICFree(cborPayload);
+ cborPayload = NULL;
+ // Case when pstat is zero.
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PstatToCBORPayload(NULL, &cborPayload, &size));
+ // Case when size is 0.
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PstatToCBORPayload(&pstat, &cborPayload, 0));
+ OICFree(cborPayload);
}
-TEST(JSONToBinTest, NullJSONToBin)
+TEST(PstatResourceTest, CBORPayloadToPstat)
{
- OicSecPstat_t *pstat1 = JSONToPstatBin(NULL);
- EXPECT_TRUE(pstat1 == NULL);
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, CBORPayloadToPstat(NULL, 0, NULL));
}
-TEST(MarshalingAndUnMarshalingTest, BinToPstatJSONAndJSONToPstatBin)
+TEST(PstatResourceTest, PstatToCBORPayloadAndCBORPayloadToPstat)
{
- const char* id = "ZGV2aWNlaWQAAAAAABhanw==";
OicSecPstat_t pstat;
pstat.cm = NORMAL;
pstat.commitHash = 0;
- uint32_t outLen = 0;
- unsigned char base64Buff[sizeof(((OicUuid_t*) 0)->id)] = {};
- EXPECT_EQ(B64_OK, b64Decode(id, strlen(id), base64Buff, sizeof(base64Buff), &outLen));
- memcpy(pstat.deviceID.id, base64Buff, outLen);
+ uint8_t deviceId[] = {0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x69, 0x64, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x5a, 0x9f};
+ memcpy(pstat.deviceID.id, deviceId, sizeof(deviceId));
pstat.isOp = true;
pstat.tm = NORMAL;
pstat.om = SINGLE_SERVICE_CLIENT_DRIVEN;
pstat.smLen = 2;
- pstat.sm = (OicSecDpom_t*)OICCalloc(pstat.smLen, sizeof(OicSecDpom_t));
- if(!pstat.sm)
- {
- FAIL() << "Failed to allocate the pstat.sm";
- }
+ pstat.sm = (OicSecDpom_t*)OICCalloc(pstat.smLen, sizeof(pstat.sm));
+ ASSERT_TRUE(NULL != pstat.sm);
pstat.sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
pstat.sm[1] = SINGLE_SERVICE_SERVER_DRIVEN;
- char* jsonPstat = BinToPstatJSON(&pstat);
- if(!jsonPstat)
+
+ size_t size = 0;
+ uint8_t *cbor = NULL;
+ EXPECT_EQ(OC_STACK_OK, PstatToCBORPayload(&pstat, &cbor, &size));
+ if (!cbor)
{
OICFree(pstat.sm);
- FAIL() << "Failed to convert BinToPstatJSON";
+ FAIL() << "Failed to convert PstatToCBORPayload";
return;
}
- printf("BinToJSON Dump:\n%s\n\n", jsonPstat);
- EXPECT_TRUE(jsonPstat != NULL);
- OicSecPstat_t *pstat1 = JSONToPstatBin(jsonPstat);
- EXPECT_TRUE(pstat1 != NULL);
- if(pstat1)
- {
- OICFree(pstat1->sm);
- }
- OICFree(pstat1);
- OICFree(jsonPstat);
- OICFree(pstat.sm);
-}
-
-TEST(PstatTests, JSONMarshalliingTests)
-{
- char *jsonStr1 = ReadFile(UNIT_TEST_JSON_FILE_NAME);
- if (NULL != jsonStr1)
- {
- cJSON_Minify(jsonStr1);
- /* Workaround : cJSON_Minify does not remove all the unwanted characters
- from the end. Here is an attempt to remove those characters */
- int len = strlen(jsonStr1);
- while (len > 0)
- {
- if (jsonStr1[--len] == '}')
- {
- break;
- }
- }
- jsonStr1[len + 1] = 0;
-
- OicSecPstat_t* pstat = JSONToPstatBin(jsonStr1);
- EXPECT_TRUE(NULL != pstat);
-
- char* jsonStr2 = BinToPstatJSON(pstat);
- EXPECT_STRNE(jsonStr1, jsonStr2);
+ ASSERT_TRUE(NULL != cbor);
+ OicSecPstat_t *pstat1 = NULL;
+ EXPECT_EQ(OC_STACK_OK, CBORPayloadToPstat(cbor, size, &pstat1));
+ ASSERT_TRUE(NULL != pstat1);
+ EXPECT_EQ(pstat.commitHash, pstat1->commitHash);
+ EXPECT_EQ(pstat.isOp, pstat1->isOp);
+ EXPECT_EQ(pstat.tm, pstat1->tm);
+ EXPECT_EQ(pstat.om, pstat1->om);
+ EXPECT_EQ(pstat.smLen, pstat1->smLen);
+ EXPECT_EQ(pstat.sm[0], pstat1->sm[0]);
+ EXPECT_EQ(pstat.sm[1], pstat1->sm[1]);
- OICFree(jsonStr1);
- OICFree(jsonStr2);
- OICFree(pstat);
- }
- else
- {
- printf("Please copy %s into unittest folder\n", UNIT_TEST_JSON_FILE_NAME);
- }
+ DeletePstatBinData(pstat1);
+ OICFree(cbor);
+ OICFree(pstat.sm);
}