Merge "Merge easysetup branch into master"
[platform/upstream/iotivity.git] / service / easy-setup / sdk / mediator / src / provisioninghandler.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include "ocpayload.h"
27 #include "provisioninghandler.h"
28 #include "common.h"
29 // External includes
30
31 #include "camutex.h"
32 #include "cathreadpool.h"
33 #include "logger.h"
34 #include "oic_malloc.h"
35
36 /**
37  * @var g_provisioningMutex
38  * @brief Mutex to synchronize access to g_caDtlsContext.
39  */
40 static ca_mutex g_provisioningMutex = NULL;
41 static ca_cond g_provisioningCond = NULL;
42 bool g_provisioningCondFlag = false;
43
44 static EnrolleeNWProvInfo_t* netProvInfo;
45
46 /**
47  * @var cbData
48  * @brief Callback for providing provisioning status callback to application
49  */
50 static OCProvisioningStatusCB cbData = NULL;
51 static ca_thread_pool_t g_threadPoolHandle = NULL;
52
53 void ErrorCallback(ProvStatus status)
54 {
55     ProvisioningInfo *provInfo = GetCallbackObjectOnError(status);
56     cbData(provInfo);
57     ResetProgress();
58 }
59
60 OCStackResult InitProvisioningHandler()
61 {
62     OCStackResult ret = OC_STACK_ERROR;
63     /* Initialize OCStack*/
64     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
65     {
66         OIC_LOG(ERROR, TAG, "OCStack init error");
67         return ret;
68     }
69
70     g_provisioningMutex = ca_mutex_new();
71
72     OIC_LOG(DEBUG, TAG, "ca_thread_pool_init initializing");
73
74     if (CA_STATUS_OK != ca_thread_pool_init(2, &g_threadPoolHandle))
75     {
76         OIC_LOG(DEBUG, TAG, "thread_pool_init failed");
77         return OC_STACK_ERROR;
78     }
79
80     g_provisioningCond = ca_cond_new();
81     if (NULL == g_provisioningCond)
82     {
83         OIC_LOG(DEBUG, TAG, "Failed to create condition");
84         ca_mutex_free(g_provisioningMutex);
85         ca_thread_pool_free(g_threadPoolHandle);
86         return OC_STACK_ERROR;
87     }
88
89     char *string = "listeningFunc invoked in a thread";
90     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, listeningFunc, (void *) string))
91     {
92         OIC_LOG(DEBUG, TAG, "thread_pool_add_task failed");
93         ca_thread_pool_free(g_threadPoolHandle);
94         ca_mutex_unlock(g_provisioningMutex);
95         ca_mutex_free(g_provisioningMutex);
96         ca_cond_free(g_provisioningCond);
97         return OC_STACK_ERROR;
98     }
99
100     ResetProgress();
101
102     return OC_STACK_OK;
103 }
104
105 OCStackResult TerminateProvisioningHandler()
106 {
107     OCStackResult ret = OC_STACK_ERROR;
108     if (OCStop() != OC_STACK_OK)
109     {
110         OIC_LOG(ERROR, TAG, "OCStack stop error");
111     }
112
113     ca_mutex_lock(g_provisioningMutex);
114     g_provisioningCondFlag = true;
115     //ca_cond_signal(g_provisioningCond);
116     ca_mutex_unlock(g_provisioningMutex);
117
118     ca_mutex_free(g_provisioningMutex);
119     g_provisioningMutex = NULL;
120
121     ca_thread_pool_free(g_threadPoolHandle);
122     g_threadPoolHandle = NULL;
123
124     ret = OC_STACK_OK;
125     return ret;
126 }
127
128 void listeningFunc(void *data)
129 {
130     while (!g_provisioningCondFlag)
131     {
132         OCStackResult result;
133
134         ca_mutex_lock(g_provisioningMutex);
135         result = OCProcess();
136         ca_mutex_unlock(g_provisioningMutex);
137
138         if (result != OC_STACK_OK)
139         {
140             OIC_LOG(ERROR, TAG, "OCStack stop error");
141         }
142
143         // To minimize CPU utilization we may wish to do this with sleep
144         sleep(1);
145     }
146 }
147
148 OCStackApplicationResult ProvisionEnrolleeResponse(void* ctx, OCDoHandle handle,
149         OCClientResponse * clientResponse)
150 {
151
152     ProvisioningInfo *provInfo;
153
154     if (!ValidateEnrolleResponse(clientResponse))
155     {
156         ErrorCallback( DEVICE_NOT_PROVISIONED);
157         return OC_STACK_DELETE_TRANSACTION;
158     }
159
160     char* tnn;
161     char* cd;
162
163     OCRepPayload* input = (OCRepPayload*) (clientResponse->payload);
164
165     while (input)
166     {
167
168         int64_t ps;
169         if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_PS, &ps))
170         {
171
172             if (ps == 1)
173             {
174                 OIC_LOG_V(DEBUG, TAG, "PS is proper");
175                 input = input->next;
176                 continue;
177             }
178             else
179             {
180                 OIC_LOG_V(DEBUG, TAG, "PS is NOT proper");
181                 goto Error;
182
183             }
184         }
185
186         if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_TNN, &tnn))
187         {
188             if (!strcmp(tnn, netProvInfo->netAddressInfo.WIFI.ssid))
189             {
190                 OIC_LOG_V(DEBUG, TAG, "SSID is proper");
191                 input = input->next;
192                 continue;
193             }
194             else
195             {
196                 OIC_LOG_V(DEBUG, TAG, "SSID is NOT proper");
197                 goto Error;
198             }
199         }
200
201         if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_CD, &cd))
202         {
203             if (!strcmp(cd, netProvInfo->netAddressInfo.WIFI.pwd))
204             {
205                 OIC_LOG_V(DEBUG, TAG, "Password is proper");
206                 input = input->next;
207                 continue;
208             }
209             else
210             {
211                 OIC_LOG_V(DEBUG, TAG, "Password is NOT proper");
212                 goto Error;
213             }
214         }
215
216         LogProvisioningResponse(input->values);
217
218         input = input->next;
219
220     }
221
222     SuccessCallback(clientResponse);
223
224     return OC_STACK_KEEP_TRANSACTION;
225
226     Error:
227     {
228
229         ErrorCallback( DEVICE_NOT_PROVISIONED);
230
231         return OC_STACK_DELETE_TRANSACTION;
232     }
233
234 }
235
236 OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri,
237         OCDevAddr *destination)
238 {
239     OIC_LOG_V(INFO, TAG, "\n\nExecuting ProvisionEnrollee%s", __func__);
240
241     OCRepPayload* payload = OCRepPayloadCreate();
242
243     OCRepPayloadSetUri(payload, resUri);
244     OCRepPayloadSetPropString(payload, OC_RSRVD_ES_TNN, netProvInfo->netAddressInfo.WIFI.ssid);
245     OCRepPayloadSetPropString(payload, OC_RSRVD_ES_CD, netProvInfo->netAddressInfo.WIFI.pwd);
246
247     OIC_LOG_V(DEBUG, TAG, "OCPayload ready for ProvisionEnrollee");
248
249     OCStackResult ret = InvokeOCDoResource(query, OC_REST_PUT, destination, OC_HIGH_QOS,
250             ProvisionEnrolleeResponse, payload, NULL, 0);
251
252     return ret;
253 }
254
255 OCStackApplicationResult GetProvisioningStatusResponse(void* ctx, OCDoHandle handle,
256         OCClientResponse * clientResponse)
257 {
258
259     ProvisioningInfo *provInfo;
260
261     if (!ValidateEnrolleResponse(clientResponse))
262     {
263         ErrorCallback( DEVICE_NOT_PROVISIONED);
264         ClearMemory();
265         return OC_STACK_DELETE_TRANSACTION;
266     }
267
268     OCRepPayload* input = (OCRepPayload*) (clientResponse->payload);
269
270     char query[OIC_STRING_MAX_VALUE] =
271     { '\0' };
272     char resURI[MAX_URI_LENGTH] =
273     { '\0' };
274
275     OIC_LOG_V(DEBUG, TAG, "resUri = %s", input->uri);
276
277     strncpy(resURI, input->uri, sizeof(resURI));
278
279     snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY, clientResponse->addr->addr, IP_PORT,
280             resURI);
281
282     //OCPayloadLogRep(DEBUG,TAG,input);
283
284     if (ProvisionEnrollee(OC_HIGH_QOS, query, OC_RSRVD_ES_URI_PROV, clientResponse->addr)
285             != OC_STACK_OK)
286     {
287         OIC_LOG(INFO, TAG,
288                 "GetProvisioningStatusResponse received NULL clientResponse.Invoking Provisioing Status Callback");
289
290         ErrorCallback( DEVICE_NOT_PROVISIONED);
291         ClearMemory();
292         return OC_STACK_DELETE_TRANSACTION;
293     }
294
295     return OC_STACK_KEEP_TRANSACTION;
296
297 }
298
299 OCStackResult InvokeOCDoResource(const char* query, OCMethod method, const OCDevAddr *dest,
300         OCQualityOfService qos, OCClientResponseHandler cb, OCRepPayload* payload,
301         OCHeaderOption * options, uint8_t numOptions)
302 {
303     OCStackResult ret;
304     OCCallbackData cbData;
305
306     cbData.cb = cb;
307     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
308     cbData.cd = NULL;
309
310     ret = OCDoResource(NULL, method, query, dest, (OCPayload*) payload, OC_CONNTYPE, qos, &cbData,
311             options, numOptions);
312
313     if (ret != OC_STACK_OK)
314     {
315         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
316     }
317
318     return ret;
319 }
320
321 OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query,
322         const OCDevAddr *destination)
323 {
324     OCStackResult ret = OC_STACK_ERROR;
325     OCHeaderOption options[MAX_HEADER_OPTIONS];
326
327     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
328
329     uint8_t option0[] =
330     { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
331     uint8_t option1[] =
332     { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
333     memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
334     options[0].protocolID = OC_COAP_ID;
335     options[0].optionID = 2048;
336     memcpy(options[0].optionData, option0, sizeof(option0));
337     options[0].optionLength = 10;
338     options[1].protocolID = OC_COAP_ID;
339     options[1].optionID = 3000;
340     memcpy(options[1].optionData, option1, sizeof(option1));
341     options[1].optionLength = 10;
342
343     ret = InvokeOCDoResource(query, OC_REST_GET, destination, OC_HIGH_QOS,
344             GetProvisioningStatusResponse, NULL, options, 2);
345     return ret;
346 }
347
348 OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,
349         OCProvisioningStatusCB provisioningStatusCallback)
350 {
351
352     OCStackResult result = OC_STACK_ERROR;
353
354     if (!ValidateEasySetupParams(netInfo, provisioningStatusCallback))
355     {
356         goto Error;
357     }
358
359     //Only basis test is done for below API
360     if (!SetProgress(provisioningStatusCallback))
361     {
362         // Device provisioning session is running already.
363         OIC_LOG(INFO, TAG, PCF("Device provisioning session is running already"));
364         goto Error;
365     }
366
367     if (!ConfigEnrolleeObject(netInfo))
368     {
369         goto Error;
370     }
371
372     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, FindProvisioningResource,
373             (void *) ""))
374     {
375         goto Error;
376     }
377
378     return OC_STACK_OK;
379
380     Error:
381     {
382         ErrorCallback( DEVICE_NOT_PROVISIONED);
383         ClearMemory();
384         return OC_STACK_ERROR;
385     }
386
387 }
388
389 void StopProvisioningProcess()
390 {
391     //Only basis test is done for below API
392     ResetProgress();
393 }
394
395 // This is a function called back when a device is discovered
396 OCStackApplicationResult FindProvisioningResourceResponse(void* ctx, OCDoHandle handle,
397         OCClientResponse * clientResponse)
398 {
399
400     OIC_LOG(INFO, TAG, PCF("Entering FindProvisioningResourceResponse"));
401
402     if (!ValidateFinddResourceResponse(clientResponse))
403     {
404         ErrorCallback( DEVICE_NOT_PROVISIONED);
405         return OC_STACK_DELETE_TRANSACTION;
406     }
407
408     OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
409
410     ProvisioningInfo *provInfo;
411     char szQueryUri[64] =
412     { 0 };
413
414     OCDiscoveryPayload* discoveryPayload = (OCDiscoveryPayload*) (clientResponse->payload);
415
416     // Need to conform if below check is required or not. As Null check of clientResponse->payload is already performed above
417     if (!discoveryPayload)
418     {
419         OIC_LOG_V(DEBUG, TAG, "Failed To parse");
420         ErrorCallback( DEVICE_NOT_PROVISIONED);
421         return OC_STACK_DELETE_TRANSACTION;
422     }
423
424     OIC_LOG_V(DEBUG, TAG, "resUri = %s", discoveryPayload->resources->uri);
425
426     snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,
427             clientResponse->devAddr.addr, IP_PORT, discoveryPayload->resources->uri);
428
429     OIC_LOG_V(DEBUG, TAG, "query before GetProvisioningStatus call = %s", szQueryUri);
430
431     if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri, &clientResponse->devAddr) != OC_STACK_OK)
432     {
433         ErrorCallback( DEVICE_NOT_PROVISIONED);
434         return OC_STACK_DELETE_TRANSACTION;
435     }
436
437     return OC_STACK_KEEP_TRANSACTION;
438
439 }
440
441 void FindProvisioningResource(void *data)
442 {
443     OCStackResult ret = OC_STACK_ERROR;
444
445     /* Start a discovery query*/
446     char szQueryUri[64] =
447     { 0 };
448
449     snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
450             netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);
451
452     OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);
453
454     OCCallbackData ocCBData;
455
456     ocCBData.cb = FindProvisioningResourceResponse;
457     ocCBData.context = (void*) DEFAULT_CONTEXT_VALUE;
458     ocCBData.cd = NULL;
459
460     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, NULL, OC_CONNTYPE, OC_LOW_QOS,
461             &ocCBData, NULL, 0);
462
463     if (ret != OC_STACK_OK)
464     {
465         ErrorCallback( DEVICE_NOT_PROVISIONED);
466         ClearMemory();
467     }
468 }
469
470 OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,
471         OCClientResponse* clientResponse)
472 {
473     OIC_LOG(INFO, TAG, PCF("Entering SubscribeProvPresenceCallback"));
474
475     OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
476
477     if (clientResponse->result != OC_STACK_OK)
478     {
479         OIC_LOG(ERROR, TAG, "OCStack stop error");
480         return response;
481     }
482
483     if (clientResponse)
484     {
485         OIC_LOG(INFO, TAG, PCF("Client Response exists"));
486
487         if (clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
488         {
489             OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");
490             return response;
491         }
492
493         OCRepPayload* discoveryPayload = (OCRepPayload*) (clientResponse->payload);
494         if (!discoveryPayload)
495         {
496             OIC_LOG_V(DEBUG, TAG, "invalid payload");
497             return response;
498         }
499
500         char sourceIPAddr[OIC_STRING_MAX_VALUE] =
501         { '\0' };
502         snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%s", clientResponse->addr->addr);
503
504         OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s", discoveryPayload->uri, sourceIPAddr);
505
506         /* Start a discovery query*/
507         char szQueryUri[64] =
508         { 0 };
509
510         snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY, sourceIPAddr, IP_PORT);
511
512         /*if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {
513          OIC_LOG(ERROR, TAG, "FindProvisioningResource failed");
514          return OC_STACK_KEEP_TRANSACTION;
515          }*/
516     }
517     else
518     {
519         // clientResponse is invalid
520         OIC_LOG(ERROR, TAG, PCF("Client Response is NULL!"));
521     }
522     return OC_STACK_KEEP_TRANSACTION;
523 }
524
525 OCStackResult SubscribeProvPresence(OCQualityOfService qos, const char* requestURI)
526 {
527     OCStackResult ret = OC_STACK_ERROR;
528
529     OCCallbackData cbData;
530
531     cbData.cb = &SubscribeProvPresenceCallback;
532     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
533     cbData.cd = NULL;
534
535     ret = OCDoResource(NULL, OC_REST_PRESENCE, requestURI, 0, 0, OC_CONNTYPE, OC_LOW_QOS, &cbData,
536             NULL, 0);
537
538     if (ret != OC_STACK_OK)
539     {
540         OIC_LOG(ERROR, TAG, "OCStack resource error");
541     }
542
543     return ret;
544 }
545
546 OCStackResult FindNetworkResource()
547 {
548     OCStackResult ret = OC_STACK_ERROR;
549     if (OCStop() != OC_STACK_OK)
550     {
551         OIC_LOG(ERROR, TAG, "OCStack stop error");
552     }
553
554     return ret;
555 }
556
557 ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse,
558         ProvStatus provStatus)
559 {
560
561     ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
562
563     if (provInfo == NULL)
564     {
565         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
566         return NULL;
567     }
568
569     OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
570
571     if (devAddr == NULL)
572     {
573         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
574         return NULL;
575     }
576
577     strncpy(devAddr->addr, clientResponse->addr->addr, sizeof(devAddr->addr));
578     devAddr->port = clientResponse->addr->port;
579
580     provInfo->provDeviceInfo.addr = devAddr;
581
582     provInfo->provStatus = provStatus;
583
584     return provInfo;
585 }
586
587 bool ValidateEasySetupParams(const EnrolleeNWProvInfo_t *netInfo,
588         OCProvisioningStatusCB provisioningStatusCallback)
589 {
590
591     if (netInfo == NULL || netInfo->netAddressInfo.WIFI.ipAddress == NULL)
592     {
593         OIC_LOG(ERROR, TAG, "Request URI is NULL");
594         return false;
595     }
596
597     if (provisioningStatusCallback == NULL)
598     {
599         OIC_LOG(ERROR, TAG, "ProvisioningStatusCallback is NULL");
600         return false;
601     }
602
603     return true;
604
605 }
606
607 bool InProgress()
608 {
609
610     // It means already Easy Setup provisioning session is going on.
611     if (NULL != cbData)
612     {
613         OIC_LOG(ERROR, TAG, "Easy setup session is already in progress");
614         return true;
615     }
616
617     return false;
618 }
619
620 bool SetProgress(OCProvisioningStatusCB provisioningStatusCallback)
621 {
622     ca_mutex_lock(g_provisioningMutex);
623
624     if (InProgress())
625         return false;
626
627     cbData = provisioningStatusCallback;
628
629     ca_mutex_unlock(g_provisioningMutex);
630
631     return true;
632 }
633
634 bool ResetProgress()
635 {
636     ca_mutex_lock(g_provisioningMutex);
637
638     cbData = NULL;
639
640     ca_mutex_unlock(g_provisioningMutex);
641 }
642
643 ProvisioningInfo* CreateCallBackObject()
644 {
645
646     ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
647
648     if (provInfo == NULL)
649     {
650         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
651         return NULL;
652     }
653
654     OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
655
656     if (devAddr == NULL)
657     {
658         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
659         return NULL;
660     }
661
662     provInfo->provDeviceInfo.addr = devAddr;
663
664     return provInfo;
665
666 }
667
668 ProvisioningInfo* GetCallbackObjectOnError(ProvStatus status)
669 {
670
671     ProvisioningInfo *provInfo = CreateCallBackObject();
672     strncpy(provInfo->provDeviceInfo.addr->addr, netProvInfo->netAddressInfo.WIFI.ipAddress,
673             sizeof(provInfo->provDeviceInfo.addr->addr));
674     provInfo->provDeviceInfo.addr->port = IP_PORT;
675     provInfo->provStatus = status;
676     return provInfo;
677 }
678
679 ProvisioningInfo* GetCallbackObjectOnSuccess(OCClientResponse * clientResponse,
680         ProvStatus provStatus)
681 {
682     ProvisioningInfo *provInfo = CreateCallBackObject();
683     strncpy(provInfo->provDeviceInfo.addr->addr, clientResponse->addr->addr,
684             sizeof(provInfo->provDeviceInfo.addr->addr));
685     provInfo->provDeviceInfo.addr->port = clientResponse->addr->port;
686     provInfo->provStatus = provStatus;
687     return provInfo;
688 }
689
690 bool ValidateFinddResourceResponse(OCClientResponse * clientResponse)
691 {
692
693     if (!(clientResponse) || !(clientResponse->payload))
694     {
695
696         OIC_LOG_V(INFO, TAG, "ProvisionEnrolleeResponse received Null clientResponse");
697
698         return false;
699
700     }
701 return true;
702 }
703
704 bool ValidateEnrolleResponse(OCClientResponse * clientResponse)
705 {
706
707     if (!(clientResponse) || !(clientResponse->payload))
708     {
709
710         OIC_LOG_V(INFO, TAG, "ProvisionEnrolleeResponse received Null clientResponse");
711
712         return false;
713
714     }
715
716     if (clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
717     {
718
719         OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");
720         return false;
721
722     }
723
724     // If flow reachese here means no error condition hit.
725     return true;
726
727 }
728
729
730 void SuccessCallback(OCClientResponse * clientResponse)
731 {
732     ProvisioningInfo *provInfo = GetCallbackObjectOnSuccess(clientResponse, DEVICE_PROVISIONED);
733     cbData(provInfo);
734     ResetProgress();
735 }
736
737 bool ClearMemory()
738 {
739
740     OIC_LOG(DEBUG, TAG, "thread_pool_add_task of FindProvisioningResource failed");
741     ca_thread_pool_free(g_threadPoolHandle);
742     ca_mutex_unlock(g_provisioningMutex);
743     ca_mutex_free(g_provisioningMutex);
744     ca_cond_free(g_provisioningCond);
745
746     return true;
747
748 }
749
750 bool ConfigEnrolleeObject(const EnrolleeNWProvInfo_t *netInfo)
751 {
752
753     //Copy Network Provisioning  Information
754     netProvInfo = (EnrolleeNWProvInfo_t *) OICCalloc(1, sizeof(EnrolleeNWProvInfo_t));
755
756     if (netProvInfo == NULL)
757     {
758         OIC_LOG(ERROR, TAG, "Invalid input..");
759         return false;
760     }
761
762     memcpy(netProvInfo, netInfo, sizeof(EnrolleeNWProvInfo_t));
763
764     OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. SSID = %s",
765             netProvInfo->netAddressInfo.WIFI.ssid);
766
767     OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. PWD = %s",
768             netProvInfo->netAddressInfo.WIFI.pwd);
769
770     return true;
771
772 }
773
774 void LogProvisioningResponse(OCRepPayloadValue* val)
775 {
776
777     switch (val->type)
778     {
779         case OCREP_PROP_NULL:
780             OIC_LOG_V(DEBUG, TAG, "\t\t%s: NULL", val->name);
781             break;
782         case OCREP_PROP_INT:
783             OIC_LOG_V(DEBUG, TAG, "\t\t%s(int):%lld", val->name, val->i);
784             break;
785         case OCREP_PROP_DOUBLE:
786             OIC_LOG_V(DEBUG, TAG, "\t\t%s(double):%f", val->name, val->d);
787             break;
788         case OCREP_PROP_BOOL:
789             OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");
790             break;
791         case OCREP_PROP_STRING:
792             OIC_LOG_V(DEBUG, TAG, "\t\t%s(string):%s", val->name, val->str);
793             break;
794         case OCREP_PROP_OBJECT:
795             // Note: Only prints the URI (if available), to print further, you'll
796             // need to dig into the object better!
797             OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep):%s", val->name, val->obj->uri);
798             break;
799         case OCREP_PROP_ARRAY:
800             switch (val->arr.type)
801             {
802                 case OCREP_PROP_INT:
803                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(int array):%lld x %lld x %lld", val->name,
804                             val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
805                     break;
806                 case OCREP_PROP_DOUBLE:
807                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(double array):%lld x %lld x %lld", val->name,
808                             val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
809                     break;
810                 case OCREP_PROP_BOOL:
811                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool array):%lld x %lld x %lld", val->name,
812                             val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
813                     break;
814                 case OCREP_PROP_STRING:
815                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(string array):%lld x %lld x %lld", val->name,
816                             val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
817                     break;
818                 case OCREP_PROP_OBJECT:
819                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep array):%lld x %lld x %lld", val->name,
820                             val->arr.dimensions[0], val->arr.dimensions[1], val->arr.dimensions[2]);
821                     break;
822                 default:
823                     //OIC_LOG_V(ERROR, TAG, "\t\t%s <-- Unknown/unsupported array type!",
824                     //  val->name);
825                     break;
826             }
827             break;
828         default:
829             /*OC_LOG_V(ERROR, TAG
830              , "\t\t%s <-- Unknown type!", val->name);*/
831             break;
832     }
833 }
834