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