Merge branch 'master' into easysetup & CBOR changes
[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                     continue;\r
169                 }\r
170                 else{\r
171                     OIC_LOG_V(DEBUG, TAG, "PS is NOT proper");\r
172                     provInfo = PrepareProvisioingStatusCB(clientResponse,\r
173                             DEVICE_NOT_PROVISIONED);\r
174                     cbData(provInfo);\r
175 \r
176                 }\r
177             }\r
178 \r
179             const char* tnn;\r
180             if(OCRepPayloadGetPropString(input,OC_RSRVD_ES_TNN,&tnn)){\r
181                 if(!strcmp(tnn, netProvInfo->netAddressInfo.WIFI.ssid))\r
182                 {\r
183                     OIC_LOG_V(DEBUG, TAG, "SSID is proper");\r
184                     continue;\r
185                 }\r
186                 else{\r
187                     OIC_LOG_V(DEBUG, TAG, "SSID is NOT proper");\r
188                     provInfo = PrepareProvisioingStatusCB(clientResponse,\r
189                             DEVICE_NOT_PROVISIONED);\r
190                     cbData(provInfo);\r
191                 }\r
192             }\r
193             const char* cd;\r
194             if(OCRepPayloadGetPropString(input, OC_RSRVD_ES_CD,&cd)){\r
195                 if(!strcmp(cd,netProvInfo->netAddressInfo.WIFI.pwd))\r
196                 {\r
197                     OIC_LOG_V(DEBUG, TAG, "Password is proper");\r
198                     continue;\r
199                 }\r
200                 else{\r
201                     OIC_LOG_V(DEBUG, TAG, "Password is NOT proper");\r
202                     provInfo = PrepareProvisioingStatusCB(clientResponse,\r
203                             DEVICE_NOT_PROVISIONED);\r
204                     cbData(provInfo);\r
205                 }\r
206             }\r
207 \r
208             OCRepPayloadValue* val = input->values;\r
209 \r
210             switch(val->type)\r
211             {\r
212                 case OCREP_PROP_NULL:\r
213                     OIC_LOG_V(DEBUG, TAG, "\t\t%s: NULL", val->name);\r
214                     break;\r
215                 case OCREP_PROP_INT:\r
216                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(int):%lld", val->name, val->i);\r
217                     break;\r
218                 case OCREP_PROP_DOUBLE:\r
219                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(double):%f", val->name, val->d);\r
220                     break;\r
221                 case OCREP_PROP_BOOL:\r
222                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");\r
223                     break;\r
224                 case OCREP_PROP_STRING:\r
225                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(string):%s", val->name, val->str);\r
226                     break;\r
227                 case OCREP_PROP_OBJECT:\r
228                     // Note: Only prints the URI (if available), to print further, you'll\r
229                     // need to dig into the object better!\r
230                     OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep):%s", val->name, val->obj->uri);\r
231                     break;\r
232                 case OCREP_PROP_ARRAY:\r
233                     switch(val->arr.type)\r
234                     {\r
235                         case OCREP_PROP_INT:\r
236                             OIC_LOG_V(DEBUG, TAG, "\t\t%s(int array):%lld x %lld x %lld",\r
237                                     val->name,\r
238                                     val->arr.dimensions[0], val->arr.dimensions[1],\r
239                                     val->arr.dimensions[2]);\r
240                             break;\r
241                         case OCREP_PROP_DOUBLE:\r
242                             OIC_LOG_V(DEBUG, TAG, "\t\t%s(double array):%lld x %lld x %lld",\r
243                                     val->name,\r
244                                     val->arr.dimensions[0], val->arr.dimensions[1],\r
245                                     val->arr.dimensions[2]);\r
246                             break;\r
247                         case OCREP_PROP_BOOL:\r
248                             OIC_LOG_V(DEBUG, TAG, "\t\t%s(bool array):%lld x %lld x %lld",\r
249                                     val->name,\r
250                                     val->arr.dimensions[0], val->arr.dimensions[1],\r
251                                     val->arr.dimensions[2]);\r
252                             break;\r
253                         case OCREP_PROP_STRING:\r
254                             OIC_LOG_V(DEBUG, TAG, "\t\t%s(string array):%lld x %lld x %lld",\r
255                                     val->name,\r
256                                     val->arr.dimensions[0], val->arr.dimensions[1],\r
257                                     val->arr.dimensions[2]);\r
258                             break;\r
259                         case OCREP_PROP_OBJECT:\r
260                             OIC_LOG_V(DEBUG, TAG, "\t\t%s(OCRep array):%lld x %lld x %lld",\r
261                                     val->name,\r
262                                     val->arr.dimensions[0], val->arr.dimensions[1],\r
263                                     val->arr.dimensions[2]);\r
264                             break;\r
265                         default:\r
266                             //OIC_LOG_V(ERROR, TAG, "\t\t%s <-- Unknown/unsupported array type!",\r
267                             //  val->name);\r
268                             break;\r
269                     }\r
270                     break;\r
271                         default:\r
272                             /*OC_LOG_V(ERROR, TAG\r
273                                 , "\t\t%s <-- Unknown type!", val->name);*/\r
274                             break;\r
275             }\r
276             input=input->next;\r
277         }\r
278 \r
279 \r
280 \r
281 \r
282 \r
283 \r
284 \r
285         provInfo = PrepareProvisioingStatusCB(clientResponse,\r
286                 DEVICE_PROVISIONED);\r
287         cbData(provInfo);\r
288 \r
289         return OC_STACK_KEEP_TRANSACTION;\r
290     } else {\r
291         OIC_LOG(INFO, TAG,\r
292                 "ProvisionEnrolleeResponse received NULL clientResponse. \\r
293         Invoking Provisioing Status Callback");\r
294         provInfo = PrepareProvisioingStatusCB(clientResponse,\r
295                 DEVICE_NOT_PROVISIONED);\r
296         cbData(provInfo);\r
297         return OC_STACK_DELETE_TRANSACTION;\r
298     }\r
299 }\r
300 \r
301 \r
302 \r
303 OCStackResult ProvisionEnrollee(OCQualityOfService qos, const char* query, const char* resUri) {\r
304     OIC_LOG_V(INFO, TAG, "\n\nExecuting ProvisionEnrollee%s", __func__);\r
305 \r
306 \r
307     OCRepPayload* payload = OCRepPayloadCreate();\r
308 \r
309     OCRepPayloadSetUri(payload,resUri);\r
310     OCRepPayloadSetPropString(payload,OC_RSRVD_ES_TNN,netProvInfo->netAddressInfo.WIFI.ssid);\r
311     OCRepPayloadSetPropString(payload,OC_RSRVD_ES_CD,netProvInfo->netAddressInfo.WIFI.pwd);\r
312 \r
313     OIC_LOG_V(DEBUG, TAG, "OCPayload ready for ProvisionEnrollee");\r
314 \r
315     OCStackResult ret = InvokeOCDoResource(query, OC_REST_PUT, OC_HIGH_QOS,\r
316             ProvisionEnrolleeResponse, payload, NULL, 0);\r
317 \r
318     return ret;\r
319 }\r
320 \r
321 \r
322 OCStackApplicationResult GetProvisioningStatusResponse(void* ctx,\r
323         OCDoHandle handle, OCClientResponse * clientResponse) {\r
324     ProvisioningInfo *provInfo;\r
325 \r
326     if (clientResponse == NULL) {\r
327         OIC_LOG(INFO, TAG,\r
328                 "getReqCB received NULL clientResponse. \\r
329         Invoking Provisioing Status Callback");\r
330         provInfo = PrepareProvisioingStatusCB(clientResponse,\r
331                 DEVICE_NOT_PROVISIONED);\r
332         cbData(provInfo);\r
333         return OC_STACK_DELETE_TRANSACTION;\r
334     }\r
335 \r
336     if (clientResponse->rcvdVendorSpecificHeaderOptions\r
337             && clientResponse->numRcvdVendorSpecificHeaderOptions) {\r
338         OIC_LOG(INFO, TAG, "Received vendor specific options");\r
339         uint8_t i = 0;\r
340         OCHeaderOption * rcvdOptions =\r
341                 clientResponse->rcvdVendorSpecificHeaderOptions;\r
342         for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions;\r
343                 i++) {\r
344             if (((OCHeaderOption) rcvdOptions[i]).protocolID == OC_COAP_ID) {\r
345                 OIC_LOG_V(INFO, TAG,\r
346                         "Received option with OC_COAP_ID and ID %u with",\r
347                         ((OCHeaderOption) rcvdOptions[i]).optionID);\r
348 \r
349                 OIC_LOG_BUFFER(INFO, TAG,\r
350                         ((OCHeaderOption) rcvdOptions[i]).optionData,\r
351                         MAX_HEADER_OPTION_DATA_LENGTH);\r
352             }\r
353         }\r
354     }\r
355 \r
356     char query[OIC_STRING_MAX_VALUE] = { '\0' };\r
357 \r
358 \r
359     if (clientResponse->payload) {\r
360 \r
361         if(clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
362 \r
363         {\r
364             OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
365             return OC_STACK_DELETE_TRANSACTION;\r
366         }\r
367 \r
368         OCRepPayload* input = (OCRepPayload*)(clientResponse->payload);\r
369         if(!input)\r
370         {\r
371             OIC_LOG_V(DEBUG, TAG, "Failed To parse");\r
372             return OC_STACK_DELETE_TRANSACTION;\r
373         }\r
374         OIC_LOG_V(DEBUG, TAG, "resUri = %s",input->uri);\r
375 \r
376         char resURI[MAX_URI_LENGTH]={'\0'};\r
377 \r
378         strncpy(resURI, input->uri, sizeof(resURI));\r
379 \r
380         snprintf(query, sizeof(query), UNICAST_PROV_STATUS_QUERY,\r
381                 clientResponse->addr->addr,\r
382                 IP_PORT, resURI);\r
383 \r
384         //OCPayloadLogRep(DEBUG,TAG,input);\r
385 \r
386         if (ProvisionEnrollee(OC_HIGH_QOS, query, resURI) != OC_STACK_OK) {\r
387             OIC_LOG(INFO, TAG,\r
388                     "GetProvisioningStatusResponse received NULL clientResponse. \\r
389             Invoking Provisioing Status Callback");\r
390             provInfo = PrepareProvisioingStatusCB(clientResponse,\r
391                     DEVICE_NOT_PROVISIONED);\r
392             cbData(provInfo);\r
393 \r
394             return OC_STACK_DELETE_TRANSACTION;\r
395         }\r
396     } else {\r
397         OIC_LOG(INFO, TAG,\r
398                 "GetProvisioningStatusResponse received NULL clientResponse. \\r
399         Invoking Provisioing Status Callback");\r
400         provInfo = PrepareProvisioingStatusCB(clientResponse,\r
401                 DEVICE_NOT_PROVISIONED);\r
402         cbData(provInfo);\r
403         return OC_STACK_DELETE_TRANSACTION;\r
404     }\r
405     return OC_STACK_DELETE_TRANSACTION;\r
406 }\r
407 \r
408 OCStackResult InvokeOCDoResource(const char* query, OCMethod method,\r
409         OCQualityOfService qos, OCClientResponseHandler cb,OCRepPayload* request,\r
410         OCHeaderOption * options, uint8_t numOptions) {\r
411     OCStackResult ret;\r
412     OCCallbackData cbData;\r
413 \r
414     cbData.cb = cb;\r
415     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;\r
416     cbData.cd = NULL;\r
417 \r
418     ret = OCDoResource(NULL, method, query, 0, &request->base, OC_CONNTYPE, qos,\r
419             &cbData, options, numOptions);\r
420 \r
421     if (ret != OC_STACK_OK) {\r
422         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d",\r
423                 ret, method);\r
424     }\r
425 \r
426     return ret;\r
427 }\r
428 \r
429 OCStackResult GetProvisioningStatus(OCQualityOfService qos, const char* query) {\r
430     OCStackResult ret = OC_STACK_ERROR;\r
431     OCHeaderOption options[MAX_HEADER_OPTIONS];\r
432 \r
433     OIC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);\r
434 \r
435     uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };\r
436     uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };\r
437     memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);\r
438     options[0].protocolID = OC_COAP_ID;\r
439     options[0].optionID = 2048;\r
440     memcpy(options[0].optionData, option0, sizeof(option0));\r
441     options[0].optionLength = 10;\r
442     options[1].protocolID = OC_COAP_ID;\r
443     options[1].optionID = 3000;\r
444     memcpy(options[1].optionData, option1, sizeof(option1));\r
445     options[1].optionLength = 10;\r
446 \r
447     ret = InvokeOCDoResource(query, OC_REST_GET, OC_HIGH_QOS,\r
448             GetProvisioningStatusResponse, NULL, options, 2);\r
449     return ret;\r
450 }\r
451 \r
452 OCStackResult StartProvisioningProcess(const EnrolleeNWProvInfo_t *netInfo,\r
453         OCProvisioningStatusCB provisioningStatusCallback) {\r
454     OCStackResult result = OC_STACK_ERROR;\r
455 \r
456     if (netInfo->netAddressInfo.WIFI.ipAddress == NULL) {\r
457         OIC_LOG(ERROR, TAG, "Request URI is NULL");\r
458         return result;\r
459     }\r
460 \r
461     if (provisioningStatusCallback == NULL) {\r
462         OIC_LOG(ERROR, TAG, "ProvisioningStatusCallback is NULL");\r
463         return result;\r
464     }\r
465 \r
466     cbData = provisioningStatusCallback;\r
467 \r
468     //Copy Network Provisioning  Information\r
469     netProvInfo = (EnrolleeNWProvInfo_t *)OICCalloc(1, sizeof(EnrolleeNWProvInfo_t));\r
470 \r
471     if (NULL == netProvInfo)\r
472     {\r
473         OIC_LOG(ERROR, TAG, "Invalid input..");\r
474         return OC_STACK_ERROR;\r
475     }\r
476     memcpy(netProvInfo, netInfo, sizeof(EnrolleeNWProvInfo_t));\r
477 \r
478     OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. SSID = %s",\r
479             netProvInfo->netAddressInfo.WIFI.ssid);\r
480 \r
481     OIC_LOG_V(DEBUG, TAG, "Network Provisioning Info. PWD = %s",\r
482             netProvInfo->netAddressInfo.WIFI.pwd);\r
483 \r
484 \r
485     if (CA_STATUS_OK\r
486             != ca_thread_pool_add_task(g_threadPoolHandle, FindProvisioningResource,\r
487                     (void *) "")) {\r
488         OIC_LOG(DEBUG, TAG, "thread_pool_add_task of FindProvisioningResource failed");\r
489         ca_thread_pool_free(g_threadPoolHandle);\r
490         ca_mutex_unlock(g_provisioningMutex);\r
491         ca_mutex_free(g_provisioningMutex);\r
492         ca_cond_free(g_provisioningCond);\r
493         return OC_STACK_ERROR;\r
494     }\r
495     return OC_STACK_OK;\r
496 }\r
497 \r
498 void StopProvisioningProcess() {\r
499     cbData = NULL;\r
500 }\r
501 \r
502 \r
503 // This is a function called back when a device is discovered\r
504 OCStackApplicationResult FindProvisioningResourceResponse(void* ctx,\r
505         OCDoHandle handle, OCClientResponse * clientResponse) {\r
506     OIC_LOG(INFO, TAG, PCF("Entering FindProvisioningResourceResponse"));\r
507 \r
508     OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;\r
509 \r
510     ProvisioningInfo *provInfo;\r
511 \r
512     if (clientResponse->result != OC_STACK_OK) {\r
513         OIC_LOG(ERROR, TAG,\r
514                 "OCStack stop error. Calling Provisioing Status Callback");\r
515 \r
516         provInfo = PrepareProvisioingStatusCB(clientResponse,\r
517                 DEVICE_NOT_PROVISIONED);\r
518 \r
519         cbData(provInfo);\r
520         return response;\r
521     }\r
522 \r
523     if (clientResponse) {\r
524 \r
525 \r
526         if(clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
527         {\r
528             OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
529             return OC_STACK_DELETE_TRANSACTION;\r
530         }\r
531 \r
532         OCRepPayload* discoveryPayload= (OCRepPayload*)(clientResponse->payload);\r
533         if(!discoveryPayload)\r
534         {\r
535             OIC_LOG_V(DEBUG, TAG, "Failed To parse");\r
536             provInfo = PrepareProvisioingStatusCB(clientResponse,\r
537                     DEVICE_NOT_PROVISIONED);\r
538             cbData(provInfo);\r
539             return response;\r
540         }\r
541         OIC_LOG_V(DEBUG, TAG, "resUri = %s",discoveryPayload->uri);\r
542         char szQueryUri[64] = { 0 };\r
543 \r
544         snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROV_STATUS_QUERY,\r
545                 clientResponse->devAddr.addr, IP_PORT, discoveryPayload->uri);\r
546         OIC_LOG_V(DEBUG, TAG, "query before GetProvisioningStatus call = %s", szQueryUri);\r
547 \r
548         if (GetProvisioningStatus(OC_HIGH_QOS, szQueryUri) != OC_STACK_OK) {\r
549             OIC_LOG(INFO, TAG,\r
550                     "GetProvisioningStatus returned error. \\r
551             Invoking Provisioing Status Callback");\r
552             provInfo = PrepareProvisioingStatusCB(clientResponse,\r
553                     DEVICE_NOT_PROVISIONED);\r
554 \r
555             cbData(provInfo);\r
556             return OC_STACK_DELETE_TRANSACTION;\r
557         }\r
558     } else {\r
559         // clientResponse is invalid\r
560         OIC_LOG(ERROR, TAG,\r
561                 "Invalid response for Provisioning Discovery request. \\r
562         Invoking Provisioing Status Callback");\r
563         provInfo = PrepareProvisioingStatusCB(clientResponse,\r
564                 DEVICE_NOT_PROVISIONED);\r
565         cbData(provInfo);\r
566         return response;\r
567     }\r
568     return OC_STACK_KEEP_TRANSACTION;\r
569 }\r
570 \r
571 \r
572 void FindProvisioningResource(void *data)\r
573 {\r
574     OCStackResult ret = OC_STACK_ERROR;\r
575 \r
576     /* Start a discovery query*/\r
577     char szQueryUri[64] = { 0 };\r
578 \r
579     snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,\r
580             netProvInfo->netAddressInfo.WIFI.ipAddress, IP_PORT);\r
581 \r
582     OIC_LOG_V(DEBUG, TAG, "szQueryUri = %s", szQueryUri);\r
583 \r
584     OCCallbackData ocCBData;\r
585 \r
586     ocCBData.cb = FindProvisioningResourceResponse;\r
587     ocCBData.context = (void*) DEFAULT_CONTEXT_VALUE;\r
588     ocCBData.cd = NULL;\r
589 \r
590     ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,\r
591             OC_LOW_QOS, &ocCBData, NULL, 0);\r
592 \r
593     if (ret != OC_STACK_OK) {\r
594         OIC_LOG(ERROR, TAG, "OCStack resource error");\r
595 \r
596         OIC_LOG(ERROR, TAG,\r
597                 "FindProvisioningResource failed. \\r
598         Invoking Provisioing Status Callback");\r
599 \r
600         ProvisioningInfo *provInfo;\r
601         provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));\r
602 \r
603         if(provInfo == NULL)\r
604         {\r
605             OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
606             return;\r
607         }\r
608 \r
609         OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));\r
610 \r
611         if(devAddr == NULL)\r
612         {\r
613             OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
614             return;\r
615         }\r
616 \r
617         strncpy(devAddr->addr, netProvInfo->netAddressInfo.WIFI.ipAddress, sizeof(devAddr->addr));\r
618         devAddr->port= IP_PORT;\r
619         provInfo->provDeviceInfo.addr = devAddr;\r
620         provInfo->provStatus = DEVICE_NOT_PROVISIONED;\r
621 \r
622 \r
623         cbData(provInfo);\r
624     }\r
625 }\r
626 \r
627 OCStackApplicationResult SubscribeProvPresenceCallback(void* ctx, OCDoHandle handle,\r
628         OCClientResponse* clientResponse) {\r
629     OIC_LOG(INFO, TAG, PCF("Entering SubscribeProvPresenceCallback"));\r
630 \r
631     OCStackApplicationResult response = OC_STACK_DELETE_TRANSACTION;\r
632 \r
633     if (clientResponse->result != OC_STACK_OK) {\r
634         OIC_LOG(ERROR, TAG, "OCStack stop error");\r
635         return response;\r
636     }\r
637 \r
638     if (clientResponse) {\r
639         OIC_LOG(INFO, TAG, PCF("Client Response exists"));\r
640 \r
641         if(clientResponse->payload && clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)\r
642         {\r
643             OIC_LOG_V(DEBUG, TAG, "Incoming payload not a representation");\r
644             return response;\r
645         }\r
646 \r
647         OCRepPayload* discoveryPayload= (OCRepPayload*)(clientResponse->payload);\r
648         if(!discoveryPayload)\r
649         {\r
650             OIC_LOG_V(DEBUG, TAG, "invalid payload");\r
651             return response;\r
652         }\r
653 \r
654         char sourceIPAddr[OIC_STRING_MAX_VALUE] = { '\0' };\r
655         snprintf(sourceIPAddr, sizeof(sourceIPAddr), "%s", clientResponse->addr->addr);\r
656 \r
657         OIC_LOG_V(DEBUG, TAG, "Discovered %s @ %s",\r
658                 discoveryPayload->uri, sourceIPAddr);\r
659 \r
660         /* Start a discovery query*/\r
661         char szQueryUri[64] = { 0 };\r
662 \r
663         snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PROVISIONING_QUERY,\r
664                 sourceIPAddr, IP_PORT);\r
665 \r
666         /*if (FindProvisioningResource(qos, szQueryUri) != OC_STACK_OK) {\r
667             OIC_LOG(ERROR, TAG, "FindProvisioningResource failed");\r
668             return OC_STACK_KEEP_TRANSACTION;\r
669         }*/\r
670     } else {\r
671         // clientResponse is invalid\r
672         OIC_LOG(ERROR, TAG, PCF("Client Response is NULL!"));\r
673     }\r
674     return OC_STACK_KEEP_TRANSACTION;\r
675 }\r
676 \r
677 \r
678 OCStackResult SubscribeProvPresence(OCQualityOfService qos,\r
679         const char* requestURI) {\r
680     OCStackResult ret = OC_STACK_ERROR;\r
681 \r
682     OCCallbackData cbData;\r
683 \r
684     cbData.cb = &SubscribeProvPresenceCallback;\r
685     cbData.context = (void*) DEFAULT_CONTEXT_VALUE;\r
686     cbData.cd = NULL;\r
687 \r
688     ret = OCDoResource(NULL, OC_REST_PRESENCE, requestURI, 0, 0, OC_CONNTYPE,\r
689             OC_LOW_QOS, &cbData, NULL, 0);\r
690 \r
691     if (ret != OC_STACK_OK) {\r
692         OIC_LOG(ERROR, TAG, "OCStack resource error");\r
693     }\r
694 \r
695     return ret;\r
696 }\r
697 \r
698 OCStackResult FindNetworkResource() {\r
699     OCStackResult ret = OC_STACK_ERROR;\r
700     if (OCStop() != OC_STACK_OK) {\r
701         OIC_LOG(ERROR, TAG, "OCStack stop error");\r
702     }\r
703 \r
704     return ret;\r
705 }\r
706 \r
707 ProvisioningInfo* PrepareProvisioingStatusCB(OCClientResponse * clientResponse, ProvStatus provStatus) {\r
708 \r
709     ProvisioningInfo *provInfo = (ProvisioningInfo *) OICCalloc(1, sizeof(ProvisioningInfo));\r
710 \r
711     if(provInfo == NULL)\r
712     {\r
713         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
714         return NULL;\r
715     }\r
716 \r
717     OCDevAddr *devAddr = (OCDevAddr *) OICCalloc(1, sizeof(OCDevAddr));\r
718 \r
719     if(devAddr == NULL)\r
720     {\r
721         OIC_LOG_V(ERROR, TAG, "Failed to allocate memory");\r
722         return NULL;\r
723     }\r
724 \r
725     strncpy(devAddr->addr, clientResponse->addr->addr, sizeof(devAddr->addr));\r
726     devAddr->port= clientResponse->addr->port;\r
727 \r
728     provInfo->provDeviceInfo.addr = devAddr;\r
729 \r
730     provInfo->provStatus = provStatus;\r
731 \r
732     return provInfo;\r
733 }\r
734 \r
735 \r
736 \r
737 \r