Merge branch 'master' into easysetup and fixed OCStack issue
[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
27 #include "provisioninghandler.h"
28
29 // External includes
30 #include "cJSON.h"
31 #include "camutex.h"
32 #include "cathreadpool.h"
33 #include "logger.h"
34 #include "oic_malloc.h"
35
36
37 /**
38  * @var g_provisioningMutex
39  * @brief Mutex to synchronize access to g_caDtlsContext.
40  */
41 static ca_mutex g_provisioningMutex = NULL;
42 static ca_cond g_provisioningCond = NULL;
43 bool g_provisioningCondFlag = false;
44
45 static EnrolleeNWProvInfo_t* netProvInfo;
46
47 /**
48  * @var cbData
49  * @brief Callback for providing provisioning status callback to application
50  */
51 static OCProvisioningStatusCB cbData = NULL;
52 static ca_thread_pool_t g_threadPoolHandle = NULL;
53
54 OCStackResult InitProvisioningHandler() {
55     OCStackResult ret = OC_STACK_ERROR;
56     /* Initialize OCStack*/
57     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK) {
58         OIC_LOG(ERROR, TAG, "OCStack init error");
59         return ret;
60     }
61
62     g_provisioningMutex = ca_mutex_new();
63
64     OIC_LOG(DEBUG, TAG, "ca_thread_pool_init initializing");
65
66     if (CA_STATUS_OK != ca_thread_pool_init(2, &g_threadPoolHandle)) {
67         OIC_LOG(DEBUG, TAG, "thread_pool_init failed");
68         return OC_STACK_ERROR;
69     }
70
71     g_provisioningCond = ca_cond_new();
72     if (NULL == g_provisioningCond) {
73         OIC_LOG(DEBUG, TAG, "Failed to create condition");
74         ca_mutex_free(g_provisioningMutex);
75         ca_thread_pool_free(g_threadPoolHandle);
76         return OC_STACK_ERROR;
77     }
78
79     char *string = "listeningFunc invoked in a thread";
80     if (CA_STATUS_OK
81             != ca_thread_pool_add_task(g_threadPoolHandle, listeningFunc,
82                     (void *) string)) {
83         OIC_LOG(DEBUG, TAG, "thread_pool_add_task failed");
84         ca_thread_pool_free(g_threadPoolHandle);
85         ca_mutex_unlock(g_provisioningMutex);
86         ca_mutex_free(g_provisioningMutex);
87         ca_cond_free(g_provisioningCond);
88         return OC_STACK_ERROR;
89     }
90     return OC_STACK_OK;
91 }
92
93 OCStackResult TerminateProvisioningHandler() {
94     OCStackResult ret = OC_STACK_ERROR;
95     if (OCStop() != OC_STACK_OK) {
96         OIC_LOG(ERROR, TAG, "OCStack stop error");
97     }
98
99     ca_mutex_lock(g_provisioningMutex);
100     g_provisioningCondFlag = true;
101     //ca_cond_signal(g_provisioningCond);
102     ca_mutex_unlock(g_provisioningMutex);
103
104     ca_mutex_free(g_provisioningMutex);
105     g_provisioningMutex = NULL;
106
107     ca_thread_pool_free(g_threadPoolHandle);
108     g_threadPoolHandle = NULL;
109
110     ret = OC_STACK_OK;
111     return ret;
112 }
113
114 void listeningFunc(void *data) {
115     while (!g_provisioningCondFlag) {
116         OCStackResult result;
117
118         ca_mutex_lock(g_provisioningMutex);
119         result = OCProcess();
120         ca_mutex_unlock(g_provisioningMutex);
121
122         if (result != OC_STACK_OK) {
123             OIC_LOG(ERROR, TAG, "OCStack stop error");
124         }
125
126         // To minimize CPU utilization we may wish to do this with sleep
127         sleep(1);
128     }
129 }
130
131 OCStackApplicationResult ProvisionEnrolleeResponse(void* ctx, OCDoHandle handle,
132         OCClientResponse * clientResponse) {
133     ProvisioningInfo *provInfo;
134
135     if (clientResponse) {
136         OIC_LOG_V(INFO, TAG, "Put Response JSON = %s",
137                 clientResponse->resJSONPayload);
138     } else {
139         OIC_LOG_V(INFO, TAG,
140                 "ProvisionEnrolleeResponse received Null clientResponse");
141         provInfo = PrepareProvisioingStatusCB(clientResponse,
142                 DEVICE_NOT_PROVISIONED);
143         cbData(provInfo);
144         return OC_STACK_DELETE_TRANSACTION;
145     }
146
147     OIC_LOG_V(DEBUG, TAG, "ProvisionEnrolleeResponse %s ",
148             clientResponse->resJSONPayload);
149
150     if (clientResponse->resJSONPayload) {
151         cJSON *observeJson = cJSON_CreateObject();
152         observeJson = cJSON_Parse(clientResponse->resJSONPayload);
153
154         cJSON *ocArray = cJSON_GetObjectItem(observeJson, OC_RSRVD_OC);
155         cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
156
157         cJSON *representationArray = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_REPRESENTATION);
158         char *ocArray_str = cJSON_PrintUnformatted(representationArray);
159
160         if (strstr(ocArray_str, "[{}") == ocArray_str) {
161             OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
162             cJSON_Delete(observeJson);
163             return OC_STACK_DELETE_TRANSACTION;
164         }
165
166         int countofrep = cJSON_GetArraySize(representationArray);
167
168         for (int i = 0; i < countofrep; ++i) {
169             cJSON *arrayJSON = cJSON_GetArrayItem(representationArray, i);
170             OIC_LOG_V(DEBUG, TAG, "rep#%d's name : %s", i, arrayJSON->string);
171
172             if (!strcmp(arrayJSON->string, OC_RSRVD_ES_PS))
173             {
174                 if(arrayJSON->valueint == 1)
175                 {
176                     OIC_LOG_V(DEBUG, TAG, "PS is proper");
177                     continue;
178                 }
179                 else{
180                     OIC_LOG_V(DEBUG, TAG, "PS is NOT proper");
181                     provInfo = PrepareProvisioingStatusCB(clientResponse,
182                             DEVICE_NOT_PROVISIONED);
183                     cbData(provInfo);
184                 }
185             }
186
187             if (!strcmp(arrayJSON->string, OC_RSRVD_ES_TNN))
188             {
189                 if(!strcmp(arrayJSON->valuestring, netProvInfo->netAddressInfo.WIFI.ssid))
190                 {
191                     OIC_LOG_V(DEBUG, TAG, "SSID is proper");
192                     continue;
193                 }
194                 else{
195                     OIC_LOG_V(DEBUG, TAG, "SSID is NOT proper");
196                     provInfo = PrepareProvisioingStatusCB(clientResponse,
197                             DEVICE_NOT_PROVISIONED);
198                     cbData(provInfo);
199                 }
200             }
201
202             if (!strcmp(arrayJSON->string, OC_RSRVD_ES_CD))
203             {
204                 if(!strcmp(arrayJSON->valuestring, netProvInfo->netAddressInfo.WIFI.pwd))
205                 {
206                     OIC_LOG_V(DEBUG, TAG, "Password is proper");
207                     continue;
208                 }
209                 else{
210                     OIC_LOG_V(DEBUG, TAG, "Password is NOT proper");
211                     provInfo = PrepareProvisioingStatusCB(clientResponse,
212                             DEVICE_NOT_PROVISIONED);
213                     cbData(provInfo);
214                 }
215             }
216
217             switch (arrayJSON->type) {
218             case cJSON_False:
219             case cJSON_True:
220                 OIC_LOG_V(DEBUG, TAG, "rep#%d's int value : %d", i,
221                         arrayJSON->valueint);
222                 break;
223             case cJSON_Number:
224                 OIC_LOG_V(DEBUG, TAG, "rep#%d's double value : %f", i,
225                         arrayJSON->valuedouble);
226                 break;
227             case cJSON_String:
228                 OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %s", i,
229                         arrayJSON->valuestring);
230                 break;
231             case cJSON_NULL:
232             default:
233                 OIC_LOG_V(DEBUG, TAG, "rep#%d's value : NULL", i);
234                 break;
235             }
236         }
237
238         cJSON_Delete(observeJson);
239
240         provInfo = PrepareProvisioingStatusCB(clientResponse,
241                 DEVICE_PROVISIONED);
242         cbData(provInfo);
243
244         return OC_STACK_KEEP_TRANSACTION;
245     } else {
246         OIC_LOG(INFO, TAG,
247                 "ProvisionEnrolleeResponse received NULL clientResponse. \
248                                 Invoking Provisioing Status Callback");
249         provInfo = PrepareProvisioingStatusCB(clientResponse,
250                 DEVICE_NOT_PROVISIONED);
251         cbData(provInfo);
252         return OC_STACK_DELETE_TRANSACTION;
253     }
254 }
255
256 OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri) {
257     OIC_LOG_V(INFO, TAG, "\n\nExecuting ProvisionEnrollee%s", __func__);
258
259     cJSON *jsonFinal = cJSON_CreateObject();
260     cJSON *json = cJSON_CreateObject();
261     cJSON *jsonArray;
262     cJSON *format;
263     char* payload = NULL;
264
265     cJSON_AddStringToObject(json, OC_RSRVD_HREF, resUri);
266     cJSON_AddItemToObject(json, OC_RSRVD_REPRESENTATION, format = cJSON_CreateObject());
267     cJSON_AddStringToObject(format, OC_RSRVD_ES_TNN, netProvInfo->netAddressInfo.WIFI.ssid);
268     cJSON_AddStringToObject(format, OC_RSRVD_ES_CD, netProvInfo->netAddressInfo.WIFI.pwd);
269     cJSON_AddItemToObject(jsonFinal, OC_RSRVD_OC, jsonArray = cJSON_CreateArray());
270     cJSON_AddItemToArray(jsonArray, json);
271
272     OIC_LOG_V(DEBUG, TAG, "ProvisionEnrollee : %s",
273             cJSON_PrintUnformatted(jsonFinal));
274     payload = cJSON_Print(jsonFinal);
275     OIC_LOG_V(DEBUG, TAG, "Payload : %s", payload);
276
277     OCStackResult ret = InvokeOCDoResource(query, OC_REST_PUT, OC_HIGH_QOS,
278             ProvisionEnrolleeResponse, payload, NULL, 0);
279
280     cJSON_Delete(json);
281     return ret;
282 }
283
284 OCStackApplicationResult GetProvisioningStatusResponse(void* ctx,
285         OCDoHandle handle, OCClientResponse * clientResponse) {
286     ProvisioningInfo *provInfo;
287
288     if (clientResponse == NULL) {
289         OIC_LOG(INFO, TAG,
290                 "getReqCB received NULL clientResponse. \
291             Invoking Provisioing Status Callback");
292         provInfo = PrepareProvisioingStatusCB(clientResponse,
293                 DEVICE_NOT_PROVISIONED);
294         cbData(provInfo);
295         return OC_STACK_DELETE_TRANSACTION;
296     }
297
298     if (clientResponse->rcvdVendorSpecificHeaderOptions
299             && clientResponse->numRcvdVendorSpecificHeaderOptions) {
300         OIC_LOG(INFO, TAG, "Received vendor specific options");
301         uint8_t i = 0;
302         OCHeaderOption * rcvdOptions =
303                 clientResponse->rcvdVendorSpecificHeaderOptions;
304         for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions;
305                 i++) {
306             if (((OCHeaderOption) rcvdOptions[i]).protocolID == OC_COAP_ID) {
307                 OIC_LOG_V(INFO, TAG,
308                         "Received option with OC_COAP_ID and ID %u with",
309                         ((OCHeaderOption) rcvdOptions[i]).optionID);
310
311                 OIC_LOG_BUFFER(INFO, TAG,
312                         ((OCHeaderOption) rcvdOptions[i]).optionData,
313                         MAX_HEADER_OPTION_DATA_LENGTH);
314             }
315         }
316     }
317
318     char query[OIC_STRING_MAX_VALUE] = { '\0' };
319
320
321     if (clientResponse->resJSONPayload) {
322         cJSON *observeJson = cJSON_CreateObject();
323         observeJson = cJSON_Parse(clientResponse->resJSONPayload);
324
325         cJSON *ocArray = cJSON_GetObjectItem(observeJson, OC_RSRVD_OC);
326         cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
327
328         cJSON *resUriObj = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_HREF);
329
330         OIC_LOG_V(DEBUG, TAG, "resUriObj = %s, valueString = %s",
331             resUriObj->string, resUriObj->valuestring);
332
333         char resURI[MAX_URI_LENGTH]={'\0'};
334
335         strncpy(resURI, resUriObj->valuestring, sizeof(resURI));
336
337         snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY,
338                 clientResponse->addr->addr,
339                 IP_PORT, resURI);
340
341         cJSON *representationArray = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_REPRESENTATION);
342         char *ocArray_str = cJSON_PrintUnformatted(representationArray);
343
344         if (strstr(ocArray_str, "[{}") == ocArray_str) {
345             OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
346             cJSON_Delete(observeJson);
347             return OC_STACK_DELETE_TRANSACTION;
348         }
349
350         int countofrep = cJSON_GetArraySize(representationArray);
351
352         for (int i = 0; i < countofrep; ++i) {
353             cJSON *arrayJSON = cJSON_GetArrayItem(representationArray, i);
354             OIC_LOG_V(DEBUG, TAG, "rep#%d's name : %s", i, arrayJSON->string);
355
356             switch (arrayJSON->type) {
357             case cJSON_False:
358             case cJSON_True:
359                 OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %d", i,
360                         arrayJSON->valueint);
361                 break;
362             case cJSON_Number:
363                 OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %f", i,
364                         arrayJSON->valuedouble);
365                 break;
366             case cJSON_String:
367                 OIC_LOG_V(DEBUG, TAG, "rep#%d's value : %s", i,
368                         arrayJSON->valuestring);
369                 break;
370             case cJSON_NULL:
371             default:
372                 OIC_LOG_V(DEBUG, TAG, "rep#%d's value : NULL", i);
373                 break;
374             }
375         }
376         cJSON_Delete(observeJson);
377
378         if (ProvisionEnrollee(OC_HIGH_QOS, query, resURI) != OC_STACK_OK) {
379             OIC_LOG(INFO, TAG,
380                     "GetProvisioningStatusResponse received NULL clientResponse. \
381                 Invoking Provisioing Status Callback");
382             provInfo = PrepareProvisioingStatusCB(clientResponse,
383                     DEVICE_NOT_PROVISIONED);
384             cbData(provInfo);
385
386             return OC_STACK_DELETE_TRANSACTION;
387         }
388     } else {
389         OIC_LOG(INFO, TAG,
390                 "GetProvisioningStatusResponse received NULL clientResponse. \
391             Invoking Provisioing Status Callback");
392         provInfo = PrepareProvisioingStatusCB(clientResponse,
393                 DEVICE_NOT_PROVISIONED);
394         cbData(provInfo);
395         return OC_STACK_DELETE_TRANSACTION;
396     }
397     return OC_STACK_DELETE_TRANSACTION;
398 }
399
400 OCStackResult InvokeOCDoResource(const char* query, OCMethod method,
401         OCQualityOfService qos, OCClientResponseHandler cb, const char* request,
402         OCHeaderOption * options, uint8_t numOptions) {
403     OCStackResult ret;
404     OCCallbackData cbData;
405
406     cbData.cb = cb;
407     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
408     cbData.cd = NULL;
409
410     ret = OCDoResource(NULL, method, query, 0, request, OC_CONNTYPE, qos,
411             &cbData, options, numOptions);
412
413     if (ret != OC_STACK_OK) {
414         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d",
415                 ret, method);
416     }
417
418     return ret;
419 }
420
421 OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query) {
422     OCStackResult ret = OC_STACK_ERROR;
423     OCHeaderOption options[MAX_HEADER_OPTIONS];
424
425     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
426
427     uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
428     uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
429     memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
430     options[0].protocolID = OC_COAP_ID;
431     options[0].optionID = 2048;
432     memcpy(options[0].optionData, option0, sizeof(option0));
433     options[0].optionLength = 10;
434     options[1].protocolID = OC_COAP_ID;
435     options[1].optionID = 3000;
436     memcpy(options[1].optionData, option1, sizeof(option1));
437     options[1].optionLength = 10;
438
439     ret = InvokeOCDoResource(query, OC_REST_GET, OC_HIGH_QOS,
440             GetProvisioningStatusResponse, NULL, options, 2);
441     return ret;
442 }
443
444 OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,
445         OCProvisioningStatusCB provisioningStatusCallback) {
446     OCStackResult result = OC_STACK_ERROR;
447
448     if (netInfo->netAddressInfo.WIFI.ipAddress == NULL) {
449         OIC_LOG(ERROR, TAG, "Request URI is NULL");
450         return result;
451     }
452
453     if (provisioningStatusCallback == NULL) {
454         OIC_LOG(ERROR, TAG, "ProvisioningStatusCallback is NULL");
455         return result;
456     }
457
458     cbData = provisioningStatusCallback;
459
460     //Copy Network Provisioning  Information
461     netProvInfo = (EnrolleeNWProvInfo_t *)OICCalloc(1, sizeof(EnrolleeNWProvInfo_t));
462
463     if (NULL == netProvInfo)
464     {
465         OIC_LOG(ERROR, TAG, "Invalid input..");
466         return OC_STACK_ERROR;
467     }
468     memcpy(netProvInfo, netInfo, sizeof(EnrolleeNWProvInfo_t));
469
470     OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. SSID = %s",
471         netProvInfo->netAddressInfo.WIFI.ssid);
472
473     OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. PWD = %s",
474         netProvInfo->netAddressInfo.WIFI.pwd);
475
476
477     if (CA_STATUS_OK
478             != ca_thread_pool_add_task(g_threadPoolHandle, FindProvisioningResource,
479                     (void *) "")) {
480         OIC_LOG(DEBUG, TAG, "thread_pool_add_task of FindProvisioningResource failed");
481         ca_thread_pool_free(g_threadPoolHandle);
482         ca_mutex_unlock(g_provisioningMutex);
483         ca_mutex_free(g_provisioningMutex);
484         ca_cond_free(g_provisioningCond);
485         return OC_STACK_ERROR;
486     }
487     return OC_STACK_OK;
488 }
489
490 void StopProvisioningProcess() {
491     cbData = NULL;
492 }
493
494 // This is a function called back when a device is discovered
495 OCStackApplicationResult FindProvisioningResourceResponse(void* ctx,
496         OCDoHandle handle, OCClientResponse * clientResponse) {
497     OIC_LOG(INFO, TAG, PCF("Entering FindProvisioningResourceResponse"));
498
499     OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
500
501     ProvisioningInfo *provInfo;
502
503     if (clientResponse->result != OC_STACK_OK) {
504         OIC_LOG(ERROR, TAG,
505                 "OCStack stop error. Calling Provisioing Status Callback");
506
507         provInfo = PrepareProvisioingStatusCB(clientResponse,
508                 DEVICE_NOT_PROVISIONED);
509
510         cbData(provInfo);
511         return response;
512     }
513
514     if (clientResponse) {
515         cJSON *discoveryJson = cJSON_CreateObject();
516         discoveryJson = cJSON_Parse((char *) clientResponse->resJSONPayload);
517
518         cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, OC_RSRVD_OC);
519         char *ocArray_str = cJSON_PrintUnformatted(ocArray);
520
521         if (strstr(ocArray_str, "[{}") == ocArray_str) {
522             OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
523             cJSON_Delete(discoveryJson);
524
525             provInfo = PrepareProvisioingStatusCB(clientResponse,
526                     DEVICE_NOT_PROVISIONED);
527             cbData(provInfo);
528             return response;
529         }
530
531         cJSON *ocArray_sub = cJSON_GetArrayItem(ocArray, 0);
532         cJSON *resUriObj = cJSON_GetObjectItem(ocArray_sub, OC_RSRVD_HREF);
533
534         OIC_LOG_V(DEBUG, TAG, "resUriObj = %s, valueString = %s",
535             resUriObj->string, resUriObj->valuestring);
536
537
538         char szQueryUri[64] = { 0 };
539
540         snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,
541                 clientResponse->devAddr.addr, IP_PORT, resUriObj->valuestring);
542         OIC_LOG_V(DEBUG, TAG, "query before GetProvisioningStatus call = %s", szQueryUri);
543
544         if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri) != OC_STACK_OK) {
545             OIC_LOG(INFO, TAG,
546                     "GetProvisioningStatus returned error. \
547                                 Invoking Provisioing Status Callback");
548             provInfo = PrepareProvisioingStatusCB(clientResponse,
549                     DEVICE_NOT_PROVISIONED);
550
551             cbData(provInfo);
552             return OC_STACK_DELETE_TRANSACTION;
553         }
554     } else {
555         // clientResponse is invalid
556         OIC_LOG(ERROR, TAG,
557                 "Invalid response for Provisioning Discovery request. \
558         Invoking Provisioing Status Callback");
559         provInfo = PrepareProvisioingStatusCB(clientResponse,
560                 DEVICE_NOT_PROVISIONED);
561         cbData(provInfo);
562         return response;
563     }
564     return OC_STACK_KEEP_TRANSACTION;
565 }
566
567 void FindProvisioningResource(void *data)
568 {
569     OCStackResult ret = OC_STACK_ERROR;
570
571     /* Start a discovery query*/
572     char szQueryUri[64] = { 0 };
573
574     snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
575             netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);
576
577     OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);
578
579     OCCallbackData ocCBData;
580
581     ocCBData.cb = FindProvisioningResourceResponse;
582     ocCBData.context = (void*) DEFAULT_CONTEXT_VALUE;
583     ocCBData.cd = NULL;
584
585     ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
586             OC_LOW_QOS, &ocCBData, NULL, 0);
587
588     if (ret != OC_STACK_OK) {
589         OIC_LOG(ERROR, TAG, "OCStack resource error");
590
591         OIC_LOG(ERROR, TAG,
592                 "FindProvisioningResource failed. \
593             Invoking Provisioing Status Callback");
594
595         ProvisioningInfo *provInfo;
596         provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
597
598         if(provInfo == NULL)
599         {
600             OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
601             return;
602         }
603
604         OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
605
606         if(devAddr == NULL)
607         {
608             OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
609             return;
610         }
611
612         strncpy(devAddr->addr, netProvInfo->netAddressInfo.WIFI.ipAddress, sizeof(devAddr->addr));
613         devAddr->port= IP_PORT;
614         provInfo->provDeviceInfo.addr = devAddr;
615         provInfo->provStatus = DEVICE_NOT_PROVISIONED;
616
617
618         cbData(provInfo);
619     }
620 }
621
622 OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,
623         OCClientResponse* clientResponse) {
624     OIC_LOG(INFO, TAG, PCF("Entering SubscribeProvPresenceCallback"));
625
626     OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;
627
628     if (clientResponse->result != OC_STACK_OK) {
629         OIC_LOG(ERROR, TAG, "OCStack stop error");
630         return response;
631     }
632
633     if (clientResponse) {
634         OIC_LOG(INFO, TAG, PCF("Client Response exists"));
635
636         cJSON *discoveryJson = cJSON_CreateObject();
637         discoveryJson = cJSON_Parse((char *) clientResponse->resJSONPayload);
638
639         cJSON *ocArray = cJSON_GetObjectItem(discoveryJson, OC_RSRVD_OC);
640         char *ocArray_str = cJSON_PrintUnformatted(ocArray);
641
642         if (strstr(ocArray_str, "[{}") == ocArray_str) {
643             OIC_LOG_V(DEBUG, TAG, "invalid payload : %s", ocArray_str);
644             cJSON_Delete(discoveryJson);
645             return response;
646         }
647
648         char sourceIPAddr[OIC_STRING_MAX_VALUE] = { '\0' };
649         snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%s", clientResponse->addr->addr);
650
651         OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s",
652                 clientResponse->resJSONPayload, sourceIPAddr);
653
654         /* Start a discovery query*/
655         char szQueryUri[64] = { 0 };
656
657         snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,
658                 sourceIPAddr, IP_PORT);
659
660         /*if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {
661             OIC_LOG(ERROR, TAG, "FindProvisioningResource failed");
662             return OC_STACK_KEEP_TRANSACTION;
663         }*/
664     } else {
665         // clientResponse is invalid
666         OIC_LOG(ERROR, TAG, PCF("Client Response is NULL!"));
667     }
668     return OC_STACK_KEEP_TRANSACTION;
669 }
670
671 OCStackResult SubscribeProvPresence(OCQualityOfService qos,
672         const char* requestURI) {
673     OCStackResult ret = OC_STACK_ERROR;
674
675     OCCallbackData cbData;
676
677     cbData.cb = &SubscribeProvPresenceCallback;
678     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;
679     cbData.cd = NULL;
680
681     ret = OCDoResource(NULL, OC_REST_PRESENCE, requestURI, 0, 0, OC_CONNTYPE,
682             OC_LOW_QOS, &cbData, NULL, 0);
683
684     if (ret != OC_STACK_OK) {
685         OIC_LOG(ERROR, TAG, "OCStack resource error");
686     }
687
688     return ret;
689 }
690
691 OCStackResult FindNetworkResource() {
692     OCStackResult ret = OC_STACK_ERROR;
693     if (OCStop() != OC_STACK_OK) {
694         OIC_LOG(ERROR, TAG, "OCStack stop error");
695     }
696
697     return ret;
698 }
699
700 ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse, ProvStatus provStatus) {
701
702     ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));
703
704     if(provInfo == NULL)
705     {
706         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
707         return NULL;
708     }
709
710     OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));
711
712     if(devAddr == NULL)
713     {
714         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");
715         return NULL;
716     }
717
718     strncpy(devAddr->addr, clientResponse->addr->addr, sizeof(devAddr->addr));
719     devAddr->port= clientResponse->addr->port;
720
721     provInfo->provDeviceInfo.addr = devAddr;
722
723     provInfo->provStatus = provStatus;
724
725     return provInfo;
726 }
727