replace : iotivity -> iotivity-sec
[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             OCProvisionDev_t *ptr = GetDevice(&pDInfo->pCandidateList,
699                                                          clientResponse->devAddr.addr,
700                                                          clientResponse->devAddr.port);
701             if(!ptr)
702             {
703                 OIC_LOG(ERROR, TAG, "Can not find device information in the discovery candidate device list");
704                 return OC_STACK_DELETE_TRANSACTION;
705             }
706
707             OCStackResult res = UpdateSecurePortOfDevice(&pDInfo->pCandidateList,
708                                                          clientResponse->devAddr.addr,
709                                                          clientResponse->devAddr.port,
710                                                          securePort
711 #ifdef __WITH_TLS__
712                                                          ,resPayload->tcpPort
713 #endif
714                                                          );
715             if (OC_STACK_OK != res)
716             {
717                 OIC_LOG(ERROR, TAG, "Error while getting secure port.");
718                 return OC_STACK_DELETE_TRANSACTION;
719             }
720
721             res = MoveDeviceList(pDInfo->ppDevicesList, &pDInfo->pCandidateList, &clientResponse->devAddr);
722             if(OC_STACK_OK != res)
723             {
724                 OIC_LOG(ERROR, TAG, "Error while move the discovered device to list.");
725                 return OC_STACK_DELETE_TRANSACTION;
726             }
727
728             if(pDInfo->isSingleDiscovery)
729             {
730                 pDInfo->isFound = true;
731             }
732
733 /*
734  * Since security version discovery does not used anymore, disable security version discovery.
735  * Need to discussion to removing all version discovery related codes.
736  */
737 #if 0
738             res = SecurityVersionDiscovery(pDInfo, clientResponse);
739             if(OC_STACK_OK != res)
740             {
741                 OIC_LOG(ERROR, TAG, "Failed to SecurityVersionDiscovery");
742                 return OC_STACK_DELETE_TRANSACTION;
743             }
744 #endif
745             OIC_LOG(INFO, TAG, "Exiting SecurePortDiscoveryHandler.");
746         }
747
748         return  OC_STACK_DELETE_TRANSACTION;
749     }
750     else
751     {
752         OIC_LOG(INFO, TAG, "Skiping Null response");
753     }
754
755     return  OC_STACK_DELETE_TRANSACTION;
756 }
757
758 static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
759                                 OCClientResponse *clientResponse)
760 {
761     if (ctx == NULL)
762     {
763         OIC_LOG(ERROR, TAG, "Lost List of device information");
764         return OC_STACK_KEEP_TRANSACTION;
765     }
766     (void)UNUSED;
767     if (clientResponse)
768     {
769         if  (NULL == clientResponse->payload)
770         {
771             OIC_LOG(INFO, TAG, "Skiping Null payload");
772             return OC_STACK_KEEP_TRANSACTION;
773         }
774         if (OC_STACK_OK != clientResponse->result)
775         {
776             OIC_LOG(INFO, TAG, "Error in response");
777             return OC_STACK_KEEP_TRANSACTION;
778         }
779         else
780         {
781             if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
782             {
783                 OIC_LOG(INFO, TAG, "Unknown payload type");
784                 return OC_STACK_KEEP_TRANSACTION;
785             }
786
787             OicSecDoxm_t *ptrDoxm = NULL;
788             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
789             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
790
791             OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
792             if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
793             {
794                 OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
795                 return OC_STACK_KEEP_TRANSACTION;
796             }
797             else
798             {
799                 OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
800
801                 //If this is owend device discovery we have to filter out the responses.
802                 DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
803                 OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
804
805                 // Get my device ID from doxm resource
806                 OicUuid_t myId;
807                 memset(&myId, 0, sizeof(myId));
808                 OCStackResult res = GetDoxmDeviceID(&myId);
809                 if(OC_STACK_OK != res)
810                 {
811                     OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
812                     DeleteDoxmBinData(ptrDoxm);
813                     return OC_STACK_KEEP_TRANSACTION;
814                 }
815
816                 // If this is owned discovery response but owner is not me then discard it.
817                 if( (pDInfo->isOwnedDiscovery) &&
818                     (0 != memcmp(&ptrDoxm->owner.id, &myId.id, sizeof(myId.id))) )
819                 {
820                     OIC_LOG(DEBUG, TAG, "Discovered device is not owend by me");
821                     DeleteDoxmBinData(ptrDoxm);
822                     return OC_STACK_KEEP_TRANSACTION;
823                 }
824
825                 //if targetId and discovered deviceID are different, discard it
826                 if ((pDInfo->isSingleDiscovery) &&
827                     (0 != memcmp(&ptrDoxm->deviceID.id, &pDInfo->targetId->id, sizeof(pDInfo->targetId->id))) )
828                 {
829                     OIC_LOG(DEBUG, TAG, "Discovered device is not target device");
830                     DeleteDoxmBinData(ptrDoxm);
831                     return OC_STACK_KEEP_TRANSACTION;
832                 }
833                 //If self reply, discard it
834                 if (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id)))
835                 {
836                     OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
837                     DeleteDoxmBinData(ptrDoxm);
838                     return OC_STACK_KEEP_TRANSACTION;
839                 }
840
841                 res = AddDevice(ppDevicesList, &clientResponse->devAddr,
842                         clientResponse->connType, ptrDoxm);
843                 if (OC_STACK_OK != res)
844                 {
845                     OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
846                     DeleteDoxmBinData(ptrDoxm);
847                     return OC_STACK_KEEP_TRANSACTION;
848                 }
849                 res = SecurePortDiscovery(pDInfo, clientResponse);
850                 if(OC_STACK_OK != res)
851                 {
852                     OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
853                     DeleteDoxmBinData(ptrDoxm);
854                     return OC_STACK_KEEP_TRANSACTION;
855                 }
856
857                 OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
858             }
859             return  OC_STACK_KEEP_TRANSACTION;
860         }
861     }
862     else
863     {
864         OIC_LOG(INFO, TAG, "Skiping Null response");
865         return OC_STACK_KEEP_TRANSACTION;
866     }
867
868     return  OC_STACK_DELETE_TRANSACTION;
869 }
870
871 static void DeviceDiscoveryDeleteHandler(void *ctx)
872 {
873     OIC_LOG(DEBUG, TAG, "IN DeviceDiscoveryDeleteHandler");
874     if (NULL == ctx)
875     {
876         OIC_LOG(WARNING, TAG, "Not found context in DeviceDiscoveryDeleteHandler");
877         return;
878     }
879
880     DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
881     if (NULL != pDInfo->pCandidateList)
882     {
883         OCProvisionDev_t *pDev = NULL;
884         LL_FOREACH(pDInfo->pCandidateList, pDev)
885         {
886             OIC_LOG_V(DEBUG, TAG, "OCCancel - %s : %d",
887                             pDev->endpoint.addr, pDev->endpoint.port);
888             if(OC_STACK_OK !=  OCCancel(pDev->handle,OC_HIGH_QOS,NULL,0))
889             {
890                 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
891             }
892         }
893         PMDeleteDeviceList(pDInfo->pCandidateList);
894     }
895     OIC_LOG(DEBUG, TAG, "OUT DeviceDiscoveryDeleteHandler");
896 }
897
898 /**
899  * Discover owned/unowned device in the specified endpoint/deviceID.
900  * It will return the found device even though timeout is not exceeded.
901  *
902  * @param[in] waittime           Timeout in seconds
903  * @param[in] deviceID           deviceID of target device.
904  * @param[out] ppFoundDevice     OCProvisionDev_t of found device
905  *
906  * @return OC_STACK_OK on success otherwise error.\n
907  *         OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not initailized.
908  */
909 OCStackResult PMSingleDeviceDiscovery(unsigned short waittime, const OicUuid_t* deviceID,
910                                  OCProvisionDev_t **ppFoundDevice)
911 {
912     OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscovery");
913
914     if (NULL != *ppFoundDevice)
915     {
916         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
917         return OC_STACK_INVALID_PARAM;
918     }
919
920     if (NULL == deviceID)
921     {
922         OIC_LOG(ERROR, TAG, "Invalid device ID");
923         return OC_STACK_INVALID_PARAM;
924     }
925
926
927     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
928     if(NULL == pDInfo)
929     {
930         OIC_LOG(ERROR, TAG, "PMSingleDeviceDiscovery : Memory allocation failed.");
931         return OC_STACK_NO_MEMORY;
932     }
933
934     pDInfo->ppDevicesList = ppFoundDevice;
935     pDInfo->pCandidateList = NULL;
936     pDInfo->isOwnedDiscovery = false;
937     pDInfo->isSingleDiscovery = true;
938     pDInfo->isFound = false;
939     pDInfo->targetId = deviceID;
940
941     OCCallbackData cbData;
942     cbData.cb = &DeviceDiscoveryHandler;
943     cbData.context = (void *)pDInfo;
944     cbData.cd = &DeviceDiscoveryDeleteHandler;
945
946     OCStackResult res = OC_STACK_ERROR;
947
948     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
949     snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "/oic/sec/doxm");
950
951     OCDoHandle handle = NULL;
952     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
953                                      CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
954     if (res != OC_STACK_OK)
955     {
956         OIC_LOG(ERROR, TAG, "OCStack resource error");
957         OICFree(pDInfo);
958         return res;
959     }
960
961     //Waiting for each response.
962     res = OC_STACK_OK;
963     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
964     while (OC_STACK_OK == res && !pDInfo->isFound)
965     {
966         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
967
968         long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
969         if (elapsed > waittime)
970         {
971             break;
972         }
973         res = OCProcess();
974     }
975
976     if(OC_STACK_OK != res)
977     {
978         OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
979         OICFree(pDInfo);
980         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
981         if(OC_STACK_OK !=  resCancel)
982         {
983             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
984         }
985         return res;
986     }
987
988     res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
989     if (OC_STACK_OK != res)
990     {
991         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
992         OICFree(pDInfo);
993         return res;
994     }
995     if (!pDInfo->isFound)
996     {
997         res = OC_STACK_TIMEOUT;
998     }
999     OICFree(pDInfo);
1000     OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscovery");
1001     return res;
1002 }
1003
1004 /**
1005  * Discover owned/unowned devices in the same IP subnet. .
1006  *
1007  * @param[in] waittime      Timeout in seconds.
1008  * @param[in] isOwned       bool flag for owned / unowned discovery
1009  * @param[in] ppDevicesList        List of OCProvisionDev_t.
1010  *
1011  * @return OC_STACK_OK on success otherwise error.
1012  */
1013 OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppDevicesList)
1014 {
1015     OIC_LOG(DEBUG, TAG, "IN PMDeviceDiscovery");
1016
1017     if (NULL != *ppDevicesList)
1018     {
1019         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1020         return OC_STACK_INVALID_PARAM;
1021     }
1022
1023     const char DOXM_OWNED_FALSE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=FALSE";
1024     const char DOXM_OWNED_TRUE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=TRUE";
1025
1026     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
1027     if(NULL == pDInfo)
1028     {
1029         OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
1030         return OC_STACK_NO_MEMORY;
1031     }
1032
1033     pDInfo->ppDevicesList = ppDevicesList;
1034     pDInfo->pCandidateList = NULL;
1035     pDInfo->isOwnedDiscovery = isOwned;
1036     pDInfo->isSingleDiscovery = false;
1037     pDInfo->targetId = NULL;
1038
1039     OCCallbackData cbData;
1040     cbData.cb = &DeviceDiscoveryHandler;
1041     cbData.context = (void *)pDInfo;
1042     cbData.cd = &DeviceDiscoveryDeleteHandler;
1043     OCStackResult res = OC_STACK_ERROR;
1044
1045     const char* query = isOwned ? DOXM_OWNED_TRUE_MULTICAST_QUERY :
1046                                   DOXM_OWNED_FALSE_MULTICAST_QUERY;
1047
1048     OCDoHandle handle = NULL;
1049     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1050                                      CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
1051     if (res != OC_STACK_OK)
1052     {
1053         OIC_LOG(ERROR, TAG, "OCStack resource error");
1054         OICFree(pDInfo);
1055         return res;
1056     }
1057
1058     //Waiting for each response.
1059     res = PMTimeout(waittime, true);
1060     if(OC_STACK_OK != res)
1061     {
1062         OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
1063         OICFree(pDInfo);
1064         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1065         if(OC_STACK_OK !=  resCancel)
1066         {
1067             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1068         }
1069         return res;
1070     }
1071     res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
1072     if (OC_STACK_OK != res)
1073     {
1074         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1075         OICFree(pDInfo);
1076         return res;
1077     }
1078     OIC_LOG(DEBUG, TAG, "OUT PMDeviceDiscovery");
1079     OICFree(pDInfo);
1080     return res;
1081 }
1082
1083 OCStackResult PMSingleDeviceDiscoveryInUnicast(unsigned short waittime, const OicUuid_t* deviceID,
1084                                  const char* hostAddress, OCConnectivityType connType,
1085                                  OCProvisionDev_t **ppFoundDevice)
1086 {
1087     OIC_LOG(DEBUG, TAG, "IN PMSingleDeviceDiscoveryInUnicast");
1088
1089     if (NULL != *ppFoundDevice)
1090     {
1091         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1092         return OC_STACK_INVALID_PARAM;
1093     }
1094
1095     if (NULL == deviceID)
1096     {
1097         OIC_LOG(ERROR, TAG, "Invalid device ID");
1098         return OC_STACK_INVALID_PARAM;
1099     }
1100
1101     DiscoveryInfo *pDInfo = (DiscoveryInfo*)OICCalloc(1, sizeof(DiscoveryInfo));
1102     if (NULL == pDInfo)
1103     {
1104         OIC_LOG(ERROR, TAG, "PMSingleDeviceDiscoveryInUnicast : Memory allocation failed.");
1105         return OC_STACK_NO_MEMORY;
1106     }
1107
1108     pDInfo->ppDevicesList = ppFoundDevice;
1109     pDInfo->pCandidateList = NULL;
1110     pDInfo->isOwnedDiscovery = false;
1111     pDInfo->isSingleDiscovery = true;
1112     pDInfo->isFound = false;
1113     pDInfo->targetId = deviceID;
1114
1115     OCCallbackData cbData;
1116     cbData.cb = &DeviceDiscoveryHandler;
1117     cbData.context = (void *)pDInfo;
1118     cbData.cd = &DeviceDiscoveryDeleteHandler;
1119
1120     OCStackResult res = OC_STACK_ERROR;
1121
1122     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1] = { '\0' };
1123     if (hostAddress == NULL)
1124     {
1125         hostAddress = "";
1126     }
1127     snprintf(query, MAX_URI_LENGTH + MAX_QUERY_LENGTH + 1, "%s/oic/sec/doxm", hostAddress);
1128     connType = connType & CT_MASK_ADAPTER;
1129
1130     OCDoHandle handle = NULL;
1131     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1132             connType, OC_HIGH_QOS, &cbData, NULL, 0);
1133
1134     if (res != OC_STACK_OK)
1135     {
1136         OIC_LOG(ERROR, TAG, "OCStack resource error");
1137         OICFree(pDInfo);
1138         pDInfo = NULL;
1139         return res;
1140     }
1141
1142     res = OC_STACK_OK;
1143     uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
1144     while (OC_STACK_OK == res && !pDInfo->isFound)
1145     {
1146         uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
1147
1148         long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
1149         if (elapsed > waittime)
1150         {
1151             break;
1152         }
1153         res = OCProcess();
1154     }
1155
1156     if (OC_STACK_OK != res)
1157     {
1158         OIC_LOG (ERROR, TAG, "Failed to wait response for secure discovery.");
1159         OICFree(pDInfo);
1160         pDInfo = NULL;
1161         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1162         if (OC_STACK_OK !=  resCancel)
1163         {
1164             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1165         }
1166         return res;
1167     }
1168
1169     res = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1170     if (OC_STACK_OK != res)
1171     {
1172         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1173         OICFree(pDInfo);
1174         pDInfo = NULL;
1175         return res;
1176     }
1177     OIC_LOG(DEBUG, TAG, "OUT PMSingleDeviceDiscoveryInUnicast");
1178
1179     if (!pDInfo->isFound)
1180     {
1181         res = OC_STACK_TIMEOUT;
1182     }
1183
1184     OICFree(pDInfo);
1185     pDInfo = NULL;
1186     return res;
1187 }
1188
1189 #ifdef MULTIPLE_OWNER
1190 static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
1191                                 OCClientResponse *clientResponse)
1192 {
1193     if (ctx == NULL)
1194     {
1195         OIC_LOG(ERROR, TAG, "Lost List of device information");
1196         return OC_STACK_KEEP_TRANSACTION;
1197     }
1198     (void)UNUSED;
1199     if (clientResponse)
1200     {
1201         if  (NULL == clientResponse->payload)
1202         {
1203             OIC_LOG(INFO, TAG, "Skipping Null payload");
1204             return OC_STACK_KEEP_TRANSACTION;
1205         }
1206         if (OC_STACK_OK != clientResponse->result)
1207         {
1208             OIC_LOG(INFO, TAG, "Error in response");
1209             return OC_STACK_KEEP_TRANSACTION;
1210         }
1211         else
1212         {
1213             if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
1214             {
1215                 OIC_LOG(INFO, TAG, "Unknown payload type");
1216                 return OC_STACK_KEEP_TRANSACTION;
1217             }
1218
1219             OicSecDoxm_t *ptrDoxm = NULL;
1220             uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
1221             size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
1222
1223             OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
1224             if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
1225             {
1226                 OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
1227                 return OC_STACK_KEEP_TRANSACTION;
1228             }
1229             else
1230             {
1231                 OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
1232
1233                 //If this is owend device discovery we have to filter out the responses.
1234                 DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
1235                 OCProvisionDev_t **ppDevicesList = &pDInfo->pCandidateList;
1236
1237                 // Get my device ID from doxm resource
1238                 OicUuid_t myId;
1239                 memset(&myId, 0, sizeof(myId));
1240                 OCStackResult res = GetDoxmDevOwnerId(&myId);
1241                 if(OC_STACK_OK != res)
1242                 {
1243                     OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
1244                     DeleteDoxmBinData(ptrDoxm);
1245                     return OC_STACK_KEEP_TRANSACTION;
1246                 }
1247
1248                 res = GetDoxmDeviceID(&myId);
1249                 if(OC_STACK_OK != res)
1250                 {
1251                     OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
1252                     DeleteDoxmBinData(ptrDoxm);
1253                     return OC_STACK_KEEP_TRANSACTION;
1254                 }
1255                 //if this is owned discovery and this is PT's reply, discard it
1256                 if((pDInfo->isOwnedDiscovery) &&
1257                         (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))) )
1258                 {
1259                     OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
1260                     DeleteDoxmBinData(ptrDoxm);
1261                     return OC_STACK_KEEP_TRANSACTION;
1262                 }
1263
1264                 if(pDInfo->isOwnedDiscovery)
1265                 {
1266                     OicSecSubOwner_t* subOwner = NULL;
1267                     LL_FOREACH(ptrDoxm->subOwners, subOwner)
1268                     {
1269                         if(memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
1270                         {
1271                             break;
1272                         }
1273                     }
1274
1275                     if(subOwner)
1276                     {
1277                         res = AddDevice(ppDevicesList, &clientResponse->devAddr,
1278                                 clientResponse->connType, ptrDoxm);
1279                         if (OC_STACK_OK != res)
1280                         {
1281                             OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
1282                             DeleteDoxmBinData(ptrDoxm);
1283                             return OC_STACK_KEEP_TRANSACTION;
1284                         }
1285
1286                         res = SecurePortDiscovery(pDInfo, clientResponse);
1287                         if(OC_STACK_OK != res)
1288                         {
1289                             OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
1290                             DeleteDoxmBinData(ptrDoxm);
1291                             return OC_STACK_KEEP_TRANSACTION;
1292                         }
1293                     }
1294                     else
1295                     {
1296                         OIC_LOG(ERROR, TAG, "discarding device's reply, because not a SubOwner.");
1297                         DeleteDoxmBinData(ptrDoxm);
1298                         return OC_STACK_KEEP_TRANSACTION;
1299                     }
1300                 }
1301                 else
1302                 {
1303                     if(ptrDoxm->mom && OIC_MULTIPLE_OWNER_DISABLE != ptrDoxm->mom->mode)
1304                     {
1305                         res = AddDevice(ppDevicesList, &clientResponse->devAddr,
1306                                 clientResponse->connType, ptrDoxm);
1307                         if (OC_STACK_OK != res)
1308                         {
1309                             OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
1310                             DeleteDoxmBinData(ptrDoxm);
1311                             return OC_STACK_KEEP_TRANSACTION;
1312                         }
1313
1314                         res = SecurePortDiscovery(pDInfo, clientResponse);
1315                         if(OC_STACK_OK != res)
1316                         {
1317                             OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
1318                             DeleteDoxmBinData(ptrDoxm);
1319                             return OC_STACK_KEEP_TRANSACTION;
1320                         }
1321                     }
1322                     else
1323                     {
1324                         OIC_LOG(ERROR, TAG, "discarding mom disabled device's reply");
1325                         DeleteDoxmBinData(ptrDoxm);
1326                         return OC_STACK_KEEP_TRANSACTION;
1327                     }
1328                 }
1329
1330                 OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
1331             }
1332
1333             return  OC_STACK_KEEP_TRANSACTION;
1334         }
1335     }
1336     else
1337     {
1338         OIC_LOG(INFO, TAG, "Skiping Null response");
1339         return OC_STACK_KEEP_TRANSACTION;
1340     }
1341
1342     return  OC_STACK_DELETE_TRANSACTION;
1343 }
1344
1345
1346 /**
1347  * Discover multiple OTM enabled devices in the same IP subnet.
1348  *
1349  * @param[in] waittime      Timeout in seconds.
1350  * @param[in] ppDevicesList        List of OCProvisionDev_t.
1351  *
1352  * @return OC_STACK_OK on success otherwise error.
1353  */
1354 OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList)
1355 {
1356     OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerEnabledDeviceDiscovery");
1357
1358     if (NULL != *ppDevicesList)
1359     {
1360         OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
1361         return OC_STACK_INVALID_PARAM;
1362     }
1363
1364     char DOXM_MOM_ENABLE_MULTICAST_QUERY[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1365     char DOXM_MULTIPLE_OWNED_MULTICAST_QUERY[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1366     snprintf(DOXM_MOM_ENABLE_MULTICAST_QUERY, sizeof(DOXM_MOM_ENABLE_MULTICAST_QUERY),
1367              "%s?%s=%d&%s=TRUE",
1368              OIC_RSRC_DOXM_URI, OIC_JSON_MOM_NAME, OIC_MULTIPLE_OWNER_DISABLE,
1369              OIC_JSON_OWNED_NAME);
1370     snprintf(DOXM_MULTIPLE_OWNED_MULTICAST_QUERY, sizeof(DOXM_MOM_ENABLE_MULTICAST_QUERY),
1371              "%s?%s=TRUE",
1372              OIC_RSRC_DOXM_URI, OIC_JSON_OWNED_NAME);
1373
1374     DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
1375     if(NULL == pDInfo)
1376     {
1377         OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
1378         return OC_STACK_NO_MEMORY;
1379     }
1380
1381     pDInfo->ppDevicesList = ppDevicesList;
1382     pDInfo->pCandidateList = NULL;
1383     pDInfo->isOwnedDiscovery = isMultipleOwned;
1384
1385     OCCallbackData cbData;
1386     cbData.cb = &MOTDeviceDiscoveryHandler;
1387     cbData.context = (void *)pDInfo;
1388     cbData.cd = NULL;
1389     OCStackResult res = OC_STACK_ERROR;
1390
1391     const char* query = isMultipleOwned ? DOXM_MULTIPLE_OWNED_MULTICAST_QUERY :
1392                                           DOXM_MOM_ENABLE_MULTICAST_QUERY;
1393
1394     OCDoHandle handle = NULL;
1395     res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
1396                                      CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
1397     if (res != OC_STACK_OK)
1398     {
1399         OIC_LOG(ERROR, TAG, "OCStack resource error");
1400         OICFree(pDInfo);
1401         return res;
1402     }
1403
1404     //Waiting for each response.
1405     res = PMTimeout(waittime, true);
1406     if(OC_STACK_OK != res)
1407     {
1408         OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
1409         OICFree(pDInfo);
1410         OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
1411         if(OC_STACK_OK !=  resCancel)
1412         {
1413             OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1414         }
1415         return res;
1416     }
1417     res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
1418     if (OC_STACK_OK != res)
1419     {
1420         OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1421         OICFree(pDInfo);
1422         return res;
1423     }
1424     OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerEnabledDeviceDiscovery");
1425     OICFree(pDInfo);
1426     return res;
1427 }
1428
1429 #endif //MULTIPLE_OWNER
1430
1431 static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
1432                                          const OCClientResponse *clientResponse)
1433 {
1434     OIC_LOG(DEBUG, TAG, "IN SecurePortDiscovery");
1435
1436     if(NULL == discoveryInfo || NULL == clientResponse)
1437     {
1438         return OC_STACK_INVALID_PARAM;
1439     }
1440
1441     OCProvisionDev_t *pDev = GetDevice(&discoveryInfo->pCandidateList,
1442                         clientResponse->devAddr.addr, clientResponse->devAddr.port);
1443     if(NULL == pDev)
1444     {
1445         OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to get device");
1446         return OC_STACK_ERROR;
1447     }
1448
1449     //Try to the unicast discovery to getting secure port
1450     char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
1451     if(!PMGenerateQuery(false,
1452                         pDev->endpoint.addr, pDev->endpoint.port,
1453                         pDev->connType,
1454                         query, sizeof(query), OC_RSRVD_WELL_KNOWN_URI))
1455     {
1456         OIC_LOG(ERROR, TAG, "SecurePortDiscovery : Failed to generate query");
1457         return OC_STACK_ERROR;
1458     }
1459     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1460
1461     // Set filter query with rt=oic.r.doxm
1462     const char RES_DOXM_QUERY_FMT[] = "%s?%s=%s";
1463     char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1464     snprintf(uri, sizeof(uri), RES_DOXM_QUERY_FMT, query,
1465             OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DOXM);
1466
1467     OIC_LOG_V(DEBUG, TAG, "URI=%s", uri);
1468
1469     OCCallbackData cbData;
1470     cbData.cb = &SecurePortDiscoveryHandler;
1471     cbData.context = (void*)discoveryInfo;
1472     cbData.cd = NULL;
1473     OCStackResult ret = OCDoResource(&pDev->handle, OC_REST_DISCOVER, uri, 0, 0,
1474             pDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1475     if(OC_STACK_OK != ret)
1476     {
1477         OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
1478         return ret;
1479     }
1480     else
1481     {
1482         OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
1483     }
1484
1485     OIC_LOG(DEBUG, TAG, "OUT SecurePortDiscovery");
1486
1487     return ret;
1488 }
1489
1490 /*
1491  * Since security version discovery does not used anymore, disable security version discovery.
1492  * Need to discussion to removing all version discovery related codes.
1493  */
1494 #if 0
1495 static OCStackResult SecurityVersionDiscovery(DiscoveryInfo* discoveryInfo,
1496                                               const OCClientResponse *clientResponse)
1497 {
1498     OIC_LOG(DEBUG, TAG, "IN SecurityVersionDiscovery");
1499
1500     if(NULL == discoveryInfo || NULL == clientResponse)
1501     {
1502         return OC_STACK_INVALID_PARAM;
1503     }
1504
1505     //Try to the unicast discovery to getting security version
1506     char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
1507     if(!PMGenerateQuery(false,
1508                         clientResponse->devAddr.addr, clientResponse->devAddr.port,
1509                         clientResponse->connType,
1510                         query, sizeof(query), OIC_RSRC_VER_URI))
1511     {
1512         OIC_LOG(ERROR, TAG, "SecurityVersionDiscovery : Failed to generate query");
1513         return OC_STACK_ERROR;
1514     }
1515     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1516
1517     OCCallbackData cbData;
1518     cbData.cb = &SecurityVersionDiscoveryHandler;
1519     cbData.context = (void*)discoveryInfo;
1520     cbData.cd = NULL;
1521     OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
1522             clientResponse->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1523     if(OC_STACK_OK != ret)
1524     {
1525         OIC_LOG(ERROR, TAG, "Failed to Security Version Discovery");
1526         return ret;
1527     }
1528     else
1529     {
1530         OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
1531     }
1532
1533     OIC_LOG(DEBUG, TAG, "OUT SecurityVersionDiscovery");
1534
1535     return ret;
1536 }
1537 #endif
1538
1539 /**
1540  * Function to print OCProvisionDev_t for debug purpose.
1541  *
1542  * @param[in] pDev Pointer to OCProvisionDev_t. It's information will be printed by OIC_LOG_XX
1543  *
1544  */
1545 void PMPrintOCProvisionDev(const OCProvisionDev_t* pDev)
1546 {
1547     if (pDev)
1548     {
1549         OIC_LOG(DEBUG, TAG, "+++++ OCProvisionDev_t Information +++++");
1550         OIC_LOG_V(DEBUG, TAG, "IP %s", pDev->endpoint.addr);
1551         OIC_LOG_V(DEBUG, TAG, "PORT %d", pDev->endpoint.port);
1552         OIC_LOG_V(DEBUG, TAG, "S-PORT %d", pDev->securePort);
1553         OIC_LOG(DEBUG, TAG, "++++++++++++++++++++++++++++++++++++++++");
1554     }
1555     else
1556     {
1557         OIC_LOG(DEBUG, TAG, "+++++ OCProvisionDev_t is NULL +++++");
1558     }
1559 }
1560
1561 bool PMDeleteFromUUIDList(OCUuidList_t **pUuidList, OicUuid_t *targetId)
1562 {
1563     if(*pUuidList == NULL || targetId == NULL)
1564     {
1565         return false;
1566     }
1567     OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
1568     LL_FOREACH_SAFE(*pUuidList, tmp1, tmp2)
1569     {
1570         if(0 == memcmp(tmp1->dev.id, targetId->id, sizeof(targetId->id)))
1571         {
1572             LL_DELETE(*pUuidList, tmp1);
1573             OICFree(tmp1);
1574             return true;
1575         }
1576     }
1577     return false;
1578 }