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