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