+OCStackResult PMSingleDeviceDiscoveryInUnicast(unsigned short waittime, const OicUuid_t* deviceID,
+ const char* hostAddress, OCConnectivityType connType,
+ OCProvisionDev_t **ppFoundDevice)
+{
+ OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscoveryInUnicast");
+
+ if (NULL != *ppFoundDevice)
+ {
+ OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if (NULL == deviceID)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid device ID");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ DiscoveryInfo *pDInfo = (DiscoveryInfo*)OICCalloc(1, sizeof(DiscoveryInfo));
+ if (NULL == pDInfo)
+ {
+ OIC_LOG(ERROR, TAG, "PMSingleDeviceDiscoveryInUnicast : Memory allocation failed.");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ pDInfo->ppDevicesList = ppFoundDevice;
+ pDInfo->pCandidateList = NULL;
+ pDInfo->isOwnedDiscovery = false;
+ pDInfo->isSingleDiscovery = true;
+ pDInfo->isFound = false;
+ pDInfo->targetId = deviceID;
+
+ OCCallbackData cbData;
+ cbData.cb = &DeviceDiscoveryHandler;
+ cbData.context = (void *)pDInfo;
+ cbData.cd = &DeviceDiscoveryDeleteHandler;
+
+ OCStackResult res = OC_STACK_ERROR;
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
+ if (hostAddress == NULL)
+ {
+ hostAddress = "";
+ }
+ snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "%s/oic/sec/doxm", hostAddress);
+ connType = connType & CT_MASK_ADAPTER;
+
+ OCDoHandle handle = NULL;
+ res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
+ connType, OC_HIGH_QOS, &cbData, NULL, 0);
+
+ if (res != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ OICFree(pDInfo);
+ pDInfo = NULL;
+ return res;
+ }
+
+ res = OC_STACK_OK;
+ uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
+ while (OC_STACK_OK == res && !pDInfo->isFound)
+ {
+ uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
+
+ long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
+ if (elapsed > waittime)
+ {
+ break;
+ }
+ res = OCProcess();
+ }
+
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to wait response for secure discovery.");
+ OICFree(pDInfo);
+ pDInfo = NULL;
+ OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+ if (OC_STACK_OK != resCancel)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+ }
+ return res;
+ }
+
+ res = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+ OICFree(pDInfo);
+ pDInfo = NULL;
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscoveryInUnicast");
+
+ if (!pDInfo->isFound)
+ {
+ res = OC_STACK_TIMEOUT;
+ }
+
+ OICFree(pDInfo);
+ pDInfo = NULL;
+ return res;
+}
+
+#ifdef MULTIPLE_OWNER
+static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ if (ctx == NULL)
+ {
+ OIC_LOG(ERROR, TAG, "Lost List of device information");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ (void)UNUSED;
+ if (clientResponse)
+ {
+ if (NULL == clientResponse->payload)
+ {
+ OIC_LOG(INFO, TAG, "Skipping Null payload");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ if (OC_STACK_OK != clientResponse->result)
+ {
+ OIC_LOG(INFO, TAG, "Error in response");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+ {
+ OIC_LOG(INFO, TAG, "Unknown payload type");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ OicSecDoxm_t *ptrDoxm = NULL;
+ uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
+ size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
+
+ OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
+ if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
+ {
+ OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
+
+ //If this is owend device discovery we have to filter out the responses.
+ DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
+ OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
+
+ // Get my device ID from doxm resource
+ OicUuid_t myId;
+ memset(&myId, 0, sizeof(myId));
+ OCStackResult res = GetDoxmDevOwnerId(&myId);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = GetDoxmDeviceID(&myId);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ //if this is owned discovery and this is PT's reply, discard it
+ if((pDInfo->isOwnedDiscovery) &&
+ (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))) )
+ {
+ OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ if(pDInfo->isOwnedDiscovery)
+ {
+ OicSecSubOwner_t* subOwner = NULL;
+ LL_FOREACH(ptrDoxm->subOwners, subOwner)
+ {
+ if(memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
+ {
+ break;
+ }
+ }
+
+ if(subOwner)
+ {
+ res = AddDevice(ppDevicesList, &clientResponse->devAddr,
+ clientResponse->connType, ptrDoxm);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = SecurePortDiscovery(pDInfo, clientResponse);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "discarding device's reply, because not a SubOwner.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ if(ptrDoxm->mom && OIC_MULTIPLE_OWNER_DISABLE != ptrDoxm->mom->mode)
+ {
+ res = AddDevice(ppDevicesList, &clientResponse->devAddr,
+ clientResponse->connType, ptrDoxm);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = SecurePortDiscovery(pDInfo, clientResponse);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "discarding mom disabled device's reply");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+
+ OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "Skiping Null response");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+/**
+ * Discover multiple OTM enabled devices in the same IP subnet.
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] ppDevicesList List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList)
+{
+ OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerEnabledDeviceDiscovery");
+
+ if (NULL != *ppDevicesList)
+ {
+ OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ char DOXM_MOM_ENABLE_MULTICAST_QUERY[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ char DOXM_MULTIPLE_OWNED_MULTICAST_QUERY[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ snprintf(DOXM_MOM_ENABLE_MULTICAST_QUERY, sizeof(DOXM_MOM_ENABLE_MULTICAST_QUERY),
+ "%s?%s=%d&%s=TRUE",
+ OIC_RSRC_DOXM_URI, OIC_JSON_MOM_NAME, OIC_MULTIPLE_OWNER_DISABLE,
+ OIC_JSON_OWNED_NAME);
+ snprintf(DOXM_MULTIPLE_OWNED_MULTICAST_QUERY, sizeof(DOXM_MOM_ENABLE_MULTICAST_QUERY),
+ "%s?%s=TRUE",
+ OIC_RSRC_DOXM_URI, OIC_JSON_OWNED_NAME);
+
+ DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
+ if(NULL == pDInfo)
+ {
+ OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ pDInfo->ppDevicesList = ppDevicesList;
+ pDInfo->pCandidateList = NULL;
+ pDInfo->isOwnedDiscovery = isMultipleOwned;
+
+ OCCallbackData cbData;
+ cbData.cb = &MOTDeviceDiscoveryHandler;
+ cbData.context = (void *)pDInfo;
+ cbData.cd = NULL;
+ OCStackResult res = OC_STACK_ERROR;
+
+ const char* query = isMultipleOwned ? DOXM_MULTIPLE_OWNED_MULTICAST_QUERY :
+ DOXM_MOM_ENABLE_MULTICAST_QUERY;
+
+ OCDoHandle handle = NULL;
+ res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
+ CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ OICFree(pDInfo);
+ return res;
+ }
+
+ //Waiting for each response.
+ res = PMTimeout(waittime, true);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
+ OICFree(pDInfo);
+ OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+ if(OC_STACK_OK != resCancel)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+ }
+ return res;
+ }
+ res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+ OICFree(pDInfo);
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerEnabledDeviceDiscovery");
+ OICFree(pDInfo);
+ return res;
+}
+
+#endif //MULTIPLE_OWNER
+
+static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
+ const OCClientResponse *clientResponse)
+{
+ OIC_LOG(DEBUG, TAG, "IN SecurePortDiscovery");
+
+ if(NULL == discoveryInfo || NULL == clientResponse)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t *pDev = GetDevice(&discoveryInfo->pCandidateList,
+ clientResponse->devAddr.addr, clientResponse->devAddr.port);
+ if(NULL == pDev)
+ {
+ OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to get device");
+ return OC_STACK_ERROR;
+ }
+
+ //Try to the unicast discovery to getting secure port
+ char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
+ if(!PMGenerateQuery(false,
+ pDev->endpoint.addr, pDev->endpoint.port,
+ pDev->connType,
+ query, sizeof(query), OC_RSRVD_WELL_KNOWN_URI))
+ {
+ OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ // Set filter query with rt=oic.r.doxm
+ const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
+ char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, query,
+ OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
+
+ OIC_LOG_V(DEBUG, TAG, "URI=%s", uri);
+
+ OCCallbackData cbData;
+ cbData.cb = &SecurePortDiscoveryHandler;
+ cbData.context = (void*)discoveryInfo;
+ cbData.cd = NULL;
+ OCStackResult ret = OCDoResource(&pDev->handle, OC_REST_DISCOVER, uri, 0, 0,
+ pDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ if(OC_STACK_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
+ return ret;
+ }
+ else
+ {
+ OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT SecurePortDiscovery");
+
+ return ret;
+}
+
+/*
+ * Since security version discovery does not used anymore, disable security version discovery.
+ * Need to discussion to removing all version discovery related codes.
+ */
+#if 0
+static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
+ const OCClientResponse *clientResponse)
+{
+ OIC_LOG(DEBUG, TAG, "IN SecurityVersionDiscovery");
+
+ if(NULL == discoveryInfo || NULL == clientResponse)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ //Try to the unicast discovery to getting security version
+ char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
+ if(!PMGenerateQuery(false,
+ clientResponse->devAddr.addr, clientResponse->devAddr.port,
+ clientResponse->connType,
+ query, sizeof(query), OIC_RSRC_VER_URI))
+ {
+ OIC_LOG(ERROR, TAG, "SecurityVersionDiscovery : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData;
+ cbData.cb = &SecurityVersionDiscoveryHandler;
+ cbData.context = (void*)discoveryInfo;
+ cbData.cd = NULL;
+ OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
+ clientResponse->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ if(OC_STACK_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Security Version Discovery");
+ return ret;
+ }
+ else
+ {
+ OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT SecurityVersionDiscovery");
+
+ return ret;
+}
+#endif
+