1 /* *****************************************************************
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * *****************************************************************/
20 #ifndef _POSIX_C_SOURCE
21 #define _POSIX_C_SOURCE 200112L
23 #include "iotivity_config.h"
30 #ifdef HAVE_SYS_TIME_H
38 #include "oic_malloc.h"
39 #include "oic_string.h"
43 #include "ocpayload.h"
44 #include "payload_logging.h"
45 #include "cainterface.h"
47 #include "directpairing.h"
48 #include "srmresourcestrings.h" //@note: SRM's internal header
49 #include "doxmresource.h" //@note: SRM's internal header
50 #include "pconfresource.h" //@note: SRM's internal header
51 #include "dpairingresource.h" //@note: SRM's internal header
52 #include "credresource.h"
55 #include "pmutility.h"
57 #include "srmutility.h"
64 #define TAG ("OIC_DP")
65 static const uint16_t CBOR_SIZE = 1024;
68 * Structure to carry direct-pairing API data to callback.
70 typedef struct DPairData
72 OCDirectPairingDev_t *peer; /**< Pointer to pairing target info.**/
73 char pin[DP_PIN_LENGTH]; /**< PIN **/
74 OCDirectPairingResultCB resultCallback; /**< Pointer to result callback.**/
75 void *userCtx; /** < user context to pass in callback **/
78 static OCDirectPairingDev_t *g_dp_paired = NULL;
79 static OCDirectPairingDev_t *g_dp_discover = NULL;
80 static DPairData_t *g_dp_proceed_ctx = NULL;
84 * Function to search node in linked list that matches given IP and port.
86 * @param[in] pList List of OCProvisionDev_t.
87 * @param[in] addr address of target device.
88 * @param[in] port port of remote server.
90 * @return pointer of OCProvisionDev_t if exist, otherwise NULL
92 OCDirectPairingDev_t* getDev(OCDirectPairingDev_t **ppList, const char* addr, const uint16_t port)
96 OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
100 OCDirectPairingDev_t *ptr = NULL;
101 LL_FOREACH(*ppList, ptr)
103 if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)
115 * Add device information to list.
117 * @param[in] pList List of OCProvisionDev_t.
118 * @param[in] addr address of target device.
119 * @param[in] port port of remote server.
120 * @param[in] adapter adapter type of endpoint.
121 * @param[in] doxm pointer to doxm instance.
122 * @param[in] connType connectivity type of endpoint
124 * @return OC_STACK_OK for success and errorcode otherwise.
126 OCStackResult addDev(OCDirectPairingDev_t **ppList, OCDevAddr *endpoint,
127 OCConnectivityType conn, OicSecPconf_t *pconf)
129 if(NULL == endpoint || NULL == pconf)
131 OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
132 return OC_STACK_INVALID_PARAM;
135 OCDirectPairingDev_t *ptr = getDev(ppList, endpoint->addr, endpoint->port);
138 ptr = (OCDirectPairingDev_t *)OICCalloc(1, sizeof (OCDirectPairingDev_t));
141 OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
142 return OC_STACK_NO_MEMORY;
145 memcpy(&ptr->endpoint, endpoint, sizeof(OCDevAddr));
146 ptr->connType = conn;
147 ptr->securePort = DEFAULT_SECURE_PORT;
148 ptr->edp = pconf->edp;
149 ptr->prm = pconf->prm;
150 pconf->prm = NULL; // to prevent free
151 ptr->prmLen = pconf->prmLen;
152 memcpy(&ptr->deviceID, &pconf->deviceID, sizeof(OicUuid_t));
153 memcpy(&ptr->rowner, &pconf->rownerID, sizeof(OicUuid_t));
156 LL_PREPEND(*ppList, ptr);
157 OIC_LOG(INFO, TAG, "device added !");
165 * Add device information to list.
167 * @param[in] ppList List of OCProvisionDev_t.
168 * @param[in] pDev target device.
170 * @return OC_STACK_OK for success and errorcode otherwise.
172 OCStackResult addDev2(OCDirectPairingDev_t **ppList, OCDirectPairingDev_t *pDev)
176 OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
177 return OC_STACK_INVALID_PARAM;
180 OCDirectPairingDev_t *ptr = getDev(ppList, pDev->endpoint.addr, pDev->endpoint.port);
183 ptr = (OCDirectPairingDev_t *)OICCalloc(1, sizeof (OCDirectPairingDev_t));
186 OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
187 return OC_STACK_NO_MEMORY;
190 memcpy(&ptr->endpoint, &pDev->endpoint, sizeof(OCDevAddr));
191 ptr->connType = pDev->connType;
192 ptr->securePort = pDev->securePort;
193 ptr->edp = pDev->edp;
194 ptr->prmLen = pDev->prmLen;
195 ptr->prm = (OicSecPrm_t*)OICCalloc(ptr->prmLen, sizeof (OicSecPrm_t));
196 if (NULL == ptr->prm)
198 OIC_LOG(ERROR, TAG, "Error while allocating memory for prm !!");
199 return OC_STACK_NO_MEMORY;
201 memcpy(ptr->prm, pDev->prm, sizeof(OicSecPrm_t)*ptr->prmLen);
202 memcpy(&ptr->deviceID, &pDev->deviceID, sizeof(OicUuid_t));
203 memcpy(&ptr->rowner, &pDev->rowner, sizeof(OicUuid_t));
206 LL_PREPEND(*ppList, ptr);
207 OIC_LOG(INFO, TAG, "device added !");
216 * This function deletes list of provision target devices
218 * @param[in] pDevicesList List of OCProvisionDev_t.
220 void delList(OCDirectPairingDev_t *pList)
224 OCDirectPairingDev_t *del = NULL, *tmp = NULL;
225 LL_FOREACH_SAFE(pList, del, tmp)
227 LL_DELETE(pList, del);
236 bool DPGenerateQuery(bool isSecure,
237 const char* address, const uint16_t port,
238 const OCConnectivityType connType,
239 char* buffer, size_t bufferSize, const char* uri)
241 if(!address || !buffer || !uri)
243 OIC_LOG(ERROR, TAG, "DPGenerateQuery : Invalid parameters.");
247 static char QPREFIX_COAP[] = "coap://";
248 static char QPREFIX_COAPS[] = "coaps://";
249 static char QPREFIX_COAP_TCP[] = "coap+tcp://";
250 static char QPREFIX_COAPS_TCP[] = "coaps+tcp://";
253 char* prefix = (isSecure == true) ? QPREFIX_COAPS : QPREFIX_COAP;
255 switch(connType & CT_MASK_ADAPTER)
257 // @todo: Remove this ifdef. On Arduino, CT_ADAPTER_TCP resolves to the same value
258 // as CT_ADAPTER_IP, resulting in a compiler error.
262 prefix = (isSecure == true) ? QPREFIX_COAPS_TCP : QPREFIX_COAP_TCP;
266 switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)
269 snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",
270 prefix, address, port, uri);
274 char addressEncoded[CA_MAX_URI_LENGTH] = {0};
276 OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
277 sizeof(addressEncoded),
279 if (OC_STACK_OK != result)
281 OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : encoding error %d\n", result);
285 snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",
286 prefix, addressEncoded, port, uri);
290 OIC_LOG(ERROR, TAG, "Unknown address format.");
293 // snprintf return value check
296 OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : Error (snprintf) %d\n", snRet);
299 else if ((size_t)snRet >= bufferSize)
301 OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : Truncated (snprintf) %d\n", snRet);
307 // TODO: We need to verify tinyDTLS in below cases
308 case CT_ADAPTER_GATT_BTLE:
309 case CT_ADAPTER_RFCOMM_BTEDR:
310 OIC_LOG(ERROR, TAG, "Not supported connectivity adapter.");
315 OIC_LOG(ERROR, TAG, "Unknown connectivity adapter.");
322 const OCDirectPairingDev_t* DPGetDiscoveredDevices()
324 return g_dp_discover;
327 const OCDirectPairingDev_t* DPGetPairedDevices()
334 delList(g_dp_discover);
335 delList(g_dp_paired);
339 * Callback handler of FinalizeDirectPairing.
341 * @param[in] ctx ctx value passed to callback from calling function.
342 * @param[in] UNUSED handle to an invocation
343 * @param[in] clientResponse Response from queries to remote servers.
344 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
345 * and OC_STACK_KEEP_TRANSACTION to keep it.
347 static OCStackApplicationResult DirectPairingFinalizeHandler(void *ctx, OCDoHandle UNUSED,
348 OCClientResponse *clientResponse)
350 OIC_LOG_V(INFO, TAG, "IN DirectPairingFinalizeHandler()");
354 OIC_LOG(ERROR, TAG, "Context is Null");
355 return OC_STACK_DELETE_TRANSACTION;
359 DPairData_t *dpairData = (DPairData_t*)ctx;
360 OCDirectPairingDev_t *peer = dpairData->peer;
361 OCDirectPairingResultCB resultCallback = dpairData->resultCallback;
365 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
368 OIC_LOG(INFO, TAG, "DirectPairingFinalizeHandler : success PUT"
369 " request to /oic/sec/dpairing");
371 CAEndpoint_t endpoint;
372 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
373 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peer->endpoint.addr);
374 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
375 endpoint.port = peer->securePort;
377 OicUuid_t ptDeviceID = {.id={0}};
378 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
380 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
381 resultCallback(dpairData->userCtx, peer, OC_STACK_ERROR);
382 return OC_STACK_DELETE_TRANSACTION;
385 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
386 res = SavePairingPSK((OCDevAddr*)&endpoint, &peer->deviceID, &ptDeviceID, false);
387 if(OC_STACK_OK != res)
389 OIC_LOG(ERROR, TAG, "Failed to PairingPSK generation");
390 resultCallback(dpairData->userCtx, peer, res);
391 return OC_STACK_DELETE_TRANSACTION;
394 // close temporary sesion
395 CAResult_t caResult = CAcloseSslSession((const CAEndpoint_t*)&endpoint);
396 if(CA_STATUS_OK != caResult)
398 OIC_LOG(INFO, TAG, "Fail to close temporary dtls session");
401 caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL, CA_ADAPTER_IP);
402 if(CA_STATUS_OK != caResult)
404 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
406 #endif // __WITH_DTLS__ or __WITH_TLS__
408 OIC_LOG(INFO, TAG, "Direct-Papring was successfully completed.");
410 // update paired list
411 OCDirectPairingDev_t *dev = getDev(&g_dp_discover, peer->endpoint.addr,
412 peer->endpoint.port);
413 res = addDev2(&g_dp_paired, dev);
414 if (OC_STACK_OK != res)
416 OIC_LOG(ERROR, TAG, "Error while adding a device to paired list.");
419 resultCallback(dpairData->userCtx, peer, OC_STACK_OK);
421 return OC_STACK_DELETE_TRANSACTION;
425 OIC_LOG(INFO, TAG, "Direct-Papring received error response.");
430 OIC_LOG(ERROR, TAG, "DirectPairingFinalizeHandler received Null clientResponse");
433 resultCallback(dpairData->userCtx, peer, OC_STACK_ERROR);
435 return OC_STACK_DELETE_TRANSACTION;
439 * Finalize direct-pairing .
441 * @param[in] peer target device to establish direct-pairing.
442 * @param[in] resultCallback result event callback.
444 * @return OC_STACK_OK on success otherwise error.
446 OCStackResult FinalizeDirectPairing(void *ctx, OCDirectPairingDev_t* peer,
447 OCDirectPairingResultCB resultCallback)
451 return OC_STACK_INVALID_PARAM;
454 OicUuid_t deviceID = {.id={0}};
455 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
457 OIC_LOG(ERROR, TAG, "Error while retrieving device ID");
458 return OC_STACK_ERROR;
461 OicSecDpairing_t dpair;
462 memset(&dpair, 0, sizeof(OicSecDpairing_t));
463 dpair.spm = (OicSecPrm_t)PRM_NOT_ALLOWED;
464 memcpy(&dpair.pdeviceID, &deviceID, sizeof(OicUuid_t));
466 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
469 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
470 return OC_STACK_NO_MEMORY;
472 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
474 OCStackResult ret = DpairingToCBORPayload(&dpair, &(secPayload->securityData),
475 &(secPayload->payloadSize));
477 if(OC_STACK_OK != ret)
480 OIC_LOG(ERROR, TAG, "Failed to DpairingToCBORPayload");
481 return OC_STACK_NO_MEMORY;
483 OIC_LOG(DEBUG, TAG, "DPARING CBOR data:");
484 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
486 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
487 if(!DPGenerateQuery(true,
491 query, sizeof(query), OIC_RSRC_DPAIRING_URI))
493 OIC_LOG(ERROR, TAG, "DPDirectPairing : Failed to generate query");
494 return OC_STACK_ERROR;
496 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
498 DPairData_t *dpairData = (DPairData_t *) OICCalloc(1, sizeof(DPairData_t));
499 if (dpairData == NULL)
501 OICFree(secPayload->securityData);
503 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
504 return OC_STACK_NO_MEMORY;
506 dpairData->peer = peer;
507 dpairData->resultCallback = resultCallback;
508 dpairData->userCtx = ctx;
510 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
511 cbData.cb = DirectPairingFinalizeHandler;
512 cbData.context = (void*)dpairData;
515 OCMethod method = OC_REST_PUT;
516 OCDoHandle handle = NULL;
517 OIC_LOG(DEBUG, TAG, "Sending DPAIRNG setting to resource server");
518 ret = OCDoResource(&handle, method, query,
519 &peer->endpoint, (OCPayload*)secPayload,
520 peer->connType, OC_LOW_QOS, &cbData, NULL, 0);
521 if(OC_STACK_OK != ret)
523 OIC_LOG(ERROR, TAG, "error in OCDoResource");
524 return OC_STACK_ERROR;
531 * Function to handle the handshake result in Direct-Pairing.
532 * This function will be invoked after DTLS handshake
533 * @param endPoint [IN] The remote endpoint.
534 * @param errorInfo [IN] Error information from the endpoint.
537 void DirectPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
539 OIC_LOG_V(INFO, TAG, "IN DirectPairingDTLSHandshakeCB");
542 if(g_dp_proceed_ctx && g_dp_proceed_ctx->peer && endpoint && info)
544 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
545 endpoint->addr, endpoint->port, info->result);
547 OCDirectPairingDev_t *peer = g_dp_proceed_ctx->peer;
548 OCDirectPairingResultCB resultCallback = g_dp_proceed_ctx->resultCallback;
551 //Make sure the address matches.
552 if(strncmp(peer->endpoint.addr, endpoint->addr, sizeof(endpoint->addr)) == 0 &&
553 peer->securePort == endpoint->port)
555 //In case of success, send next coaps request.
556 if(CA_STATUS_OK == info->result)
558 OIC_LOG(INFO, TAG, "Now, finalize Direct-Pairing procedure.");
560 res = FinalizeDirectPairing(g_dp_proceed_ctx->userCtx, peer, resultCallback);
561 if(OC_STACK_OK != res)
563 OIC_LOG(ERROR, TAG, "Failed to finalize direct-pairing");
564 resultCallback(g_dp_proceed_ctx->userCtx, peer, res);
567 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
569 OIC_LOG(INFO, TAG, "DirectPairingDTLSHandshakeCB - Authentication failed");
570 resultCallback(g_dp_proceed_ctx->userCtx, peer, OC_STACK_AUTHENTICATION_FAILURE);
573 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
574 CAregisterSslHandshakeCallback(NULL);
575 #endif // __WITH_DTLS__ or __WITH_TLS__
576 res = RemoveCredential(&peer->deviceID);
577 if(OC_STACK_RESOURCE_DELETED != res)
579 OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
582 OICFree(g_dp_proceed_ctx);
583 g_dp_proceed_ctx = NULL;
587 OIC_LOG_V(INFO, TAG, "DirectPairingDTLSHandshakeCB - Not matched to peer address");
591 OIC_LOG_V(INFO, TAG, "OUT DirectPairingDTLSHandshakeCB");
595 * Callback handler of DPDirectPairing.
597 * @param[in] ctx ctx value passed to callback from calling function.
598 * @param[in] UNUSED handle to an invocation
599 * @param[in] clientResponse Response from queries to remote servers.
600 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
601 * and OC_STACK_KEEP_TRANSACTION to keep it.
603 static OCStackApplicationResult DirectPairingHandler(void *ctx, OCDoHandle UNUSED,
604 OCClientResponse *clientResponse)
606 OIC_LOG_V(INFO, TAG, "IN DirectPairingHandler.");
610 OIC_LOG(ERROR, TAG, "Context is Null");
611 return OC_STACK_DELETE_TRANSACTION;
614 OCStackResult res = OC_STACK_ERROR;
615 DPairData_t *dpairData = (DPairData_t*)ctx;
616 OCDirectPairingResultCB resultCallback = (OCDirectPairingResultCB)dpairData->resultCallback;
617 OicUuid_t subjectId = {.id={0}};
621 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
624 OIC_LOG(INFO, TAG, "DirectPairingHandler : success POST request to /oic/sec/dpairing");
626 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
628 res = AddTmpPskWithPIN(&dpairData->peer->deviceID,
629 SYMMETRIC_PAIR_WISE_KEY,
630 (char*)dpairData->pin, DP_PIN_LENGTH,
631 &dpairData->peer->rowner, &subjectId);
632 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
635 // Start to establish a secure channel with Pin-based PSK cipher suite
638 caresult = CAEnableAnonECDHCipherSuite(false);
639 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
641 caresult = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
642 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
644 //Register proceeding peer info. & DTLS event handler to catch the dtls event while handshake
645 g_dp_proceed_ctx = dpairData;
646 res = CAregisterSslHandshakeCallback(DirectPairingDTLSHandshakeCB);
647 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
650 CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
651 VERIFY_NON_NULL(TAG, endpoint, FATAL);
652 memcpy(endpoint,&dpairData->peer->endpoint,sizeof(CAEndpoint_t));
653 endpoint->port = dpairData->peer->securePort;
654 OIC_LOG_V(INFO, TAG, "Initiate DTLS handshake to %s(%d)", endpoint->addr,
657 caresult = CAInitiateHandshake(endpoint);
659 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
660 #endif // __WITH_DTLS__ or __WITH_TLS__
667 OIC_LOG(INFO, TAG, "DirectPairingHandler : fail POST request to /oic/sec/dpairing");
672 OIC_LOG(ERROR, TAG, "DirectPairingHandler received Null clientResponse");
675 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
677 #endif // __WITH_DTLS__ or __WITH_TLS__
679 if (OC_STACK_OK != res)
681 if (0 < strlen((const char*)subjectId.id))
683 RemoveCredential(&dpairData->peer->deviceID);
685 g_dp_proceed_ctx = NULL;
688 resultCallback(dpairData->userCtx, dpairData->peer, res);
690 OIC_LOG_V(INFO, TAG, "OUT DirectPairingHandler.");
691 return OC_STACK_DELETE_TRANSACTION;
695 * Start direct-pairing .
697 * @param[in] peer target device to establish direct-pairing.
698 * @param[in] pmSel selected pairing method.
699 * @param[in] pinNumber secret value for dtls connection.
701 * @return OC_STACK_OK on success otherwise error.
703 OCStackResult DPDirectPairing(void *ctx, OCDirectPairingDev_t* peer, OicSecPrm_t pmSel,
704 char *pinNumber, OCDirectPairingResultCB resultCallback)
706 if(NULL == peer || NULL == pinNumber)
708 return OC_STACK_INVALID_PARAM;
711 OicUuid_t deviceID = {.id={0}};
712 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
714 OIC_LOG(ERROR, TAG, "Error while retrieving device ID");
715 return OC_STACK_ERROR;
718 OicSecDpairing_t dpair;
719 memset(&dpair, 0, sizeof(OicSecDpairing_t));
721 memcpy(&dpair.pdeviceID, &deviceID, sizeof(OicUuid_t));
723 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
726 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
727 return OC_STACK_NO_MEMORY;
729 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
731 OCStackResult ret = DpairingToCBORPayload(&dpair, &(secPayload->securityData),
732 &(secPayload->payloadSize));
734 if(OC_STACK_OK != ret)
737 OIC_LOG(ERROR, TAG, "Failed to DpairingToCBORPayload");
738 return OC_STACK_NO_MEMORY;
740 OIC_LOG(DEBUG, TAG, "DPARING CBOR data:");
741 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
743 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
744 if(!DPGenerateQuery(false,
749 query, sizeof(query), OIC_RSRC_DPAIRING_URI))
751 OIC_LOG(ERROR, TAG, "DPDirectPairing : Failed to generate query");
752 return OC_STACK_ERROR;
754 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
756 DPairData_t *dpairData = (DPairData_t *) OICCalloc(1, sizeof(DPairData_t));
757 if (dpairData == NULL)
759 OICFree(secPayload->securityData);
761 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
762 return OC_STACK_NO_MEMORY;
764 dpairData->peer = peer;
765 memcpy(dpairData->pin, pinNumber, DP_PIN_LENGTH);
766 dpairData->resultCallback = resultCallback;
767 dpairData->userCtx = ctx;
769 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
770 cbData.cb = DirectPairingHandler;
771 cbData.context = (void*)dpairData;
774 OCMethod method = OC_REST_POST;
775 OCDoHandle handle = NULL;
776 OIC_LOG(DEBUG, TAG, "Sending DPAIRNG setting to resource server");
777 ret = OCDoResource(&handle, method, query,
778 &peer->endpoint, (OCPayload*)secPayload,
779 peer->connType, OC_LOW_QOS, &cbData, NULL, 0);
780 if(OC_STACK_OK != ret)
782 OIC_LOG(ERROR, TAG, "error in OCDoResource");
783 return OC_STACK_ERROR;
791 * Callback handler for getting secure port information using /oic/res discovery.
793 * @param[in] ctx user context
794 * @param[in] handle Handle for response
795 * @param[in] clientResponse Response information(It will contain payload)
797 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
798 * OC_STACK_DELETE_TRANSACTION to delete it.
800 static OCStackApplicationResult DirectPairingPortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
801 OCClientResponse *clientResponse)
803 OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing Secure Port DISCOVER "
804 "query recvd successfully");
810 if (NULL == clientResponse->payload)
812 OIC_LOG(INFO, TAG, "Skiping Null payload");
816 if (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)
818 OIC_LOG(INFO, TAG, "Wrong payload type");
819 return OC_STACK_DELETE_TRANSACTION;
822 uint16_t securePort = 0;
823 OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
824 OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
826 if (resPayload && resPayload->secure)
828 securePort = resPayload->port;
832 OIC_LOG(INFO, TAG, "Can not find secure port information.");
833 return OC_STACK_DELETE_TRANSACTION;
836 OCDirectPairingDev_t *ptr = getDev(&g_dp_discover,
837 clientResponse->devAddr.addr, clientResponse->devAddr.port);
840 OIC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");
841 return OC_STACK_DELETE_TRANSACTION;
843 ptr->securePort = securePort;
845 OIC_LOG(INFO, TAG, "Exiting DirectPairingPortDiscoveryHandler.");
848 return OC_STACK_DELETE_TRANSACTION;
852 OIC_LOG(INFO, TAG, "Skiping Null response");
854 return OC_STACK_DELETE_TRANSACTION;
858 * Callback handler for DPDeviceDiscovery API.
860 * @param[in] ctx User context
861 * @param[in] handle Handler for response
862 * @param[in] clientResponse Response information (It will contain payload)
863 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
864 * OC_STACK_DELETE_TRANSACTION to delete it.
866 static OCStackApplicationResult DirectPairingDiscoveryHandler(void* ctx, OCDoHandle UNUSED,
867 OCClientResponse * clientResponse)
869 OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing DISCOVER query recvd successfully");
875 OIC_LOG_V(INFO, TAG, "StackResult: %d", clientResponse->result);
877 "Device =============> Discovered @ %s:%d",
878 clientResponse->devAddr.addr,
879 clientResponse->devAddr.port);
881 if (NULL == clientResponse->payload)
883 OIC_LOG(INFO, TAG, "Skiping Null payload");
884 return OC_STACK_KEEP_TRANSACTION;
886 if (OC_STACK_OK != clientResponse->result)
888 OIC_LOG(INFO, TAG, "Error in response");
889 return OC_STACK_KEEP_TRANSACTION;
892 OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
893 OicSecPconf_t *pconf = NULL;
895 OCStackResult res = CBORPayloadToPconf(
896 ((OCSecurityPayload*)clientResponse->payload)->securityData,
898 if (OC_STACK_OK != res )
900 OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
901 return OC_STACK_KEEP_TRANSACTION;
908 memcpy(&endpoint, &clientResponse->devAddr, sizeof(OCDevAddr));
910 OCStackResult res = addDev(&g_dp_discover, &endpoint,
911 clientResponse->connType, pconf);
912 DeletePconfBinData(pconf);
913 if (OC_STACK_OK != res)
915 OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
916 return OC_STACK_KEEP_TRANSACTION;
920 char rsrc_uri[MAX_URI_LENGTH+1] = {0};
921 int wr_len = snprintf(rsrc_uri, sizeof(rsrc_uri), "%s?%s=%s",
922 OC_RSRVD_WELL_KNOWN_URI, OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DPAIRING);
923 if(wr_len <= 0 || (size_t)wr_len >= sizeof(rsrc_uri))
925 OIC_LOG(ERROR, TAG, "rsrc_uri_string_print failed");
926 return OC_STACK_KEEP_TRANSACTION;
929 //Try to the unicast discovery to getting secure port
930 char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
931 if(!DPGenerateQuery(false,
932 clientResponse->devAddr.addr, clientResponse->devAddr.port,
933 clientResponse->connType,
934 query, sizeof(query), rsrc_uri))
936 OIC_LOG(ERROR, TAG, "DirectPairingDiscoveryHandler : Failed to generate query");
937 return OC_STACK_KEEP_TRANSACTION;
939 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
941 OCCallbackData cbData;
942 cbData.cb = &DirectPairingPortDiscoveryHandler;
943 cbData.context = NULL;
945 OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
946 clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0);
947 if(OC_STACK_OK != ret)
949 OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
950 return OC_STACK_KEEP_TRANSACTION;
954 OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
957 return OC_STACK_KEEP_TRANSACTION;
962 OIC_LOG(INFO, TAG, "Skiping Null response");
965 return OC_STACK_DELETE_TRANSACTION;
969 * Discover direct-pairing devices in the same IP subnet. .
971 * @param[in] waittime Timeout in seconds.
973 * @return OC_STACK_OK on success otherwise error.
975 OCStackResult DPDeviceDiscovery(unsigned short waittime)
977 OIC_LOG(DEBUG, TAG, "IN DPDeviceDiscovery");
981 delList(g_dp_discover);
982 g_dp_discover = NULL;
987 const char DP_DISCOVERY_QUERY[] = "/oic/sec/pconf";
989 OCCallbackData cbData;
990 cbData.cb = DirectPairingDiscoveryHandler;
991 cbData.context = NULL;
994 /* Start a DP discovery query*/
995 OIC_LOG_V(INFO, TAG, "Initiating Direct-Pairing Discovery : %s\n", DP_DISCOVERY_QUERY);
996 OCDoHandle handle = NULL;
997 ret = OCDoResource(&handle, OC_REST_DISCOVER, DP_DISCOVERY_QUERY, 0, 0, CT_DEFAULT,
998 OC_LOW_QOS, &cbData, NULL, 0);
999 if (ret != OC_STACK_OK)
1001 OIC_LOG(ERROR, TAG, "OCStack resource error");
1008 #if defined(_MSC_VER)
1009 time_t startTime = NULL;
1010 clock_res = (time(&startTime) == -1);
1012 struct timespec startTime = {.tv_sec=0, .tv_nsec=0};
1013 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
1014 clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
1019 OIC_LOG(ERROR, TAG, "clock error");
1020 if(OC_STACK_OK != OCCancel(handle, OC_LOW_QOS, NULL, 0))
1022 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1024 return OC_STACK_ERROR;
1029 #if defined(_MSC_VER)
1030 time_t currTime = NULL;
1031 clock_res = (time(&currTime) == -1);
1033 struct timespec currTime = {.tv_sec=0, .tv_nsec=0};
1034 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
1035 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
1040 OIC_LOG(ERROR, TAG, "clock error");
1041 ret = OC_STACK_ERROR;
1044 #if defined(_MSC_VER)
1045 long elapsed = currTime - startTime;
1047 long elapsed = (currTime.tv_sec - startTime.tv_sec);
1049 if (elapsed > waittime)
1055 struct timespec timeout = {.tv_sec=0, .tv_nsec=100000000L};
1057 nanosleep(&timeout, NULL);
1061 // Waiting for each response.
1062 ret = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1063 if (OC_STACK_OK != ret)
1065 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1067 OIC_LOG(DEBUG, TAG, "OUT DPDeviceDiscovery");