From: Ashwini Kumar Date: Mon, 23 May 2016 08:26:22 +0000 (+0530) Subject: Add C++ API for Direct pairing X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1863a89819d8f9964f91165e90a1e4aee59d7a1d;p=contrib%2Fiotivity.git Add C++ API for Direct pairing Added C++ API for direct pairing feature Updated unittests for C++ Added direct pairing sample Fixed Construct resource to '|' Secure flag instead of '&' Note: this change needs https://gerrit.iotivity.org/gerrit/#/c/8273/ Change-Id: I4a1cfc27206adf7308388406d0c8821aa46d87a8 Signed-off-by: Ashwini Kumar Reviewed-on: https://gerrit.iotivity.org/gerrit/8277 Tested-by: jenkins-iotivity Reviewed-by: Chul Lee Reviewed-by: Randeep Singh --- diff --git a/resource/csdk/security/src/directpairing.c b/resource/csdk/security/src/directpairing.c index 5606598..be68b04 100644 --- a/resource/csdk/security/src/directpairing.c +++ b/resource/csdk/security/src/directpairing.c @@ -1008,6 +1008,7 @@ OCStackResult DPDeviceDiscovery(unsigned short waittime) } else { + OCProcess(); nanosleep(&timeout, NULL); } } diff --git a/resource/examples/SConscript b/resource/examples/SConscript index 5d84295..5b2c1d8 100644 --- a/resource/examples/SConscript +++ b/resource/examples/SConscript @@ -91,11 +91,14 @@ lightserver = examples_env.Program('lightserver', 'lightserver.cpp') devicediscoveryserver = examples_env.Program('devicediscoveryserver', 'devicediscoveryserver.cpp') devicediscoveryclient = examples_env.Program('devicediscoveryclient', 'devicediscoveryclient.cpp') threadingsample = examples_env.Program('threadingsample', 'threadingsample.cpp') +directpairingclient = examples_env.Program('directpairingclient', 'directpairingclient.cpp') clientjson = examples_env.Install(env.get('BUILD_DIR') + '/resource/examples/', env.get('SRC_DIR') + '/resource/examples/' + 'oic_svr_db_client.dat') serverjson = examples_env.Install(env.get('BUILD_DIR') + '/resource/examples/', env.get('SRC_DIR') + '/resource/examples/' + 'oic_svr_db_server.dat') +directpairingdat = examples_env.Install(env.get('BUILD_DIR') + '/resource/examples/', + env.get('SRC_DIR') + '/resource/examples/' + 'oic_svr_db_client_directpairing.dat') Alias("examples", [simpleserver, simpleclient, simpleserverHQ, simpleclientHQ, fridgeserver, fridgeclient, @@ -105,7 +108,7 @@ Alias("examples", [simpleserver, simpleclient, groupserver, groupclient, lightserver, devicediscoveryserver, devicediscoveryclient, - threadingsample, - serverjson, clientjson + threadingsample, directpairingclient, + serverjson, clientjson, directpairingdat ]) env.AppendTarget('examples') diff --git a/resource/examples/directpairingclient.cpp b/resource/examples/directpairingclient.cpp new file mode 100644 index 0000000..6ab04fe --- /dev/null +++ b/resource/examples/directpairingclient.cpp @@ -0,0 +1,411 @@ +/* ***************************************************************** + * + * Copyright 2016 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "logger.h" +#include "oic_malloc.h" +#include "oic_string.h" +#include "OCPlatform.h" +#include "OCApi.h" + +#define MAX_URI_LENGTH (64) +#define MAX_PERMISSION_LENGTH (5) +#define CREATE (1) +#define READ (2) +#define UPDATE (4) +#define DELETE (8) +#define NOTIFY (16) +#define DASH '-' +#define PREDEFINED_TIMEOUT (10) +#define MAX_OWNED_DEVICE (10) +#define TAG "provisioningclient" + +#define JSON_DB_PATH "./oic_svr_db_client.json" +#define DAT_DB_PATH "./oic_svr_db_client.dat" +#define DEV_STATUS_ON "DEV_STATUS_ON" +#define DEV_STATUS_OFF "DEV_STATUS_OFF" + +#define DP_DISCOVERY_TIMEOUT 4 +#define DP_PIN_LENGTH 8 + +#define BOLD_BEGIN "\033[1m" +#define RED_BEGIN "\033[1;31m" +#define GREEN_BEGIN "\033[1;92m" +#define COLOR_END "\033[0m" + +using namespace OC; + +static int ask = 1; +static PairedDevices discoveredDeviceList, pairedDeviceList; + +static FILE* client_open(const char* /*fileName*/, const char *mode) +{ + return fopen(DAT_DB_PATH, mode); +} + + +static void printMenu() +{ + std::cout << GREEN_BEGIN "Choose an option:" COLOR_END<getDeviceID() << std::endl; + } +} + +static void findCallback(PairedDevices discoveredDevList) +{ + + if (0 == discoveredDevList.size()) + { + std::cout<< "No Direct-pairing Support device Found" << std::endl; + } + else + { + std::cout << "Discovered Direct-Pairing Support Device"<< std::endl; + discoveredDeviceList = discoveredDevList; + printDevices(discoveredDevList); + } + + printMenu(); + printPrompt(); + fflush(NULL); +} + +static bool printPairingMethod(int choice) +{ + if (NULL == discoveredDeviceList[choice])// || false == discoveredDeviceList[choice]->edp) + { + std::cout<< "Invalid device or Not support direct-pairing..\n\n" << std::endl; + return false; + } + + auto prms = discoveredDeviceList[choice]->getPairingMethods(); + if (0 == prms.size()) + { + std::cout << "Not exist any support method..\n\n" << std::endl; + return false; + } + + bool ret = true; + std::cout << "\n* List of supported pairing methods *" << std::endl; + + for (unsigned int i = 0; i < prms.size(); i++) + { + std::cout<< "[" << i+1 << "]"; + switch (prms[i]) + { + case DP_PRE_CONFIGURED: + std::cout<<"Pre-Configured PIN"< ptr, OCStackResult result) +{ + + if (OC_STACK_OK == result) + { + std::cout << " Direct-Pairing SUCCESS" << std::endl; + std::cout << "Taget Add info:" << ptr->getHost() << std::endl; + } + else { + std::cout <<" Direct-Pairing FAILED" << std::endl; + } + + printMenu(); + printPrompt(); + fflush(NULL); +} + +static void pairedDevListCB(PairedDevices pairedDevList) +{ + + if (0 == pairedDevList.size()) + { + std::cout << "No Paired Devcie Found" << std::endl; + } + else + { + pairedDeviceList = pairedDevList; + printDevices(pairedDevList); + } + + printMenu(); + printPrompt(); + fflush(NULL); +} + +static void getCallback(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + (void)(headerOptions); + try + { + if (OC_STACK_OK == eCode) + { + std::cout << "Callback Context for GET query recvd successfully" << std::endl; + std::cout << "Resource URI: " << rep.getUri() << std::endl; + + bool state = false; + int power = 0; + rep.getValue("state", state); + rep.getValue("power", power); + + std::cout << "\tstate: " << state << std::endl; + std::cout << "\tpower: " << power << std::endl; + } + else + { + std::cout << "getCallback Response error: " << eCode << std::endl; + } + } + catch(std::exception& e) + { + std::cout << "Exception: " << e.what() << " in onGet" << std::endl; + } +} + +static bool InputPIN(std::string& pin) +{ + std::cout <<" > Enter PIN Number for authentication (ex - '00000000' [8 digit] ):" ; + + std::cin >> pin; + + if (pin.size() != DP_PIN_LENGTH) + { + std::cout<<"Invalid PIN"<> choice; + + switch(choice) { + case 1: + { + OCStackResult result = OC::OCPlatform::findDirectPairingDevices( + DP_DISCOVERY_TIMEOUT, findCallback); + + if (OC_STACK_NO_RESOURCE == result) + { + std::cout << "!! No Direct-Pairing Support Device found"< Enter Peer Device Number to initiate Direct-Pairing:" << std::endl; + printPrompt(); + std::cin >> choice; + if (choice < 1 || choice > discoveredDeviceList.size()) + { + std::cout << "!!Device Number is incorrect, Try Again" << std::endl; + break; + } + OCPrm_t pmSel = DP_NOT_ALLOWED; + choice--; + if (false == printPairingMethod(choice)) + { + std::cout << "Target does not support the Direct-Pairing" << std::endl; + break; + } + + std::cout << " > Enter pairing method: "<< std::endl; + printPrompt(); + std::cin >> pMethodIDx; + auto prms = discoveredDeviceList[choice]->getPairingMethods(); + if (0 >= pMethodIDx || prms.size() < pMethodIDx) + { + std::cout <<"Invalid mode selection" << std::endl; + break; + } + + pmSel = prms[pMethodIDx - 1]; + if (false == InputPIN(pin)) + { + break; + } + + OCStackResult result = OC::OCPlatform::doDirectPairing(discoveredDeviceList[choice], pmSel, pin, resultCallback); + + if (OC_STACK_OK != result) + { + std::cout << "!!Error - doDirectPairing failed." << std::endl; + } + ask = 0; + break; + } + case 3: + { + std::cout << "- List all discovered and paired devices) -"; + std::cout << " > List of discovered devices" << std::endl; + printDevices(discoveredDeviceList); + std::cout << std::endl; + + std::cout << " > List of paired devices" << std::endl; + OCStackResult result = OC::OCPlatform::getDirectPairedDevices(pairedDevListCB); + printDevices(pairedDeviceList); + std::cout << std::endl; + + if (OC_STACK_NO_RESOURCE == result) + { + std::cout << "!! No Paired device found"<> choice; + choice--; + + std::vector ledTypes = {"core.led"}; + std::vector ifaces = {DEFAULT_INTERFACE}; + + OCConnectivityType ct = pairedDeviceList[choice]->getConnType(); + + std::cout << "\n\n HOST address is : " << pairedDeviceList[choice]->getHost() << "\n\n"; + OCResource::Ptr led = OC::OCPlatform::constructResourceObject( + pairedDeviceList[choice]->getHost(), + "/a/led", ct, false, ledTypes, ifaces); + + if(!led) + { + std::cout << "Error: Led Object construction returned null" << std::endl; + break; + } + OCStackResult res = led->get(QueryParamsMap(), getCallback); + + if (OC_STACK_OK != res) + { + std::cout << "Error: get Failed for Led" << std::endl; + } + break; + } + case 9: + { + out = 1; + break; + } + default: + { + std::cout << GREEN_BEGIN "Wrong Option : Try Again" COLOR_END << std::endl; + printMenu(); + printPrompt(); + break; + } + } + } + } + catch(OCException& e) + { + oclog() << "Exception in main: "<< e.what(); + } + + return 0; +} diff --git a/resource/examples/oic_svr_db_client_directpairing.dat b/resource/examples/oic_svr_db_client_directpairing.dat new file mode 100644 index 0000000..116deb8 Binary files /dev/null and b/resource/examples/oic_svr_db_client_directpairing.dat differ diff --git a/resource/examples/oic_svr_db_client_directpairing.json b/resource/examples/oic_svr_db_client_directpairing.json new file mode 100644 index 0000000..0c83965 --- /dev/null +++ b/resource/examples/oic_svr_db_client_directpairing.json @@ -0,0 +1,88 @@ +{ + "acl": { + "aclist": { + "aces": [ + { + "subjectuuid": "*", + "resources": [ + { + "href": "/oic/res", + "rel": "", + "rt": "", + "if": "" + }, + { + "href": "/oic/d", + "rel": "", + "rt": "", + "if": "" + }, + { + "href": "/oic/res/types/d", + "rel": "", + "rt": "", + "if": "" + }, + { + "href": "/oic/presence", + "rel": "", + "rt": "", + "if": "" + } + ], + "permission": 2 + }, + { + "subjectuuid": "*", + "resources": [ + { + "href": "/oic/sec/doxm", + "rel": "", + "rt": "", + "if": "" + }, + { + "href": "/oic/sec/pstat", + "rel": "", + "rt": "", + "if": "" + }, + { + "href": "/oic/sec/acl", + "rel": "", + "rt": "", + "if": "" + }, + { + "href": "/oic/sec/cred", + "rel": "", + "rt": "", + "if": "" + } + ], + "permission": 6 + } + ] + }, + "rowneruuid" : "64706169-7269-6e67-4465-765555494430" + }, + "pstat": { + "isop": false, + "deviceuuid": "64706169-7269-6e67-4465-765555494430", + "rowneruuid": "64706169-7269-6e67-4465-765555494430", + "cm": 2, + "tm": 0, + "om": 3, + "sm": 3 + }, + "doxm": { + "oxms": [0], + "oxmsel": 0, + "sct": 1, + "owned": false, + "deviceuuid": "64706169-7269-6e67-4465-765555494430", + "devowneruuid": "", + "rowneruuid": "64706169-7269-6e67-4465-765555494430", + "dpc": false + } +} diff --git a/resource/include/IClientWrapper.h b/resource/include/IClientWrapper.h index 6a3d525..0cbfa53 100644 --- a/resource/include/IClientWrapper.h +++ b/resource/include/IClientWrapper.h @@ -23,7 +23,6 @@ #include #include - #include namespace OC @@ -111,6 +110,14 @@ namespace OC virtual OCStackResult GetDefaultQos(QualityOfService& qos) = 0; + virtual OCStackResult FindDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback& callback) = 0; + + virtual OCStackResult GetDirectPairedDevices(GetDirectPairedCallback& callback) = 0; + + virtual OCStackResult DoDirectPairing(std::shared_ptr peer, const OCPrm_t& pmSel, + const std::string& pinNumber, DirectPairingCallback& resultCallback) = 0; + virtual ~IClientWrapper(){} }; } diff --git a/resource/include/InProcClientWrapper.h b/resource/include/InProcClientWrapper.h index 33d3e22..c13edb1 100644 --- a/resource/include/InProcClientWrapper.h +++ b/resource/include/InProcClientWrapper.h @@ -92,6 +92,13 @@ namespace OC ObserveCallback callback; ObserveContext(ObserveCallback cb) : callback(cb){} }; + + struct DirectPairingContext + { + DirectPairingCallback callback; + DirectPairingContext(DirectPairingCallback cb) : callback(cb){} + + }; } class InProcClientWrapper : public IClientWrapper @@ -161,12 +168,23 @@ namespace OC virtual OCStackResult UnsubscribePresence(OCDoHandle handle); OCStackResult GetDefaultQos(QualityOfService& QoS); + + + virtual OCStackResult FindDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback& callback); + + virtual OCStackResult GetDirectPairedDevices(GetDirectPairedCallback& callback); + + virtual OCStackResult DoDirectPairing(std::shared_ptr peer, const OCPrm_t& pmSel, + const std::string& pinNumber, DirectPairingCallback& resultCallback); + private: void listeningFunc(); std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams); OCPayload* assembleSetResourcePayload(const OCRepresentation& attributes); OCHeaderOption* assembleHeaderOptions(OCHeaderOption options[], const HeaderOptions& headerOptions); + void convert(const OCDPDev_t *list, PairedDevices& dpList); std::thread m_listeningThread; bool m_threadRun; std::weak_ptr m_csdkLock; diff --git a/resource/include/OCApi.h b/resource/include/OCApi.h index d124502..7717c86 100644 --- a/resource/include/OCApi.h +++ b/resource/include/OCApi.h @@ -41,6 +41,7 @@ namespace OC class OCResource; class OCResourceRequest; class OCResourceResponse; + class OCDirectPairing; } // namespace OC namespace OC @@ -249,6 +250,8 @@ namespace OC // Used in GET, PUT, POST methods on links to other remote resources of a group. const std::string GROUP_INTERFACE = "oic.mi.grp"; + //Typedef for list direct paired devices + typedef std::vector> PairedDevices; typedef std::function)> FindCallback; @@ -277,6 +280,11 @@ namespace OC typedef std::function ObserveCallback; + + typedef std::function, OCStackResult)> DirectPairingCallback; + + typedef std::function GetDirectPairedCallback; + } // namespace OC #endif diff --git a/resource/include/OCDirectPairing.h b/resource/include/OCDirectPairing.h new file mode 100644 index 0000000..3f27b83 --- /dev/null +++ b/resource/include/OCDirectPairing.h @@ -0,0 +1,69 @@ +//****************************************************************** +// +// Copyright 2016 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_DIRECT_PAIRING_H_ +#define OC_DIRECT_PAIRING_H_ +#include + +namespace OC +{ + class OCDirectPairing + { + public: + OCDirectPairing(OCDPDev_t *ptr); + /** + * Function to get the host address of direct pairing device. + * + * @return Returns host address in the format + * :IP:securePort + */ + std::string getHost(); + + /** + * Function to get the device ID of the direct pairing device. + * + * @return Returns device ID (UUID) + */ + std::string getDeviceID(); + + /** + * Function to get the pairing methods supported by direct pairing device. + * + * @return Returns vector of pairing methods supported. + * DP_NOT_ALLOWED + * DP_PRE_CONFIGURED + * DP_RANDOM_PIN + */ + std::vector getPairingMethods(); + + /** + * Function to get the connectivity Type. + * + * @return Returns connectivity Type + */ + OCConnectivityType getConnType(); + + OCDPDev_t* getDev(); + + private: + OCDPDev_t *m_devPtr; + }; +} +#endif //OC_DIRECT_PAIRING_H_ diff --git a/resource/include/OCPlatform.h b/resource/include/OCPlatform.h index 2828b9e..37c4b54 100644 --- a/resource/include/OCPlatform.h +++ b/resource/include/OCPlatform.h @@ -523,45 +523,45 @@ namespace OC SubscribeCallback presenceHandler); /** - * unsubscribes from a previously subscribed server's presence events. Note that - * you may for a short time still receive events from the server since it may take time - * for the unsubscribe to take effect. - * - * @param presenceHandle the handle object provided by the subscribePresence call that - * identifies this subscription. - * - * @return Returns ::OC_STACK_OK if success. - */ + * unsubscribes from a previously subscribed server's presence events. Note that + * you may for a short time still receive events from the server since it may take time + * for the unsubscribe to take effect. + * + * @param presenceHandle the handle object provided by the subscribePresence call that + * identifies this subscription. + * + * @return Returns ::OC_STACK_OK if success. + */ OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle); /** - * Creates a resource proxy object so that get/put/observe functionality - * can be used without discovering the object in advance. Note that the - * consumer of this method needs to provide all of the details required to - * correctly contact and observe the object. If the consumer lacks any of - * this information, they should discover the resource object normally. - * Additionally, you can only create this object if OCPlatform was initialized - * to be a Client or Client/Server. Otherwise, this will return an empty - * shared ptr. - * - * @param host a string containing a resolvable host address of the server - * holding the resource. Currently this should be in the format - * coap://address:port, though in the future, we expect this to - * change to //address:port - * - * @param uri the rest of the resource's URI that will permit messages to be - * properly routed. Example: /a/light - * - * @param connectivityType ::OCConnectivityType type of connectivity indicating the - * interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL - * - * @param isObservable a boolean containing whether the resource supports observation - * - * @param resourceTypes a collection of resource types implemented by the resource - * - * @param interfaces a collection of interfaces that the resource supports/implements - * @return OCResource::Ptr a shared pointer to the new resource object - */ + * Creates a resource proxy object so that get/put/observe functionality + * can be used without discovering the object in advance. Note that the + * consumer of this method needs to provide all of the details required to + * correctly contact and observe the object. If the consumer lacks any of + * this information, they should discover the resource object normally. + * Additionally, you can only create this object if OCPlatform was initialized + * to be a Client or Client/Server. Otherwise, this will return an empty + * shared ptr. + * + * @param host a string containing a resolvable host address of the server + * holding the resource. Currently this should be in the format + * coap://address:port, though in the future, we expect this to + * change to //address:port + * + * @param uri the rest of the resource's URI that will permit messages to be + * properly routed. Example: /a/light + * + * @param connectivityType ::OCConnectivityType type of connectivity indicating the + * interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL + * + * @param isObservable a boolean containing whether the resource supports observation + * + * @param resourceTypes a collection of resource types implemented by the resource + * + * @param interfaces a collection of interfaces that the resource supports/implements + * @return OCResource::Ptr a shared pointer to the new resource object + */ OCResource::Ptr constructResourceObject(const std::string& host, const std::string& uri, OCConnectivityType connectivityType, bool isObservable, @@ -569,14 +569,48 @@ namespace OC const std::vector& interfaces); /** - * Allows application entity handler to send response to an incoming request. - * - * @param pResponse OCResourceResponse pointer that will permit to set values related - * to resource response. - * - * @return Returns ::OC_STACK_OK if success. - */ + * Allows application entity handler to send response to an incoming request. + * + * @param pResponse OCResourceResponse pointer that will permit to set values related + * to resource response. + * + * @return Returns ::OC_STACK_OK if success. + */ OCStackResult sendResponse(const std::shared_ptr pResponse); + + /** + * Find all the Direct Pairing capable devices. + * + * @param waittime timeoutbefore the callback is called + * @param callback function to callback with discovered devices after timeout + * + * @return Returns ::OC_STACK_OK if success + */ + OCStackResult findDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback callback); + + /** + * Get all the Direct paired devices. + * + * @param callback function to callback with the list of paired devices + * + * @return Returns ::OC_STACK_OK if success + */ + OCStackResult getDirectPairedDevices(GetDirectPairedCallback callback); + + /** + * Perform the Direct Pairing with the selected peer device + * + * @param peer device to direct pair with + * @param pmSel Selected pairing method + * @param pinNumber pin to validate peer & perform the direct pairing + * @param resultCallback callback function that will get the result of the operation + * + * @return Returns ::OC_STACK_OK if success + */ + OCStackResult doDirectPairing(std::shared_ptr peer, OCPrm_t pmSel, + const std::string& pinNumber, + DirectPairingCallback resultCallback); } } diff --git a/resource/include/OCPlatform_impl.h b/resource/include/OCPlatform_impl.h index 45441fe..51217f0 100644 --- a/resource/include/OCPlatform_impl.h +++ b/resource/include/OCPlatform_impl.h @@ -37,6 +37,7 @@ #include "OCResourceRequest.h" #include "OCResourceResponse.h" #include "OCRepresentation.h" +#include "OCDirectPairing.h" #include "oc_logger.hpp" @@ -232,6 +233,15 @@ namespace OC std::weak_ptr csdkLock(); + OCStackResult findDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback callback); + + OCStackResult getDirectPairedDevices(GetDirectPairedCallback callback); + + OCStackResult doDirectPairing(std::shared_ptr peer, OCPrm_t pmSel, + const std::string& pinNumber, + DirectPairingCallback resultCallback); + private: PlatformConfig m_cfg; diff --git a/resource/include/OCProvisioningManager.h b/resource/include/OCProvisioningManager.h index 0a949e3..535572c 100644 --- a/resource/include/OCProvisioningManager.h +++ b/resource/include/OCProvisioningManager.h @@ -268,6 +268,17 @@ namespace OC ResultCallBack resultCallback); /** + * API to provision DirectPairing to devices. + * + * @param pconf pointer to PCONF (Pairing Configuration). + * @param resultCallback Callback will be called when provisioning request receives + * a response from first resource server. + * @return ::OC_STACK_OK in case of success and other value otherwise. + */ + OCStackResult provisionDirectPairing(const OicSecPconf_t *pconf, + ResultCallBack resultCallback); + + /** * This method is used to get linked devices' IDs. * * @param uuidList Information about the list of linked devices uuids. diff --git a/resource/include/OutOfProcClientWrapper.h b/resource/include/OutOfProcClientWrapper.h index 2438cb1..3719a63 100644 --- a/resource/include/OutOfProcClientWrapper.h +++ b/resource/include/OutOfProcClientWrapper.h @@ -123,6 +123,18 @@ namespace OC virtual OCStackResult GetDefaultQos(QualityOfService& /*QoS*/) {return OC_STACK_NOTIMPL;} + + virtual OCStackResult FindDirectPairingDevices(unsigned short /*waittime*/, + GetDirectPairedCallback& /*callback*/) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult GetDirectPairedDevices(GetDirectPairedCallback& /*callback*/) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult DoDirectPairing(std::shared_ptr /*peer*/, + const OCPrm_t& /*pmSel*/, + const std::string& /*pinNumber*/, DirectPairingCallback& /*resultCallback*/) + {return OC_STACK_NOTIMPL;} }; } diff --git a/resource/provisioning/examples/provisioningclient.cpp b/resource/provisioning/examples/provisioningclient.cpp index b2c9825..ad53059 100644 --- a/resource/provisioning/examples/provisioningclient.cpp +++ b/resource/provisioning/examples/provisioningclient.cpp @@ -56,10 +56,16 @@ #define DISCOVERY_TIMEOUT 5 +static const OicSecPrm_t SUPPORTED_PRMS[1] = +{ + PRM_PRE_CONFIGURED, +}; + using namespace OC; DeviceList_t pUnownedDevList, pOwnedDevList; static int transferDevIdx, ask = 1; +static OicSecPconf_t g_pconf; static FILE* client_open(const char *UNUSED_PARAM, const char *mode) { @@ -79,8 +85,9 @@ void printMenu() std::cout << " 7. Unlink Devices"<resourcesLen; i++) + { + OICFree((acl)->resources[i]); + } + OICFree((acl)->resources); + + /* Clean ACL node itself */ + /* Required only if acl was created in heap */ + OICFree((acl)); + } + memset(&g_pconf, 0, sizeof(OicSecPconf_t)); +} + +static OicSecPdAcl_t* InputPdACL() +{ + int ret; + char *temp_rsc, *temp_pms; + + printf("******************************************************************************\n"); + printf("-Set ACL policy for target DP device\n"); + printf("******************************************************************************\n"); + + OicSecPdAcl_t *acl = (OicSecPdAcl_t *)OICCalloc(1,sizeof(OicSecPdAcl_t)); + if (NULL == acl) + { + OIC_LOG(ERROR, TAG, "Error while memory allocation"); + return NULL; + } + + //Set Resource. + printf("Num. of Resource : "); + ret = scanf("%zu", &acl->resourcesLen); + if ((1 != ret) || (acl->resourcesLen <= 0 || acl->resourcesLen > 50)) + { + printf("Error while input\n"); + OICFree(acl); + return NULL; + } + printf("-URI of resource\n"); + printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n"); + acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *)); + if (NULL == acl->resources) + { + OIC_LOG(ERROR, TAG, "Error while memory allocation"); + OICFree(acl); + return NULL; + } + for (size_t i = 0; i < acl->resourcesLen; i++) + { + printf("[%zu]Resource : ", i + 1); + ret = scanf("%64ms", &temp_rsc); + if (1 != ret) + { + printf("Error while input\n"); + OICFree(acl->resources); + OICFree(acl); + return NULL; + } + + acl->resources[i] = OICStrdup(temp_rsc); + OICFree(temp_rsc); + if (NULL == acl->resources[i]) + { + OIC_LOG(ERROR, TAG, "Error while memory allocation"); + OICFree(acl->resources); + OICFree(acl); + return NULL; + } + } + + // Set Permission + do + { + printf("-Set the permission(C,R,U,D,N)\n"); + printf("ex) CRUDN, CRU_N,..(5 Charaters)\n"); + printf("Permission : "); + ret = scanf("%5ms", &temp_pms); + if (1 != ret) + { + printf("Error while input\n"); + OICFree(acl->resources); + OICFree(acl); + return NULL; + } + ret = CalculateAclPermission(temp_pms, &(acl->permission)); + OICFree(temp_pms); + } while (0 != ret ); + + return acl; +} + +void provisionDirectPairingCB(PMResultList_t *result, int hasError) +{ + if (hasError) + { + std::cout << "Error in provisioning operation!"<size(); i++) + { + std::cout << "Result is = " << result->at(i).res <<" for device "; + printUuid(result->at(i).deviceId); + } + + delete result; + } + deletePconf(); + printMenu(); + ask = 1; +} + +static void provisionDP(int dev_num) +{ + OCStackResult rst; + std::string pin(""); + + // set enable dp + g_pconf.edp = true; + + // set default supported PRM types + g_pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t); + g_pconf.prm = (OicSecPrm_t *)OICCalloc(g_pconf.prmLen, sizeof(OicSecPrm_t)); + if(g_pconf.prm) + { + for (size_t i=0; i < g_pconf.prmLen; i++) + { + g_pconf.prm[i] = SUPPORTED_PRMS[i]; + } + } + else + { + OIC_LOG(ERROR, TAG, "create prm error return"); + goto PVDP_ERROR; + } + + std::cout << "Enter PIN to be configured: "; + while (1) + { + std::cin >> pin; + if (pin.length() == DP_PIN_LENGTH) + { + break; + } + else + { + std::cout << "PIN length should be 8, Enter again: "; + } + } + + memcpy(g_pconf.pin.val, pin.c_str(), DP_PIN_LENGTH); + + // set default pdacl + + g_pconf.pdacls = InputPdACL(); + if(!g_pconf.pdacls) + { + OIC_LOG(ERROR, TAG, "InputPdACL error return"); + goto PVDP_ERROR; + } + + // call |OCProvisionDirectPairing| API actually + // calling this API with callback actually acts like blocking + // for error checking, the return value saved and printed + rst = pOwnedDevList[dev_num-1]->provisionDirectPairing(&g_pconf, provisionDirectPairingCB); + if(OC_STACK_OK != rst) + { + OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst); + if (OC_STACK_UNAUTHORIZED_REQ == rst) + { + OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)"); + } + goto PVDP_ERROR; + } + return; + +PVDP_ERROR: + deletePconf(); // after here |acl| points nothing + ask = 1; +} + int main(void) { OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink }; @@ -890,6 +1087,36 @@ int main(void) } case 11: + { + unsigned int devNum; + + if (!pOwnedDevList.size()) + { + std::cout <<"There are no Owned devices yet," + " may need to discover"<getDeviceID() <<" From IP:"; + std::cout << pOwnedDevList[i]->getDevAddr() <> devNum; + if (devNum > pOwnedDevList.size()) + { + std::cout <<"Invalid device number"< lock(*cLock); result = OCInitPM(dbPath.c_str()); @@ -52,7 +52,7 @@ namespace OC auto csdkLock = OCPlatform_impl::Instance().csdkLock(); auto cLock = csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCDiscoverUnownedDevices(timeout, &pDevList); @@ -91,7 +91,7 @@ namespace OC auto csdkLock = OCPlatform_impl::Instance().csdkLock(); auto cLock = csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCDiscoverOwnedDevices(timeout, &pDevList); @@ -124,13 +124,13 @@ namespace OC OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData, InputPinCallback inputPin) { - if(NULL == callbackData || oxm >= OIC_OXM_COUNT) + if (NULL == callbackData || oxm >= OIC_OXM_COUNT) { oclog() <<"Invalid callbackData or OXM type"; return OC_STACK_INVALID_PARAM; } - if((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin) + if ((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin) { oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null"; return OC_STACK_INVALID_PARAM; @@ -139,11 +139,11 @@ namespace OC OCStackResult result; auto cLock = OCPlatform_impl::Instance().csdkLock().lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCSetOwnerTransferCallbackData(oxm, callbackData); - if(result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm)) + if (result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm)) { SetInputPinCB(inputPin); } @@ -167,7 +167,7 @@ namespace OC auto csdkLock = OCPlatform_impl::Instance().csdkLock(); auto cLock = csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); @@ -207,7 +207,7 @@ namespace OC OCStackResult OCSecure::setDisplayPinCB(GeneratePinCallback displayPin) { - if(!displayPin) + if (!displayPin) { oclog() <<"displayPin can't be null"; return OC_STACK_INVALID_PARAM; @@ -216,7 +216,7 @@ namespace OC OCStackResult result = OC_STACK_OK; auto cLock = OCPlatform_impl::Instance().csdkLock().lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); SetGeneratePinCB(displayPin); @@ -269,7 +269,7 @@ namespace OC OCSecureResource::~OCSecureResource() { - if(devPtr) + if (devPtr) { OCDeleteDiscoveredDevices(devPtr); } @@ -277,7 +277,7 @@ namespace OC OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback) { - if(!resultCallback) + if (!resultCallback) { oclog() <<"Result callback can't be null"; return OC_STACK_INVALID_CALLBACK; @@ -286,7 +286,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { ProvisionContext* context = new ProvisionContext(resultCallback); @@ -305,12 +305,12 @@ namespace OC OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl, ResultCallBack resultCallback) { - if(!acl) + if (!acl) { oclog() <<"ACL can't be null"; return OC_STACK_INVALID_PARAM; } - if(!resultCallback) + if (!resultCallback) { oclog() <<"result callback can not be null"; return OC_STACK_INVALID_CALLBACK; @@ -319,7 +319,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { ProvisionContext* context = new ProvisionContext(resultCallback); @@ -339,7 +339,7 @@ namespace OC OCStackResult OCSecureResource::provisionCredentials(const Credential &cred, const OCSecureResource &device2, ResultCallBack resultCallback) { - if(!resultCallback) + if (!resultCallback) { oclog() << "Result calback can't be null"; return OC_STACK_INVALID_CALLBACK; @@ -348,7 +348,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { ProvisionContext* context = new ProvisionContext(resultCallback); @@ -371,7 +371,7 @@ namespace OC const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2, ResultCallBack resultCallback) { - if(!resultCallback) + if (!resultCallback) { oclog() << "Result callback can not be null"; return OC_STACK_INVALID_CALLBACK; @@ -380,7 +380,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { ProvisionContext* context = new ProvisionContext(resultCallback); @@ -403,7 +403,7 @@ namespace OC OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2, ResultCallBack resultCallback) { - if(!resultCallback) + if (!resultCallback) { oclog() << "Result calback can't be null"; return OC_STACK_INVALID_CALLBACK; @@ -412,7 +412,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { ProvisionContext* context = new ProvisionContext(resultCallback); @@ -432,7 +432,7 @@ namespace OC OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery, ResultCallBack resultCallback) { - if(!resultCallback) + if (!resultCallback) { oclog() << "Result calback can't be null"; return OC_STACK_INVALID_CALLBACK; @@ -441,7 +441,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { ProvisionContext* context = new ProvisionContext(resultCallback); @@ -465,7 +465,7 @@ namespace OC auto devUuid = devPtr->doxm->deviceID; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); @@ -488,6 +488,40 @@ namespace OC return result; } + OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf, + ResultCallBack resultCallback) + { + if (!pconf) + { + oclog() <<"PCONF can't be null"; + return OC_STACK_INVALID_PARAM; + } + if (!resultCallback) + { + oclog() <<"result callback can not be null"; + return OC_STACK_INVALID_CALLBACK; + } + + OCStackResult result; + auto cLock = m_csdkLock.lock(); + + if (cLock) + { + ProvisionContext* context = new ProvisionContext(resultCallback); + + std::lock_guard lock(*cLock); + result = OCProvisionDirectPairing(static_cast(context), + devPtr, const_cast(pconf), + &OCSecureResource::callbackWrapper); + } + else + { + oclog() <<"Mutex not found"; + result = OC_STACK_ERROR; + } + return result; + } + std::string OCSecureResource::getDeviceID() { std::ostringstream deviceId(""); @@ -498,6 +532,7 @@ namespace OC if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID)) { deviceId << devID; + free(devID); } else { diff --git a/resource/provisioning/unittests/OCProvisioningTest.cpp b/resource/provisioning/unittests/OCProvisioningTest.cpp index 38e27bf..9e44e06 100644 --- a/resource/provisioning/unittests/OCProvisioningTest.cpp +++ b/resource/provisioning/unittests/OCProvisioningTest.cpp @@ -173,4 +173,23 @@ namespace OCProvisioningTest OICFree(acl2); } + TEST(ProvisionDirectPairingTest, ProvisionDirectPairingTestNullPconf) + { + OCSecureResource device; + EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionDirectPairing(nullptr, resultCallback)); + } + + TEST(ProvisionDirectPairingTest, ProvisionDirectPairingTestNullCallback) + { + OCSecureResource device; + OicSecPconf_t *pconf = (OicSecPconf_t *)OICCalloc(1,sizeof(OicSecPconf_t)); + EXPECT_EQ(OC_STACK_INVALID_CALLBACK, device.provisionDirectPairing(pconf, nullptr)); + OICFree(pconf); + } + + TEST(ProvisionDirectPairingTest, ProvisionDirectPairingTestNullCallbackNUllPconf) + { + OCSecureResource device; + EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionDirectPairing(nullptr, nullptr)); + } } diff --git a/resource/src/InProcClientWrapper.cpp b/resource/src/InProcClientWrapper.cpp index 23752b9..ae3e0de 100644 --- a/resource/src/InProcClientWrapper.cpp +++ b/resource/src/InProcClientWrapper.cpp @@ -37,7 +37,7 @@ namespace OC // if the config type is server, we ought to never get called. If the config type // is both, we count on the server to run the thread and do the initialize - if(m_cfg.mode == ModeType::Client) + if (m_cfg.mode == ModeType::Client) { OCTransportFlags serverFlags = static_cast(m_cfg.serverConnectivity & CT_MASK_FLAGS); @@ -45,7 +45,7 @@ namespace OC static_cast(m_cfg.clientConnectivity & CT_MASK_FLAGS); OCStackResult result = OCInit1(OC_CLIENT, serverFlags, clientFlags); - if(OC_STACK_OK != result) + if (OC_STACK_OK != result) { throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); } @@ -57,7 +57,7 @@ namespace OC InProcClientWrapper::~InProcClientWrapper() { - if(m_threadRun && m_listeningThread.joinable()) + if (m_threadRun && m_listeningThread.joinable()) { m_threadRun = false; m_listeningThread.join(); @@ -65,7 +65,7 @@ namespace OC // only stop if we are the ones who actually called 'init'. We are counting // on the server to do the stop. - if(m_cfg.mode == ModeType::Client) + if (m_cfg.mode == ModeType::Client) { OCStop(); } @@ -77,7 +77,7 @@ namespace OC { OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCProcess(); @@ -87,7 +87,7 @@ namespace OC result = OC_STACK_ERROR; } - if(result != OC_STACK_OK) + if (result != OC_STACK_OK) { // TODO: do something with result if failed? } @@ -99,7 +99,7 @@ namespace OC OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse) { - if(clientResponse->payload == nullptr || + if (clientResponse->payload == nullptr || ( clientResponse->payload->type != PAYLOAD_TYPE_DEVICE && clientResponse->payload->type != PAYLOAD_TYPE_PLATFORM && @@ -116,7 +116,7 @@ namespace OC //OCPayloadDestroy(clientResponse->payload); std::vector::const_iterator it = oc.representations().begin(); - if(it == oc.representations().end()) + if (it == oc.representations().end()) { return OCRepresentation(); } @@ -140,7 +140,7 @@ namespace OC ClientCallbackContext::ListenContext* context = static_cast(ctx); - if(clientResponse->result != OC_STACK_OK) + if (clientResponse->result != OC_STACK_OK) { oclog() << "listenCallback(): failed to create resource. clientResponse: " << clientResponse->result @@ -149,7 +149,7 @@ namespace OC return OC_STACK_KEEP_TRANSACTION; } - if(!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY) + if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY) { oclog() << "listenCallback(): clientResponse payload was null or the wrong type" << std::flush; @@ -158,7 +158,7 @@ namespace OC auto clientWrapper = context->clientWrapper.lock(); - if(!clientWrapper) + if (!clientWrapper) { oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper" << std::flush; @@ -241,7 +241,7 @@ namespace OC OCConnectivityType connectivityType, FindCallback& callback, QualityOfService QoS) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -259,7 +259,7 @@ namespace OC ); auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCDoResource(nullptr, OC_REST_DISCOVER, @@ -355,7 +355,7 @@ namespace OC FindDeviceCallback& callback, QualityOfService QoS) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -372,7 +372,7 @@ namespace OC ); auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCDoResource(nullptr, OC_REST_DISCOVER, @@ -393,7 +393,7 @@ namespace OC void parseServerHeaderOptions(OCClientResponse* clientResponse, HeaderOptions& serverHeaderOptions) { - if(clientResponse) + if (clientResponse) { // Parse header options from server uint16_t optionID; @@ -426,7 +426,7 @@ namespace OC OCRepresentation rep; HeaderOptions serverHeaderOptions; OCStackResult result = clientResponse->result; - if(result == OC_STACK_OK) + if (result == OC_STACK_OK) { parseServerHeaderOptions(clientResponse, serverHeaderOptions); try @@ -450,7 +450,7 @@ namespace OC const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, GetCallback& callback, QualityOfService QoS) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -467,7 +467,7 @@ namespace OC auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; @@ -524,13 +524,13 @@ namespace OC std::string InProcClientWrapper::assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams) { - if(uri.back() == '/') + if (uri.back() == '/') { uri.resize(uri.size()-1); } ostringstream paramsList; - if(queryParams.size() > 0) + if (queryParams.size() > 0) { paramsList << '?'; } @@ -541,7 +541,7 @@ namespace OC } std::string queryString = paramsList.str(); - if(queryString.back() == ';') + if (queryString.back() == ';') { queryString.resize(queryString.size() - 1); } @@ -569,7 +569,7 @@ namespace OC const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, PostCallback& callback, QualityOfService QoS) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -585,7 +585,7 @@ namespace OC auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; @@ -615,7 +615,7 @@ namespace OC const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, PutCallback& callback, QualityOfService QoS) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -631,7 +631,7 @@ namespace OC auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); OCDoHandle handle; @@ -663,7 +663,7 @@ namespace OC static_cast(ctx); HeaderOptions serverHeaderOptions; - if(clientResponse->result == OC_STACK_OK) + if (clientResponse->result == OC_STACK_OK) { parseServerHeaderOptions(clientResponse, serverHeaderOptions); } @@ -679,7 +679,7 @@ namespace OC DeleteCallback& callback, QualityOfService /*QoS*/) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -694,7 +694,7 @@ namespace OC auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { OCHeaderOption options[MAX_HEADER_OPTIONS]; @@ -728,7 +728,7 @@ namespace OC HeaderOptions serverHeaderOptions; uint32_t sequenceNumber = clientResponse->sequenceNumber; OCStackResult result = clientResponse->result; - if(clientResponse->result == OC_STACK_OK) + if (clientResponse->result == OC_STACK_OK) { parseServerHeaderOptions(clientResponse, serverHeaderOptions); try @@ -743,7 +743,7 @@ namespace OC std::thread exec(context->callback, serverHeaderOptions, attrs, result, sequenceNumber); exec.detach(); - if(sequenceNumber == OC_OBSERVE_DEREGISTER) + if (sequenceNumber == OC_OBSERVE_DEREGISTER) { return OC_STACK_DELETE_TRANSACTION; } @@ -756,7 +756,7 @@ namespace OC const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, ObserveCallback& callback, QualityOfService QoS) { - if(!callback) + if (!callback) { return OC_STACK_INVALID_PARAM; } @@ -788,7 +788,7 @@ namespace OC auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; @@ -821,7 +821,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); OCHeaderOption options[MAX_HEADER_OPTIONS]; @@ -863,7 +863,7 @@ namespace OC const std::string& host, const std::string& resourceType, OCConnectivityType connectivityType, SubscribeCallback& presenceHandler) { - if(!presenceHandler) + if (!presenceHandler) { return OC_STACK_INVALID_PARAM; } @@ -882,12 +882,12 @@ namespace OC std::ostringstream os; os << host << OC_RSRVD_PRESENCE_URI; - if(!resourceType.empty()) + if (!resourceType.empty()) { os << "?rt=" << resourceType; } - if(!cLock) + if (!cLock) { delete ctx; return OC_STACK_ERROR; @@ -904,7 +904,7 @@ namespace OC OCStackResult result; auto cLock = m_csdkLock.lock(); - if(cLock) + if (cLock) { std::lock_guard lock(*cLock); result = OCCancel(handle, OC_LOW_QOS, NULL, 0); @@ -928,7 +928,7 @@ namespace OC { int i = 0; - if( headerOptions.size() == 0) + if ( headerOptions.size() == 0) { return nullptr; } @@ -944,4 +944,144 @@ namespace OC return options; } + + std::shared_ptr cloneDevice(const OCDPDev_t* dev) + { + if (!dev) + { + return nullptr; + } + + OCDPDev_t* result = new OCDPDev_t(*dev); + result->prm = new OCPrm_t[dev->prmLen]; + memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen); + return std::shared_ptr(new OCDirectPairing(result)); + } + + void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList) + { + while(list) + { + dpList.push_back(cloneDevice(list)); + list = list->next; + } + } + + OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback& callback) + { + if (!callback || 0 == waittime) + { + return OC_STACK_INVALID_PARAM; + } + + OCStackResult result = OC_STACK_ERROR; + const OCDPDev_t *list = nullptr; + PairedDevices dpDeviceList; + + auto cLock = m_csdkLock.lock(); + + if (cLock) + { + std::lock_guard lock(*cLock); + + list = OCDiscoverDirectPairingDevices(waittime); + if (NULL == list) + { + result = OC_STACK_NO_RESOURCE; + oclog() << "findDirectPairingDevices(): No device found for direct pairing" + << std::flush; + } + else { + convert(list, dpDeviceList); + std::thread exec(callback, dpDeviceList); + exec.detach(); + result = OC_STACK_OK; + } + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback) + { + if (!callback) + { + return OC_STACK_INVALID_PARAM; + } + + OCStackResult result = OC_STACK_ERROR; + const OCDPDev_t *list = nullptr; + PairedDevices dpDeviceList; + + auto cLock = m_csdkLock.lock(); + + if (cLock) + { + std::lock_guard lock(*cLock); + + list = OCGetDirectPairedDevices(); + if (NULL == list) + { + result = OC_STACK_NO_RESOURCE; + oclog() << "findDirectPairingDevices(): No device found for direct pairing" + << std::flush; + } + else { + convert(list, dpDeviceList); + std::thread exec(callback, dpDeviceList); + exec.detach(); + result = OC_STACK_OK; + } + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + void directPairingCallback(void *ctx, OCDPDev_t *peer, + OCStackResult result) + { + + ClientCallbackContext::DirectPairingContext* context = + static_cast(ctx); + + std::thread exec(context->callback, cloneDevice(peer), result); + exec.detach(); + } + + OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr peer, + const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback) + { + if (!peer || !callback) + { + oclog() << "Invalid parameters" << std::flush; + return OC_STACK_INVALID_PARAM; + } + + OCStackResult result = OC_STACK_ERROR; + ClientCallbackContext::DirectPairingContext* context = + new ClientCallbackContext::DirectPairingContext(callback); + + auto cLock = m_csdkLock.lock(); + if (cLock) + { + std::lock_guard lock(*cLock); + result = OCDoDirectPairing(static_cast(context), peer->getDev(), + pmSel, const_cast(pinNumber.c_str()), directPairingCallback); + } + else + { + delete context; + result = OC_STACK_ERROR; + } + return result; + } } diff --git a/resource/src/OCDirectPairing.cpp b/resource/src/OCDirectPairing.cpp new file mode 100644 index 0000000..4e50ac7 --- /dev/null +++ b/resource/src/OCDirectPairing.cpp @@ -0,0 +1,85 @@ +//****************************************************************** +// +// Copyright 2016 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCDirectPairing.h" +#include + +namespace OC +{ + static const char COAP[] = "coap://"; + static const char COAPS[] = "coaps://"; + static const int UUID_LENGTH = (128/8); //UUID length + + OCDirectPairing::OCDirectPairing(OCDPDev_t *ptr):m_devPtr(ptr) + { + } + + std::string OCDirectPairing::getHost() + { + bool ipv6 = false; + std::ostringstream host(""); + if (m_devPtr->connType & CT_IP_USE_V6) + { + ipv6 = true; + } + + host << COAPS << (ipv6?"[":"") << m_devPtr->endpoint.addr; + host << (ipv6?"]:":":") << m_devPtr->securePort; + + return host.str(); + } + + std::string OCDirectPairing::getDeviceID() + { + std::ostringstream deviceId(""); + + for (int i = 0; i < UUID_LENGTH; i++) + { + if (i == 4 || i == 6 || i == 8 || i == 10) + { + deviceId << '-'; + } + deviceId << std::hex << std::setfill('0') << std::setw(2) << static_cast(m_devPtr->deviceID.id[i]); + } + + return deviceId.str(); + } + + std::vector OCDirectPairing::getPairingMethods() + { + std::vector prms; + + for (size_t i = 0; i < m_devPtr->prmLen; i++) + { + prms.push_back(m_devPtr->prm[i]); + } + return prms; + } + + OCConnectivityType OCDirectPairing::getConnType() + { + return m_devPtr->connType; + } + + OCDPDev_t* OCDirectPairing::getDev() + { + return m_devPtr; + } +} diff --git a/resource/src/OCPlatform.cpp b/resource/src/OCPlatform.cpp index e2e7aa5..b722750 100644 --- a/resource/src/OCPlatform.cpp +++ b/resource/src/OCPlatform.cpp @@ -43,7 +43,7 @@ namespace OC } OCStackResult notifyAllObservers(OCResourceHandle resourceHandle, - QualityOfService QoS) + QualityOfService QoS) { return OCPlatform_impl::Instance().notifyAllObservers(resourceHandle, QoS); } @@ -54,52 +54,52 @@ namespace OC } OCStackResult notifyListOfObservers(OCResourceHandle resourceHandle, - ObservationIds& observationIds, - const std::shared_ptr pResponse) + ObservationIds& observationIds, + const std::shared_ptr pResponse) { return OCPlatform_impl::Instance().notifyListOfObservers(resourceHandle, - observationIds, pResponse); + observationIds, pResponse); } OCStackResult notifyListOfObservers(OCResourceHandle resourceHandle, - ObservationIds& observationIds, - const std::shared_ptr pResponse, - QualityOfService QoS) + ObservationIds& observationIds, + const std::shared_ptr pResponse, + QualityOfService QoS) { return OCPlatform_impl::Instance().notifyListOfObservers(resourceHandle, - observationIds, pResponse, QoS); + observationIds, pResponse, QoS); } OCResource::Ptr constructResourceObject(const std::string& host, - const std::string& uri, - OCConnectivityType connectivityType, - bool isObservable, - const std::vector& resourceTypes, - const std::vector& interfaces) + const std::string& uri, + OCConnectivityType connectivityType, + bool isObservable, + const std::vector& resourceTypes, + const std::vector& interfaces) { return OCPlatform_impl::Instance().constructResourceObject(host, - uri, connectivityType, - isObservable, - resourceTypes, interfaces); + uri, connectivityType, + isObservable, + resourceTypes, interfaces); } OCStackResult findResource(const std::string& host, - const std::string& resourceName, - OCConnectivityType connectivityType, - FindCallback resourceHandler) + const std::string& resourceName, + OCConnectivityType connectivityType, + FindCallback resourceHandler) { return OCPlatform_impl::Instance().findResource(host, resourceName, - connectivityType, resourceHandler); + connectivityType, resourceHandler); } OCStackResult findResource(const std::string& host, - const std::string& resourceName, - OCConnectivityType connectivityType, - FindCallback resourceHandler, - QualityOfService QoS) + const std::string& resourceName, + OCConnectivityType connectivityType, + FindCallback resourceHandler, + QualityOfService QoS) { return OCPlatform_impl::Instance().findResource(host, resourceName, - connectivityType, resourceHandler, QoS); + connectivityType, resourceHandler, QoS); } OCStackResult findResource(const std::string& host, @@ -124,57 +124,57 @@ namespace OC } OCStackResult getDeviceInfo(const std::string& host, - const std::string& deviceURI, - OCConnectivityType connectivityType, - FindDeviceCallback deviceInfoHandler) + const std::string& deviceURI, + OCConnectivityType connectivityType, + FindDeviceCallback deviceInfoHandler) { return OCPlatform_impl::Instance().getDeviceInfo(host, deviceURI, - connectivityType, deviceInfoHandler); + connectivityType, deviceInfoHandler); } OCStackResult getDeviceInfo(const std::string& host, - const std::string& deviceURI, - OCConnectivityType connectivityType, - FindDeviceCallback deviceInfoHandler, - QualityOfService QoS) + const std::string& deviceURI, + OCConnectivityType connectivityType, + FindDeviceCallback deviceInfoHandler, + QualityOfService QoS) { return OCPlatform_impl::Instance().getDeviceInfo(host, deviceURI, connectivityType, - deviceInfoHandler, QoS); + deviceInfoHandler, QoS); } OCStackResult getPlatformInfo(const std::string& host, - const std::string& platformURI, - OCConnectivityType connectivityType, - FindPlatformCallback platformInfoHandler) + const std::string& platformURI, + OCConnectivityType connectivityType, + FindPlatformCallback platformInfoHandler) { return OCPlatform_impl::Instance().getPlatformInfo(host, platformURI, - connectivityType, platformInfoHandler); + connectivityType, platformInfoHandler); } OCStackResult getPlatformInfo(const std::string& host, - const std::string& platformURI, - OCConnectivityType connectivityType, - FindPlatformCallback platformInfoHandler, - QualityOfService QoS) + const std::string& platformURI, + OCConnectivityType connectivityType, + FindPlatformCallback platformInfoHandler, + QualityOfService QoS) { return OCPlatform_impl::Instance().getPlatformInfo(host, platformURI, connectivityType, - platformInfoHandler, QoS); + platformInfoHandler, QoS); } OCStackResult registerResource(OCResourceHandle& resourceHandle, - std::string& resourceURI, - const std::string& resourceTypeName, - const std::string& resourceInterface, - EntityHandler entityHandler, - uint8_t resourceProperty) + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler entityHandler, + uint8_t resourceProperty) { return OCPlatform_impl::Instance().registerResource(resourceHandle, resourceURI, - resourceTypeName, resourceInterface, - entityHandler, resourceProperty); + resourceTypeName, resourceInterface, + entityHandler, resourceProperty); } OCStackResult registerResource(OCResourceHandle& resourceHandle, - const std::shared_ptr< OCResource > resource) + const std::shared_ptr< OCResource > resource) { return OCPlatform_impl::Instance().registerResource(resourceHandle, resource); } @@ -195,42 +195,41 @@ namespace OC } OCStackResult unbindResource(OCResourceHandle collectionHandle, - OCResourceHandle resourceHandle) + OCResourceHandle resourceHandle) { return OCPlatform_impl::Instance().unbindResource(collectionHandle, resourceHandle); } OCStackResult unbindResources(const OCResourceHandle collectionHandle, - const std::vector& resourceHandles - ) + const std::vector& resourceHandles) { return OCPlatform_impl::Instance().unbindResources(collectionHandle, resourceHandles); } OCStackResult bindResource(const OCResourceHandle collectionHandle, - const OCResourceHandle resourceHandle) + const OCResourceHandle resourceHandle) { return OCPlatform_impl::Instance().bindResource(collectionHandle, resourceHandle); } OCStackResult bindResources(const OCResourceHandle collectionHandle, - const std::vector& resourceHandles - ) + const std::vector& resourceHandles + ) { return OCPlatform_impl::Instance().bindResources(collectionHandle, resourceHandles); } OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle, - const std::string& resourceTypeName) + const std::string& resourceTypeName) { return OCPlatform_impl::Instance().bindTypeToResource(resourceHandle,resourceTypeName); } OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle, - const std::string& resourceInterfaceName) + const std::string& resourceInterfaceName) { return OCPlatform_impl::Instance().bindInterfaceToResource(resourceHandle, - resourceInterfaceName); + resourceInterfaceName); } OCStackResult startPresence(const unsigned int announceDurationSeconds) @@ -244,22 +243,22 @@ namespace OC } OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, - const std::string& host, - OCConnectivityType connectivityType, - SubscribeCallback presenceHandler) + const std::string& host, + OCConnectivityType connectivityType, + SubscribeCallback presenceHandler) { return OCPlatform_impl::Instance().subscribePresence(presenceHandle, host, - connectivityType, presenceHandler); + connectivityType, presenceHandler); } OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, - const std::string& host, - const std::string& resourceType, - OCConnectivityType connectivityType, - SubscribeCallback presenceHandler) + const std::string& host, + const std::string& resourceType, + OCConnectivityType connectivityType, + SubscribeCallback presenceHandler) { return OCPlatform_impl::Instance().subscribePresence(presenceHandle, host, - resourceType, connectivityType, presenceHandler); + resourceType, connectivityType, presenceHandler); } OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle) @@ -271,6 +270,27 @@ namespace OC { return OCPlatform_impl::Instance().sendResponse(pResponse); } + + OCStackResult findDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback directPairingHandler) + { + return OCPlatform_impl::Instance().findDirectPairingDevices(waittime, + directPairingHandler); + } + + OCStackResult getDirectPairedDevices(GetDirectPairedCallback directPairingHandler) + { + return OCPlatform_impl::Instance().getDirectPairedDevices(directPairingHandler); + } + + OCStackResult doDirectPairing(std::shared_ptr peer, OCPrm_t pmSel, + const std::string& pinNumber, + DirectPairingCallback resultCallback) + { + return OCPlatform_impl::Instance().doDirectPairing(peer, pmSel, + pinNumber, resultCallback); + } + } // namespace OCPlatform } //namespace OC diff --git a/resource/src/OCPlatform_impl.cpp b/resource/src/OCPlatform_impl.cpp index 059944c..03fa1d9 100644 --- a/resource/src/OCPlatform_impl.cpp +++ b/resource/src/OCPlatform_impl.cpp @@ -387,5 +387,31 @@ namespace OC { return m_csdkLock; } + + OCStackResult OCPlatform_impl::findDirectPairingDevices(unsigned short waittime, + GetDirectPairedCallback directPairingHandler) + { + return checked_guard(m_client, &IClientWrapper::FindDirectPairingDevices, + waittime, directPairingHandler); + + } + + OCStackResult OCPlatform_impl::getDirectPairedDevices( + GetDirectPairedCallback directPairingHandler) + { + + return checked_guard(m_client, &IClientWrapper::GetDirectPairedDevices, + directPairingHandler); + } + + OCStackResult OCPlatform_impl::doDirectPairing(std::shared_ptr peer, + OCPrm_t pmSel, + const std::string& pinNumber, + DirectPairingCallback resultCallback) + { + return checked_guard(m_client, &IClientWrapper::DoDirectPairing, + peer, pmSel, pinNumber, resultCallback); + } + } //namespace OC diff --git a/resource/src/OCResource.cpp b/resource/src/OCResource.cpp index a3c8ec8..9ea55f6 100644 --- a/resource/src/OCResource.cpp +++ b/resource/src/OCResource.cpp @@ -122,7 +122,7 @@ void OCResource::setHost(const std::string& host) else if(host.compare(0, sizeof(COAPS) - 1, COAPS) == 0) { prefix_len = sizeof(COAPS) - 1; - m_devAddr.flags = static_cast(m_devAddr.flags & OC_SECURE); + m_devAddr.flags = static_cast(m_devAddr.flags | OC_SECURE); } else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0) { diff --git a/resource/src/SConscript b/resource/src/SConscript index f1106a1..acfe0e1 100644 --- a/resource/src/SConscript +++ b/resource/src/SConscript @@ -80,7 +80,8 @@ oclib_src = [ 'InProcServerWrapper.cpp', 'InProcClientWrapper.cpp', 'OCResourceRequest.cpp', - 'CAManager.cpp' + 'CAManager.cpp', + 'OCDirectPairing.cpp' ] oclib = oclib_env.SharedLibrary('oc', oclib_src) @@ -115,6 +116,7 @@ oclib_env.UserInstallTargetHeader(header_dir + 'OCResourceResponse.h', 'resource oclib_env.UserInstallTargetHeader(header_dir + 'OCUtilities.h', 'resource', 'OCUtilities.h') oclib_env.UserInstallTargetHeader(header_dir + 'CAManager.h', 'resource', 'CAManager.h') +oclib_env.UserInstallTargetHeader(header_dir + 'OCDirectPairing.h', 'resource', 'OCDirectPairing.h') # Add Provisioning library if target_os in ['linux', 'android', 'tizen'] and env.get('SECURED') == '1': diff --git a/resource/unittests/OCPlatformTest.cpp b/resource/unittests/OCPlatformTest.cpp index fc59f96..93f62e4 100644 --- a/resource/unittests/OCPlatformTest.cpp +++ b/resource/unittests/OCPlatformTest.cpp @@ -62,6 +62,14 @@ namespace OCPlatformTest { } + void directPairHandler(std::shared_ptr /*dev*/, OCStackResult /*res*/) + { + } + + void pairedHandler(const PairedDevices& /*list*/) + { + } + //Helper methods void DeleteStringLL(OCStringLL* ll) { @@ -818,4 +826,46 @@ namespace OCPlatformTest OC_MULTICAST_IP, CT_DEFAULT, &presenceHandler)); EXPECT_EQ(OC_STACK_OK, OCPlatform::unsubscribePresence(presenceHandle)); } + + TEST(FindDirectPairingTest, FindDirectPairingNullCallback) + { + EXPECT_ANY_THROW(OCPlatform::findDirectPairingDevices(1, nullptr)); + } + + TEST(FindDirectPairingTest, FindDirectPairingZeroTimeout) + { + EXPECT_ANY_THROW(OCPlatform::findDirectPairingDevices(0, &pairedHandler)); + } + + TEST(GetDirectPairedTest, GetDirectPairedNullCallback) + { + EXPECT_ANY_THROW(OCPlatform::getDirectPairedDevices(nullptr)); + } + + TEST(DoDirectPairingTest, DoDirectPairingNullCallback) + { + OCDPDev_t peer; + OCPrm_t pmSel = DP_PRE_CONFIGURED; + std::string pin(""); + std::shared_ptr s_dp(new OCDirectPairing(&peer)); + EXPECT_ANY_THROW(OCPlatform::doDirectPairing(s_dp, pmSel, pin, nullptr)); + } + + TEST(DoDirectPairingTest, DoDirectPairingNullPeer) + { + OCDPDev_t peer; + OCPrm_t pmSel = DP_PRE_CONFIGURED; + std::string pin(""); + std::shared_ptr s_dp(new OCDirectPairing(&peer)); + EXPECT_ANY_THROW(OCPlatform::doDirectPairing(nullptr, pmSel, pin, &directPairHandler)); + } + + TEST(DoDirectPairingTest, DoDirectPairingNullPeerNullCallback) + { + OCDPDev_t peer; + OCPrm_t pmSel = DP_PRE_CONFIGURED; + std::string pin(""); + std::shared_ptr s_dp(new OCDirectPairing(&peer)); + EXPECT_ANY_THROW(OCPlatform::doDirectPairing(nullptr, pmSel, pin, nullptr)); + } }