#include <stdlib.h>
#include <string.h>
+#include <inttypes.h>
#include "cainterface.h"
#include "logger.h"
#include "srmutility.h"
#include "pstatresource.h"
#include "doxmresource.h"
+#include "ocresourcehandler.h"
#define TAG "OIC_SRM_PSI"
-//SVR database buffer block size
+/**
+ * Helps cover adding the name of the resource, map addition, and ending while
+ * performing CBOR encoding.
+ */
+#define CBOR_ENCODING_SIZE_ADDITION 255
+
+/**
+ * Virtual database buffer block size
+ */
#ifdef _WIN32
#define DB_FILE_SIZE_BLOCK 1023
#else
const size_t DB_FILE_SIZE_BLOCK = 1023;
#endif
+typedef enum _PSDatabase
+{
+ PS_DATABASE_SECURITY = 0,
+ PS_DATABASE_DEVICEPROPERTIES
+} PSDatabase;
+
+/**
+ * Writes CBOR payload to the specified database in persistent storage.
+ *
+ * @param databaseName is the name of the database to access through persistent storage.
+ * @param payload is the CBOR payload to write to the database in persistent storage.
+ * @param size is the size of payload.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+static OCStackResult WritePayloadToPS(const char *databaseName, uint8_t *payload, size_t size)
+{
+ if (!databaseName || !payload || (size <= 0))
+ {
+ OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result = OC_STACK_ERROR;
+
+ OIC_LOG_V(DEBUG, TAG, "Writing in the file: %" PRIuPTR, size);
+
+ OCPersistentStorage* ps = OCGetPersistentStorageHandler();
+ if (ps)
+ {
+ FILE *fp = ps->open(databaseName, "wb");
+ if (fp)
+ {
+ size_t numberItems = ps->write(payload, 1, size, fp);
+ if (size == numberItems)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Written %" PRIuPTR " bytes into %s", size, databaseName);
+ result = OC_STACK_OK;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed writing %" PRIuPTR " in %s", numberItems, databaseName);
+ }
+ ps->close(fp);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "File open failed.");
+ }
+ }
+
+ return result;
+}
+
/**
- * Gets the Secure Virtual Database size
+ * Gets the database size
*
- * @param ps - pointer of OCPersistentStorage for the Secure Virtual Resource(s)
+ * @param ps is a pointer to OCPersistentStorage for the Virtual Resource(s).
+ * @param databaseName is the name of the database to access through persistent storage.
*
- * @return size_t - total size of the SVR database
+ * @return size_t - total size of the database
*/
-static size_t GetSVRDatabaseSize(const OCPersistentStorage *ps)
+static size_t GetDatabaseSize(const OCPersistentStorage *ps, const char *databaseName)
{
if (!ps)
{
size_t size = 0;
char buffer[DB_FILE_SIZE_BLOCK]; // can not initialize with declaration
// but maybe not needed to initialize
- FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
+ FILE *fp = ps->open(databaseName, "rb");
if (fp)
{
size_t bytesRead = 0;
}
/**
- * Gets the Secure Virtual Database from the Persistent Storage
+ * Reads the database from PS
+ *
+ * @note Caller of this method MUST use OICFree() method to release memory
+ * referenced by the data argument.
*
- * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
- * @param data - pointer of the returned Secure Virtual Resource(s)
- * @param size - pointer of the returned size of Secure Virtual Resource(s)
+ * @param databaseName is the name of the database to access through persistent storage.
+ * @param resourceName is the name of the field for which file content are read.
+ * if the value is NULL it will send the content of the whole file.
+ * @param data is the pointer to the file contents read from the database.
+ * @param size is the size of the file contents read.
*
- * @return OCStackResult - result of getting Secure Virtual Resource(s)
+ * @return ::OC_STACK_OK for Success, otherwise some error value
*/
-OCStackResult GetSecureVirtualDatabaseFromPS(const char *rsrcName, uint8_t **data, size_t *size)
+OCStackResult ReadDatabaseFromPS(const char *databaseName, const char *resourceName, uint8_t **data, size_t *size)
{
- OIC_LOG(DEBUG, TAG, "GetSecureVirtualDatabaseFromPS IN");
- if (!data || *data || !size)
+ OIC_LOG(DEBUG, TAG, "ReadDatabaseFromPS IN");
+
+ if (!databaseName || !data || *data || !size)
{
return OC_STACK_INVALID_PARAM;
}
size_t fileSize = 0;
OCStackResult ret = OC_STACK_ERROR;
- OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
+ OCPersistentStorage *ps = OCGetPersistentStorageHandler();
VERIFY_NOT_NULL(TAG, ps, ERROR);
- fileSize = GetSVRDatabaseSize(ps);
+ fileSize = GetDatabaseSize(ps, databaseName);
OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
if (fileSize)
{
fsData = (uint8_t *) OICCalloc(1, fileSize);
VERIFY_NOT_NULL(TAG, fsData, ERROR);
- fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
+ fp = ps->open(databaseName, "rb");
VERIFY_NOT_NULL(TAG, fp, ERROR);
if (ps->read(fsData, 1, fileSize, fp) == fileSize)
{
- if (rsrcName)
+ if (resourceName)
{
CborParser parser; // will be initialized in |cbor_parser_init|
CborValue cbor; // will be initialized in |cbor_parser_init|
cbor_parser_init(fsData, fileSize, 0, &parser, &cbor);
CborValue cborValue = {0};
- CborError cborFindResult = cbor_value_map_find_value(&cbor, rsrcName, &cborValue);
+ CborError cborFindResult = cbor_value_map_find_value(&cbor, resourceName, &cborValue);
if (CborNoError == cborFindResult && cbor_value_is_byte_string(&cborValue))
{
cborFindResult = cbor_value_dup_byte_string(&cborValue, data, size, NULL);
- VERIFY_SUCCESS(TAG, CborNoError==cborFindResult, ERROR);
+ VERIFY_SUCCESS(TAG, CborNoError == cborFindResult, ERROR);
ret = OC_STACK_OK;
}
// in case of |else (...)|, svr_data not found
}
- // return everything in case rsrcName is NULL
+ // return everything in case resourceName is NULL
else
{
*size = fileSize;
}
}
}
- OIC_LOG(DEBUG, TAG, "GetSecureVirtualDatabaseFromPS OUT");
+ OIC_LOG(DEBUG, TAG, "ReadDatabaseFromPS OUT");
exit:
if (fp)
}
/**
- * Updates the Secure Virtual Resource(s) into the Persistent Storage.
- * This function stores cbor-payload of each resource by appending resource name,
- * and empty payload implies deleting the value
+ * This method updates the database in PS
*
- * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
- * @param psPayload - pointer of the updated Secure Virtual Resource(s)
- * @param psSize - the updated size of Secure Virtual Resource(s)
+ * @param databaseName is the name of the database to access through persistent storage.
+ * @param resourceName is the name of the resource that will be updated.
+ * @param payload is the pointer to memory where the CBOR payload is located.
+ * @param size is the size of the CBOR payload.
*
- * @return OCStackResult - result of updating Secure Virtual Resource(s)
+ * @return ::OC_STACK_OK for Success, otherwise some error value
*/
-OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPayload, size_t psSize)
+OCStackResult UpdateResourceInPS(const char *databaseName, const char *resourceName, const uint8_t *payload, size_t size)
{
- OIC_LOG(DEBUG, TAG, "UpdateSecureResourceInPS IN");
- if (!rsrcName)
+ OIC_LOG(DEBUG, TAG, "UpdateResourceInPS IN");
+ if (!databaseName || !resourceName)
{
return OC_STACK_INVALID_PARAM;
}
uint8_t *pstatCbor = NULL;
uint8_t *doxmCbor = NULL;
uint8_t *amaclCbor = NULL;
- uint8_t *svcCbor = NULL;
uint8_t *credCbor = NULL;
uint8_t *pconfCbor = NULL;
uint8_t *resetPfCbor = NULL;
uint8_t *crlCbor = NULL;
+ uint8_t *dpCbor = NULL;
int64_t cborEncoderResult = CborNoError;
- OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
+ OCStackResult ret = ReadDatabaseFromPS(databaseName, NULL, &dbData, &dbSize);
if (dbData && dbSize)
{
+ PSDatabase database = PS_DATABASE_SECURITY;
+ size_t allocSize = 0;
size_t aclCborLen = 0;
size_t pstatCborLen = 0;
size_t doxmCborLen = 0;
size_t amaclCborLen = 0;
- size_t svcCborLen = 0;
size_t credCborLen = 0;
size_t pconfCborLen = 0;
size_t resetPfCborLen = 0;
size_t crlCborLen = 0;
+ size_t dpCborLen = 0;
+
+ // Determine which database we are working with so we can scope our operations
+ if (0 == strcmp(OC_DEVICE_PROPS_FILE_NAME, databaseName))
+ {
+ database = PS_DATABASE_DEVICEPROPERTIES;
+ }
// Gets each secure virtual resource from persistent storage
// this local scoping intended, for destroying large cbor instances after use
CborValue curVal = {0};
CborError cborFindResult = CborNoError;
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
- }
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
- }
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
- }
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_AMACL_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindResult = cbor_value_dup_byte_string(&curVal, &amaclCbor, &amaclCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMACL Name Value.");
- }
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
- }
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PCONF_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
- }
- cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
- if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ // Only search for and copy resources owned by the target database
+ if (PS_DATABASE_SECURITY == database)
{
- cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
- }
- int64_t cborFindCrlResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRL_NAME, &curVal);
- if (CborNoError == cborFindCrlResult && cbor_value_is_byte_string(&curVal))
- {
- cborFindCrlResult = cbor_value_dup_byte_string(&curVal, &crlCbor, &crlCborLen, NULL);
- if (CborNoError != cborFindCrlResult && CborErrorOutOfMemory != cborFindCrlResult)
+ // Security database
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_AMACL_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &amaclCbor, &amaclCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMACL Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
{
- OIC_LOG(ERROR, TAG, "Failed Finding optional CRL Name Value.");
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PCONF_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
+ }
+ int64_t cborFindCrlResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRL_NAME, &curVal);
+ if ((CborNoError == cborFindCrlResult) && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindCrlResult = cbor_value_dup_byte_string(&curVal, &crlCbor, &crlCborLen, NULL);
+ if ((CborNoError != cborFindCrlResult) && (CborErrorOutOfMemory != cborFindCrlResult))
+ {
+ OIC_LOG(ERROR, TAG, "Failed Finding optional CRL Name Value.");
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "Successfully Finding optional CRL Name Value.");
+ }
}
- else
+ }
+ else
+ {
+ // Device Properties database
+ cborFindResult = cbor_value_map_find_value(&cbor, OC_JSON_DEVICE_PROPS_NAME, &curVal);
+ if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
{
- OIC_LOG(INFO, TAG, "Successfully Finding optional CRL Name Value.");
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &dpCbor, &dpCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Properties Name Value.");
}
}
}
- // Updates the added |psPayload| with the existing secure virtual resource(s)
+ // Updates the added |payload| with the existing secure virtual resource(s)
// this local scoping intended, for destroying large cbor instances after use
{
- size_t size = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
- + svcCborLen + credCborLen + pconfCborLen + resetPfCborLen + crlCborLen
- + psSize + 255;
- // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
+ if (PS_DATABASE_SECURITY == database)
+ {
+ allocSize = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
+ + credCborLen + pconfCborLen + resetPfCborLen + crlCborLen
+ + size + CBOR_ENCODING_SIZE_ADDITION;
+ }
+ else
+ {
+ allocSize = dpCborLen + size + CBOR_ENCODING_SIZE_ADDITION;
+ }
- outPayload = (uint8_t *) OICCalloc(1, size);
+
+ outPayload = (uint8_t *)OICCalloc(1, allocSize);
VERIFY_NOT_NULL(TAG, outPayload, ERROR);
CborEncoder encoder; // will be initialized in |cbor_parser_init|
- cbor_encoder_init(&encoder, outPayload, size, 0);
- CborEncoder secRsrc; // will be initialized in |cbor_encoder_create_map|
- cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
+ cbor_encoder_init(&encoder, outPayload, allocSize, 0);
+ CborEncoder resource; // will be initialized in |cbor_encoder_create_map|
+ cborEncoderResult |= cbor_encoder_create_map(&encoder, &resource, CborIndefiniteLength);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
- if (psPayload && psSize)
+ if (payload && size)
{
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, rsrcName, strlen(rsrcName));
+ cborEncoderResult |= cbor_encode_text_string(&resource, resourceName, strlen(resourceName));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, psPayload, psSize);
+ cborEncoderResult |= cbor_encode_byte_string(&resource, payload, size);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
}
- if (strcmp(OIC_JSON_ACL_NAME, rsrcName) && aclCborLen)
- {
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
- }
- if (strcmp(OIC_JSON_PSTAT_NAME, rsrcName) && pstatCborLen)
- {
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
- }
- if (strcmp(OIC_JSON_DOXM_NAME, rsrcName) && doxmCborLen)
- {
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
- }
- if (strcmp(OIC_JSON_AMACL_NAME, rsrcName) && amaclCborLen)
- {
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, amaclCbor, amaclCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Value.");
- }
- if (strcmp(OIC_JSON_CRED_NAME, rsrcName) && credCborLen)
- {
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Value.");
- }
- if (strcmp(OIC_JSON_PCONF_NAME, rsrcName) && pconfCborLen)
- {
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PCONF_NAME, strlen(OIC_JSON_PCONF_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pconfCbor, pconfCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
- }
- if (strcmp(OIC_JSON_RESET_PF_NAME, rsrcName) && resetPfCborLen)
+
+ if (PS_DATABASE_SECURITY == database)
{
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
+ // Security database
+ if (strcmp(OIC_JSON_ACL_NAME, resourceName) && aclCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, aclCbor, aclCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
+ }
+ else if (strcmp(OIC_JSON_PSTAT_NAME, resourceName) && pstatCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, pstatCbor, pstatCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
+ }
+ else if (strcmp(OIC_JSON_DOXM_NAME, resourceName) && doxmCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, doxmCbor, doxmCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
+ }
+ else if (strcmp(OIC_JSON_AMACL_NAME, resourceName) && amaclCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, amaclCbor, amaclCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Value.");
+ }
+ else if (strcmp(OIC_JSON_CRED_NAME, resourceName) && credCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, credCbor, credCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Value.");
+ }
+ else if (strcmp(OIC_JSON_PCONF_NAME, resourceName) && pconfCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_PCONF_NAME, strlen(OIC_JSON_PCONF_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, pconfCbor, pconfCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
+ }
+ else if (strcmp(OIC_JSON_RESET_PF_NAME, resourceName) && resetPfCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, resetPfCbor, resetPfCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
+ }
+ else if (strcmp(OIC_JSON_CRL_NAME, resourceName) && crlCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_CRL_NAME, strlen(OIC_JSON_CRL_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, crlCbor, crlCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Value.");
+ }
}
- if (strcmp(OIC_JSON_CRL_NAME, rsrcName) && crlCborLen)
+ else
{
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRL_NAME, strlen(OIC_JSON_CRL_NAME));
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Name.");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, crlCbor, crlCborLen);
- VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Value.");
+ // Device Properties database
+ if (strcmp(OC_JSON_DEVICE_PROPS_NAME, resourceName) && dpCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&resource, OC_JSON_DEVICE_PROPS_NAME, strlen(OC_JSON_DEVICE_PROPS_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Properties Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&resource, dpCbor, dpCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Properties Value.");
+ }
}
- cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
+ cborEncoderResult |= cbor_encoder_close_container(&encoder, &resource);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
}
}
- else if (psPayload && psSize)
+ else if (payload && size)
{
- size_t size = psSize + 255;
- // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
+ size_t allocSize = size + CBOR_ENCODING_SIZE_ADDITION;
- outPayload = (uint8_t *) OICCalloc(1, size);
+ outPayload = (uint8_t *)OICCalloc(1, allocSize);
VERIFY_NOT_NULL(TAG, outPayload, ERROR);
CborEncoder encoder; // will be initialized in |cbor_parser_init|
- cbor_encoder_init(&encoder, outPayload, size, 0);
- CborEncoder secRsrc; // will be initialized in |cbor_encoder_create_map|
- cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
+ cbor_encoder_init(&encoder, outPayload, allocSize, 0);
+ CborEncoder resource; // will be initialized in |cbor_encoder_create_map|
+ cborEncoderResult |= cbor_encoder_create_map(&encoder, &resource, CborIndefiniteLength);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
- cborEncoderResult |= cbor_encode_text_string(&secRsrc, rsrcName, strlen(rsrcName));
+ cborEncoderResult |= cbor_encode_text_string(&resource, resourceName, strlen(resourceName));
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
- cborEncoderResult |= cbor_encode_byte_string(&secRsrc, psPayload, psSize);
+ cborEncoderResult |= cbor_encode_byte_string(&resource, payload, size);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
- cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
+ cborEncoderResult |= cbor_encoder_close_container(&encoder, &resource);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
}
- if (outPayload && outSize)
- {
- OIC_LOG_V(DEBUG, TAG, "Writing in the file: %zu", outSize);
- OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
- if (ps)
- {
- FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "wb");
- if (fp)
- {
- size_t numberItems = ps->write(outPayload, 1, outSize, fp);
- if (outSize == numberItems)
- {
- OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", outSize);
- ret = OC_STACK_OK;
- }
- else
- {
- OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
- }
- ps->close(fp);
- }
- else
- {
- OIC_LOG(ERROR, TAG, "File open failed.");
- }
- }
- }
+ ret = WritePayloadToPS(databaseName, outPayload, outSize);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR);
- OIC_LOG(DEBUG, TAG, "UpdateSecureResourceInPS OUT");
+ OIC_LOG(DEBUG, TAG, "UpdateResourceInPS OUT");
exit:
OICFree(dbData);
OICFree(pstatCbor);
OICFree(doxmCbor);
OICFree(amaclCbor);
- OICFree(svcCbor);
OICFree(credCbor);
OICFree(pconfCbor);
OICFree(resetPfCbor);
OICFree(crlCbor);
+ OICFree(dpCbor);
return ret;
}
/**
+ * Reads the Secure Virtual Database from PS
+ *
+ * @note Caller of this method MUST use OICFree() method to release memory
+ * referenced by return value.
+ *
+ * @param resourceName is the name of the field for which file content are read.
+ * if the value is NULL it will send the content of the whole file.
+ * @param data is the pointer to the file contents read from the database.
+ * @param size is the size of the file contents read.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult GetSecureVirtualDatabaseFromPS(const char *resourceName, uint8_t **data, size_t *size)
+{
+ return ReadDatabaseFromPS(SVR_DB_DAT_FILE_NAME, resourceName, data, size);
+}
+
+/**
+ * This method updates the Secure Virtual Database in PS
+ *
+ * @param resourceName is the name of the secure resource that will be updated.
+ * @param payload is the pointer to memory where the CBOR payload is located.
+ * @param size is the size of the CBOR payload.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult UpdateSecureResourceInPS(const char *resourceName, const uint8_t *payload, size_t size)
+{
+ return UpdateResourceInPS(SVR_DB_DAT_FILE_NAME, resourceName, payload, size);
+}
+
+/**
* Resets the Secure Virtual Resource(s).
* This function reads the Reset Profile
* and resets the secure virtual resources accordingly.
int64_t cborEncoderResult = CborNoError;
OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
-
if(dbData && dbSize)
{
size_t aclCborLen = 0;
}
{
- size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + resetPfCborLen + 255;
- // This added '255' is arbitrary value added to cover the name of the resource, map addition, and ending
+ size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + resetPfCborLen + CBOR_ENCODING_SIZE_ADDITION;
outPayload = (uint8_t *) OICCalloc(1, size);
VERIFY_NOT_NULL(TAG, outPayload, ERROR);
outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
}
- if (outPayload && outSize)
- {
- OIC_LOG_V(DEBUG, TAG, "Writing in the file: %zu", outSize);
- OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
- if (ps)
- {
- FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "wb");
- if (fp)
- {
- size_t numberItems = ps->write(outPayload, 1, outSize, fp);
- if (outSize == numberItems)
- {
- OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", outSize);
- ret= OC_STACK_OK;
- }
- else
- {
- OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
- }
- ps->close(fp);
- }
- else
- {
- OIC_LOG(ERROR, TAG, "File open failed.");
- }
-
- }
- }
+ ret = WritePayloadToPS(SVR_DB_DAT_FILE_NAME, outPayload, outSize);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR);
}
SRMDeInitSecureResources();
}
{
- size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + 255;
+ size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + CBOR_ENCODING_SIZE_ADDITION;
resetPfCbor = (uint8_t *) OICCalloc(1, size);
VERIFY_NOT_NULL(TAG, resetPfCbor, ERROR);
CborEncoder encoder; // will be initialized in |cbor_parser_init|
#include "ocendpoint.h"
#include "ocstackinternal.h"
#include "oickeepalive.h"
+#include "ocpayloadcbor.h"
+#include "psinterface.h"
#ifdef ROUTING_GATEWAY
#include "routingmanager.h"
/// Module Name
#define TAG "OIC_RI_RESOURCE"
-// using 1k as block size since most persistent storage implementations use a power of 2.
-#define INTROSPECTION_FILE_SIZE_BLOCK 1024
+// Using 1k as block size since most persistent storage implementations use a power of 2.
+#define INTROSPECTION_FILE_SIZE_BLOCK 1024
#define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \
{OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
+/**
+ * Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
+ * The value of payload size is increased up to CBOR_MAX_SIZE.
+ */
+static const uint16_t CBOR_SIZE = 512;
+
+/**
+ * Max cbor size payload.
+ */
+static const uint16_t CBOR_MAX_SIZE = 4400;
+
extern OCResource *headResource;
/**
CAEndpoint_t *networkInfo,
size_t infoSize);
+/**
+ * Sets the value of an attribute on a resource.
+ */
+static OCStackResult SetAttributeInternal(OCResource *resource,
+ const char *attribute,
+ const void *value,
+ bool updateDatabase);
+
//-----------------------------------------------------------------------------
// Default resource entity handler function
//-----------------------------------------------------------------------------
return OC_STACK_OK;
}
+void CleanUpDeviceProperties(OCDeviceProperties **deviceProperties)
+{
+ if (!deviceProperties || !(*deviceProperties))
+ {
+ return;
+ }
+
+ OICFreeAndSetToNull((void**)(deviceProperties));
+}
+
+static OCStackResult CreateDeviceProperties(const char *piid, OCDeviceProperties **deviceProperties)
+{
+ OIC_LOG(DEBUG, TAG, "CreateDeviceProperties IN");
+
+ OCStackResult result = OC_STACK_OK;
+
+ if (!piid || !deviceProperties)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ *deviceProperties = (OCDeviceProperties*)OICCalloc(1, sizeof(OCDeviceProperties));
+ if (*deviceProperties)
+ {
+ OICStrcpy((*deviceProperties)->protocolIndependentId, UUID_STRING_SIZE, piid);
+ }
+ else
+ {
+ result = OC_STACK_NO_MEMORY;
+ }
+
+ OIC_LOG(DEBUG, TAG, "CreateDeviceProperties OUT");
+
+ return result;
+}
+
+static OCStackResult GenerateDeviceProperties(OCDeviceProperties **deviceProperties)
+{
+ OCStackResult result = OC_STACK_OK;
+ OicUuid_t generatedProtocolIndependentId = {.id = {0}};
+ char* protocolIndependentId = NULL;
+
+ if (!deviceProperties)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ *deviceProperties = NULL;
+
+ // Generate a UUID for the Protocol Independent ID
+ if (OCGenerateUuid(generatedProtocolIndependentId.id))
+ {
+ protocolIndependentId = (char*)OICCalloc(UUID_STRING_SIZE, sizeof(char));
+ if (protocolIndependentId)
+ {
+ if (!OCConvertUuidToString(generatedProtocolIndependentId.id, protocolIndependentId))
+ {
+ OIC_LOG(ERROR, TAG, "ConvertUuidToStr failed");
+ result = OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ result = OC_STACK_NO_MEMORY;
+ }
+ }
+ else
+ {
+ OIC_LOG(FATAL, TAG, "Generate UUID for Device Properties Protocol Independent ID failed!");
+ result = OC_STACK_ERROR;
+ }
+
+ if (OC_STACK_OK == result)
+ {
+ result = CreateDeviceProperties(protocolIndependentId, deviceProperties);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed");
+ }
+ }
+
+ // Clean Up
+ OICFreeAndSetToNull((void**)&protocolIndependentId);
+
+ return result;
+}
+
+OCStackResult CBORPayloadToDeviceProperties(const uint8_t *payload, size_t size, OCDeviceProperties **deviceProperties)
+{
+ OCStackResult result = OC_STACK_OK;
+ CborError cborResult = CborNoError;
+ char* protocolIndependentId = NULL;
+ CborParser parser;
+ CborValue dpCbor;
+ CborValue dpMap;
+
+ if (!payload || (size <= 0) || !deviceProperties)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ *deviceProperties = NULL;
+
+ cbor_parser_init(payload, size, 0, &parser, &dpCbor);
+
+ // Protocol Independent ID - Mandatory
+ cborResult = cbor_value_map_find_value(&dpCbor, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, &dpMap);
+ if ((CborNoError == cborResult) && cbor_value_is_text_string(&dpMap))
+ {
+ size_t len = 0;
+
+ cborResult = cbor_value_dup_text_string(&dpMap, &protocolIndependentId, &len, NULL);
+ if (CborNoError != cborResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to get Protocol Independent Id!");
+ result = OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Protocol Independent Id is not present or invalid!");
+ result = OC_STACK_ERROR;
+ }
+
+ if (OC_STACK_OK == result)
+ {
+ result = CreateDeviceProperties(protocolIndependentId, deviceProperties);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed");
+ }
+ }
+
+ // Clean Up
+ OICFreeAndSetToNull((void**)&protocolIndependentId);
+
+ return result;
+}
+
+OCStackResult DevicePropertiesToCBORPayload(const OCDeviceProperties *deviceProperties, uint8_t **payload, size_t *size)
+{
+ OCStackResult result = OC_STACK_OK;
+ CborError cborResult = CborNoError;
+ uint8_t *cborPayload = NULL;
+ size_t cborLen = CBOR_SIZE;
+ CborEncoder encoder;
+ CborEncoder dpMap;
+
+ if (!deviceProperties || !payload || !size || (*size > CBOR_MAX_SIZE))
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Reset the CBOR length if we need to
+ if (*size > 0)
+ {
+ cborLen = *size;
+ }
+
+ *payload = NULL;
+ *size = 0;
+
+ cborPayload = (uint8_t*)OICCalloc(1, cborLen);
+ if (NULL != cborPayload)
+ {
+ cbor_encoder_init(&encoder, cborPayload, cborLen, 0);
+
+ // Create the Device Properties encoder map
+ cborResult = cbor_encoder_create_map(&encoder, &dpMap, CborIndefiniteLength);
+ if (CborNoError != cborResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create encoder map!");
+ result = OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ result = OC_STACK_NO_MEMORY;
+ }
+
+ // Protocol Independent ID - Mandatory
+ if (OC_STACK_OK == result)
+ {
+ cborResult = cbor_encode_text_string(&dpMap, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, strlen(OC_RSRVD_PROTOCOL_INDEPENDENT_ID));
+ if (CborNoError == cborResult)
+ {
+ cborResult = cbor_encode_text_string(&dpMap,
+ deviceProperties->protocolIndependentId,
+ strlen(deviceProperties->protocolIndependentId));
+ if (CborNoError != cborResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to encode protocolIndependentId!");
+ result = OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to encode OC_RSRVD_PROTOCOL_INDEPENDENT_ID!");
+ result = OC_STACK_ERROR;
+ }
+ }
+
+ // Encoding is finished
+ if (OC_STACK_OK == result)
+ {
+ cborResult = cbor_encoder_close_container(&encoder, &dpMap);
+ if (CborNoError != cborResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to close dpMap container!");
+ result = OC_STACK_ERROR;
+ }
+ }
+
+ if (OC_STACK_OK == result)
+ {
+ *size = cbor_encoder_get_buffer_size(&encoder, cborPayload);
+ *payload = cborPayload;
+ cborPayload = NULL;
+ }
+ else if ((CborErrorOutOfMemory == cborResult) && (cborLen < CBOR_MAX_SIZE))
+ {
+ OICFreeAndSetToNull((void**)&cborPayload);
+
+ // Realloc and try again
+ cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
+ result = DevicePropertiesToCBORPayload(deviceProperties, payload, &cborLen);
+ if (OC_STACK_OK == result)
+ {
+ *size = cborLen;
+ }
+ }
+ else
+ {
+ OICFreeAndSetToNull((void**)&cborPayload);
+ }
+
+ return result;
+}
+
+static OCStackResult UpdateDeviceInfoResourceWithDeviceProperties(const OCDeviceProperties *deviceProperties, bool updateDatabase)
+{
+ OCStackResult result = OC_STACK_OK;
+ OCResource *resource = NULL;
+
+ if (!deviceProperties)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
+ if (resource)
+ {
+ result = SetAttributeInternal(resource, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, deviceProperties->protocolIndependentId, updateDatabase);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "OCSetPropertyValue failed to set Protocol Independent ID");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Resource does not exist.");
+ result = OC_STACK_NO_RESOURCE;
+ }
+
+ return result;
+}
+
+static OCStackResult ReadDevicePropertiesFromDatabase(OCDeviceProperties **deviceProperties)
+{
+ uint8_t *data = NULL;
+ size_t size = 0;
+
+ OCStackResult result = ReadDatabaseFromPS(OC_DEVICE_PROPS_FILE_NAME, OC_JSON_DEVICE_PROPS_NAME, &data, &size);
+ if (OC_STACK_OK == result)
+ {
+ // Read device properties from PS
+ result = CBORPayloadToDeviceProperties(data, size, deviceProperties);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(WARNING, TAG, "CBORPayloadToDeviceProperties failed");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "ReadDatabaseFromPS failed");
+ }
+
+ // Clean Up
+ OICFreeAndSetToNull((void**)&data);
+
+ return result;
+}
+
+static OCStackResult UpdateDevicePropertiesDatabase(const OCDeviceProperties *deviceProperties)
+{
+ OCStackResult result = OC_STACK_OK;
+ uint8_t *payload = NULL;
+ size_t size = 0;
+
+ if (!deviceProperties)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Check to see if persistent storage exists. If it doesn't then
+ // we just allow the device properties to exist in memory and
+ // it is the application's job to manage them.
+ if (!OCGetPersistentStorageHandler())
+ {
+ OIC_LOG(DEBUG, TAG, "Persistent Storage handler is NULL.");
+ return OC_STACK_OK;
+ }
+
+ // Convert OCDeviceProperties into CBOR to use for updating Persistent Storage
+ result = DevicePropertiesToCBORPayload(deviceProperties, &payload, &size);
+ if ((OC_STACK_OK == result) && payload)
+ {
+ result = UpdateResourceInPS(OC_DEVICE_PROPS_FILE_NAME, OC_JSON_DEVICE_PROPS_NAME, payload, size);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG_V(ERROR, TAG, "UpdateResourceInPS failed with %d!", result);
+ }
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "DevicePropertiesToCBORPayload failed with %d!", result);
+ }
+
+ // Clean Up
+ OICFreeAndSetToNull((void**)&payload);
+
+ return result;
+}
+
+OCStackResult InitializeDeviceProperties()
+{
+ OIC_LOG(DEBUG, TAG, "InitializeDeviceProperties IN");
+
+ OCStackResult result = OC_STACK_OK;
+ OCDeviceProperties *deviceProperties = NULL;
+ bool updateDatabase = false;
+
+ // Populate OCDeviceProperties from persistent storage
+ result = ReadDevicePropertiesFromDatabase(&deviceProperties);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "ReadDevicePropertiesFromDatabase failed");
+ }
+
+ // If the device properties in persistent storage are corrupted or
+ // not available for some reason, a default OCDeviceProperties is created.
+ if ((OC_STACK_OK != result) || !deviceProperties)
+ {
+ result = GenerateDeviceProperties(&deviceProperties);
+ if (OC_STACK_OK == result)
+ {
+ updateDatabase = true;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "GenerateDeviceProperties failed");
+ }
+ }
+
+ // Set the device properties information on the device info resource. This will
+ // also persist OCDeviceProperties so they can be used in the future if they are
+ // not already in the database.
+ if (OC_STACK_OK == result)
+ {
+ result = UpdateDeviceInfoResourceWithDeviceProperties(deviceProperties, updateDatabase);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "UpdateDeviceInfoResourceWithDeviceProperties failed");
+ }
+ }
+
+ // Clean Up
+ CleanUpDeviceProperties(&deviceProperties);
+
+ OIC_LOG(DEBUG, TAG, "InitializeDeviceProperties OUT");
+
+ return result;
+}
+
static size_t GetIntrospectionDataSize(const OCPersistentStorage *ps)
{
size_t size = 0;
return res;
}
-OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value)
+static OCStackResult SetAttributeInternal(OCResource *resource,
+ const char *attribute,
+ const void *value,
+ bool updateDatabase)
{
- // See if the attribute already exists in the list.
OCAttribute *resAttrib = NULL;
+
+ // See if the attribute already exists in the list.
for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
{
if (0 == strcmp(attribute, resAttrib->attrName))
}
VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
+ // The resource has changed from what is stored in the database. Update the database to
+ // reflect the new value.
+ if (updateDatabase)
+ {
+ OCDeviceProperties *deviceProperties = NULL;
+
+ OCStackResult result = CreateDeviceProperties((const char*)value, &deviceProperties);
+ if (OC_STACK_OK == result)
+ {
+ result = UpdateDevicePropertiesDatabase(deviceProperties);
+ if (OC_STACK_OK != result)
+ {
+ OIC_LOG(ERROR, TAG, "UpdateDevicePropertiesDatabase failed!");
+ }
+
+ CleanUpDeviceProperties(&deviceProperties);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed!");
+ }
+ }
+
return OC_STACK_OK;
exit:
OCDeleteResourceAttributes(resAttrib);
return OC_STACK_NO_MEMORY;
+}
+
+static OCStackResult IsDatabaseUpdateNeeded(const char *attribute, const void *value, bool *update)
+{
+ OCStackResult result = OC_STACK_OK;
+ void *currentPIID = NULL;
+
+ if (!attribute || !value || !update)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ *update = false;
+
+ // Protocol Independent ID
+ if (0 == strcmp(OC_RSRVD_PROTOCOL_INDEPENDENT_ID, attribute))
+ {
+ result = OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, ¤tPIID);
+ if (OC_STACK_OK == result)
+ {
+ // PIID has already been set on the resource and stored in the database. Check to see
+ // if the value is changing so the database can be updated accordingly.
+ if (0 != strcmp((char *)currentPIID, (char*)value))
+ {
+ *update = true;
+ }
+ }
+ else if (OC_STACK_NO_RESOURCE == result)
+ {
+ // PIID has not been set yet so we should always update the database.
+ *update = true;
+ result = OC_STACK_OK;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG,
+ "Call to OCGetPropertyValue for the current PIID failed with error: %d", result);
+ }
+ }
+
+ // Clean Up
+ OICFreeAndSetToNull(¤tPIID);
+
+ return result;
+}
+
+OCStackResult OCSetAttribute(OCResource *resource, const char *attribute, const void *value)
+{
+ bool updateDatabase = false;
+
+ // Check to see if we also need to update the database for this attribute. If the current
+ // value matches what is stored in the database we can skip the update and an unnecessary
+ // write.
+ if (OC_STACK_OK != IsDatabaseUpdateNeeded(attribute, value, &updateDatabase))
+ {
+ OIC_LOG_V(WARNING, TAG,
+ "Could not determine if a database update was needed for %s. Proceeding without updating the database.",
+ attribute);
+ updateDatabase = false;
+ }
+ return SetAttributeInternal(resource, attribute, value, updateDatabase);
}
OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)