-//******************************************************************\r
-//\r
-// Copyright 2015 Samsung Electronics All Rights Reserved.\r
-//\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
-//\r
-// Licensed under the Apache License, Version 2.0 (the "License");\r
-// you may not use this file except in compliance with the License.\r
-// You may obtain a copy of the License at\r
-//\r
-// http://www.apache.org/licenses/LICENSE-2.0\r
-//\r
-// Unless required by applicable law or agreed to in writing, software\r
-// distributed under the License is distributed on an "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-// See the License for the specific language governing permissions and\r
-// limitations under the License.\r
-//\r
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <signal.h>\r
-#include <unistd.h>\r
-#include "ocpayload.h"\r
-#include "provisioninghandler.h"\r
-\r
-// External includes\r
-\r
-#include "camutex.h"\r
-#include "cathreadpool.h"\r
-#include "logger.h"\r
-#include "oic_malloc.h"\r
-\r
-\r
-/**\r
- * @var g_provisioningMutex\r
- * @brief Mutex to synchronize access to g_caDtlsContext.\r
- */\r
-static ca_mutex g_provisioningMutex = NULL;\r
-static ca_cond g_provisioningCond = NULL;\r
-bool g_provisioningCondFlag = false;\r
-\r
-static EnrolleeNWProvInfo_t* netProvInfo;\r
-\r
-/**\r
- * @var cbData\r
- * @brief Callback for providing provisioning status callback to application\r
- */\r
-static OCProvisioningStatusCB cbData = NULL;\r
-static ca_thread_pool_t g_threadPoolHandle = NULL;\r
-\r
-OCStackResult InitProvisioningHandler() {\r
- OCStackResult ret = OC_STACK_ERROR;\r
- /* Initialize OCStack*/\r
- if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack init error");\r
- return ret;\r
- }\r
-\r
- g_provisioningMutex = ca_mutex_new();\r
-\r
- OIC_LOG(DEBUG, TAG, "ca_thread_pool_init initializing");\r
-\r
- if (CA_STATUS_OK != ca_thread_pool_init(2, &g_threadPoolHandle)) {\r
- OIC_LOG(DEBUG, TAG, "thread_pool_init failed");\r
- return OC_STACK_ERROR;\r
- }\r
-\r
- g_provisioningCond = ca_cond_new();\r
- if (NULL == g_provisioningCond) {\r
- OIC_LOG(DEBUG, TAG, "Failed to create condition");\r
- ca_mutex_free(g_provisioningMutex);\r
- ca_thread_pool_free(g_threadPoolHandle);\r
- return OC_STACK_ERROR;\r
- }\r
-\r
- char *string = "listeningFunc invoked in a thread";\r
- if (CA_STATUS_OK\r
- != ca_thread_pool_add_task(g_threadPoolHandle, listeningFunc,\r
- (void *) string)) {\r
- OIC_LOG(DEBUG, TAG, "thread_pool_add_task failed");\r
- ca_thread_pool_free(g_threadPoolHandle);\r
- ca_mutex_unlock(g_provisioningMutex);\r
- ca_mutex_free(g_provisioningMutex);\r
- ca_cond_free(g_provisioningCond);\r
- return OC_STACK_ERROR;\r
- }\r
- return OC_STACK_OK;\r
-}\r
-\r
-OCStackResult TerminateProvisioningHandler() {\r
- OCStackResult ret = OC_STACK_ERROR;\r
- if (OCStop() != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack stop error");\r
- }\r
-\r
- ca_mutex_lock(g_provisioningMutex);\r
- g_provisioningCondFlag = true;\r
- //ca_cond_signal(g_provisioningCond);\r
- ca_mutex_unlock(g_provisioningMutex);\r
-\r
- ca_mutex_free(g_provisioningMutex);\r
- g_provisioningMutex = NULL;\r
-\r
- ca_thread_pool_free(g_threadPoolHandle);\r
- g_threadPoolHandle = NULL;\r
-\r
- ret = OC_STACK_OK;\r
- return ret;\r
-}\r
-\r
-void listeningFunc(void *data) {\r
- while (!g_provisioningCondFlag) {\r
- OCStackResult result;\r
-\r
- ca_mutex_lock(g_provisioningMutex);\r
- result = OCProcess();\r
- ca_mutex_unlock(g_provisioningMutex);\r
-\r
- if (result != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack stop error");\r
- }\r
-\r
- // To minimize CPU utilization we may wish to do this with sleep\r
- sleep(1);\r
- }\r
-}\r
-\r
-OCStackApplicationResult ProvisionEnrolleeResponse(void* ctx, OCDoHandle handle,\r
- OCClientResponse * clientResponse) {\r
- ProvisioningInfo *provInfo;\r
-\r
- if (clientResponse) {\r
- OIC_LOG_V(INFO, TAG, "Put Response");\r
- } else {\r
- OIC_LOG_V(INFO, TAG,\r
- "ProvisionEnrolleeResponse received Null clientResponse");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-\r
- if (clientResponse->payload) {\r
-\r
- if(clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-\r
- OCRepPayload* input = (OCRepPayload*)(clientResponse->payload);\r
- if(!input)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Failed To parse");\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-\r
- while(input){\r
-\r
- int64_t ps;\r
- if(OCRepPayloadGetPropInt(input,OC_RSRVD_ES_PS,&ps)) {\r
- if(ps == 1)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "PS is proper");\r
- continue;\r
- }\r
- else{\r
- OIC_LOG_V(DEBUG, TAG, "PS is NOT proper");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
-\r
- }\r
- }\r
-\r
- const char* tnn;\r
- if(OCRepPayloadGetPropString(input,OC_RSRVD_ES_TNN,&tnn)){\r
- if(!strcmp(tnn, netProvInfo->netAddressInfo.WIFI.ssid))\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "SSID is proper");\r
- continue;\r
- }\r
- else{\r
- OIC_LOG_V(DEBUG, TAG, "SSID is NOT proper");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- }\r
- }\r
- const char* cd;\r
- if(OCRepPayloadGetPropString(input, OC_RSRVD_ES_CD,&cd)){\r
- if(!strcmp(cd,netProvInfo->netAddressInfo.WIFI.pwd))\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Password is proper");\r
- continue;\r
- }\r
- else{\r
- OIC_LOG_V(DEBUG, TAG, "Password is NOT proper");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- }\r
- }\r
-\r
- OCRepPayloadValue* val = input->values;\r
-\r
- switch(val->type)\r
- {\r
- case OCREP_PROP_NULL:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s: NULL", val->name);\r
- break;\r
- case OCREP_PROP_INT:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(int):%lld", val->name, val->i);\r
- break;\r
- case OCREP_PROP_DOUBLE:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(double):%f", val->name, val->d);\r
- break;\r
- case OCREP_PROP_BOOL:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");\r
- break;\r
- case OCREP_PROP_STRING:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(string):%s", val->name, val->str);\r
- break;\r
- case OCREP_PROP_OBJECT:\r
- // Note: Only prints the URI (if available), to print further, you'll\r
- // need to dig into the object better!\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep):%s", val->name, val->obj->uri);\r
- break;\r
- case OCREP_PROP_ARRAY:\r
- switch(val->arr.type)\r
- {\r
- case OCREP_PROP_INT:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(int array):%lld x %lld x %lld",\r
- val->name,\r
- val->arr.dimensions[0], val->arr.dimensions[1],\r
- val->arr.dimensions[2]);\r
- break;\r
- case OCREP_PROP_DOUBLE:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(double array):%lld x %lld x %lld",\r
- val->name,\r
- val->arr.dimensions[0], val->arr.dimensions[1],\r
- val->arr.dimensions[2]);\r
- break;\r
- case OCREP_PROP_BOOL:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool array):%lld x %lld x %lld",\r
- val->name,\r
- val->arr.dimensions[0], val->arr.dimensions[1],\r
- val->arr.dimensions[2]);\r
- break;\r
- case OCREP_PROP_STRING:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(string array):%lld x %lld x %lld",\r
- val->name,\r
- val->arr.dimensions[0], val->arr.dimensions[1],\r
- val->arr.dimensions[2]);\r
- break;\r
- case OCREP_PROP_OBJECT:\r
- OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep array):%lld x %lld x %lld",\r
- val->name,\r
- val->arr.dimensions[0], val->arr.dimensions[1],\r
- val->arr.dimensions[2]);\r
- break;\r
- default:\r
- //OIC_LOG_V(ERROR, TAG, "\t\t%s <-- Unknown/unsupported array type!",\r
- // val->name);\r
- break;\r
- }\r
- break;\r
- default:\r
- /*OC_LOG_V(ERROR, TAG\r
- , "\t\t%s <-- Unknown type!", val->name);*/\r
- break;\r
- }\r
- input=input->next;\r
- }\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_PROVISIONED);\r
- cbData(provInfo);\r
-\r
- return OC_STACK_KEEP_TRANSACTION;\r
- } else {\r
- OIC_LOG(INFO, TAG,\r
- "ProvisionEnrolleeResponse received NULL clientResponse. \\r
- Invoking Provisioing Status Callback");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-}\r
-\r
-\r
-\r
-OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri) {\r
- OIC_LOG_V(INFO, TAG, "\n\nExecuting ProvisionEnrollee%s", __func__);\r
-\r
-\r
- OCRepPayload* payload = OCRepPayloadCreate();\r
-\r
- OCRepPayloadSetUri(payload,resUri);\r
- OCRepPayloadSetPropString(payload,OC_RSRVD_ES_TNN,netProvInfo->netAddressInfo.WIFI.ssid);\r
- OCRepPayloadSetPropString(payload,OC_RSRVD_ES_CD,netProvInfo->netAddressInfo.WIFI.pwd);\r
-\r
- OIC_LOG_V(DEBUG, TAG, "OCPayload ready for ProvisionEnrollee");\r
-\r
- OCStackResult ret = InvokeOCDoResource(query, OC_REST_PUT, OC_HIGH_QOS,\r
- ProvisionEnrolleeResponse, payload, NULL, 0);\r
-\r
- return ret;\r
-}\r
-\r
-\r
-OCStackApplicationResult GetProvisioningStatusResponse(void* ctx,\r
- OCDoHandle handle, OCClientResponse * clientResponse) {\r
- ProvisioningInfo *provInfo;\r
-\r
- if (clientResponse == NULL) {\r
- OIC_LOG(INFO, TAG,\r
- "getReqCB received NULL clientResponse. \\r
- Invoking Provisioing Status Callback");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-\r
- if (clientResponse->rcvdVendorSpecificHeaderOptions\r
- && clientResponse->numRcvdVendorSpecificHeaderOptions) {\r
- OIC_LOG(INFO, TAG, "Received vendor specific options");\r
- uint8_t i = 0;\r
- OCHeaderOption * rcvdOptions =\r
- clientResponse->rcvdVendorSpecificHeaderOptions;\r
- for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions;\r
- i++) {\r
- if (((OCHeaderOption) rcvdOptions[i]).protocolID == OC_COAP_ID) {\r
- OIC_LOG_V(INFO, TAG,\r
- "Received option with OC_COAP_ID and ID %u with",\r
- ((OCHeaderOption) rcvdOptions[i]).optionID);\r
-\r
- OIC_LOG_BUFFER(INFO, TAG,\r
- ((OCHeaderOption) rcvdOptions[i]).optionData,\r
- MAX_HEADER_OPTION_DATA_LENGTH);\r
- }\r
- }\r
- }\r
-\r
- char query[OIC_STRING_MAX_VALUE] = { '\0' };\r
-\r
-\r
- if (clientResponse->payload) {\r
-\r
- if(clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
-\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-\r
- OCRepPayload* input = (OCRepPayload*)(clientResponse->payload);\r
- if(!input)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Failed To parse");\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
- OIC_LOG_V(DEBUG, TAG, "resUri = %s",input->uri);\r
-\r
- char resURI[MAX_URI_LENGTH]={'\0'};\r
-\r
- strncpy(resURI, input->uri, sizeof(resURI));\r
-\r
- snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY,\r
- clientResponse->addr->addr,\r
- IP_PORT, resURI);\r
-\r
- //OCPayloadLogRep(DEBUG,TAG,input);\r
-\r
- if (ProvisionEnrollee(OC_HIGH_QOS, query, resURI) != OC_STACK_OK) {\r
- OIC_LOG(INFO, TAG,\r
- "GetProvisioningStatusResponse received NULL clientResponse. \\r
- Invoking Provisioing Status Callback");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
-\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
- } else {\r
- OIC_LOG(INFO, TAG,\r
- "GetProvisioningStatusResponse received NULL clientResponse. \\r
- Invoking Provisioing Status Callback");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
- return OC_STACK_DELETE_TRANSACTION;\r
-}\r
-\r
-OCStackResult InvokeOCDoResource(const char* query, OCMethod method,\r
- OCQualityOfService qos, OCClientResponseHandler cb,OCRepPayload* request,\r
- OCHeaderOption * options, uint8_t numOptions) {\r
- OCStackResult ret;\r
- OCCallbackData cbData;\r
-\r
- cbData.cb = cb;\r
- cbData.context = (void*) DEFAULT_CONTEXT_VALUE;\r
- cbData.cd = NULL;\r
-\r
- ret = OCDoResource(NULL, method, query, 0, &request->base, OC_CONNTYPE, qos,\r
- &cbData, options, numOptions);\r
-\r
- if (ret != OC_STACK_OK) {\r
- OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d",\r
- ret, method);\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query) {\r
- OCStackResult ret = OC_STACK_ERROR;\r
- OCHeaderOption options[MAX_HEADER_OPTIONS];\r
-\r
- OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);\r
-\r
- uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };\r
- uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };\r
- memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);\r
- options[0].protocolID = OC_COAP_ID;\r
- options[0].optionID = 2048;\r
- memcpy(options[0].optionData, option0, sizeof(option0));\r
- options[0].optionLength = 10;\r
- options[1].protocolID = OC_COAP_ID;\r
- options[1].optionID = 3000;\r
- memcpy(options[1].optionData, option1, sizeof(option1));\r
- options[1].optionLength = 10;\r
-\r
- ret = InvokeOCDoResource(query, OC_REST_GET, OC_HIGH_QOS,\r
- GetProvisioningStatusResponse, NULL, options, 2);\r
- return ret;\r
-}\r
-\r
-OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,\r
- OCProvisioningStatusCB provisioningStatusCallback) {\r
- OCStackResult result = OC_STACK_ERROR;\r
-\r
- if (netInfo->netAddressInfo.WIFI.ipAddress == NULL) {\r
- OIC_LOG(ERROR, TAG, "Request URI is NULL");\r
- return result;\r
- }\r
-\r
- if (provisioningStatusCallback == NULL) {\r
- OIC_LOG(ERROR, TAG, "ProvisioningStatusCallback is NULL");\r
- return result;\r
- }\r
-\r
- cbData = provisioningStatusCallback;\r
-\r
- //Copy Network Provisioning Information\r
- netProvInfo = (EnrolleeNWProvInfo_t *)OICCalloc(1, sizeof(EnrolleeNWProvInfo_t));\r
-\r
- if (NULL == netProvInfo)\r
- {\r
- OIC_LOG(ERROR, TAG, "Invalid input..");\r
- return OC_STACK_ERROR;\r
- }\r
- memcpy(netProvInfo, netInfo, sizeof(EnrolleeNWProvInfo_t));\r
-\r
- OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. SSID = %s",\r
- netProvInfo->netAddressInfo.WIFI.ssid);\r
-\r
- OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. PWD = %s",\r
- netProvInfo->netAddressInfo.WIFI.pwd);\r
-\r
-\r
- if (CA_STATUS_OK\r
- != ca_thread_pool_add_task(g_threadPoolHandle, FindProvisioningResource,\r
- (void *) "")) {\r
- OIC_LOG(DEBUG, TAG, "thread_pool_add_task of FindProvisioningResource failed");\r
- ca_thread_pool_free(g_threadPoolHandle);\r
- ca_mutex_unlock(g_provisioningMutex);\r
- ca_mutex_free(g_provisioningMutex);\r
- ca_cond_free(g_provisioningCond);\r
- return OC_STACK_ERROR;\r
- }\r
- return OC_STACK_OK;\r
-}\r
-\r
-void StopProvisioningProcess() {\r
- cbData = NULL;\r
-}\r
-\r
-\r
-// This is a function called back when a device is discovered\r
-OCStackApplicationResult FindProvisioningResourceResponse(void* ctx,\r
- OCDoHandle handle, OCClientResponse * clientResponse) {\r
- OIC_LOG(INFO, TAG, PCF("Entering FindProvisioningResourceResponse"));\r
-\r
- OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;\r
-\r
- ProvisioningInfo *provInfo;\r
-\r
- if (clientResponse->result != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG,\r
- "OCStack stop error. Calling Provisioing Status Callback");\r
-\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
-\r
- cbData(provInfo);\r
- return response;\r
- }\r
-\r
- if (clientResponse) {\r
-\r
-\r
- if(clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
-\r
- OCRepPayload* discoveryPayload= (OCRepPayload*)(clientResponse->payload);\r
- if(!discoveryPayload)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Failed To parse");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- return response;\r
- }\r
- OIC_LOG_V(DEBUG, TAG, "resUri = %s",discoveryPayload->uri);\r
- char szQueryUri[64] = { 0 };\r
-\r
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,\r
- clientResponse->devAddr.addr, IP_PORT, discoveryPayload->uri);\r
- OIC_LOG_V(DEBUG, TAG, "query before GetProvisioningStatus call = %s", szQueryUri);\r
-\r
- if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri) != OC_STACK_OK) {\r
- OIC_LOG(INFO, TAG,\r
- "GetProvisioningStatus returned error. \\r
- Invoking Provisioing Status Callback");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
-\r
- cbData(provInfo);\r
- return OC_STACK_DELETE_TRANSACTION;\r
- }\r
- } else {\r
- // clientResponse is invalid\r
- OIC_LOG(ERROR, TAG,\r
- "Invalid response for Provisioning Discovery request. \\r
- Invoking Provisioing Status Callback");\r
- provInfo = PrepareProvisioingStatusCB(clientResponse,\r
- DEVICE_NOT_PROVISIONED);\r
- cbData(provInfo);\r
- return response;\r
- }\r
- return OC_STACK_KEEP_TRANSACTION;\r
-}\r
-\r
-\r
-void FindProvisioningResource(void *data)\r
-{\r
- OCStackResult ret = OC_STACK_ERROR;\r
-\r
- /* Start a discovery query*/\r
- char szQueryUri[64] = { 0 };\r
-\r
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,\r
- netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);\r
-\r
- OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);\r
-\r
- OCCallbackData ocCBData;\r
-\r
- ocCBData.cb = FindProvisioningResourceResponse;\r
- ocCBData.context = (void*) DEFAULT_CONTEXT_VALUE;\r
- ocCBData.cd = NULL;\r
-\r
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,\r
- OC_LOW_QOS, &ocCBData, NULL, 0);\r
-\r
- if (ret != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack resource error");\r
-\r
- OIC_LOG(ERROR, TAG,\r
- "FindProvisioningResource failed. \\r
- Invoking Provisioing Status Callback");\r
-\r
- ProvisioningInfo *provInfo;\r
- provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));\r
-\r
- if(provInfo == NULL)\r
- {\r
- OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
- return;\r
- }\r
-\r
- OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));\r
-\r
- if(devAddr == NULL)\r
- {\r
- OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
- return;\r
- }\r
-\r
- strncpy(devAddr->addr, netProvInfo->netAddressInfo.WIFI.ipAddress, sizeof(devAddr->addr));\r
- devAddr->port= IP_PORT;\r
- provInfo->provDeviceInfo.addr = devAddr;\r
- provInfo->provStatus = DEVICE_NOT_PROVISIONED;\r
-\r
-\r
- cbData(provInfo);\r
- }\r
-}\r
-\r
-OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,\r
- OCClientResponse* clientResponse) {\r
- OIC_LOG(INFO, TAG, PCF("Entering SubscribeProvPresenceCallback"));\r
-\r
- OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;\r
-\r
- if (clientResponse->result != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack stop error");\r
- return response;\r
- }\r
-\r
- if (clientResponse) {\r
- OIC_LOG(INFO, TAG, PCF("Client Response exists"));\r
-\r
- if(clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
- return response;\r
- }\r
-\r
- OCRepPayload* discoveryPayload= (OCRepPayload*)(clientResponse->payload);\r
- if(!discoveryPayload)\r
- {\r
- OIC_LOG_V(DEBUG, TAG, "invalid payload");\r
- return response;\r
- }\r
-\r
- char sourceIPAddr[OIC_STRING_MAX_VALUE] = { '\0' };\r
- snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%s", clientResponse->addr->addr);\r
-\r
- OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s",\r
- discoveryPayload->uri, sourceIPAddr);\r
-\r
- /* Start a discovery query*/\r
- char szQueryUri[64] = { 0 };\r
-\r
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,\r
- sourceIPAddr, IP_PORT);\r
-\r
- /*if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "FindProvisioningResource failed");\r
- return OC_STACK_KEEP_TRANSACTION;\r
- }*/\r
- } else {\r
- // clientResponse is invalid\r
- OIC_LOG(ERROR, TAG, PCF("Client Response is NULL!"));\r
- }\r
- return OC_STACK_KEEP_TRANSACTION;\r
-}\r
-\r
-\r
-OCStackResult SubscribeProvPresence(OCQualityOfService qos,\r
- const char* requestURI) {\r
- OCStackResult ret = OC_STACK_ERROR;\r
-\r
- OCCallbackData cbData;\r
-\r
- cbData.cb = &SubscribeProvPresenceCallback;\r
- cbData.context = (void*) DEFAULT_CONTEXT_VALUE;\r
- cbData.cd = NULL;\r
-\r
- ret = OCDoResource(NULL, OC_REST_PRESENCE, requestURI, 0, 0, OC_CONNTYPE,\r
- OC_LOW_QOS, &cbData, NULL, 0);\r
-\r
- if (ret != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack resource error");\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-OCStackResult FindNetworkResource() {\r
- OCStackResult ret = OC_STACK_ERROR;\r
- if (OCStop() != OC_STACK_OK) {\r
- OIC_LOG(ERROR, TAG, "OCStack stop error");\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse, ProvStatus provStatus) {\r
-\r
- ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));\r
-\r
- if(provInfo == NULL)\r
- {\r
- OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
- return NULL;\r
- }\r
-\r
- OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));\r
-\r
- if(devAddr == NULL)\r
- {\r
- OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
- return NULL;\r
- }\r
-\r
- strncpy(devAddr->addr, clientResponse->addr->addr, sizeof(devAddr->addr));\r
- devAddr->port= clientResponse->addr->port;\r
-\r
- provInfo->provDeviceInfo.addr = devAddr;\r
-\r
- provInfo->provStatus = provStatus;\r
-\r
- return provInfo;\r
-}\r
-\r
-\r
-\r
-\r
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include "ocpayload.h"
+#include "provisioninghandler.h"
+#include "common.h"
+// External includes
+
+#include "camutex.h"
+#include "cathreadpool.h"
+#include "logger.h"
+#include "oic_malloc.h"
+
+/**
+ * @var g_provisioningMutex
+ * @brief Mutex to synchronize access to g_caDtlsContext.
+ */
+static ca_mutex g_provisioningMutex = NULL;
+static ca_cond g_provisioningCond = NULL;
+bool g_provisioningCondFlag = false;
+
+static EnrolleeNWProvInfo_t* netProvInfo;
+
+/**
+ * @var cbData
+ * @brief Callback for providing provisioning status callback to application
+ */
+static OCProvisioningStatusCB cbData = NULL;
+static ca_thread_pool_t g_threadPoolHandle = NULL;
+
+void ErrorCallback(ProvStatus status)
+{
+ ProvisioningInfo *provInfo = GetCallbackObjectOnError(status);
+ cbData(provInfo);
+ ResetProgress();
+}
+
+OCStackResult InitProvisioningHandler()
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ /* Initialize OCStack*/
+ if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack init error");
+ return ret;
+ }
+
+ g_provisioningMutex = ca_mutex_new();
+
+ OIC_LOG(DEBUG, TAG, "ca_thread_pool_init initializing");
+
+ if (CA_STATUS_OK != ca_thread_pool_init(2, &g_threadPoolHandle))
+ {
+ OIC_LOG(DEBUG, TAG, "thread_pool_init failed");
+ return OC_STACK_ERROR;
+ }
+
+ g_provisioningCond = ca_cond_new();
+ if (NULL == g_provisioningCond)
+ {
+ OIC_LOG(DEBUG, TAG, "Failed to create condition");
+ ca_mutex_free(g_provisioningMutex);
+ ca_thread_pool_free(g_threadPoolHandle);
+ return OC_STACK_ERROR;
+ }
+
+ char *string = "listeningFunc invoked in a thread";
+ if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, listeningFunc, (void *) string))
+ {
+ OIC_LOG(DEBUG, TAG, "thread_pool_add_task failed");
+ ca_thread_pool_free(g_threadPoolHandle);
+ ca_mutex_unlock(g_provisioningMutex);
+ ca_mutex_free(g_provisioningMutex);
+ ca_cond_free(g_provisioningCond);
+ return OC_STACK_ERROR;
+ }
+
+ ResetProgress();
+
+ return OC_STACK_OK;
+}
+
+OCStackResult TerminateProvisioningHandler()
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ if (OCStop() != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ ca_mutex_lock(g_provisioningMutex);
+ g_provisioningCondFlag = true;
+ //ca_cond_signal(g_provisioningCond);
+ ca_mutex_unlock(g_provisioningMutex);
+
+ ca_mutex_free(g_provisioningMutex);
+ g_provisioningMutex = NULL;
+
+ ca_thread_pool_free(g_threadPoolHandle);
+ g_threadPoolHandle = NULL;
+
+ ret = OC_STACK_OK;
+ return ret;
+}
+
+void listeningFunc(void *data)
+{
+ while (!g_provisioningCondFlag)
+ {
+ OCStackResult result;
+
+ ca_mutex_lock(g_provisioningMutex);
+ result = OCProcess();
+ ca_mutex_unlock(g_provisioningMutex);
+
+ if (result != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ // To minimize CPU utilization we may wish to do this with sleep
+ sleep(1);
+ }
+}
+
+OCStackApplicationResult ProvisionEnrolleeResponse(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse)
+{
+
+ ProvisioningInfo *provInfo;
+
+ if (!ValidateEnrolleResponse(clientResponse))
+ {
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ char* tnn;
+ char* cd;
+
+ OCRepPayload* input = (OCRepPayload*) (clientResponse->payload);
+
+ while (input)
+ {
+
+ int64_t ps;
+ if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_PS, &ps))
+ {
+
+ if (ps == 1)
+ {
+ OIC_LOG_V(DEBUG, TAG, "PS is proper");
+ input = input->next;
+ continue;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "PS is NOT proper");
+ goto Error;
+
+ }
+ }
+
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_TNN, &tnn))
+ {
+ if (!strcmp(tnn, netProvInfo->netAddressInfo.WIFI.ssid))
+ {
+ OIC_LOG_V(DEBUG, TAG, "SSID is proper");
+ input = input->next;
+ continue;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "SSID is NOT proper");
+ goto Error;
+ }
+ }
+
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_CD, &cd))
+ {
+ if (!strcmp(cd, netProvInfo->netAddressInfo.WIFI.pwd))
+ {
+ OIC_LOG_V(DEBUG, TAG, "Password is proper");
+ input = input->next;
+ continue;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "Password is NOT proper");
+ goto Error;
+ }
+ }
+
+ LogProvisioningResponse(input->values);
+
+ input = input->next;
+
+ }
+
+ SuccessCallback(clientResponse);
+
+ return OC_STACK_KEEP_TRANSACTION;
+
+ Error:
+ {
+
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+}
+
+OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri,
+ OCDevAddr *destination)
+{
+ OIC_LOG_V(INFO, TAG, "\n\nExecuting ProvisionEnrollee%s", __func__);
+
+ OCRepPayload* payload = OCRepPayloadCreate();
+
+ OCRepPayloadSetUri(payload, resUri);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_TNN, netProvInfo->netAddressInfo.WIFI.ssid);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_CD, netProvInfo->netAddressInfo.WIFI.pwd);
+
+ OIC_LOG_V(DEBUG, TAG, "OCPayload ready for ProvisionEnrollee");
+
+ OCStackResult ret = InvokeOCDoResource(query, OC_REST_PUT, destination, OC_HIGH_QOS,
+ ProvisionEnrolleeResponse, payload, NULL, 0);
+
+ return ret;
+}
+
+OCStackApplicationResult GetProvisioningStatusResponse(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse)
+{
+
+ ProvisioningInfo *provInfo;
+
+ if (!ValidateEnrolleResponse(clientResponse))
+ {
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ ClearMemory();
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OCRepPayload* input = (OCRepPayload*) (clientResponse->payload);
+
+ char query[OIC_STRING_MAX_VALUE] =
+ { '\0' };
+ char resURI[MAX_URI_LENGTH] =
+ { '\0' };
+
+ OIC_LOG_V(DEBUG, TAG, "resUri = %s", input->uri);
+
+ strncpy(resURI, input->uri, sizeof(resURI));
+
+ snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY, clientResponse->addr->addr, IP_PORT,
+ resURI);
+
+ //OCPayloadLogRep(DEBUG,TAG,input);
+
+ if (ProvisionEnrollee(OC_HIGH_QOS, query, OC_RSRVD_ES_URI_PROV, clientResponse->addr)
+ != OC_STACK_OK)
+ {
+ OIC_LOG(INFO, TAG,
+ "GetProvisioningStatusResponse received NULL clientResponse.Invoking Provisioing Status Callback");
+
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ ClearMemory();
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+
+}
+
+OCStackResult InvokeOCDoResource(const char* query, OCMethod method, const OCDevAddr *dest,
+ OCQualityOfService qos, OCClientResponseHandler cb, OCRepPayload* payload,
+ OCHeaderOption * options, uint8_t numOptions)
+{
+ OCStackResult ret;
+ OCCallbackData cbData;
+
+ cbData.cb = cb;
+ cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ ret = OCDoResource(NULL, method, query, dest, (OCPayload*) payload, OC_CONNTYPE, qos, &cbData,
+ options, numOptions);
+
+ if (ret != OC_STACK_OK)
+ {
+ OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
+ }
+
+ return ret;
+}
+
+OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query,
+ const OCDevAddr *destination)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ OCHeaderOption options[MAX_HEADER_OPTIONS];
+
+ OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+
+ uint8_t option0[] =
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ uint8_t option1[] =
+ { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
+ memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
+ options[0].protocolID = OC_COAP_ID;
+ options[0].optionID = 2048;
+ memcpy(options[0].optionData, option0, sizeof(option0));
+ options[0].optionLength = 10;
+ options[1].protocolID = OC_COAP_ID;
+ options[1].optionID = 3000;
+ memcpy(options[1].optionData, option1, sizeof(option1));
+ options[1].optionLength = 10;
+
+ ret = InvokeOCDoResource(query, OC_REST_GET, destination, OC_HIGH_QOS,
+ GetProvisioningStatusResponse, NULL, options, 2);
+ return ret;
+}
+
+OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,
+ OCProvisioningStatusCB provisioningStatusCallback)
+{
+
+ OCStackResult result = OC_STACK_ERROR;
+
+ if (!ValidateEasySetupParams(netInfo, provisioningStatusCallback))
+ {
+ goto Error;
+ }
+
+ //Only basis test is done for below API
+ if (!SetProgress(provisioningStatusCallback))
+ {
+ // Device provisioning session is running already.
+ OIC_LOG(INFO, TAG, PCF("Device provisioning session is running already"));
+ goto Error;
+ }
+
+ if (!ConfigEnrolleeObject(netInfo))
+ {
+ goto Error;
+ }
+
+ if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, FindProvisioningResource,
+ (void *) ""))
+ {
+ goto Error;
+ }
+
+ return OC_STACK_OK;
+
+ Error:
+ {
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ ClearMemory();
+ return OC_STACK_ERROR;
+ }
+
+}
+
+void StopProvisioningProcess()
+{
+ //Only basis test is done for below API
+ ResetProgress();
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult FindProvisioningResourceResponse(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse)
+{
+
+ OIC_LOG(INFO, TAG, PCF("Entering FindProvisioningResourceResponse"));
+
+ if (!ValidateFinddResourceResponse(clientResponse))
+ {
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
+
+ ProvisioningInfo *provInfo;
+ char szQueryUri[64] =
+ { 0 };
+
+ OCDiscoveryPayload* discoveryPayload = (OCDiscoveryPayload*) (clientResponse->payload);
+
+ // Need to conform if below check is required or not. As Null check of clientResponse->payload is already performed above
+ if (!discoveryPayload)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Failed To parse");
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "resUri = %s", discoveryPayload->resources->uri);
+
+ snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,
+ clientResponse->devAddr.addr, IP_PORT, discoveryPayload->resources->uri);
+
+ OIC_LOG_V(DEBUG, TAG, "query before GetProvisioningStatus call = %s", szQueryUri);
+
+ if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri, &clientResponse->devAddr) != OC_STACK_OK)
+ {
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+
+}
+
+void FindProvisioningResource(void *data)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ /* Start a discovery query*/
+ char szQueryUri[64] =
+ { 0 };
+
+ snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
+ netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);
+
+ OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);
+
+ OCCallbackData ocCBData;
+
+ ocCBData.cb = FindProvisioningResourceResponse;
+ ocCBData.context = (void*) DEFAULT_CONTEXT_VALUE;
+ ocCBData.cd = NULL;
+
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, NULL, OC_CONNTYPE, OC_LOW_QOS,
+ &ocCBData, NULL, 0);
+
+ if (ret != OC_STACK_OK)
+ {
+ ErrorCallback( DEVICE_NOT_PROVISIONED);
+ ClearMemory();
+ }
+}
+
+OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse* clientResponse)
+{
+ OIC_LOG(INFO, TAG, PCF("Entering SubscribeProvPresenceCallback"));
+
+ OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
+
+ if (clientResponse->result != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ return response;
+ }
+
+ if (clientResponse)
+ {
+ OIC_LOG(INFO, TAG, PCF("Client Response exists"));
+
+ if (clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");
+ return response;
+ }
+
+ OCRepPayload* discoveryPayload = (OCRepPayload*) (clientResponse->payload);
+ if (!discoveryPayload)
+ {
+ OIC_LOG_V(DEBUG, TAG, "invalid payload");
+ return response;
+ }
+
+ char sourceIPAddr[OIC_STRING_MAX_VALUE] =
+ { '\0' };
+ snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%s", clientResponse->addr->addr);
+
+ OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s", discoveryPayload->uri, sourceIPAddr);
+
+ /* Start a discovery query*/
+ char szQueryUri[64] =
+ { 0 };
+
+ snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY, sourceIPAddr, IP_PORT);
+
+ /*if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {
+ OIC_LOG(ERROR, TAG, "FindProvisioningResource failed");
+ return OC_STACK_KEEP_TRANSACTION;
+ }*/
+ }
+ else
+ {
+ // clientResponse is invalid
+ OIC_LOG(ERROR, TAG, PCF("Client Response is NULL!"));
+ }
+ return OC_STACK_KEEP_TRANSACTION;
+}
+
+OCStackResult SubscribeProvPresence(OCQualityOfService qos, const char* requestURI)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ OCCallbackData cbData;
+
+ cbData.cb = &SubscribeProvPresenceCallback;
+ cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ ret = OCDoResource(NULL, OC_REST_PRESENCE, requestURI, 0, 0, OC_CONNTYPE, OC_LOW_QOS, &cbData,
+ NULL, 0);
+
+ if (ret != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ return ret;
+}
+
+OCStackResult FindNetworkResource()
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ if (OCStop() != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ return ret;
+}
+
+ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse,
+ ProvStatus provStatus)
+{
+
+ ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
+
+ if (provInfo == NULL)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
+ return NULL;
+ }
+
+ OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
+
+ if (devAddr == NULL)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
+ return NULL;
+ }
+
+ strncpy(devAddr->addr, clientResponse->addr->addr, sizeof(devAddr->addr));
+ devAddr->port = clientResponse->addr->port;
+
+ provInfo->provDeviceInfo.addr = devAddr;
+
+ provInfo->provStatus = provStatus;
+
+ return provInfo;
+}
+
+bool ValidateEasySetupParams(const EnrolleeNWProvInfo_t *netInfo,
+ OCProvisioningStatusCB provisioningStatusCallback)
+{
+
+ if (netInfo == NULL || netInfo->netAddressInfo.WIFI.ipAddress == NULL)
+ {
+ OIC_LOG(ERROR, TAG, "Request URI is NULL");
+ return false;
+ }
+
+ if (provisioningStatusCallback == NULL)
+ {
+ OIC_LOG(ERROR, TAG, "ProvisioningStatusCallback is NULL");
+ return false;
+ }
+
+ return true;
+
+}
+
+bool InProgress()
+{
+
+ // It means already Easy Setup provisioning session is going on.
+ if (NULL != cbData)
+ {
+ OIC_LOG(ERROR, TAG, "Easy setup session is already in progress");
+ return true;
+ }
+
+ return false;
+}
+
+bool SetProgress(OCProvisioningStatusCB provisioningStatusCallback)
+{
+ ca_mutex_lock(g_provisioningMutex);
+
+ if (InProgress())
+ return false;
+
+ cbData = provisioningStatusCallback;
+
+ ca_mutex_unlock(g_provisioningMutex);
+
+ return true;
+}
+
+bool ResetProgress()
+{
+ ca_mutex_lock(g_provisioningMutex);
+
+ cbData = NULL;
+
+ ca_mutex_unlock(g_provisioningMutex);
+}
+
+ProvisioningInfo* CreateCallBackObject()
+{
+
+ ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
+
+ if (provInfo == NULL)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
+ return NULL;
+ }
+
+ OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
+
+ if (devAddr == NULL)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
+ return NULL;
+ }
+
+ provInfo->provDeviceInfo.addr = devAddr;
+
+ return provInfo;
+
+}
+
+ProvisioningInfo* GetCallbackObjectOnError(ProvStatus status)
+{
+
+ ProvisioningInfo *provInfo = CreateCallBackObject();
+ strncpy(provInfo->provDeviceInfo.addr->addr, netProvInfo->netAddressInfo.WIFI.ipAddress,
+ sizeof(provInfo->provDeviceInfo.addr->addr));
+ provInfo->provDeviceInfo.addr->port = IP_PORT;
+ provInfo->provStatus = status;
+ return provInfo;
+}
+
+ProvisioningInfo* GetCallbackObjectOnSuccess(OCClientResponse * clientResponse,
+ ProvStatus provStatus)
+{
+ ProvisioningInfo *provInfo = CreateCallBackObject();
+ strncpy(provInfo->provDeviceInfo.addr->addr, clientResponse->addr->addr,
+ sizeof(provInfo->provDeviceInfo.addr->addr));
+ provInfo->provDeviceInfo.addr->port = clientResponse->addr->port;
+ provInfo->provStatus = provStatus;
+ return provInfo;
+}
+
+bool ValidateFinddResourceResponse(OCClientResponse * clientResponse)
+{
+
+ if (!(clientResponse) || !(clientResponse->payload))
+ {
+
+ OIC_LOG_V(INFO, TAG, "ProvisionEnrolleeResponse received Null clientResponse");
+
+ return false;
+
+ }
+return true;
+}
+
+bool ValidateEnrolleResponse(OCClientResponse * clientResponse)
+{
+
+ if (!(clientResponse) || !(clientResponse->payload))
+ {
+
+ OIC_LOG_V(INFO, TAG, "ProvisionEnrolleeResponse received Null clientResponse");
+
+ return false;
+
+ }
+
+ if (clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+ {
+
+ OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");
+ return false;
+
+ }
+
+ // If flow reachese here means no error condition hit.
+ return true;
+
+}
+
+
+void SuccessCallback(OCClientResponse * clientResponse)
+{
+ ProvisioningInfo *provInfo = GetCallbackObjectOnSuccess(clientResponse, DEVICE_PROVISIONED);
+ cbData(provInfo);
+ ResetProgress();
+}
+
+bool ClearMemory()
+{
+
+ OIC_LOG(DEBUG, TAG, "thread_pool_add_task of FindProvisioningResource failed");
+ ca_thread_pool_free(g_threadPoolHandle);
+ ca_mutex_unlock(g_provisioningMutex);
+ ca_mutex_free(g_provisioningMutex);
+ ca_cond_free(g_provisioningCond);
+
+ return true;
+
+}
+
+bool ConfigEnrolleeObject(const EnrolleeNWProvInfo_t *netInfo)
+{
+
+ //Copy Network Provisioning Information
+ netProvInfo = (EnrolleeNWProvInfo_t *) OICCalloc(1, sizeof(EnrolleeNWProvInfo_t));
+
+ if (netProvInfo == NULL)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid input..");
+ return false;
+ }
+
+ memcpy(netProvInfo, netInfo, sizeof(EnrolleeNWProvInfo_t));
+
+ OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. SSID = %s",
+ netProvInfo->netAddressInfo.WIFI.ssid);
+
+ OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. PWD = %s",
+ netProvInfo->netAddressInfo.WIFI.pwd);
+
+ return true;
+
+}
+
+void LogProvisioningResponse(OCRepPayloadValue* val)
+{
+
+ switch (val->type)
+ {
+ case OCREP_PROP_NULL:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s: NULL", val->name);
+ break;
+ case OCREP_PROP_INT:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(int):%lld", val->name, val->i);
+ break;
+ case OCREP_PROP_DOUBLE:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(double):%f", val->name, val->d);
+ break;
+ case OCREP_PROP_BOOL:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");
+ break;
+ case OCREP_PROP_STRING:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(string):%s", val->name, val->str);
+ break;
+ case OCREP_PROP_OBJECT:
+ // Note: Only prints the URI (if available), to print further, you'll
+ // need to dig into the object better!
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep):%s", val->name, val->obj->uri);
+ break;
+ case OCREP_PROP_ARRAY:
+ switch (val->arr.type)
+ {
+ case OCREP_PROP_INT:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(int array):%lld x %lld x %lld", val->name,
+ val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
+ break;
+ case OCREP_PROP_DOUBLE:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(double array):%lld x %lld x %lld", val->name,
+ val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
+ break;
+ case OCREP_PROP_BOOL:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool array):%lld x %lld x %lld", val->name,
+ val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
+ break;
+ case OCREP_PROP_STRING:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(string array):%lld x %lld x %lld", val->name,
+ val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
+ break;
+ case OCREP_PROP_OBJECT:
+ OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep array):%lld x %lld x %lld", val->name,
+ val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
+ break;
+ default:
+ //OIC_LOG_V(ERROR, TAG, "\t\t%s <-- Unknown/unsupported array type!",
+ // val->name);
+ break;
+ }
+ break;
+ default:
+ /*OC_LOG_V(ERROR, TAG
+ , "\t\t%s <-- Unknown type!", val->name);*/
+ break;
+ }
+}
+