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