4045c0ef11e768eb81a25e1d36dac7874e0a2ea8
[iotivity.git] / resource / csdk / security / provisioning / src / pmutility.c
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 #ifndef _POSIX_C_SOURCE
21 #define _POSIX_C_SOURCE 200112L
22 #endif
23
24 #include "iotivity_config.h"
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #endif
31
32 #include "ocstack.h"
33 #include "oic_malloc.h"
34 #include "oic_string.h"
35 #include "oic_time.h"
36 #include "logger.h"
37 #include "utlist.h"
38 #include "ocpayload.h"
39
40 #include "securevirtualresourcetypes.h"
41 #include "srmresourcestrings.h" //@note: SRM's internal header
42 #include "doxmresource.h"       //@note: SRM's internal header
43 #include "pstatresource.h"      //@note: SRM's internal header
44
45 #include "pmtypes.h"
46 #include "pmutility.h"
47 #include "pmutilityinternal.h"
48
49 #include "srmutility.h"
50
51 #define TAG ("OIC_PM_UTILITY")
52
53 typedef struct _DiscoveryInfo{
54     OCProvisionDev_t    **ppDevicesList;
55     OCProvisionDev_t    *pCandidateList;
56     bool                isOwnedDiscovery;
57     bool                isSingleDiscovery;
58     bool                isFound;
59     const OicUuid_t     *targetId;
60 } DiscoveryInfo;
61
62 /*
63  * Function to discover secre port information through unicast
64  *
65  * @param[in] discoveryInfo The pointer of discovery information to matain result of discovery
66  * @param[in] clientResponse  Response information(It will contain payload)
67  *
68  * @return OC_STACK_OK on success otherwise error.
69  */
70 static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
71                                          const OCClientResponse *clientResponse);
72
73 /**
74  * Callback handler for PMDeviceDiscovery API.
75  *
76  * @param[in] ctx             User context
77  * @param[in] handle          Handler for response
78  * @param[in] clientResponse  Response information (It will contain payload)
79  * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
80  *         OC_STACK_DELETE_TRANSACTION to delete it.
81  */
82 static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
83                                 OCClientResponse *clientResponse);
84
85 /*
86  * Since security version discovery does not used anymore, disable security version discovery.
87  * Need to discussion to removing all version discovery related codes.
88  */
89
90 /*
91  * Function to discover security version information through unicast
92  *
93  * @param[in] discoveryInfo The pointer of discovery information to matain result of discovery
94  * @param[in] clientResponse  Response information(It will contain payload)
95  *
96  * @return OC_STACK_OK on success otherwise error.
97  */
98 static OCStackResult SpecVersionDiscovery(DiscoveryInfo* discoveryInfo,
99                                               const OCClientResponse *clientResponse);
100 #if 0
101 /**
102  * Callback handler for getting secure port information using /oic/res discovery.
103  *
104  * @param[in] ctx             user context
105  * @param[in] handle          Handle for response
106  * @param[in] clientResponse  Response information(It will contain payload)
107  *
108  * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
109  *         OC_STACK_DELETE_TRANSACTION to delete it.
110  */
111 static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
112                                  OCClientResponse *clientResponse);
113 #endif
114
115 /*
116  * Since security version discovery does not used anymore, disable security version discovery.
117  * Need to discussion to removing all version discovery related codes.
118  */
119 #if 0
120 /**
121  * Callback handler for security version discovery.
122  *
123  * @param[in] ctx             User context
124  * @param[in] handle          Handler for response
125  * @param[in] clientResponse  Response information (It will contain payload)
126  * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
127  *         OC_STACK_DELETE_TRANSACTION to delete it.
128  */
129 static OCStackApplicationResult SecVersionDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
130                                 OCClientResponse *clientResponse);
131 #endif
132
133 #ifdef MULTIPLE_OWNER
134 OicSecMom_t* CloneOicSecMom(const OicSecMom_t* src)
135 {
136     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
137
138     if (!src)
139     {
140         OIC_LOG_V(ERROR, TAG, "%s : Invalid parameter", __func__);
141         return NULL;
142     }
143
144     OicSecMom_t* newMom = (OicSecMom_t*)OICMalloc(sizeof(*newMom));
145     if (newMom)
146     {
147         *newMom = *src;
148     }
149     else
150     {
151         OIC_LOG_V(ERROR, TAG, "%s : Failed to allocate memory", __func__);
152     }
153
154     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
155
156     return newMom;
157 }
158
159 OicSecSubOwner_t* CloneOicSecSubOwner(const OicSecSubOwner_t* src)
160 {
161     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
162
163     if (!src)
164     {
165         OIC_LOG_V(ERROR, TAG, "%s : Invalid parameter", __func__);
166         return NULL;
167     }
168
169     OicSecSubOwner_t* newSubOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(*newSubOwner));
170     VERIFY_NOT_NULL(TAG, newSubOwner, ERROR);
171
172     memcpy(newSubOwner, src, sizeof(OicSecSubOwner_t));
173
174     if (src->next)
175     {
176         newSubOwner->next = CloneOicSecSubOwner(src->next);
177         VERIFY_NOT_NULL(TAG, newSubOwner->next, ERROR);
178     }
179
180     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
181
182     return newSubOwner;
183
184 exit:
185     OIC_LOG_V(ERROR, TAG, "%s : Failed to allocate memory", __func__);
186     if (newSubOwner)
187     {
188         OICFree(newSubOwner);
189     }
190     return NULL;
191 }
192 #endif //MULTIPLE_OWNER
193
194 OicSecDoxm_t* CloneOicSecDoxm(const OicSecDoxm_t* src)
195 {
196     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
197
198     if (!src)
199     {
200         OIC_LOG_V(ERROR, TAG, "%s : Invalid parameter", __func__);
201         return NULL;
202     }
203
204     OicSecDoxm_t* newDoxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
205     VERIFY_NOT_NULL(TAG, newDoxm, ERROR);
206
207     memcpy(newDoxm, src, sizeof(OicSecDoxm_t));
208
209 #ifdef MULTIPLE_OWNER
210     newDoxm->subOwners = NULL;
211     newDoxm->mom = NULL;
212
213     if (src->subOwners)
214     {
215         newDoxm->subOwners = CloneOicSecSubOwner(src->subOwners);
216         VERIFY_NOT_NULL(TAG, newDoxm->subOwners, ERROR);
217     }
218
219     if (src->mom)
220     {
221         newDoxm->mom = CloneOicSecMom(src->mom);
222         VERIFY_NOT_NULL(TAG, newDoxm->mom, ERROR);
223     }
224 #endif //MULTIPLE_OWNER
225
226     // We have to assign NULL for not necessary information to prevent memory corruption.
227     newDoxm->oxm = NULL;
228     newDoxm->oxmLen = 0;
229
230     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
231
232     return newDoxm;
233
234 exit:
235     OIC_LOG_V(ERROR, TAG, "%s : Failed to allocate memory", __func__);
236     DeleteDoxmBinData(newDoxm);
237
238     return NULL;
239 }
240
241 /**
242  * Function to search node in linked list that matches given IP and port.
243  *
244  * @param[in] pList         List of OCProvisionDev_t.
245  * @param[in] addr          address of target device.
246  * @param[in] port          port of remote server.
247  *
248  * @return pointer of OCProvisionDev_t if exist, otherwise NULL
249  */
250 OCProvisionDev_t* GetDevice(OCProvisionDev_t **ppDevicesList, const char* addr, const uint16_t port)
251 {
252     if(NULL == addr || NULL == *ppDevicesList)
253     {
254         OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
255         return NULL;
256     }
257
258     OCProvisionDev_t *ptr = NULL;
259     LL_FOREACH(*ppDevicesList, ptr)
260     {
261         if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)
262         {
263             return ptr;
264         }
265     }
266
267     return NULL;
268 }
269
270
271 /**
272  * Add device information to list.
273  *
274  * @param[in] pList         List of OCProvisionDev_t.
275  * @param[in] endpoint      target device endpoint.
276  * @param[in] connType      connectivity type of endpoint
277  * @param[in] doxm          pointer to doxm instance.
278  *
279  * @return OC_STACK_OK for success and error code otherwise.
280  */
281 OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, OCDevAddr* endpoint,
282                         OCConnectivityType connType, OicSecDoxm_t *doxm)
283 {
284     if (NULL == endpoint)
285     {
286         return OC_STACK_INVALID_PARAM;
287     }
288
289     OCProvisionDev_t *ptr = GetDevice(ppDevicesList, endpoint->addr, endpoint->port);
290     if(!ptr)
291     {
292         ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
293         if (NULL == ptr)
294         {
295             OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
296             return OC_STACK_NO_MEMORY;
297         }
298
299         ptr->endpoint = *endpoint;
300         ptr->doxm = doxm;
301         ptr->securePort = (CT_ADAPTER_GATT_BTLE == connType) ?
302                           endpoint->port : DEFAULT_SECURE_PORT;
303         ptr->next = NULL;
304         ptr->connType = connType;
305         ptr->devStatus = DEV_STATUS_ON; //AddDevice is called when discovery(=alive)
306         OICStrcpy(ptr->specVer, SPEC_MAX_VER_LEN, DEFAULT_SPEC_VERSION); // version initialization
307         ptr->handle = NULL;
308
309         LL_PREPEND(*ppDevicesList, ptr);
310     }
311
312     return OC_STACK_OK;
313 }
314
315 /**
316  * Move device object between two device lists.
317  *
318  * @param[in] ppDstDevicesList         Destination list of OCProvisionDev_t.
319  * @param[in] ppSrcDevicesList         Source list of OCProvisionDev_t.
320  * @param[in] endpoint      target device endpoint.
321  *
322  * @return OC_STACK_OK for success and error code otherwise.
323  */
324 OCStackResult MoveDeviceList(OCProvisionDev_t **ppDstDevicesList,
325                         OCProvisionDev_t **ppSrcDevicesList, OCDevAddr* endpoint)
326 {
327     if (NULL == ppSrcDevicesList || NULL == endpoint)
328     {
329         return OC_STACK_INVALID_PARAM;
330     }
331
332     OCProvisionDev_t *ptr = GetDevice(ppSrcDevicesList, endpoint->addr, endpoint->port);
333     if(ptr)
334     {
335         LL_DELETE(*ppSrcDevicesList, ptr);
336         LL_PREPEND(*ppDstDevicesList, ptr);
337         OIC_LOG_V(DEBUG, TAG, "MoveDeviceList success : %s(%d)", endpoint->addr, endpoint->port);
338         return OC_STACK_OK;
339     }
340
341     return OC_STACK_ERROR;
342 }
343
344 /**
345  * Function to set secure port information from the given list of devices.
346  *
347  * @param[in] pList         List of OCProvisionDev_t.
348  * @param[in] addr          address of target device.
349  * @param[in] port          port of remote server.
350  * @param[in] secureport    secure port information.
351  *
352  * @return OC_STACK_OK for success and errorcode otherwise.
353  */
354 static OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr,
355                                        uint16_t port, uint16_t securePort
356 #ifdef __WITH_TLS__
357                                        ,uint16_t tcpPort
358                                        ,uint16_t tcpSecurePort
359 #endif
360                                        )
361 {
362     OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
363
364     if(!ptr)
365     {
366         OIC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");
367         return OC_STACK_ERROR;
368     }
369
370     ptr->securePort = (OC_ADAPTER_GATT_BTLE == ptr->endpoint.adapter) ?
371                       ptr->endpoint.port : securePort;
372
373 #ifdef __WITH_TLS__
374     ptr->tcpPort = tcpPort;
375     ptr->tcpSecurePort = tcpSecurePort;
376 #endif
377
378     return OC_STACK_OK;
379 }
380
381 /**
382  * Function to set security version information from the given list of devices.
383  *
384  * @param[in] pList         List of OCProvisionDev_t.
385  * @param[in] addr          address of target device.
386  * @param[in] port          port of remote server.
387  * @param[in] specVer    security version information.
388  *
389  * @return OC_STACK_OK for success and errorcode otherwise.
390  */
391 static OCStackResult UpdateSpecVersionOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr,
392                                        uint16_t port, const char* specVer)
393 {
394     if (NULL == specVer)
395     {
396         return OC_STACK_INVALID_PARAM;
397     }
398
399     OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
400
401     if(!ptr)
402     {
403         OIC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");
404         return OC_STACK_ERROR;
405     }
406
407     OICStrcpy(ptr->specVer, SPEC_MAX_VER_LEN, specVer);
408
409     return OC_STACK_OK;
410 }
411
412 /**
413  * This function deletes list of provision target devices
414  *
415  * @param[in] pDevicesList         List of OCProvisionDev_t.
416  */
417 void PMDeleteDeviceList(OCProvisionDev_t *pDevicesList)
418 {
419     if(pDevicesList)
420     {
421         OCProvisionDev_t *del = NULL, *tmp = NULL;
422         LL_FOREACH_SAFE(pDevicesList, del, tmp)
423         {
424             LL_DELETE(pDevicesList, del);
425
426             DeleteDoxmBinData(del->doxm);
427             DeletePstatBinData(del->pstat);
428             OICFree(del);
429         }
430     }
431 }
432
433 OCProvisionDev_t* PMCloneOCProvisionDev(const OCProvisionDev_t* src)
434 {
435     OIC_LOG(DEBUG, TAG, "IN PMCloneOCProvisionDev");
436
437     if (!src)
438     {
439         OIC_LOG(ERROR, TAG, "PMCloneOCProvisionDev : Invalid parameter");
440         return NULL;
441     }
442
443     // TODO: Consider use VERIFY_NON_NULL instead of if ( null check ) { goto exit; }
444     OCProvisionDev_t* newDev = (OCProvisionDev_t*)OICCalloc(1, sizeof(OCProvisionDev_t));
445     VERIFY_NOT_NULL(TAG, newDev, ERROR);
446
447     memcpy(&newDev->endpoint, &src->endpoint, sizeof(OCDevAddr));
448
449     if (src->pstat)
450     {
451         newDev->pstat= (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t));
452         VERIFY_NOT_NULL(TAG, newDev->pstat, ERROR);
453
454         memcpy(newDev->pstat, src->pstat, sizeof(OicSecPstat_t));
455         // We have to assign NULL for not necessary information to prevent memory corruption.
456         newDev->pstat->sm = NULL;
457     }
458
459     if (src->doxm)
460     {
461         newDev->doxm = CloneOicSecDoxm(src->doxm);
462         VERIFY_NOT_NULL(TAG, newDev->doxm, ERROR);
463     }
464
465     if (0 == strlen(src->specVer))
466     {
467         OICStrcpy(newDev->specVer, SPEC_MAX_VER_LEN, DEFAULT_SPEC_VERSION);
468     }
469     else
470     {
471         OICStrcpy(newDev->specVer, SPEC_MAX_VER_LEN, src->specVer);
472     }
473
474     newDev->securePort = src->securePort;
475     newDev->devStatus = src->devStatus;
476     newDev->connType = src->connType;
477     newDev->next = NULL;
478
479     OIC_LOG(DEBUG, TAG, "OUT PMCloneOCProvisionDev");
480
481     return newDev;
482
483 exit:
484     OIC_LOG(ERROR, TAG, "PMCloneOCProvisionDev : Failed to allocate memory");
485     PMDeleteDeviceList(newDev);
486     return NULL;
487 }
488
489 OCProvisionDev_t* PMCloneOCProvisionDevList(const OCProvisionDev_t* src)
490 {
491     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
492
493     if (!src)
494     {
495         OIC_LOG_V(ERROR, TAG, "%s : Invalid parameter", __func__);
496         return NULL;
497     }
498
499     OCProvisionDev_t* newDev = PMCloneOCProvisionDev(src);
500     VERIFY_NOT_NULL(TAG, newDev, ERROR);
501
502     OCProvisionDev_t* current = newDev;
503     for (OCProvisionDev_t* next = src->next; NULL != next; next = next->next)
504     {
505         current->next = PMCloneOCProvisionDev(next);
506         VERIFY_NOT_NULL(TAG, current->next, ERROR);
507
508         current = current->next;
509     }
510
511     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
512
513     return newDev;
514
515 exit:
516     OIC_LOG_V(ERROR, TAG, "%s : Failed to allocate memory", __func__);
517     PMDeleteDeviceList(newDev);
518     return NULL;
519 }
520
521 /**
522  * Timeout implementation for secure discovery. When performing secure discovery,
523  * we should wait a certain period of time for getting response of each devices.
524  *
525  * @param[in]  waittime  Timeout in seconds.
526  * @param[in]  waitForStackResponse if true timeout function will call OCProcess while waiting.
527  * @return OC_STACK_OK on success otherwise error.
528  */
529 OCStackResult PMTimeout(unsigned short waittime, bool waitForStackResponse)
530 {
531     OCStackResult res = OC_STACK_OK;
532
533     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
534     while (OC_STACK_OK == res)
535     {
536         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
537
538         long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
539         if (elapsed > waittime)
540         {
541             return OC_STACK_OK;
542         }
543         if (waitForStackResponse)
544         {
545             res = OCProcess();
546         }
547     }
548     return res;
549 }
550
551 bool OC_CALL PMGenerateQuery(bool isSecure,
552                              const char* address, uint16_t port,
553                              OCConnectivityType connType,
554                              char* buffer, size_t bufferSize, const char* uri)
555 {
556     if(!address || !buffer || !uri)
557     {
558         OIC_LOG(ERROR, TAG, "PMGenerateQuery : Invalid parameters.");
559         return false;
560     }
561
562     int snRet = 0;
563     char* prefix = (isSecure == true) ? COAPS_PREFIX : COAP_PREFIX;
564
565     switch(connType & CT_MASK_ADAPTER)
566     {
567         case CT_ADAPTER_TCP:
568             prefix = (isSecure == true) ? COAPS_TCP_PREFIX : COAP_TCP_PREFIX;
569         case CT_ADAPTER_IP:
570             switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)
571             {
572                 case CT_IP_USE_V4:
573                     snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",
574                                      prefix, address, port, uri);
575                     break;
576                 case CT_IP_USE_V6:
577                 {
578                     char addressEncoded[128] = {0};
579
580                     OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
581                                                                      sizeof(addressEncoded),
582                                                                      address);
583                     if (OC_STACK_OK != result)
584                     {
585                         OIC_LOG_V(ERROR, TAG, "PMGenerateQuery : encoding error %d\n", result);
586                         return false;
587                     }
588
589                     snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",
590                                      prefix, addressEncoded, port, uri);
591                     break;
592                 }
593                 default:
594                     OIC_LOG(ERROR, TAG, "Unknown address format.");
595                     return false;
596             }
597             break;
598         case CT_ADAPTER_GATT_BTLE:
599             snRet = snprintf(buffer, bufferSize, "%s%s%s",
600                              prefix, address, uri);
601             break;
602         case CT_ADAPTER_RFCOMM_BTEDR:
603             OIC_LOG(ERROR, TAG, "Not supported connectivity adapter.");
604             return false;
605         default:
606             OIC_LOG(ERROR, TAG, "Unknown connectivity adapter.");
607             return false;
608     }
609
610     // snprintf return value check
611     if (snRet < 0)
612     {
613         OIC_LOG_V(ERROR, TAG, "PMGenerateQuery : Error (snprintf) %d\n", snRet);
614         return false;
615     }
616     else if ((size_t)snRet >= bufferSize)
617     {
618         OIC_LOG_V(ERROR, TAG, "PMGenerateQuery : Truncated (snprintf) %d\n", snRet);
619         return false;
620     }
621
622     return true;
623 }
624
625 /*
626  * Since security version discovery does not used anymore, disable security version discovery.
627  * Need to discussion to removing all version discovery related codes.
628  */
629 static OCStackApplicationResult SpecVersionDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
630                                 OCClientResponse *clientResponse)
631 {
632     if (ctx == NULL)
633     {
634         OIC_LOG(ERROR, TAG, "Lost List of device information");
635         return OC_STACK_KEEP_TRANSACTION;
636     }
637     (void)UNUSED;
638     if (clientResponse)
639     {
640         if  (NULL == clientResponse->payload)
641         {
642             OIC_LOG(INFO, TAG, "Skiping Null payload");
643             return OC_STACK_KEEP_TRANSACTION;
644         }
645         if (OC_STACK_OK != clientResponse->result)
646         {
647             OIC_LOG(INFO, TAG, "Error in response");
648             return OC_STACK_KEEP_TRANSACTION;
649         }
650         else
651         {
652             if (PAYLOAD_TYPE_REPRESENTATION != clientResponse->payload->type)
653             {
654                 OIC_LOG(INFO, TAG, "Unknown payload type");
655                 return OC_STACK_KEEP_TRANSACTION;
656             }
657             OCRepPayloadValue* val = ((OCRepPayload*) clientResponse->payload)->values;
658
659             char specVer[SPEC_MAX_VER_LEN + 1] = {0};
660             OICStrcpy(specVer, SPEC_MAX_VER_LEN, DEFAULT_SPEC_VERSION);
661             while (val)
662             {
663                 if (val->type == OCREP_PROP_STRING)
664                 {
665                     OIC_LOG_V(DEBUG, TAG, "\t\t%s:%s", val->name, val->str);
666                     if (0 == strcmp(val->name, OC_RSRVD_SPEC_VERSION))
667                     {
668                         OICStrcpy(specVer, SPEC_MAX_VER_LEN, val->str);
669                         break;
670                     }
671                 }
672                 val = val -> next;
673             }
674             //If this is owend device discovery we have to filter out the responses.
675             DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
676             OCStackResult res = UpdateSpecVersionOfDevice(pDInfo->ppDevicesList, clientResponse->devAddr.addr,
677                                                      clientResponse->devAddr.port, specVer);
678             if (OC_STACK_OK != res)
679             {
680                 OIC_LOG(ERROR, TAG, "Error while getting security version.");
681                 return OC_STACK_KEEP_TRANSACTION;
682             }
683
684             OIC_LOG(INFO, TAG, "= Discovered security version =");
685             OIC_LOG_V(DEBUG, TAG, "IP %s", clientResponse->devAddr.addr);
686             OIC_LOG_V(DEBUG, TAG, "PORT %d", clientResponse->devAddr.port);
687             OIC_LOG_V(DEBUG, TAG, "VERSION %s", specVer);
688         }
689     }
690     else
691     {
692         OIC_LOG(INFO, TAG, "Skiping Null response");
693         return OC_STACK_KEEP_TRANSACTION;
694     }
695
696     return  OC_STACK_DELETE_TRANSACTION;
697 }
698
699 static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
700                                  OCClientResponse *clientResponse)
701 {
702     if (ctx == NULL)
703     {
704         OIC_LOG(ERROR, TAG, "Lost List of device information");
705         return OC_STACK_DELETE_TRANSACTION;
706     }
707     (void)UNUSED;
708     if (clientResponse)
709     {
710         if  (NULL == clientResponse->payload)
711         {
712             OIC_LOG(INFO, TAG, "Skiping Null payload");
713         }
714         else
715         {
716             if (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)
717             {
718                 OIC_LOG(INFO, TAG, "Wrong payload type");
719                 return OC_STACK_DELETE_TRANSACTION;
720             }
721
722             uint16_t securePort = 0;
723 #ifdef __WITH_TLS__
724             uint16_t tcpPort = 0;
725             uint16_t tcpSecurePort = 0;
726 #endif
727             OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
728
729             // Use seure port of doxm for OTM and Provision.
730             while (resPayload)
731             {
732                 if (0 == strncmp(resPayload->uri, OIC_RSRC_DOXM_URI, strlen(OIC_RSRC_DOXM_URI)))
733                 {
734                     OIC_LOG_V(INFO,TAG,"resPaylod->uri:%s",resPayload->uri);
735                     OIC_LOG(INFO, TAG, "Found doxm resource.");
736                     break;
737                 }
738                 else
739                 {
740                     resPayload = resPayload->next;
741                 }
742             }
743             if (NULL == resPayload)
744             {
745                 OIC_LOG(ERROR, TAG, "Can not find doxm resource.");
746                 return OC_STACK_DELETE_TRANSACTION;
747             }
748             if (resPayload && resPayload->secure)
749             {
750                 securePort = resPayload->port;
751             }
752             else if (resPayload && resPayload->eps)
753             {
754                 OCEndpointPayload* eps = resPayload->eps;
755                 while (eps != NULL)
756                 {
757                     if ((eps->family & OC_FLAG_SECURE) &&
758                         ((OC_IP_USE_V6 == clientResponse->devAddr.flags &&
759                           strchr(eps->addr, ':')) ||
760                          (OC_IP_USE_V4 == clientResponse->devAddr.flags &&
761                           strchr(eps->addr, '.'))))
762                     {
763                             securePort = eps->port;
764                             break;
765                     }
766                     eps = eps->next;
767                 }
768 #ifdef __WITH_TLS__
769                 eps = resPayload->eps;
770                 while (eps != NULL)
771                 {
772                     if ((eps->family & OC_FLAG_SECURE) &&
773                         ((OC_IP_USE_V6 == clientResponse->devAddr.flags &&
774                           strchr(eps->addr, ':')) ||
775                          (OC_IP_USE_V4 == clientResponse->devAddr.flags &&
776                           strchr(eps->addr, '.'))) &&
777                         0 == strncmp(eps->tps, COAPS_TCP_PREFIX, strlen(COAPS_TCP_PREFIX)-3))
778                     {
779                             tcpSecurePort = eps->port;
780                             break;
781                     }
782                     eps = eps->next;
783                 }
784                 eps = resPayload->eps;
785                 while (eps != NULL)
786                 {
787                     if(((OC_IP_USE_V6 == clientResponse->devAddr.flags && strchr(eps->addr, ':')) ||
788                         (OC_IP_USE_V4 == clientResponse->devAddr.flags && strchr(eps->addr, '.'))) &&
789                         0 == strncmp(eps->tps, COAP_TCP_PREFIX, strlen(COAP_TCP_PREFIX)-3)
790                       )
791                     {
792                         tcpPort =  eps->port;
793                         break;
794                     }
795                     eps = eps->next;
796                 }
797 #endif
798                 if (!securePort)
799                 {
800                     OIC_LOG(INFO, TAG, "Can not find secure port information.");
801                     return OC_STACK_DELETE_TRANSACTION;
802                 }
803                 else
804                 {
805                     OIC_LOG_V(INFO, TAG, "%s: secure port: %d", __func__, securePort);
806                 }
807             }
808             else
809             {
810                 OIC_LOG(INFO, TAG, "Can not find secure port information.");
811                 return OC_STACK_DELETE_TRANSACTION;
812             }
813 #ifdef __WITH_TLS__
814             OIC_LOG_V(DEBUG, TAG, "%s: TCP port from discovery = %d", __func__, resPayload->tcpPort);
815 #endif
816             DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
817             OCProvisionDev_t *ptr = GetDevice(&pDInfo->pCandidateList,
818                                               clientResponse->devAddr.addr,
819                                               clientResponse->devAddr.port);
820             if(!ptr)
821             {
822                 OIC_LOG(ERROR, TAG, "Can not find device information in the discovery candidate device list");
823                 return OC_STACK_DELETE_TRANSACTION;
824             }
825
826             OCStackResult res = UpdateSecurePortOfDevice(&pDInfo->pCandidateList,
827                                                          clientResponse->devAddr.addr,
828                                                          clientResponse->devAddr.port,
829                                                          securePort
830 #ifdef __WITH_TLS__
831                                                          ,tcpPort
832                                                          ,tcpSecurePort
833 #endif
834                                                          );
835             if (OC_STACK_OK != res)
836             {
837                 OIC_LOG(ERROR, TAG, "Error while getting secure port.");
838                 return OC_STACK_DELETE_TRANSACTION;
839             }
840
841             res = MoveDeviceList(pDInfo->ppDevicesList, &pDInfo->pCandidateList, &clientResponse->devAddr);
842             if(OC_STACK_OK != res)
843             {
844                 OIC_LOG(ERROR, TAG, "Error while move the discovered device to list.");
845                 return OC_STACK_DELETE_TRANSACTION;
846             }
847
848             if(pDInfo->isSingleDiscovery)
849             {
850                 pDInfo->isFound = true;
851             }
852
853             res = SpecVersionDiscovery(pDInfo, clientResponse);
854             if(OC_STACK_OK != res)
855             {
856                 OIC_LOG(ERROR, TAG, "Failed to SpecVersionDiscovery");
857                 return OC_STACK_DELETE_TRANSACTION;
858             }
859
860             OIC_LOG(INFO, TAG, "Exiting SecurePortDiscoveryHandler.");
861         }
862
863         return  OC_STACK_DELETE_TRANSACTION;
864     }
865     else
866     {
867         OIC_LOG(INFO, TAG, "Skiping Null response");
868     }
869
870     return  OC_STACK_DELETE_TRANSACTION;
871 }
872
873 static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
874                                 OCClientResponse *clientResponse)
875 {
876     if (ctx == NULL)
877     {
878         OIC_LOG(ERROR, TAG, "Lost List of device information");
879         return OC_STACK_KEEP_TRANSACTION;
880     }
881     (void)UNUSED;
882
883     if (!clientResponse)
884     {
885         OIC_LOG(INFO, TAG, "Skiping Null response");
886         return OC_STACK_KEEP_TRANSACTION;
887     }
888
889     if  (NULL == clientResponse->payload)
890     {
891         OIC_LOG(INFO, TAG, "Skiping Null payload");
892         return OC_STACK_KEEP_TRANSACTION;
893     }
894     if (OC_STACK_OK != clientResponse->result)
895     {
896         OIC_LOG(INFO, TAG, "Error in response");
897         return OC_STACK_KEEP_TRANSACTION;
898     }
899
900     if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
901     {
902         OIC_LOG(INFO, TAG, "Unknown payload type");
903         return OC_STACK_KEEP_TRANSACTION;
904     }
905
906     OicSecDoxm_t *ptrDoxm = NULL;
907     uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
908     size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
909
910     OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
911     if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
912     {
913         OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
914         return OC_STACK_KEEP_TRANSACTION;
915     }
916
917     OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
918
919     //If this is owend device discovery we have to filter out the responses.
920     DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
921     OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
922
923     // Get my device ID from doxm resource
924     OicUuid_t myId;
925     memset(&myId, 0, sizeof(myId));
926     res = GetDoxmDeviceID(&myId);
927     if(OC_STACK_OK != res)
928     {
929         OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
930         DeleteDoxmBinData(ptrDoxm);
931         return OC_STACK_KEEP_TRANSACTION;
932     }
933
934     // If this is owned discovery response but owner is not me then discard it.
935     if( (pDInfo->isOwnedDiscovery) &&
936         (0 != memcmp(&ptrDoxm->owner.id, &myId.id, sizeof(myId.id))) )
937     {
938         OIC_LOG(DEBUG, TAG, "Discovered device is not owend by me");
939         DeleteDoxmBinData(ptrDoxm);
940         return OC_STACK_KEEP_TRANSACTION;
941     }
942
943     //if targetId and discovered deviceID are different, discard it
944     if ((pDInfo->isSingleDiscovery) &&
945         (0 != memcmp(&ptrDoxm->deviceID.id, &pDInfo->targetId->id, sizeof(pDInfo->targetId->id))) )
946     {
947         OIC_LOG(DEBUG, TAG, "Discovered device is not target device");
948         DeleteDoxmBinData(ptrDoxm);
949         return OC_STACK_KEEP_TRANSACTION;
950     }
951     //If self reply, discard it
952     if (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id)))
953     {
954         OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
955         DeleteDoxmBinData(ptrDoxm);
956         return OC_STACK_KEEP_TRANSACTION;
957     }
958
959     res = AddDevice(ppDevicesList, &clientResponse->devAddr,
960             clientResponse->connType, ptrDoxm);
961     if (OC_STACK_OK != res)
962     {
963         OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
964         DeleteDoxmBinData(ptrDoxm);
965         return OC_STACK_KEEP_TRANSACTION;
966     }
967
968     res = SecurePortDiscovery(pDInfo, clientResponse);
969     if(OC_STACK_OK != res)
970     {
971         OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
972         DeleteDoxmBinData(ptrDoxm);
973         return OC_STACK_KEEP_TRANSACTION;
974     }
975
976     OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
977
978     return  OC_STACK_KEEP_TRANSACTION;
979 }
980
981 static void DeviceDiscoveryDeleteHandler(void *ctx)
982 {
983     OIC_LOG(DEBUG, TAG, "IN DeviceDiscoveryDeleteHandler");
984     if (NULL == ctx)
985     {
986         OIC_LOG(WARNING, TAG, "Not found context in DeviceDiscoveryDeleteHandler");
987         return;
988     }
989
990     DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
991     if (NULL != pDInfo->pCandidateList)
992     {
993         OCProvisionDev_t *pDev = NULL;
994         LL_FOREACH(pDInfo->pCandidateList, pDev)
995         {
996             OIC_LOG_V(DEBUG, TAG, "OCCancel - %s : %d",
997                             pDev->endpoint.addr, pDev->endpoint.port);
998             if(OC_STACK_OK !=  OCCancel(pDev->handle,OC_HIGH_QOS,NULL,0))
999             {
1000                 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1001             }
1002         }
1003         PMDeleteDeviceList(pDInfo->pCandidateList);
1004     }
1005     OIC_LOG(DEBUG, TAG, "OUT DeviceDiscoveryDeleteHandler");
1006 }
1007
1008 /**
1009  * Discover owned/unowned device in the specified endpoint/deviceID.
1010  * It will return the found device even though timeout is not exceeded.
1011  *
1012  * @param[in] waittime           Timeout in seconds
1013  * @param[in] deviceID           deviceID of target device.
1014  * @param[out] ppFoundDevice     OCProvisionDev_t of found device
1015  *
1016  * @return OC_STACK_OK on success otherwise error.\n
1017  *         OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not initailized.
1018  */
1019 OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const OicUuid_t* deviceID,
1020                                  OCProvisionDev_t **ppFoundDevice)
1021 {
1022     OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscovery");
1023
1024     if (NULL != *ppFoundDevice)
1025     {
1026         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1027         return OC_STACK_INVALID_PARAM;
1028     }
1029
1030     if (NULL == deviceID)
1031     {
1032         OIC_LOG(ERROR, TAG, "Invalid device ID");
1033         return OC_STACK_INVALID_PARAM;
1034     }
1035
1036
1037     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
1038     if(NULL == pDInfo)
1039     {
1040         OIC_LOG(ERROR, TAG, "PMSingleDeviceDiscovery : Memory allocation failed.");
1041         return OC_STACK_NO_MEMORY;
1042     }
1043
1044     pDInfo->ppDevicesList = ppFoundDevice;
1045     pDInfo->pCandidateList = NULL;
1046     pDInfo->isOwnedDiscovery = false;
1047     pDInfo->isSingleDiscovery = true;
1048     pDInfo->isFound = false;
1049     pDInfo->targetId = deviceID;
1050
1051     OCCallbackData cbData;
1052     cbData.cb = &DeviceDiscoveryHandler;
1053     cbData.context = (void *)pDInfo;
1054     cbData.cd = &DeviceDiscoveryDeleteHandler;
1055
1056     OCStackResult res = OC_STACK_ERROR;
1057
1058     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
1059     snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "/oic/sec/doxm");
1060
1061     OCDoHandle handle = NULL;
1062     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1063                                      CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
1064     if (res != OC_STACK_OK)
1065     {
1066         OIC_LOG(ERROR, TAG, "OCStack resource error");
1067         OICFree(pDInfo);
1068         return res;
1069     }
1070
1071     //Waiting for each response.
1072     res = OC_STACK_OK;
1073     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
1074     while (OC_STACK_OK == res && !pDInfo->isFound)
1075     {
1076         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
1077
1078         long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
1079         if (elapsed > waittime)
1080         {
1081             break;
1082         }
1083         res = OCProcess();
1084     }
1085
1086     if(OC_STACK_OK != res)
1087     {
1088         OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
1089         OICFree(pDInfo);
1090         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1091         if(OC_STACK_OK !=  resCancel)
1092         {
1093             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1094         }
1095         return res;
1096     }
1097
1098     res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
1099     if (OC_STACK_OK != res)
1100     {
1101         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1102         OICFree(pDInfo);
1103         return res;
1104     }
1105     OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscovery");
1106     OICFree(pDInfo);
1107     return res;
1108 }
1109
1110
1111 /**
1112  * Discover owned/unowned devices in the same IP subnet. .
1113  *
1114  * @param[in] waittime      Timeout in seconds.
1115  * @param[in] isOwned       bool flag for owned / unowned discovery
1116  * @param[in] ppDevicesList        List of OCProvisionDev_t.
1117  *
1118  * @return OC_STACK_OK on success otherwise error.
1119  */
1120 OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppDevicesList)
1121 {
1122     OIC_LOG(DEBUG, TAG, "IN PMDeviceDiscovery");
1123
1124     if (NULL != *ppDevicesList)
1125     {
1126         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1127         return OC_STACK_INVALID_PARAM;
1128     }
1129
1130     const char DOXM_OWNED_FALSE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=FALSE";
1131     const char DOXM_OWNED_TRUE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=TRUE";
1132
1133     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
1134     if(NULL == pDInfo)
1135     {
1136         OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
1137         return OC_STACK_NO_MEMORY;
1138     }
1139
1140     pDInfo->ppDevicesList = ppDevicesList;
1141     pDInfo->pCandidateList = NULL;
1142     pDInfo->isOwnedDiscovery = isOwned;
1143     pDInfo->isSingleDiscovery = false;
1144     pDInfo->targetId = NULL;
1145
1146     OCCallbackData cbData;
1147     cbData.cb = &DeviceDiscoveryHandler;
1148     cbData.context = (void *)pDInfo;
1149     cbData.cd = &DeviceDiscoveryDeleteHandler;
1150     OCStackResult res = OC_STACK_ERROR;
1151
1152     const char* query = isOwned ? DOXM_OWNED_TRUE_MULTICAST_QUERY :
1153                                   DOXM_OWNED_FALSE_MULTICAST_QUERY;
1154
1155     OCDoHandle handle = NULL;
1156     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1157                                      CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
1158     if (res != OC_STACK_OK)
1159     {
1160         OIC_LOG(ERROR, TAG, "OCStack resource error");
1161         OICFree(pDInfo);
1162         return res;
1163     }
1164
1165     //Waiting for each response.
1166     res = PMTimeout(waittime, true);
1167     if(OC_STACK_OK != res)
1168     {
1169         OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
1170         OICFree(pDInfo);
1171         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1172         if(OC_STACK_OK !=  resCancel)
1173         {
1174             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1175         }
1176         return res;
1177     }
1178     res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
1179     if (OC_STACK_OK != res)
1180     {
1181         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1182         OICFree(pDInfo);
1183         return res;
1184     }
1185     OIC_LOG(DEBUG, TAG, "OUT PMDeviceDiscovery");
1186     OICFree(pDInfo);
1187     return res;
1188 }
1189
1190 OCStackResult PMSingleDeviceDiscoveryInUnicast(unsigned short waittime, const OicUuid_t* deviceID,
1191                                  const char* hostAddress, OCConnectivityType connType,
1192                                  OCProvisionDev_t **ppFoundDevice)
1193 {
1194     OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscoveryInUnicast");
1195
1196     if (NULL != *ppFoundDevice)
1197     {
1198         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1199         return OC_STACK_INVALID_PARAM;
1200     }
1201
1202     if (NULL == deviceID)
1203     {
1204         OIC_LOG(ERROR, TAG, "Invalid device ID");
1205         return OC_STACK_INVALID_PARAM;
1206     }
1207
1208     DiscoveryInfo *pDInfo = (DiscoveryInfo*)OICCalloc(1, sizeof(DiscoveryInfo));
1209     if (NULL == pDInfo)
1210     {
1211         OIC_LOG(ERROR, TAG, "PMSingleDeviceDiscoveryInUnicast : Memory allocation failed.");
1212         return OC_STACK_NO_MEMORY;
1213     }
1214
1215     pDInfo->ppDevicesList = ppFoundDevice;
1216     pDInfo->pCandidateList = NULL;
1217     pDInfo->isOwnedDiscovery = false;
1218     pDInfo->isSingleDiscovery = true;
1219     pDInfo->isFound = false;
1220     pDInfo->targetId = deviceID;
1221
1222     OCCallbackData cbData;
1223     cbData.cb = &DeviceDiscoveryHandler;
1224     cbData.context = (void *)pDInfo;
1225     cbData.cd = &DeviceDiscoveryDeleteHandler;
1226
1227     OCStackResult res = OC_STACK_ERROR;
1228
1229     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
1230     if (hostAddress == NULL)
1231     {
1232         hostAddress = "";
1233     }
1234     snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "%s/oic/sec/doxm", hostAddress);
1235     connType = connType & CT_MASK_ADAPTER;
1236
1237     OCDoHandle handle = NULL;
1238     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1239             connType, OC_HIGH_QOS, &cbData, NULL, 0);
1240
1241     if (res != OC_STACK_OK)
1242     {
1243         OIC_LOG(ERROR, TAG, "OCStack resource error");
1244         OICFree(pDInfo);
1245         pDInfo = NULL;
1246         return res;
1247     }
1248
1249     res = OC_STACK_OK;
1250     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
1251     while (OC_STACK_OK == res && !pDInfo->isFound)
1252     {
1253         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
1254
1255         long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
1256         if (elapsed > waittime)
1257         {
1258             break;
1259         }
1260         res = OCProcess();
1261     }
1262
1263     if (OC_STACK_OK != res)
1264     {
1265         OIC_LOG (ERROR, TAG, "Failed to wait response for secure discovery.");
1266         OICFree(pDInfo);
1267         pDInfo = NULL;
1268         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1269         if (OC_STACK_OK !=  resCancel)
1270         {
1271             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1272         }
1273         return res;
1274     }
1275
1276     res = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1277     if (OC_STACK_OK != res)
1278     {
1279         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1280         OICFree(pDInfo);
1281         pDInfo = NULL;
1282         return res;
1283     }
1284     OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscoveryInUnicast");
1285     OICFree(pDInfo);
1286     pDInfo = NULL;
1287     return res;
1288 }
1289
1290 #ifdef MULTIPLE_OWNER
1291
1292 static const unsigned int IOTIVITY_USECS_PER_MSEC = 1000;
1293
1294 static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
1295                                 OCClientResponse *clientResponse)
1296 {
1297     if (ctx == NULL)
1298     {
1299         OIC_LOG(ERROR, TAG, "Lost List of device information");
1300         return OC_STACK_KEEP_TRANSACTION;
1301     }
1302     (void)UNUSED;
1303     if (clientResponse)
1304     {
1305         if  (NULL == clientResponse->payload)
1306         {
1307             OIC_LOG(INFO, TAG, "Skipping Null payload");
1308             return OC_STACK_KEEP_TRANSACTION;
1309         }
1310         if (OC_STACK_OK != clientResponse->result)
1311         {
1312             OIC_LOG(INFO, TAG, "Error in response");
1313             return OC_STACK_KEEP_TRANSACTION;
1314         }
1315         else
1316         {
1317             if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
1318             {
1319                 OIC_LOG(INFO, TAG, "Unknown payload type");
1320                 return OC_STACK_KEEP_TRANSACTION;
1321             }
1322
1323             OicSecDoxm_t *ptrDoxm = NULL;
1324             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
1325             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
1326
1327             OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
1328             if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
1329             {
1330                 OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
1331                 return OC_STACK_KEEP_TRANSACTION;
1332             }
1333             else
1334             {
1335                 OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
1336
1337                 //If this is owend device discovery we have to filter out the responses.
1338                 DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
1339                 OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
1340
1341                 // Get my device ID from doxm resource
1342                 OicUuid_t myId;
1343                 memset(&myId, 0, sizeof(myId));
1344
1345                 res = GetDoxmDeviceID(&myId);
1346                 if(OC_STACK_OK != res)
1347                 {
1348                     OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
1349                     DeleteDoxmBinData(ptrDoxm);
1350                     return OC_STACK_KEEP_TRANSACTION;
1351                 }
1352
1353                 //if targetId and discovered deviceID are different, discard it
1354                 if ((pDInfo->isSingleDiscovery) &&
1355                     (0 != memcmp(&ptrDoxm->deviceID.id, &pDInfo->targetId->id, sizeof(pDInfo->targetId->id))))
1356                 {
1357                     OIC_LOG(DEBUG, TAG, "Discovered device is not target device");
1358                     DeleteDoxmBinData(ptrDoxm);
1359                     return OC_STACK_KEEP_TRANSACTION;
1360                 }
1361
1362                 //if this is owned discovery and this is PT's reply, discard it
1363                 if (((pDInfo->isSingleDiscovery) || (pDInfo->isOwnedDiscovery)) &&
1364                     (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))))
1365                 {
1366                     OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
1367                     DeleteDoxmBinData(ptrDoxm);
1368                     return OC_STACK_KEEP_TRANSACTION;
1369                 }
1370
1371                 if(pDInfo->isOwnedDiscovery)
1372                 {
1373                     OicSecSubOwner_t* subOwner = NULL;
1374                     LL_FOREACH(ptrDoxm->subOwners, subOwner)
1375                     {
1376                         if(memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
1377                         {
1378                             break;
1379                         }
1380                     }
1381
1382                     if(subOwner)
1383                     {
1384                         res = AddDevice(ppDevicesList, &clientResponse->devAddr,
1385                                 clientResponse->connType, ptrDoxm);
1386                         if (OC_STACK_OK != res)
1387                         {
1388                             OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
1389                             DeleteDoxmBinData(ptrDoxm);
1390                             return OC_STACK_KEEP_TRANSACTION;
1391                         }
1392
1393                         res = SecurePortDiscovery(pDInfo, clientResponse);
1394                         if(OC_STACK_OK != res)
1395                         {
1396                             OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
1397                             DeleteDoxmBinData(ptrDoxm);
1398                             return OC_STACK_KEEP_TRANSACTION;
1399                         }
1400                     }
1401                     else
1402                     {
1403                         OIC_LOG(ERROR, TAG, "discarding device's reply, because not a SubOwner.");
1404                         DeleteDoxmBinData(ptrDoxm);
1405                         return OC_STACK_KEEP_TRANSACTION;
1406                     }
1407                 }
1408                 else
1409                 {
1410                     if(ptrDoxm->mom && OIC_MULTIPLE_OWNER_DISABLE != ptrDoxm->mom->mode)
1411                     {
1412                         res = AddDevice(ppDevicesList, &clientResponse->devAddr,
1413                                 clientResponse->connType, ptrDoxm);
1414                         if (OC_STACK_OK != res)
1415                         {
1416                             OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
1417                             DeleteDoxmBinData(ptrDoxm);
1418                             return OC_STACK_KEEP_TRANSACTION;
1419                         }
1420
1421                         res = SecurePortDiscovery(pDInfo, clientResponse);
1422                         if(OC_STACK_OK != res)
1423                         {
1424                             OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
1425                             DeleteDoxmBinData(ptrDoxm);
1426                             return OC_STACK_KEEP_TRANSACTION;
1427                         }
1428                     }
1429                     else
1430                     {
1431                         OIC_LOG(ERROR, TAG, "discarding mom disabled device's reply");
1432                         DeleteDoxmBinData(ptrDoxm);
1433                         return OC_STACK_KEEP_TRANSACTION;
1434                     }
1435                 }
1436
1437                 OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
1438             }
1439
1440             return  OC_STACK_KEEP_TRANSACTION;
1441         }
1442     }
1443     else
1444     {
1445         OIC_LOG(INFO, TAG, "Skiping Null response");
1446         return OC_STACK_KEEP_TRANSACTION;
1447     }
1448 }
1449
1450 /**
1451  * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID.
1452  * The function will return when security information for device with deviceID has been obtained or the
1453  * timeout has been exceeded.
1454  *
1455  * @param[in]  timeoutSeconds  Maximum time, in seconds, this function will listen for responses from
1456  *                             servers before returning.
1457  * @param[in]  deviceID        deviceID of target device.
1458  * @param[out] ppFoundDevice   OCProvisionDev_t of found device. Caller should use PMDeleteDeviceList 
1459  *                             to delete the device.
1460  *
1461  * @return OC_STACK_OK on success otherwise error.
1462  *         OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not initailized.
1463  */
1464 OCStackResult PMMultipleOwnerSingleDeviceDiscovery(unsigned short timeoutSeconds,
1465                                                    const OicUuid_t* deviceID,
1466                                                    OCProvisionDev_t **ppFoundDevice)
1467 {
1468     OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerSingleDeviceDiscovery");
1469
1470     if ((NULL == ppFoundDevice) || (NULL == deviceID))
1471     {
1472         return OC_STACK_INVALID_PARAM;
1473     }
1474
1475     DiscoveryInfo discoveryInfo;
1476     discoveryInfo.ppDevicesList = ppFoundDevice;
1477     discoveryInfo.pCandidateList = NULL;
1478     discoveryInfo.isOwnedDiscovery = false;
1479     discoveryInfo.isSingleDiscovery = true;
1480     discoveryInfo.isFound = false;
1481     discoveryInfo.targetId = deviceID;
1482
1483     OCCallbackData cbData;
1484     cbData.cb = &MOTDeviceDiscoveryHandler;
1485     cbData.context = (void *)&discoveryInfo;
1486     cbData.cd = NULL;
1487
1488     OCStackResult res = OC_STACK_ERROR;
1489     const char query[] = "/oic/sec/doxm?mom!=0&owned=TRUE";
1490
1491     OCDoHandle handle = NULL;
1492     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0, CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
1493     if (res != OC_STACK_OK)
1494     {
1495         OIC_LOG(ERROR, TAG, "OCStack resource error");
1496         return res;
1497     }
1498
1499     //Waiting for each response.
1500     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
1501     while ((OC_STACK_OK == res) && !discoveryInfo.isFound)
1502     {
1503         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
1504         if (currTime >= startTime)
1505         {
1506             long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
1507             if (elapsed > timeoutSeconds)
1508             {
1509                 break;
1510             }
1511
1512             // Sleep for 100 ms to free up the CPU
1513             usleep(100 * IOTIVITY_USECS_PER_MSEC);
1514
1515             res = OCProcess();
1516         }
1517         else
1518         {
1519             // System time has changed so we cannot reliably continue processing.
1520             // Function returns with no device discovered.
1521             break;
1522         }
1523     }
1524
1525     if (OC_STACK_OK != res)
1526     {
1527         OIC_LOG(ERROR, TAG, "Failed while waiting for a secure discovery response.");
1528         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1529         if (OC_STACK_OK != resCancel)
1530         {
1531             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1532         }
1533         return res;
1534     }
1535
1536     res = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1537     if (OC_STACK_OK != res)
1538     {
1539         OIC_LOG(ERROR, TAG, "Failed to remove the registered callback");
1540         return res;
1541     }
1542     OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerSingleDeviceDiscovery");
1543     return res;
1544 }
1545
1546 /**
1547  * Discover multiple OTM enabled devices in the same IP subnet.
1548  *
1549  * @param[in] waittime      Timeout in seconds.
1550  * @param[in] ppDevicesList        List of OCProvisionDev_t.
1551  *
1552  * @return OC_STACK_OK on success otherwise error.
1553  */
1554 OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList)
1555 {
1556     OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerEnabledDeviceDiscovery");
1557
1558     if (NULL != *ppDevicesList)
1559     {
1560         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1561         return OC_STACK_INVALID_PARAM;
1562     }
1563
1564     const char *DOXM_MOM_ENABLE_MULTICAST_QUERY = "/oic/sec/doxm?mom!=0&owned=TRUE";
1565     const char *DOXM_MULTIPLE_OWNED_MULTICAST_QUERY = "/oic/sec/doxm?owned=TRUE";
1566
1567     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
1568     if(NULL == pDInfo)
1569     {
1570         OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
1571         return OC_STACK_NO_MEMORY;
1572     }
1573
1574     pDInfo->ppDevicesList = ppDevicesList;
1575     pDInfo->pCandidateList = NULL;
1576     pDInfo->isOwnedDiscovery = isMultipleOwned;
1577
1578     OCCallbackData cbData;
1579     cbData.cb = &MOTDeviceDiscoveryHandler;
1580     cbData.context = (void *)pDInfo;
1581     cbData.cd = NULL;
1582     OCStackResult res = OC_STACK_ERROR;
1583
1584     const char* query = isMultipleOwned ? DOXM_MULTIPLE_OWNED_MULTICAST_QUERY :
1585                                           DOXM_MOM_ENABLE_MULTICAST_QUERY;
1586
1587     OCDoHandle handle = NULL;
1588     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1589                                      CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
1590     if (res != OC_STACK_OK)
1591     {
1592         OIC_LOG(ERROR, TAG, "OCStack resource error");
1593         OICFree(pDInfo);
1594         return res;
1595     }
1596
1597     //Waiting for each response.
1598     res = PMTimeout(waittime, true);
1599     if(OC_STACK_OK != res)
1600     {
1601         OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
1602         OICFree(pDInfo);
1603         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1604         if(OC_STACK_OK !=  resCancel)
1605         {
1606             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1607         }
1608         return res;
1609     }
1610     res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
1611     if (OC_STACK_OK != res)
1612     {
1613         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1614         OICFree(pDInfo);
1615         return res;
1616     }
1617     OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerEnabledDeviceDiscovery");
1618     OICFree(pDInfo);
1619     return res;
1620 }
1621
1622 /**
1623  * The function is responsible for determining if the caller is a subowner of the specified device.
1624  *
1625  * @param[in] device       MOT enabled device that contains a list of subowners
1626  * @param[out] isSubowner  Bool indicating whether the caller is a subowner of device
1627  *
1628  * @return OC_STACK_OK in case of success and other value otherwise.
1629  */
1630 OCStackResult PMIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner)
1631 {  
1632     if ((NULL == device) || (NULL == isSubowner))
1633     {
1634         return OC_STACK_INVALID_PARAM;
1635     }
1636
1637     OicUuid_t myId;
1638     memset(&myId, 0, sizeof(myId));
1639     OicSecSubOwner_t* subOwner = NULL;
1640
1641     *isSubowner = false;
1642
1643     OCStackResult result = GetDoxmDeviceID(&myId);
1644     if (OC_STACK_OK == result)
1645     {
1646         LL_FOREACH(device->doxm->subOwners, subOwner)
1647         {
1648             if (memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
1649             {
1650                 *isSubowner = true;
1651                 break;
1652             }
1653         }
1654     }
1655     else
1656     {
1657         OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
1658     }
1659
1660     return result;
1661 }
1662 #endif //MULTIPLE_OWNER
1663
1664 static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
1665                                          const OCClientResponse *clientResponse)
1666 {
1667     OIC_LOG(DEBUG, TAG, "IN SecurePortDiscovery");
1668
1669     if(NULL == discoveryInfo || NULL == clientResponse)
1670     {
1671         return OC_STACK_INVALID_PARAM;
1672     }
1673
1674     OCProvisionDev_t *pDev = GetDevice(&discoveryInfo->pCandidateList,
1675                         clientResponse->devAddr.addr, clientResponse->devAddr.port);
1676     if(NULL == pDev)
1677     {
1678         OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to get device");
1679         return OC_STACK_ERROR;
1680     }
1681
1682     //Try to the unicast discovery to getting secure port
1683     char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
1684     if(!PMGenerateQuery(false,
1685                         pDev->endpoint.addr, pDev->endpoint.port,
1686                         pDev->connType,
1687                         query, sizeof(query), OC_RSRVD_WELL_KNOWN_URI))
1688     {
1689         OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to generate query");
1690         return OC_STACK_ERROR;
1691     }
1692     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1693
1694     // Set filter query with rt=oic.r.doxm
1695     const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
1696     char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1697     snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, query,
1698             OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
1699
1700     OIC_LOG_V(DEBUG, TAG, "URI=%s", uri);
1701
1702     OCCallbackData cbData;
1703     cbData.cb = &SecurePortDiscoveryHandler;
1704     cbData.context = (void*)discoveryInfo;
1705     cbData.cd = NULL;
1706     OCStackResult ret = OCDoResource(&pDev->handle, OC_REST_DISCOVER, uri, 0, 0,
1707             pDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1708     if(OC_STACK_OK != ret)
1709     {
1710         OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
1711         return ret;
1712     }
1713     else
1714     {
1715         OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
1716     }
1717
1718     OIC_LOG(DEBUG, TAG, "OUT SecurePortDiscovery");
1719
1720     return ret;
1721 }
1722
1723
1724 static OCStackResult SpecVersionDiscovery(DiscoveryInfo* discoveryInfo,
1725                                               const OCClientResponse *clientResponse)
1726 {
1727     OIC_LOG(DEBUG, TAG, "IN SpecVersionDiscovery");
1728
1729     if(NULL == discoveryInfo || NULL == clientResponse)
1730     {
1731         return OC_STACK_INVALID_PARAM;
1732     }
1733
1734     //Try to the unicast discovery to getting security version
1735     char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
1736     if(!PMGenerateQuery(false,
1737                         clientResponse->devAddr.addr, clientResponse->devAddr.port,
1738                         clientResponse->connType,
1739                         query, sizeof(query), OC_RSRVD_DEVICE_URI))
1740     {
1741         OIC_LOG(ERROR, TAG, "SpecVersionDiscovery : Failed to generate query");
1742         return OC_STACK_ERROR;
1743     }
1744     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1745
1746     OCCallbackData cbData;
1747     cbData.cb = &SpecVersionDiscoveryHandler;
1748     cbData.context = (void*)discoveryInfo;
1749     cbData.cd = NULL;
1750     OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
1751             clientResponse->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1752     if(OC_STACK_OK != ret)
1753     {
1754         OIC_LOG(ERROR, TAG, "Failed to Security Version Discovery");
1755         return ret;
1756     }
1757     else
1758     {
1759         OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
1760     }
1761
1762     OIC_LOG(DEBUG, TAG, "OUT SpecVersionDiscovery");
1763
1764     return ret;
1765 }
1766
1767 /**
1768  * Function to print OCProvisionDev_t for debug purpose.
1769  *
1770  * @param[in] pDev Pointer to OCProvisionDev_t. It's information will be printed by OIC_LOG_XX
1771  *
1772  */
1773 void PMPrintOCProvisionDev(const OCProvisionDev_t* pDev)
1774 {
1775     if (pDev)
1776     {
1777         OIC_LOG(DEBUG, TAG, "+++++ OCProvisionDev_t Information +++++");
1778         OIC_LOG_V(DEBUG, TAG, "IP %s", pDev->endpoint.addr);
1779         OIC_LOG_V(DEBUG, TAG, "PORT %d", pDev->endpoint.port);
1780         OIC_LOG_V(DEBUG, TAG, "S-PORT %d", pDev->securePort);
1781         OIC_LOG(DEBUG, TAG, "++++++++++++++++++++++++++++++++++++++++");
1782     }
1783     else
1784     {
1785         OIC_LOG(DEBUG, TAG, "+++++ OCProvisionDev_t is NULL +++++");
1786     }
1787 }
1788
1789 bool PMDeleteFromUUIDList(OCUuidList_t **pUuidList, OicUuid_t *targetId)
1790 {
1791     if(*pUuidList == NULL || targetId == NULL)
1792     {
1793         return false;
1794     }
1795     OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
1796     LL_FOREACH_SAFE(*pUuidList, tmp1, tmp2)
1797     {
1798         if(0 == memcmp(tmp1->dev.id, targetId->id, sizeof(targetId->id)))
1799         {
1800             LL_DELETE(*pUuidList, tmp1);
1801             OICFree(tmp1);
1802             return true;
1803         }
1804     }
1805     return false;
1806 }