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"
41 #if defined (__TIZENRT__)
42 #include <apps/netutils/cJSON.h>
47 #include "ocpayload.h"
48 #include "payload_logging.h"
49 #include "cainterface.h"
51 #include "directpairing.h"
52 #include "srmresourcestrings.h" //@note: SRM's internal header
53 #include "doxmresource.h" //@note: SRM's internal header
54 #include "pconfresource.h" //@note: SRM's internal header
55 #include "dpairingresource.h" //@note: SRM's internal header
56 #include "credresource.h"
59 #include "pmutility.h"
61 #include "srmutility.h"
63 #define TAG ("OIC_DP")
64 static const uint16_t CBOR_SIZE = 1024;
67 * Structure to carry direct-pairing API data to callback.
69 typedef struct DPairData
71 OCDirectPairingDev_t *peer; /**< Pointer to pairing target info.**/
72 char pin[DP_PIN_LENGTH]; /**< PIN **/
73 OCDirectPairingResultCB resultCallback; /**< Pointer to result callback.**/
74 void *userCtx; /** < user context to pass in callback **/
77 static OCDirectPairingDev_t *g_dp_paired = NULL;
78 static OCDirectPairingDev_t *g_dp_discover = NULL;
79 static DPairData_t *g_dp_proceed_ctx = NULL;
83 * Function to search node in linked list that matches given IP and port.
85 * @param[in] pList List of OCProvisionDev_t.
86 * @param[in] addr address of target device.
87 * @param[in] port port of remote server.
89 * @return pointer of OCProvisionDev_t if exist, otherwise NULL
91 OCDirectPairingDev_t* getDev(OCDirectPairingDev_t **ppList, const char* addr, const uint16_t port)
95 OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
99 OCDirectPairingDev_t *ptr = NULL;
100 LL_FOREACH(*ppList, ptr)
102 if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)
114 * Add device information to list.
116 * @param[in] pList List of OCProvisionDev_t.
117 * @param[in] addr address of target device.
118 * @param[in] port port of remote server.
119 * @param[in] adapter adapter type of endpoint.
120 * @param[in] doxm pointer to doxm instance.
121 * @param[in] connType connectivity type of endpoint
123 * @return OC_STACK_OK for success and errorcode otherwise.
125 OCStackResult addDev(OCDirectPairingDev_t **ppList, OCDevAddr *endpoint,
126 OCConnectivityType conn, OicSecPconf_t *pconf)
128 if(NULL == endpoint || NULL == pconf)
130 OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
131 return OC_STACK_INVALID_PARAM;
134 OCDirectPairingDev_t *ptr = getDev(ppList, endpoint->addr, endpoint->port);
137 ptr = (OCDirectPairingDev_t *)OICCalloc(1, sizeof (OCDirectPairingDev_t));
140 OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
141 return OC_STACK_NO_MEMORY;
144 memcpy(&ptr->endpoint, endpoint, sizeof(OCDevAddr));
145 ptr->connType = conn;
146 ptr->securePort = DEFAULT_SECURE_PORT;
147 ptr->edp = pconf->edp;
148 ptr->prm = pconf->prm;
149 pconf->prm = NULL; // to prevent free
150 ptr->prmLen = pconf->prmLen;
151 memcpy(&ptr->deviceID, &pconf->deviceID, sizeof(OicUuid_t));
152 memcpy(&ptr->rowner, &pconf->rownerID, sizeof(OicUuid_t));
155 LL_PREPEND(*ppList, ptr);
156 OIC_LOG(INFO, TAG, "device added !");
164 * Add device information to list.
166 * @param[in] ppList List of OCProvisionDev_t.
167 * @param[in] pDev target device.
169 * @return OC_STACK_OK for success and errorcode otherwise.
171 OCStackResult addDev2(OCDirectPairingDev_t **ppList, OCDirectPairingDev_t *pDev)
175 OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
176 return OC_STACK_INVALID_PARAM;
179 OCDirectPairingDev_t *ptr = getDev(ppList, pDev->endpoint.addr, pDev->endpoint.port);
182 ptr = (OCDirectPairingDev_t *)OICCalloc(1, sizeof (OCDirectPairingDev_t));
185 OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
186 return OC_STACK_NO_MEMORY;
189 memcpy(&ptr->endpoint, &pDev->endpoint, sizeof(OCDevAddr));
190 ptr->connType = pDev->connType;
191 ptr->securePort = pDev->securePort;
192 ptr->edp = pDev->edp;
193 ptr->prmLen = pDev->prmLen;
194 ptr->prm = (OicSecPrm_t*)OICCalloc(ptr->prmLen, sizeof (OicSecPrm_t));
195 if (NULL == ptr->prm)
197 OIC_LOG(ERROR, TAG, "Error while allocating memory for prm !!");
198 return OC_STACK_NO_MEMORY;
200 memcpy(ptr->prm, pDev->prm, sizeof(OicSecPrm_t)*ptr->prmLen);
201 memcpy(&ptr->deviceID, &pDev->deviceID, sizeof(OicUuid_t));
202 memcpy(&ptr->rowner, &pDev->rowner, sizeof(OicUuid_t));
205 LL_PREPEND(*ppList, ptr);
206 OIC_LOG(INFO, TAG, "device added !");
215 * This function deletes list of provision target devices
217 * @param[in] pDevicesList List of OCProvisionDev_t.
219 void delList(OCDirectPairingDev_t *pList)
223 OCDirectPairingDev_t *del = NULL, *tmp = NULL;
224 LL_FOREACH_SAFE(pList, del, tmp)
226 LL_DELETE(pList, del);
235 bool DPGenerateQuery(bool isSecure,
236 const char* address, const uint16_t port,
237 const OCConnectivityType connType,
238 char* buffer, size_t bufferSize, const char* uri)
240 if(!address || !buffer || !uri)
242 OIC_LOG(ERROR, TAG, "DPGenerateQuery : Invalid parameters.");
246 static char QPREFIX_COAP[] = "coap://";
247 static char QPREFIX_COAPS[] = "coaps://";
248 static char QPREFIX_COAP_TCP[] = "coap+tcp://";
249 static char QPREFIX_COAPS_TCP[] = "coaps+tcp://";
252 char* prefix = (isSecure == true) ? QPREFIX_COAPS : QPREFIX_COAP;
254 switch(connType & CT_MASK_ADAPTER)
256 // @todo: Remove this ifdef. On Arduino, CT_ADAPTER_TCP resolves to the same value
257 // as CT_ADAPTER_IP, resulting in a compiler error.
261 prefix = (isSecure == true) ? QPREFIX_COAPS_TCP : QPREFIX_COAP_TCP;
265 switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)
268 snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",
269 prefix, address, port, uri);
273 char addressEncoded[CA_MAX_URI_LENGTH] = {0};
275 OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
276 sizeof(addressEncoded),
278 if (OC_STACK_OK != result)
280 OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : encoding error %d\n", result);
284 snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",
285 prefix, addressEncoded, port, uri);
289 OIC_LOG(ERROR, TAG, "Unknown address format.");
292 // snprintf return value check
295 OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : Error (snprintf) %d\n", snRet);
298 else if ((size_t)snRet >= bufferSize)
300 OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : Truncated (snprintf) %d\n", snRet);
306 // TODO: We need to verify tinyDTLS in below cases
307 case CT_ADAPTER_GATT_BTLE:
308 case CT_ADAPTER_RFCOMM_BTEDR:
309 OIC_LOG(ERROR, TAG, "Not supported connectivity adapter.");
314 OIC_LOG(ERROR, TAG, "Unknown connectivity adapter.");
321 const OCDirectPairingDev_t* DPGetDiscoveredDevices()
323 return g_dp_discover;
326 const OCDirectPairingDev_t* DPGetPairedDevices()
333 delList(g_dp_discover);
334 delList(g_dp_paired);
338 * Callback handler of FinalizeDirectPairing.
340 * @param[in] ctx ctx value passed to callback from calling function.
341 * @param[in] UNUSED handle to an invocation
342 * @param[in] clientResponse Response from queries to remote servers.
343 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
344 * and OC_STACK_KEEP_TRANSACTION to keep it.
346 static OCStackApplicationResult DirectPairingFinalizeHandler(void *ctx, OCDoHandle UNUSED,
347 OCClientResponse *clientResponse)
349 OIC_LOG_V(INFO, TAG, "IN DirectPairingFinalizeHandler()");
353 OIC_LOG(ERROR, TAG, "Context is Null");
354 return OC_STACK_DELETE_TRANSACTION;
358 DPairData_t *dpairData = (DPairData_t*)ctx;
359 OCDirectPairingDev_t *peer = dpairData->peer;
360 OCDirectPairingResultCB resultCallback = dpairData->resultCallback;
364 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
367 OIC_LOG(INFO, TAG, "DirectPairingFinalizeHandler : success PUT"
368 " request to /oic/sec/dpairing");
370 CAEndpoint_t endpoint;
371 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
372 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peer->endpoint.addr);
373 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
374 endpoint.port = peer->securePort;
376 OicUuid_t ptDeviceID = {.id={0}};
377 if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
379 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
380 resultCallback(dpairData->userCtx, peer, OC_STACK_ERROR);
381 return OC_STACK_DELETE_TRANSACTION;
384 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
385 res = SavePairingPSK((OCDevAddr*)&endpoint, &peer->deviceID, &ptDeviceID, false);
386 if(OC_STACK_OK != res)
388 OIC_LOG(ERROR, TAG, "Failed to PairingPSK generation");
389 resultCallback(dpairData->userCtx, peer, res);
390 return OC_STACK_DELETE_TRANSACTION;
393 // close temporary sesion
394 CAResult_t caResult = CAcloseSslSession((const CAEndpoint_t*)&endpoint);
395 if(CA_STATUS_OK != caResult)
397 OIC_LOG(INFO, TAG, "Fail to close temporary dtls session");
399 #endif // __WITH_DTLS__ or __WITH_TLS__
401 OIC_LOG(INFO, TAG, "Direct-Papring was successfully completed.");
403 // update paired list
404 OCDirectPairingDev_t *dev = getDev(&g_dp_discover, peer->endpoint.addr,
405 peer->endpoint.port);
406 res = addDev2(&g_dp_paired, dev);
407 if (OC_STACK_OK != res)
409 OIC_LOG(ERROR, TAG, "Error while adding a device to paired list.");
412 resultCallback(dpairData->userCtx, peer, OC_STACK_OK);
414 return OC_STACK_DELETE_TRANSACTION;
418 OIC_LOG(INFO, TAG, "Direct-Papring received error response.");
423 OIC_LOG(ERROR, TAG, "DirectPairingFinalizeHandler received Null clientResponse");
426 resultCallback(dpairData->userCtx, peer, OC_STACK_ERROR);
428 return OC_STACK_DELETE_TRANSACTION;
432 * Finalize direct-pairing .
434 * @param[in] peer target device to establish direct-pairing.
435 * @param[in] resultCallback result event callback.
437 * @return OC_STACK_OK on success otherwise error.
439 OCStackResult FinalizeDirectPairing(void *ctx, OCDirectPairingDev_t* peer,
440 OCDirectPairingResultCB resultCallback)
444 return OC_STACK_INVALID_PARAM;
447 OicUuid_t deviceID = {.id={0}};
448 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
450 OIC_LOG(ERROR, TAG, "Error while retrieving device ID");
451 return OC_STACK_ERROR;
454 OicSecDpairing_t dpair;
455 memset(&dpair, 0, sizeof(OicSecDpairing_t));
456 dpair.spm = (OicSecPrm_t)PRM_NOT_ALLOWED;
457 memcpy(&dpair.pdeviceID, &deviceID, sizeof(OicUuid_t));
459 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
462 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
463 return OC_STACK_NO_MEMORY;
465 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
467 OCStackResult ret = DpairingToCBORPayload(&dpair, &(secPayload->securityData),
468 &(secPayload->payloadSize));
470 if(OC_STACK_OK != ret)
473 OIC_LOG(ERROR, TAG, "Failed to DpairingToCBORPayload");
474 return OC_STACK_NO_MEMORY;
476 OIC_LOG(DEBUG, TAG, "DPARING CBOR data:");
477 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
479 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
480 if(!DPGenerateQuery(true,
484 query, sizeof(query), OIC_RSRC_DPAIRING_URI))
486 OIC_LOG(ERROR, TAG, "DPDirectPairing : Failed to generate query");
487 return OC_STACK_ERROR;
489 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
491 DPairData_t *dpairData = (DPairData_t *) OICCalloc(1, sizeof(DPairData_t));
492 if (dpairData == NULL)
494 OICFree(secPayload->securityData);
496 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
497 return OC_STACK_NO_MEMORY;
499 dpairData->peer = peer;
500 dpairData->resultCallback = resultCallback;
501 dpairData->userCtx = ctx;
503 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
504 cbData.cb = DirectPairingFinalizeHandler;
505 cbData.context = (void*)dpairData;
508 OCMethod method = OC_REST_PUT;
509 OCDoHandle handle = NULL;
510 OIC_LOG(DEBUG, TAG, "Sending DPAIRNG setting to resource server");
511 ret = OCDoResource(&handle, method, query,
512 &peer->endpoint, (OCPayload*)secPayload,
513 peer->connType, OC_LOW_QOS, &cbData, NULL, 0);
514 if(OC_STACK_OK != ret)
516 OIC_LOG(ERROR, TAG, "error in OCDoResource");
517 return OC_STACK_ERROR;
524 * Function to handle the handshake result in Direct-Pairing.
525 * This function will be invoked after DTLS handshake
526 * @param endPoint [IN] The remote endpoint.
527 * @param errorInfo [IN] Error information from the endpoint.
530 void DirectPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
532 OIC_LOG_V(INFO, TAG, "IN DirectPairingDTLSHandshakeCB");
535 if(g_dp_proceed_ctx && g_dp_proceed_ctx->peer && endpoint && info)
537 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
538 endpoint->addr, endpoint->port, info->result);
540 OCDirectPairingDev_t *peer = g_dp_proceed_ctx->peer;
541 OCDirectPairingResultCB resultCallback = g_dp_proceed_ctx->resultCallback;
544 //Make sure the address matches.
545 if(strncmp(peer->endpoint.addr, endpoint->addr, sizeof(endpoint->addr)) == 0 &&
546 peer->securePort == endpoint->port)
548 //In case of success, send next coaps request.
549 if(CA_STATUS_OK == info->result)
551 OIC_LOG(INFO, TAG, "Now, finalize Direct-Pairing procedure.");
553 res = FinalizeDirectPairing(g_dp_proceed_ctx->userCtx, peer, resultCallback);
554 if(OC_STACK_OK != res)
556 OIC_LOG(ERROR, TAG, "Failed to finalize direct-pairing");
557 resultCallback(g_dp_proceed_ctx->userCtx, peer, res);
560 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
562 OIC_LOG(INFO, TAG, "DirectPairingDTLSHandshakeCB - Authentication failed");
563 resultCallback(g_dp_proceed_ctx->userCtx, peer, OC_STACK_AUTHENTICATION_FAILURE);
566 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
567 CAregisterSslHandshakeCallback(NULL);
568 #endif // __WITH_DTLS__ or __WITH_TLS__
569 res = RemoveCredential(&peer->deviceID);
570 if(OC_STACK_RESOURCE_DELETED != res)
572 OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
575 OICFree(g_dp_proceed_ctx);
576 g_dp_proceed_ctx = NULL;
580 OIC_LOG_V(INFO, TAG, "DirectPairingDTLSHandshakeCB - Not matched to peer address");
584 OIC_LOG_V(INFO, TAG, "OUT DirectPairingDTLSHandshakeCB");
588 * Callback handler of DPDirectPairing.
590 * @param[in] ctx ctx value passed to callback from calling function.
591 * @param[in] UNUSED handle to an invocation
592 * @param[in] clientResponse Response from queries to remote servers.
593 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
594 * and OC_STACK_KEEP_TRANSACTION to keep it.
596 static OCStackApplicationResult DirectPairingHandler(void *ctx, OCDoHandle UNUSED,
597 OCClientResponse *clientResponse)
599 OIC_LOG_V(INFO, TAG, "IN DirectPairingHandler.");
603 OIC_LOG(ERROR, TAG, "Context is Null");
604 return OC_STACK_DELETE_TRANSACTION;
607 OCStackResult res = OC_STACK_ERROR;
608 DPairData_t *dpairData = (DPairData_t*)ctx;
609 OCDirectPairingResultCB resultCallback = (OCDirectPairingResultCB)dpairData->resultCallback;
610 OicUuid_t subjectId = {.id={0}};
614 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
617 OIC_LOG(INFO, TAG, "DirectPairingHandler : success POST request to /oic/sec/dpairing");
619 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
621 res = AddTmpPskWithPIN(&dpairData->peer->deviceID,
622 SYMMETRIC_PAIR_WISE_KEY,
623 (char*)dpairData->pin, DP_PIN_LENGTH,
624 &dpairData->peer->rowner, &subjectId);
625 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
628 // Start to establish a secure channel with Pin-based PSK cipher suite
631 caresult = CAEnableAnonECDHCipherSuite(false);
632 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
634 caresult = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
635 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
637 //Register proceeding peer info. & DTLS event handler to catch the dtls event while handshake
638 g_dp_proceed_ctx = dpairData;
639 res = CAregisterSslHandshakeCallback(DirectPairingDTLSHandshakeCB);
640 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
643 CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
644 VERIFY_NON_NULL(TAG, endpoint, FATAL);
645 memcpy(endpoint,&dpairData->peer->endpoint,sizeof(CAEndpoint_t));
646 endpoint->port = dpairData->peer->securePort;
647 OIC_LOG_V(INFO, TAG, "Initiate DTLS handshake to %s(%d)", endpoint->addr,
650 caresult = CAInitiateHandshake(endpoint);
652 VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);
653 #endif // __WITH_DTLS__ or __WITH_TLS__
660 OIC_LOG(INFO, TAG, "DirectPairingHandler : fail POST request to /oic/sec/dpairing");
665 OIC_LOG(ERROR, TAG, "DirectPairingHandler received Null clientResponse");
668 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
670 #endif // __WITH_DTLS__ or __WITH_TLS__
672 if (OC_STACK_OK != res)
674 if (0 < strlen((const char*)subjectId.id))
676 RemoveCredential(&dpairData->peer->deviceID);
678 g_dp_proceed_ctx = NULL;
679 OIC_LOG_V(INFO, TAG, "OUT DirectPairingHandler.");
680 return OC_STACK_DELETE_TRANSACTION;
683 resultCallback(dpairData->userCtx, dpairData->peer, res);
685 OIC_LOG_V(INFO, TAG, "OUT DirectPairingHandler.");
686 return OC_STACK_DELETE_TRANSACTION;
690 * Start direct-pairing .
692 * @param[in] peer target device to establish direct-pairing.
693 * @param[in] pmSel selected pairing method.
694 * @param[in] pinNumber secret value for dtls connection.
696 * @return OC_STACK_OK on success otherwise error.
698 OCStackResult DPDirectPairing(void *ctx, OCDirectPairingDev_t* peer, OicSecPrm_t pmSel,
699 char *pinNumber, OCDirectPairingResultCB resultCallback)
701 if(NULL == peer || NULL == pinNumber)
703 return OC_STACK_INVALID_PARAM;
706 OicUuid_t deviceID = {.id={0}};
707 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
709 OIC_LOG(ERROR, TAG, "Error while retrieving device ID");
710 return OC_STACK_ERROR;
713 OicSecDpairing_t dpair;
714 memset(&dpair, 0, sizeof(OicSecDpairing_t));
716 memcpy(&dpair.pdeviceID, &deviceID, sizeof(OicUuid_t));
718 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
721 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
722 return OC_STACK_NO_MEMORY;
724 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
726 OCStackResult ret = DpairingToCBORPayload(&dpair, &(secPayload->securityData),
727 &(secPayload->payloadSize));
729 if(OC_STACK_OK != ret)
732 OIC_LOG(ERROR, TAG, "Failed to DpairingToCBORPayload");
733 return OC_STACK_NO_MEMORY;
735 OIC_LOG(DEBUG, TAG, "DPARING CBOR data:");
736 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
738 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
739 if(!DPGenerateQuery(false,
744 query, sizeof(query), OIC_RSRC_DPAIRING_URI))
746 OIC_LOG(ERROR, TAG, "DPDirectPairing : Failed to generate query");
747 return OC_STACK_ERROR;
749 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
751 DPairData_t *dpairData = (DPairData_t *) OICCalloc(1, sizeof(DPairData_t));
752 if (dpairData == NULL)
754 OICFree(secPayload->securityData);
756 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
757 return OC_STACK_NO_MEMORY;
759 dpairData->peer = peer;
760 memcpy(dpairData->pin, pinNumber, DP_PIN_LENGTH);
761 dpairData->resultCallback = resultCallback;
762 dpairData->userCtx = ctx;
764 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
765 cbData.cb = DirectPairingHandler;
766 cbData.context = (void*)dpairData;
769 OCMethod method = OC_REST_POST;
770 OCDoHandle handle = NULL;
771 OIC_LOG(DEBUG, TAG, "Sending DPAIRNG setting to resource server");
772 ret = OCDoResource(&handle, method, query,
773 &peer->endpoint, (OCPayload*)secPayload,
774 peer->connType, OC_LOW_QOS, &cbData, NULL, 0);
775 if(OC_STACK_OK != ret)
777 OIC_LOG(ERROR, TAG, "error in OCDoResource");
778 return OC_STACK_ERROR;
786 * Callback handler for getting secure port information using /oic/res discovery.
788 * @param[in] ctx user context
789 * @param[in] handle Handle for response
790 * @param[in] clientResponse Response information(It will contain payload)
792 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
793 * OC_STACK_DELETE_TRANSACTION to delete it.
795 static OCStackApplicationResult DirectPairingPortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
796 OCClientResponse *clientResponse)
798 OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing Secure Port DISCOVER "
799 "query recvd successfully");
805 if (NULL == clientResponse->payload)
807 OIC_LOG(INFO, TAG, "Skiping Null payload");
811 if (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)
813 OIC_LOG(INFO, TAG, "Wrong payload type");
814 return OC_STACK_DELETE_TRANSACTION;
817 uint16_t securePort = 0;
818 OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
819 OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
821 if (resPayload && resPayload->secure)
823 securePort = resPayload->port;
827 OIC_LOG(INFO, TAG, "Can not find secure port information.");
828 return OC_STACK_DELETE_TRANSACTION;
831 OCDirectPairingDev_t *ptr = getDev(&g_dp_discover,
832 clientResponse->devAddr.addr, clientResponse->devAddr.port);
835 OIC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");
836 return OC_STACK_DELETE_TRANSACTION;
838 ptr->securePort = securePort;
840 OIC_LOG(INFO, TAG, "Exiting DirectPairingPortDiscoveryHandler.");
843 return OC_STACK_DELETE_TRANSACTION;
847 OIC_LOG(INFO, TAG, "Skiping Null response");
849 return OC_STACK_DELETE_TRANSACTION;
853 * Callback handler for DPDeviceDiscovery API.
855 * @param[in] ctx User context
856 * @param[in] handle Handler for response
857 * @param[in] clientResponse Response information (It will contain payload)
858 * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
859 * OC_STACK_DELETE_TRANSACTION to delete it.
861 static OCStackApplicationResult DirectPairingDiscoveryHandler(void* ctx, OCDoHandle UNUSED,
862 OCClientResponse * clientResponse)
864 OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing DISCOVER query recvd successfully");
870 OIC_LOG_V(INFO, TAG, "StackResult: %d", clientResponse->result);
872 "Device =============> Discovered @ %s:%d",
873 clientResponse->devAddr.addr,
874 clientResponse->devAddr.port);
876 if (NULL == clientResponse->payload)
878 OIC_LOG(INFO, TAG, "Skiping Null payload");
879 return OC_STACK_KEEP_TRANSACTION;
881 if (OC_STACK_OK != clientResponse->result)
883 OIC_LOG(INFO, TAG, "Error in response");
884 return OC_STACK_KEEP_TRANSACTION;
887 OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
888 OicSecPconf_t *pconf = NULL;
890 OCStackResult res = CBORPayloadToPconf(
891 ((OCSecurityPayload*)clientResponse->payload)->securityData,
893 if (OC_STACK_OK != res )
895 OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
896 return OC_STACK_KEEP_TRANSACTION;
903 memcpy(&endpoint, &clientResponse->devAddr, sizeof(OCDevAddr));
905 OCStackResult res = addDev(&g_dp_discover, &endpoint,
906 clientResponse->connType, pconf);
907 DeletePconfBinData(pconf);
908 if (OC_STACK_OK != res)
910 OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
911 return OC_STACK_KEEP_TRANSACTION;
915 char rsrc_uri[MAX_URI_LENGTH+1] = {0};
916 int wr_len = snprintf(rsrc_uri, sizeof(rsrc_uri), "%s?%s=%s",
917 OC_RSRVD_WELL_KNOWN_URI, OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DPAIRING);
918 if(wr_len <= 0 || (size_t)wr_len >= sizeof(rsrc_uri))
920 OIC_LOG(ERROR, TAG, "rsrc_uri_string_print failed");
921 return OC_STACK_KEEP_TRANSACTION;
924 //Try to the unicast discovery to getting secure port
925 char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};
926 if(!DPGenerateQuery(false,
927 clientResponse->devAddr.addr, clientResponse->devAddr.port,
928 clientResponse->connType,
929 query, sizeof(query), rsrc_uri))
931 OIC_LOG(ERROR, TAG, "DirectPairingDiscoveryHandler : Failed to generate query");
932 return OC_STACK_KEEP_TRANSACTION;
934 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
936 OCCallbackData cbData;
937 cbData.cb = &DirectPairingPortDiscoveryHandler;
938 cbData.context = NULL;
940 OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
941 clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0);
942 if(OC_STACK_OK != ret)
944 OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
945 return OC_STACK_KEEP_TRANSACTION;
949 OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
952 return OC_STACK_KEEP_TRANSACTION;
957 OIC_LOG(INFO, TAG, "Skiping Null response");
960 return OC_STACK_DELETE_TRANSACTION;
964 * Discover direct-pairing devices in the same IP subnet. .
966 * @param[in] waittime Timeout in seconds.
968 * @return OC_STACK_OK on success otherwise error.
970 OCStackResult DPDeviceDiscovery(unsigned short waittime)
972 OIC_LOG(DEBUG, TAG, "IN DPDeviceDiscovery");
976 delList(g_dp_discover);
977 g_dp_discover = NULL;
982 const char DP_DISCOVERY_QUERY[] = "/oic/sec/pconf";
984 OCCallbackData cbData;
985 cbData.cb = DirectPairingDiscoveryHandler;
986 cbData.context = NULL;
989 /* Start a DP discovery query*/
990 OIC_LOG_V(INFO, TAG, "Initiating Direct-Pairing Discovery : %s\n", DP_DISCOVERY_QUERY);
991 OCDoHandle handle = NULL;
992 ret = OCDoResource(&handle, OC_REST_DISCOVER, DP_DISCOVERY_QUERY, 0, 0, CT_DEFAULT,
993 OC_LOW_QOS, &cbData, NULL, 0);
994 if (ret != OC_STACK_OK)
996 OIC_LOG(ERROR, TAG, "OCStack resource error");
1003 #if defined(_MSC_VER)
1004 time_t startTime = NULL;
1005 clock_res = (time(&startTime) == -1);
1007 struct timespec startTime = {.tv_sec=0, .tv_nsec=0};
1008 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
1009 clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
1014 OIC_LOG(ERROR, TAG, "clock error");
1015 if(OC_STACK_OK != OCCancel(handle, OC_LOW_QOS, NULL, 0))
1017 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1019 return OC_STACK_ERROR;
1024 #if defined(_MSC_VER)
1025 time_t currTime = NULL;
1026 clock_res = (time(&currTime) == -1);
1028 struct timespec currTime = {.tv_sec=0, .tv_nsec=0};
1029 #if defined(__ANDROID__) || _POSIX_TIMERS > 0
1030 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
1035 OIC_LOG(ERROR, TAG, "clock error");
1036 ret = OC_STACK_ERROR;
1039 #if defined(_MSC_VER)
1040 long elapsed = currTime - startTime;
1042 long elapsed = (currTime.tv_sec - startTime.tv_sec);
1044 if (elapsed > waittime)
1050 struct timespec timeout = {.tv_sec=0, .tv_nsec=100000000L};
1052 nanosleep(&timeout, NULL);
1056 // Waiting for each response.
1057 ret = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1058 if (OC_STACK_OK != ret)
1060 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
1062 OIC_LOG(DEBUG, TAG, "OUT DPDeviceDiscovery");