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