1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
25 #include "oic_malloc.h"
26 #include "ocpayload.h"
27 #include "payload_logging.h"
28 #include "resourcemanager.h"
29 #include "pstatresource.h"
30 #include "doxmresource.h"
31 #include "psinterface.h"
32 #include "srmresourcestrings.h"
33 #include "srmutility.h"
35 #define TAG "SRM-PSTAT"
37 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
38 * The value of payload size is increased until reaching below max cbor size. */
39 static const uint16_t CBOR_SIZE = 512;
41 // Max cbor size payload.
42 static const uint16_t CBOR_MAX_SIZE = 4400;
44 // PSTAT Map size - Number of mandatory items
45 static const uint8_t PSTAT_MAP_SIZE = 6;
47 // Number of writeable property
48 static const uint8_t WRITEABLE_PROPERTY_SIZE = 3;
50 static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
51 static OicSecPstat_t gDefaultPstat =
54 (OicSecDpm_t)(BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
55 PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t cm
56 (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
57 PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t tm
58 {.id = {0}}, // OicUuid_t deviceID
59 SINGLE_SERVICE_CLIENT_DRIVEN, // OicSecDpom_t om */
60 1, // the number of elts in Sms
61 &gSm, // OicSecDpom_t *sm
62 0, // uint16_t commitHash
63 {.id = {0}}, // OicUuid_t rownerID
66 static OicSecPstat_t *gPstat = NULL;
68 static OCResourceHandle gPstatHandle = NULL;
71 * This method is internal method.
72 * the param roParsed is optionally used to know whether cborPayload has
73 * at least read only property value or not.
75 static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const size_t size,
76 OicSecPstat_t **secPstat, bool *roParsed);
78 void DeletePstatBinData(OicSecPstat_t* pstat)
82 //Clean 'supported modes' field
90 OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size,
93 if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size)
95 return OC_STACK_INVALID_PARAM;
98 size_t cborLen = *size;
107 OCStackResult ret = OC_STACK_ERROR;
108 size_t pstatMapSize = PSTAT_MAP_SIZE;
110 CborEncoder pstatMap;
111 char* strUuid = NULL;
113 int64_t cborEncoderResult = CborNoError;
115 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
116 VERIFY_NON_NULL(TAG, outPayload, ERROR);
117 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
119 if (false == writableOnly)
121 pstatMapSize += WRITEABLE_PROPERTY_SIZE;
124 cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, pstatMapSize);
125 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
127 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME,
128 strlen(OIC_JSON_ISOP_NAME));
129 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag.");
130 cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp);
131 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value.");
133 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME,
134 strlen(OIC_JSON_CM_NAME));
135 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag.");
136 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm);
137 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value.");
139 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME,
140 strlen(OIC_JSON_TM_NAME));
141 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag.");
142 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm);
143 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value.");
145 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME,
146 strlen(OIC_JSON_OM_NAME));
147 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag.");
148 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om);
149 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value.");
151 if (false == writableOnly)
153 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME,
154 strlen(OIC_JSON_SM_NAME));
155 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag.");
156 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->sm[0]);
157 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Value.");
159 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME,
160 strlen(OIC_JSON_DEVICE_ID_NAME));
161 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
162 ret = ConvertUuidToStr(&pstat->deviceID, &strUuid);
163 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
164 cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
165 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
169 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ROWNERID_NAME,
170 strlen(OIC_JSON_ROWNERID_NAME));
171 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
172 ret = ConvertUuidToStr(&pstat->rownerID, &strUuid);
173 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
174 cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
175 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
182 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_RT_NAME,
183 strlen(OIC_JSON_RT_NAME));
184 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
185 cborEncoderResult = cbor_encoder_create_array(&pstatMap, &rtArray, 1);
186 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
187 for (size_t i = 0; i < 1; i++)
189 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_PSTAT,
190 strlen(OIC_RSRC_TYPE_SEC_PSTAT));
191 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
193 cborEncoderResult = cbor_encoder_close_container(&pstatMap, &rtArray);
194 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
198 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_IF_NAME,
199 strlen(OIC_JSON_IF_NAME));
200 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
201 cborEncoderResult = cbor_encoder_create_array(&pstatMap, &ifArray, 1);
202 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
203 for (size_t i = 0; i < 1; i++)
205 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
206 strlen(OC_RSRVD_INTERFACE_DEFAULT));
207 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
209 cborEncoderResult = cbor_encoder_close_container(&pstatMap, &ifArray);
210 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
212 cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap);
213 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map.");
215 if (CborNoError == cborEncoderResult)
217 *size = encoder.ptr - outPayload;
218 *payload = outPayload;
222 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
224 // reallocate and try again!
226 // Since the allocated initial memory failed, double the memory.
227 cborLen += encoder.ptr - encoder.end;
228 cborEncoderResult = CborNoError;
229 ret = PstatToCBORPayload(pstat, payload, &cborLen, writableOnly);
230 if (OC_STACK_OK == ret)
236 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
242 ret = OC_STACK_ERROR;
248 OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size,
249 OicSecPstat_t **secPstat)
251 return CBORPayloadToPstatBin(cborPayload, size, secPstat, NULL);
254 static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const size_t size,
255 OicSecPstat_t **secPstat, bool *roParsed)
257 if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat || 0 == size)
259 return OC_STACK_INVALID_PARAM;
262 OCStackResult ret = OC_STACK_ERROR;
267 CborError cborFindResult = CborNoError;
268 char *strUuid = NULL;
271 cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor);
272 CborValue pstatMap = { .parser = NULL };
274 OicSecPstat_t *pstat = NULL;
275 cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
276 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map.");
278 pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
279 VERIFY_NON_NULL(TAG, pstat, ERROR);
281 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap);
282 if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap))
284 cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp);
285 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value.");
289 pstat->isOp = gPstat->isOp;
290 cborFindResult = CborNoError;
293 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DEVICE_ID_NAME, &pstatMap);
294 if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
296 cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
297 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
298 ret = ConvertStrToUuid(strUuid , &pstat->deviceID);
299 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
310 memcpy(&pstat->deviceID, &gPstat->deviceID, sizeof(OicUuid_t));
311 cborFindResult = CborNoError;
314 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_CM_NAME, &pstatMap);
315 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
319 cborFindResult = cbor_value_get_int(&pstatMap, &cm);
320 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM.");
321 pstat->cm = (OicSecDpm_t)cm;
325 pstat->cm = gPstat->cm;
326 cborFindResult = CborNoError;
329 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap);
330 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
334 cborFindResult = cbor_value_get_int(&pstatMap, &tm);
335 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM.");
336 pstat->tm = (OicSecDpm_t)tm;
340 pstat->tm = gPstat->tm;
341 cborFindResult = CborNoError;
344 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_OM_NAME, &pstatMap);
345 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
349 cborFindResult = cbor_value_get_int(&pstatMap, &om);
350 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM.");
351 pstat->om = (OicSecDpom_t)om;
355 pstat->om = gPstat->om;
356 cborFindResult = CborNoError;
359 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap);
360 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
365 pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
366 cborFindResult = cbor_value_get_int(&pstatMap, &sm);
367 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM.");
368 pstat->sm[0] = (OicSecDpom_t)sm;
377 VERIFY_NON_NULL(TAG, gPstat, ERROR);
378 pstat->smLen = gPstat->smLen;
379 pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
380 *pstat->sm = *gPstat->sm;
381 cborFindResult = CborNoError;
384 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ROWNERID_NAME, &pstatMap);
385 if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
387 cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
388 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Id Value.");
389 ret = ConvertStrToUuid(strUuid , &pstat->rownerID);
390 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
401 VERIFY_NON_NULL(TAG, gPstat, ERROR);
402 memcpy(pstat->rownerID.id, gPstat->rownerID.id, sizeof(gPstat->rownerID.id));
403 cborFindResult = CborNoError;
410 if (CborNoError != cborFindResult)
412 OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed");
413 DeletePstatBinData(pstat);
416 ret = OC_STACK_ERROR;
423 * Function to update persistent storage
425 static bool UpdatePersistentStorage(OicSecPstat_t *pstat)
430 uint8_t *cborPayload = NULL;
431 OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size, false);
432 if (OC_STACK_OK == ret)
434 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
438 OICFree(cborPayload);
444 static bool ValidateQuery(const char * query)
446 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
452 bool bInterfaceQry = false; // does querystring contains 'if' query ?
453 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
455 OicParseQueryIter_t parseIter = {.attrPos = NULL};
457 ParseQueryIterInit((unsigned char*)query, &parseIter);
459 while (GetNextQuery(&parseIter))
461 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
463 bInterfaceQry = true;
464 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
466 bInterfaceMatch = true;
470 return (bInterfaceQry ? bInterfaceMatch: true);
474 * The entity handler determines how to process a GET request.
476 static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
478 OCEntityHandlerResult ehRet = OC_EH_OK;
480 OIC_LOG(INFO, TAG, "HandlePstatGetRequest processing GET request");
482 //Checking if Get request is a query.
483 if (ehRequest->query)
485 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
486 OIC_LOG(DEBUG, TAG, "HandlePstatGetRequest processing query");
487 if (!ValidateQuery(ehRequest->query))
494 * For GET or Valid Query request return doxm resource CBOR payload.
495 * For non-valid query return NULL json payload.
496 * A device will 'always' have a default Pstat, so PstatToCBORPayload will
497 * return valid pstat resource json.
500 uint8_t *payload = NULL;
501 if (ehRet == OC_EH_OK)
503 if(OC_STACK_OK != PstatToCBORPayload(gPstat, &payload, &size, false))
505 OIC_LOG(WARNING, TAG, "PstatToCBORPayload failed in HandlePstatGetRequest");
509 // Send response payload to request originator
510 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
511 OC_EH_OK : OC_EH_ERROR;
517 * The entity handler determines how to process a POST request.
518 * Per the REST paradigm, POST can also be used to update representation of existing
519 * resource or create a new resource.
520 * For pstat, it updates only tm and om.
522 static OCEntityHandlerResult HandlePstatPostRequest(const OCEntityHandlerRequest *ehRequest)
524 OCEntityHandlerResult ehRet = OC_EH_ERROR;
525 OIC_LOG(INFO, TAG, "HandlePstatPostRequest processing POST request");
526 OicSecPstat_t *pstat = NULL;
527 static uint16_t prevMsgId = 0;
529 if (ehRequest->payload && NULL != gPstat)
531 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
532 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
533 VERIFY_NON_NULL(TAG, payload, ERROR);
535 bool roParsed = false;
536 OCStackResult ret = CBORPayloadToPstatBin(payload, size, &pstat, &roParsed);
537 VERIFY_NON_NULL(TAG, pstat, ERROR);
538 if (OC_STACK_OK == ret)
540 bool validReq = false;
542 if (true == roParsed)
544 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
545 ehRet = OC_EH_NOT_ACCEPTABLE;
549 //operation mode(om) should be one of supported modes(sm)
550 for(size_t i = 0; i < gPstat->smLen; i++)
552 if(gPstat->sm[i] == pstat->om)
561 OIC_LOG_V(ERROR, TAG, "%d is unsupported Operation Mode", (int) pstat->om);
562 ehRet = OC_EH_BAD_REQ;
567 //Currently, we dose not support the multiple service server driven yet.
568 if (pstat->om != MULTIPLE_SERVICE_SERVER_DRIVEN)
570 if ((pstat->cm & RESET) && false == pstat->isOp)
573 OIC_LOG(INFO, TAG, "State changed to Ready for Reset");
575 else if ((pstat->cm & TAKE_OWNER) && false == pstat->isOp)
578 OIC_LOG (INFO, TAG, "State changed to Ready for Ownership transfer");
580 else if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
583 OIC_LOG(INFO, TAG, "State changed to Ready for Provisioning");
585 else if (false == (pstat->cm & TAKE_OWNER) && true == pstat->isOp)
588 OIC_LOG (INFO, TAG, "State changed to Ready for Normal Operation");
592 OIC_LOG(DEBUG, TAG, "Invalid Device provisionig state");
593 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
594 ehRet = OC_EH_BAD_REQ;
601 OIC_LOG(DEBUG, TAG, "Bad request for PSTAT");
602 ehRet = OC_EH_BAD_REQ;
606 gPstat->isOp = pstat->isOp;
607 gPstat->om = pstat->om;
608 gPstat->tm = pstat->tm;
609 gPstat->cm = pstat->cm;
611 // Convert pstat data into CBOR for update to persistent storage
612 if (UpdatePersistentStorage(gPstat))
616 if (true == (pstat->cm & RESET))
618 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
621 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
622 DeletePstatBinData(pstat);
625 ret = ResetSecureResourceInPS();
626 if (OC_STACK_OK == ret)
630 DeletePstatBinData(pstat);
637 if(OC_EH_OK != ehRet)
640 * If some error is occured while ownership transfer,
641 * ownership transfer related resource should be revert back to initial status.
643 const OicSecDoxm_t* doxm = GetDoxmResourceData();
646 if(!doxm->owned && prevMsgId != ehRequest->messageID)
648 RestoreDoxmToInitState();
649 RestorePstatToInitState();
654 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
659 prevMsgId = ehRequest->messageID;
662 // Send response payload to request originator
663 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
664 OC_EH_OK : OC_EH_ERROR;
666 DeletePstatBinData(pstat);
671 * This internal method is the entity handler for pstat resources.
673 OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
674 OCEntityHandlerRequest * ehRequest,
678 OCEntityHandlerResult ehRet = OC_EH_ERROR;
679 // This method will handle REST request (GET/POST) for /oic/sec/pstat
680 if (flag & OC_REQUEST_FLAG)
682 OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
683 switch (ehRequest->method)
686 ehRet = HandlePstatGetRequest(ehRequest);
689 ehRet = HandlePstatPostRequest(ehRequest);
692 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
693 OC_EH_OK : OC_EH_ERROR;
701 * This internal method is used to create '/oic/sec/pstat' resource.
703 OCStackResult CreatePstatResource()
705 OCStackResult ret = OCCreateResource(&gPstatHandle,
706 OIC_RSRC_TYPE_SEC_PSTAT,
707 OC_RSRVD_INTERFACE_DEFAULT,
714 if (OC_STACK_OK != ret)
716 OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource");
717 DeInitPstatResource();
723 * Get the default value.
725 * @return the gDefaultPstat pointer.
727 static OicSecPstat_t* GetPstatDefault()
729 return &gDefaultPstat;
732 OCStackResult InitPstatResource()
734 OCStackResult ret = OC_STACK_ERROR;
736 // Read Pstat resource from PS
737 uint8_t *data = NULL;
739 OicUuid_t emptyUuid = {.id={0}};
740 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size);
741 // If database read failed
742 if (OC_STACK_OK != ret)
744 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
748 // Read ACL resource from PS
749 ret = CBORPayloadToPstat(data, size, &gPstat);
753 * If SVR database in persistent storage got corrupted or
754 * is not available for some reason, a default pstat is created
755 * which allows user to initiate pstat provisioning again.
757 if ((OC_STACK_OK != ret) || !gPstat)
759 gPstat = GetPstatDefault();
761 VERIFY_NON_NULL(TAG, gPstat, FATAL);
763 //In case of Pstat's device id is empty, fill the device id as doxm's device id.
764 if(0 == memcmp(&gPstat->deviceID, &emptyUuid, sizeof(OicUuid_t)))
766 OicUuid_t doxmUuid = {.id={0}};
767 if(OC_STACK_OK == GetDoxmDeviceID(&doxmUuid))
769 memcpy(&gPstat->deviceID, &doxmUuid, sizeof(OicUuid_t));
773 // Instantiate 'oic.sec.pstat'
774 ret = CreatePstatResource();
777 if (OC_STACK_OK != ret)
779 DeInitPstatResource();
784 OCStackResult DeInitPstatResource()
786 if (gPstat != &gDefaultPstat)
788 DeletePstatBinData(gPstat);
791 return OCDeleteResource(gPstatHandle);
795 * Function to restore pstat resurce to initial status.
796 * This function will use in case of error while ownership transfer
798 void RestorePstatToInitState()
802 OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
804 gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER);
805 gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER));
806 gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
807 if(gPstat->sm && 0 < gPstat->smLen)
809 gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
812 if (!UpdatePersistentStorage(gPstat))
814 OIC_LOG(ERROR, TAG, "Failed to revert PSTAT in persistent storage");
819 OCStackResult SetPstatRownerId(const OicUuid_t* newROwner)
821 OCStackResult ret = OC_STACK_ERROR;
822 uint8_t *cborPayload = NULL;
824 OicUuid_t prevId = {.id={0}};
826 if(NULL == newROwner)
828 ret = OC_STACK_INVALID_PARAM;
832 ret = OC_STACK_NO_RESOURCE;
835 if(newROwner && gPstat)
837 memcpy(prevId.id, gPstat->rownerID.id, sizeof(prevId.id));
838 memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id));
840 ret = PstatToCBORPayload(gPstat, &cborPayload, &size, false);
841 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
843 ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size);
844 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
846 OICFree(cborPayload);
852 OICFree(cborPayload);
853 memcpy(gPstat->rownerID.id, prevId.id, sizeof(prevId.id));
858 * This function returns the "isop" status of the device.
860 * @return true iff pstat.isop == 1, else false
867 OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid)
869 OCStackResult retVal = OC_STACK_ERROR;
872 *rowneruuid = gPstat->rownerID;
873 retVal = OC_STACK_OK;