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