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