From: hyuna0213.jo Date: Wed, 20 Jul 2016 22:56:24 +0000 (+0900) Subject: RD client features in base layer X-Git-Tag: 1.2.0+RC1~179 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ce6c2531d2044bdbb5ffc884a2182de7a52794cc;p=platform%2Fupstream%2Fiotivity.git RD client features in base layer - make consistency with the revised RD spec. - modified build command with RD_MODE=CLIENT or SERVER - add the RD client API in base layer. 1. publish resource to resource-directory 2. delete resource from resource-directory - remove the build script related current RD implementation in service layer. after RD server features is implemented in base layer, it will be removed totally. Change-Id: I992ff34b839cc845c5e44eb1198906bdcc0e2ec0 Signed-off-by: hyuna0213.jo Reviewed-on: https://gerrit.iotivity.org/gerrit/8983 Tested-by: jenkins-iotivity Reviewed-by: jihwan seo Reviewed-by: Jaehong Jo Reviewed-by: Habib Virji Reviewed-by: Ashok Babu Channa --- diff --git a/build_common/SConscript b/build_common/SConscript index 9756ca05e..ca26680d5 100644 --- a/build_common/SConscript +++ b/build_common/SConscript @@ -87,8 +87,8 @@ help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map help_vars.Add(BoolVariable('WITH_RA', 'Build with Remote Access module', False)) help_vars.Add(BoolVariable('WITH_TCP', 'Build with TCP adapter', False)) help_vars.Add(ListVariable('WITH_MQ', 'Build with MQ publisher/broker', 'OFF', ['OFF', 'SUB', 'PUB', 'BROKER'])) -help_vars.Add(EnumVariable('WITH_RD', 'Build including Resource Directory', '0', allowed_values=('0', '1'))) help_vars.Add(BoolVariable('WITH_CLOUD', 'Build including Cloud Connector and Cloud Client sample', False)) +help_vars.Add(ListVariable('RD_MODE', 'Resource Directory build mode', 'CLIENT', ['CLIENT', 'SERVER'])) help_vars.Add(BoolVariable('SIMULATOR', 'Build with simulator module', False)) diff --git a/resource/csdk/SConscript b/resource/csdk/SConscript index 9b31045bd..d3459d30b 100644 --- a/resource/csdk/SConscript +++ b/resource/csdk/SConscript @@ -29,6 +29,7 @@ SConscript('#resource/third_party_libs.scons', 'lib_env') liboctbstack_env = lib_env.Clone() target_os = env.get('TARGET_OS') +rd_mode = env.get('RD_MODE') with_ra = env.get('WITH_RA') with_ra_ibb = env.get('WITH_RA_IBB') with_tcp = env.get('WITH_TCP') @@ -121,12 +122,6 @@ if env.get('LOGGING'): if env.get('DTLS_WITH_X509') == '1': liboctbstack_env.AppendUnique(CPPDEFINES = ['__WITH_X509__']) -if env.get('WITH_RD') == '1': - liboctbstack_env.PrependUnique(CPPPATH = ['../../service/resource-directory/include']) - liboctbstack_env.PrependUnique(LIBPATH = [env.get('BUILD_DIR') + 'service/resource-directory/include']) - liboctbstack_env.AppendUnique(CPPDEFINES = ['-DWITH_RD']) - liboctbstack_env.AppendUnique(LIBS = ['resource_directory']) - liboctbstack_env.Append(LIBS = ['c_common']) if liboctbstack_env.get('ROUTING') in ['GW', 'EP']: @@ -148,10 +143,17 @@ liboctbstack_src = [ OCTBSTACK_SRC + 'ocobserve.c', OCTBSTACK_SRC + 'ocserverrequest.c', OCTBSTACK_SRC + 'occollection.c', - OCTBSTACK_SRC + 'oicgroup.c', - OCTBSTACK_SRC + "rdpayload.c" + OCTBSTACK_SRC + 'oicgroup.c' ] +if 'CLIENT' in rd_mode or 'SERVER' in rd_mode: + liboctbstack_src.append(OCTBSTACK_SRC + 'rdpayload.c') + liboctbstack_src.append(OCTBSTACK_SRC + 'oicresourcedirectory.c') + if 'CLIENT' in rd_mode: + liboctbstack_env.AppendUnique(CPPDEFINES = ['RD_CLIENT']) + if 'SERVER' in rd_mode: + liboctbstack_env.AppendUnique(CPPDEFINES = ['RD_SERVER']) + if with_tcp == True: liboctbstack_src.append(OCTBSTACK_SRC + 'oickeepalive.c') diff --git a/resource/csdk/connectivity/test/SConscript b/resource/csdk/connectivity/test/SConscript index 2b6a0d367..71dbddaf8 100644 --- a/resource/csdk/connectivity/test/SConscript +++ b/resource/csdk/connectivity/test/SConscript @@ -50,9 +50,6 @@ if catest_env.get('SECURED') == '1': catest_env.AppendUnique(LIBS = ['tinydtls']) catest_env.AppendUnique(LIBS = ['timer']) -if catest_env.get('WITH_RD') == '1': - catest_env.PrependUnique(LIBS = ['resource_directory']) - if catest_env.get('LOGGING'): catest_env.AppendUnique(CPPDEFINES = ['TB_LOG']) diff --git a/resource/csdk/stack/include/internal/ocresource.h b/resource/csdk/stack/include/internal/ocresource.h index 2113320bf..27409421c 100755 --- a/resource/csdk/stack/include/internal/ocresource.h +++ b/resource/csdk/stack/include/internal/ocresource.h @@ -240,6 +240,17 @@ typedef struct OCResource { /** Pointer of ActionSet which to support group action.*/ OCActionSet *actionsetHead; + + /** The instance identifier for this web link in an array of web links - used in links. */ + union + { + /** An ordinal number that is not repeated - must be unique in the collection context. */ + uint8_t ins; + /** Any unique string including a URI. */ + char *uniqueStr; + /** Use UUID for universal uniqueness - used in /oic/res to identify the device. */ + OCIdentity uniqueUUID; + }; } OCResource; diff --git a/resource/csdk/stack/include/ocstack.h b/resource/csdk/stack/include/ocstack.h index 72325a22d..ea7daf8b6 100644 --- a/resource/csdk/stack/include/ocstack.h +++ b/resource/csdk/stack/include/ocstack.h @@ -558,6 +558,37 @@ OC_EXPORT const OCDPDev_t* OCGetDirectPairedDevices(); */ OC_EXPORT OCStackResult OCDoDirectPairing(void *ctx, OCDPDev_t* peer, OCPrm_t pmSel, char *pinNumber, OCDirectPairingCB resultCallback); + +#if defined(RD_CLIENT) || defined(RD_SERVER) +/** + * This function binds an resource unique id to the resource. + * + * @param handle Handle to the resource that the contained resource is to be bound. + * @param ins Unique ID for resource. + * + * @return ::OC_STACK_OK on success, some other value upon failure. + */ +OC_EXPORT OCStackResult OCBindResourceInsToResource(OCResourceHandle handle, uint8_t ins); + +/** + * This function gets the resource unique id for a resource. + * + * @param handle Handle of resource. + * @param ins Unique ID for resource. + * + * @return Ins if resource found or 0 resource not found. + */ +OC_EXPORT OCStackResult OCGetResourceIns(OCResourceHandle handle, uint8_t *ins); + +/** + * This function gets a resource handle by resource uri. + * + * @param uri Uri of Resource to get Resource handle. + * + * @return Found resource handle or NULL if not found. + */ +OC_EXPORT OCResourceHandle OCGetResourceHandleAtUri(const char *uri); +#endif //#endif // DIRECT_PAIRING #ifdef __cplusplus diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index a78118b35..6cc333583 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -168,6 +168,9 @@ extern "C" { /** To represent interface.*/ #define OC_RSRVD_INTERFACE "if" +/** To indicate how long RD should publish this item.*/ +#define OC_RSRVD_DEVICE_TTL "lt" + /** To represent time to live.*/ #define OC_RSRVD_TTL "ttl" @@ -314,7 +317,7 @@ extern "C" { #define MAC_ADDR_BLOCKS (6) /** Max identity size. */ -#define MAX_IDENTITY_SIZE (32) +#define MAX_IDENTITY_SIZE (37) /** Universal unique identity size. */ #define UUID_IDENTITY_SIZE (128/8) @@ -349,10 +352,10 @@ extern "C" { #define OC_RSRVD_TITLE "title" /** Defines URI. */ -#define OC_RSRVD_URI "uri" +#define OC_RSRVD_URI "anchor" /** Defines media type. */ -#define OC_RSRVD_MEDIA_TYPE "mt" +#define OC_RSRVD_MEDIA_TYPE "type" /** To represent resource type with Publish RD.*/ #define OC_RSRVD_RESOURCE_TYPE_RDPUBLISH "oic.wk.rdpub" @@ -1193,20 +1196,20 @@ typedef struct OCLinksPayload { /** This is the target relative URI. */ char *href; + /** The relation of the target URI referenced by the link to the context URI; + * The default value is null. */ + char *rel; /** Resource Type - A standard OIC specified or vendor defined resource * type of the resource referenced by the target URI. */ OCStringLL *rt; /** Interface - The interfaces supported by the resource referenced by the target URI. */ OCStringLL *itf; - /** The relation of the target URI referenced by the link to the context URI; - * The default value is null. */ - char *rel; - /** Specifies if the resource referenced by the target URIis observable or not. */ - bool obs; + /** Bitmap - The bitmap holds observable, discoverable, secure option flag. */ + uint8_t p; /** A title for the link relation. Can be used by the UI to provide a context. */ char *title; /** This is used to override the context URI e.g. override the URI of the containing collection. */ - char *uri; + char *anchor; /** The instance identifier for this web link in an array of web links - used in links. */ union { @@ -1217,8 +1220,10 @@ typedef struct OCLinksPayload /** Use UUID for universal uniqueness - used in /oic/res to identify the device. */ OCIdentity uniqueUUID; }; + /** Time to keep holding resource.*/ + uint64_t ttl; /** A hint of the media type of the representation of the resource referenced by the target URI. */ - OCStringLL *mt; + OCStringLL *type; /** Holding address of the next resource. */ struct OCLinksPayload *next; } OCLinksPayload; @@ -1230,30 +1235,8 @@ typedef struct OCDeviceInfo n; /** Device identifier. */ OCIdentity di; - /** The base URI where the resources are hold. */ - char *baseURI; - /** Bitmap holds observable, discoverable, secure option flag.*/ - uint8_t bitmap; - /** Port set in case, the secure flag is set above. */ - uint16_t port; - /** Id for each set of links i.e. tag. */ - union - { - /** An ordinal number that is not repeated - must be unique in the collection context. */ - uint8_t ins; - /** Any unique string including a URI. */ - char *uniqueStr; - /** Use UUID for universal uniqueness - used in /oic/res to identify the device. */ - OCIdentity uniqueUUID; - }; - /** Defines the list of allowable resource types (for Target and anchors) in links included - * in the collection; new links being created can only be from this list. */ - char *rts; - /** When specified this is the default relationship to use when an OIC Link does not specify - * an explicit relationship with *rel* parameter. */ - char *drel; /** Time to keep holding resource.*/ - uint32_t ttl; + uint64_t ttl; } OCTagsPayload; /** Resource collection payload. */ @@ -1263,8 +1246,6 @@ typedef struct OCResourceCollectionPayload OCTagsPayload *tags; /** Array of links payload. */ OCLinksPayload *setLinks; - /** Holding address of the next resource. */ - struct OCResourceCollectionPayload *next; } OCResourceCollectionPayload; typedef struct OCDiscoveryPayload diff --git a/resource/csdk/stack/include/oicresourcedirectory.h b/resource/csdk/stack/include/oicresourcedirectory.h new file mode 100644 index 000000000..e6aa56c8a --- /dev/null +++ b/resource/csdk/stack/include/oicresourcedirectory.h @@ -0,0 +1,72 @@ +//****************************************************************** +// +// 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_RESOURCE_DIRECTORY_H_ +#define OC_RESOURCE_DIRECTORY_H_ + +#include "octypes.h" +#include "logger.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifdef RD_CLIENT +/** + * Publish RD resource to Resource Directory. + * + * @param host The address of the RD. + * @param connectivityType Type of connectivity indicating the interface. + * @param resourceHandles This is the resource handle which we need to register to RD. + * @param nHandles The counts of resource handle. + * @param cbData Asynchronous callback function that is invoked by the stack when + * response is received. The callback is generated for each response + * received. + * @param qos Quality of service. + * + * @return ::OC_STACK_OK on success, some other value upon failure. + */ +OC_EXPORT OCStackResult OCRDPublish(const char *host, OCConnectivityType connectivityType, + OCResourceHandle resourceHandles[], uint8_t nHandles, + OCCallbackData *cbData, OCQualityOfService qos); + +/** + * Delete RD resource from Resource Directory. + * + * @param host The address of the RD. + * @param connectivityType Type of connectivity indicating the interface. + * @param resourceHandles This is the resource handle which we need to delete to RD. + * @param nHandles The counts of resource handle. + * @param cbData Asynchronous callback function that is invoked by the stack when + * response is received. The callback is generated for each response + * received. + * @param qos Quality of service. + * + * @return ::OC_STACK_OK on success, some other value upon failure. + */ +OC_EXPORT OCStackResult OCRDDelete(const char *host, OCConnectivityType connectivityType, + OCResourceHandle resourceHandles[], uint8_t nHandles, + OCCallbackData *cbData, OCQualityOfService qos); +#endif +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* OC_RESOURCE_DIRECTORY_H_ */ diff --git a/resource/csdk/stack/include/payload_logging.h b/resource/csdk/stack/include/payload_logging.h index 093995556..44371c7e1 100644 --- a/resource/csdk/stack/include/payload_logging.h +++ b/resource/csdk/stack/include/payload_logging.h @@ -49,6 +49,93 @@ extern "C" OC_EXPORT const char *convertTriggerEnumToString(OCPresenceTrigger trigger); OC_EXPORT OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr); +#if defined(RD_CLIENT) || defined(RD_SERVER) +INLINE_API void OCTagsLog(const LogLevel level, const OCTagsPayload *tags) +{ + if (tags) + { + if (tags->n.deviceName) + { + OIC_LOG_V(level, PL_TAG, " Device Name : %s ", tags->n.deviceName); + } + if (tags->di.id) + { + OIC_LOG_V(level, PL_TAG, " Device ID : %s ", tags->di.id); + } + OIC_LOG_V(level, PL_TAG, " lt : %lld ",tags->ttl); + } + else + { + (void) level; + } +} + +INLINE_API void OCLinksLog(const LogLevel level, const OCLinksPayload *links) +{ + if (!links) + { + return; + } + + while (links) + { + if (links->href) + { + OIC_LOG_V(level, PL_TAG, " href: %s ",links->href); + } + OIC_LOG(level, PL_TAG, " RT: "); + OCStringLL *rt = links->rt; + while (rt) + { + if (rt->value) + { + OIC_LOG_V(level, PL_TAG, " %s", rt->value); + } + rt = rt->next; + } + OIC_LOG(level, PL_TAG, " IF: "); + OCStringLL *itf = links->itf; + while (itf) + { + if (itf->value) + { + OIC_LOG_V(level, PL_TAG, " %s", itf->value); + } + itf = itf->next; + } + OIC_LOG(level, PL_TAG, " MT: "); + OCStringLL *mt = links->type; + while (mt) + { + if (mt->value) + { + OIC_LOG_V(level, PL_TAG, " %s", mt->value); + } + mt = mt->next; + } + if (links->type) + { + OIC_LOG_V(level, PL_TAG, " %s", links->type); + } + OIC_LOG_V(level, PL_TAG, " INS: %d", links->ins); + OIC_LOG_V(level, PL_TAG, " TTL: %d", links->ttl); + OIC_LOG_V(level, PL_TAG, " P: %d", links->p); + if (links->rel) + { + OIC_LOG_V(level, PL_TAG, " REL: %s", links->rel); + } + if (links->title) + { + OIC_LOG_V(level, PL_TAG, " TITLE: %s", links->title); + } + if (links->anchor) + { + OIC_LOG_V(level, PL_TAG, " URI: %s", links->anchor); + } + links = links->next; + } +} +#endif INLINE_API void OCPayloadLogRep(LogLevel level, OCRepPayload* payload) { OIC_LOG(level, (PL_TAG), "Payload Type: Representation"); @@ -310,6 +397,7 @@ INLINE_API void OCPayloadLogSecurity(LogLevel level, OCSecurityPayload* payload) OIC_LOG_V(level, PL_TAG, "\tSecurity Data: %s", payload->securityData); } +#if defined(RD_CLIENT) || defined(RD_SERVER) INLINE_API void OCRDPayloadLog(const LogLevel level, const OCRDPayload *payload) { if (!payload) @@ -332,7 +420,7 @@ INLINE_API void OCRDPayloadLog(const LogLevel level, const OCRDPayload *payload) OCLinksLog(level, rdPublish->setLinks); } } - +#endif INLINE_API void OCPayloadLog(LogLevel level, OCPayload* payload) { if(!payload) @@ -360,9 +448,11 @@ INLINE_API void OCPayloadLog(LogLevel level, OCPayload* payload) case PAYLOAD_TYPE_SECURITY: OCPayloadLogSecurity(level, (OCSecurityPayload*)payload); break; +#if defined(RD_CLIENT) || defined(RD_SERVER) case PAYLOAD_TYPE_RD: OCRDPayloadLog(level, (OCRDPayload*)payload); break; +#endif default: OIC_LOG_V(level, PL_TAG, "Unknown Payload Type: %d", payload->type); break; diff --git a/resource/csdk/stack/include/rdpayload.h b/resource/csdk/stack/include/rdpayload.h index d75cd8ed9..2afa3201e 100644 --- a/resource/csdk/stack/include/rdpayload.h +++ b/resource/csdk/stack/include/rdpayload.h @@ -29,6 +29,12 @@ extern "C" { #endif // __cplusplus +#define OIC_RD_PUBLISH_TTL 86400 + +#define OIC_RD_DEFAULT_RESOURCE 2 + +#define DEFAULT_MESSAGE_TYPE "application/json" + /** * Converts RD payload from structure to CBOR format. It creates the outPayload * which is then transmitted over the wire. @@ -65,6 +71,21 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay */ OCRDPayload *OCRDPayloadCreate(); +#ifdef RD_CLIENT +/** + * Initializes RD Publish payload structure. + * + * @param resourceHandles The handle of registered resource. + * @param nHandles The number of registered resource handles. + * @param ttl Time to live of the published resource. + * + * @return Allocated memory for the OCRDPayload and NULL in case if + * failed to allocate memory. + */ +OCRDPayload *OCRDPublishPayloadCreate(OCResourceHandle resourceHandles[], uint8_t nHandles, + uint64_t ttl); +#endif + /** * Initializes RD Discovery payload structure and sets the bias factor. * @@ -89,37 +110,33 @@ void OCRDPayloadDestroy(OCRDPayload *payload); * Copies tag paramter to creates OCTagsPayload. * * @param deviceName The device name as set during enrollment. - * @param id The device UUID - * @param baseURI baseURI pointing to the resource directory location. - * @param bitmap The bitmap value include observe, discovery and secure bit set. - * @param port The secure port in case above bitmap is set to secure. - * @param ins Unique value per collection. - * @param rts Defines allowed resource types. - * @param drel Defines defaultr relationship. + * @param id The device UUID. * @param ttl Time to leave for the . Used only in resource directory. * * @retun Allocated memory for OCTagsPayload or else NULL in case of error. */ -OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char *id, - const char *baseURI, uint8_t bitmap, uint16_t port, uint8_t ins, const char *rts, const char *drel, uint32_t ttl); +OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char *id, uint64_t ttl); /** * Copies link resource to create LinksPayload. * * @param href URI of the resource + * @param rel Relation * @param rt Array of String pointing to resource types. * @param itf Array of String pointing to interface - * @param rel Relation - * @param obs Whether to observe or not. + * @param p Whether to observe or not. * @param title Title - * @param uri URI + * @param anchor URI * @param ins Unique value per link. + * @param ttl Time to live for this link. * @param mt Media Type - * @retun Allocated memory for OCLinksPayload or else NULL in case of error. + * @retun Allocated memory for OCLinksResource or else NULL in case of error. */ -OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringLL *itf, - const char *rel, bool obs, const char *title, const char *uri, uint8_t ins, OCStringLL *mt); +OCLinksPayload* OCCopyLinksResources(const char *href, const char *rel, OCStringLL *rt, + OCStringLL *itf, uint8_t p, const char *title, + const char *anchor, uint8_t ins, uint64_t ttl, + OCStringLL *mt); /** * Creates a resource collection object. @@ -159,22 +176,6 @@ void OCFreeCollectionResource(OCResourceCollectionPayload *payload); */ void OCDiscoveryCollectionPayloadDestroy(OCDiscoveryPayload* payload); -/** - * Prints tags payload. - * - * @param level LogLevel for the print. - * @param tags Structure of the tags payload. - */ -OC_EXPORT void OCTagsLog(const LogLevel level, const OCTagsPayload *tags); - -/** - * Prints links payload. - * - * @param level LogLevel for the print. - * @param tags Structure of the links payload. - */ -OC_EXPORT void OCLinksLog(const LogLevel level, const OCLinksPayload *links); - #ifdef __cplusplus } #endif // __cplusplus diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index 5c5a2e768..b308c0fc1 100644 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -64,9 +64,11 @@ void OCPayloadDestroy(OCPayload* payload) case PAYLOAD_TYPE_SECURITY: OCSecurityPayloadDestroy((OCSecurityPayload*)payload); break; +#if defined(RD_CLIENT) || defined(RD_SERVER) case PAYLOAD_TYPE_RD: OCRDPayloadDestroy((OCRDPayload*)payload); break; +#endif default: OIC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type); OICFree(payload); diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index e1edc0d50..60c8807f4 100644 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -28,7 +28,10 @@ #include "ocrandom.h" #include "ocresourcehandler.h" #include "cbor.h" + +#if defined(RD_CLIENT) || defined(RD_SERVER) #include "rdpayload.h" +#endif #define TAG "OIC_RI_PAYLOADCONVERT" @@ -155,8 +158,10 @@ static int64_t OCConvertPayloadHelper(OCPayload* payload, uint8_t* outPayload, s return OCConvertPresencePayload((OCPresencePayload*)payload, outPayload, size); case PAYLOAD_TYPE_SECURITY: return OCConvertSecurityPayload((OCSecurityPayload*)payload, outPayload, size); +#if defined(RD_CLIENT) || defined(RD_SERVER) case PAYLOAD_TYPE_RD: return OCRDPayloadToCbor((OCRDPayload*)payload, outPayload, size); +#endif default: OIC_LOG_V(INFO,TAG, "ConvertPayload default %d", payload->type); return CborErrorUnknownType; diff --git a/resource/csdk/stack/src/ocpayloadparse.c b/resource/csdk/stack/src/ocpayloadparse.c index c82049027..612183936 100644 --- a/resource/csdk/stack/src/ocpayloadparse.c +++ b/resource/csdk/stack/src/ocpayloadparse.c @@ -34,9 +34,12 @@ #include "ocpayloadcbor.h" #include "ocstackinternal.h" #include "payload_logging.h" -#include "rdpayload.h" #include "platform_features.h" +#if defined(RD_CLIENT) || defined(RD_SERVER) +#include "rdpayload.h" +#endif + #define TAG "OIC_RI_PAYLOADPARSE" static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *arrayVal); @@ -86,9 +89,11 @@ OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType, case PAYLOAD_TYPE_SECURITY: result = OCParseSecurityPayload(outPayload, payload, payloadSize); break; +#if defined(RD_CLIENT) || defined(RD_SERVER) case PAYLOAD_TYPE_RD: result = OCRDCborToPayload(&rootValue, outPayload); break; +#endif default: OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType); result = OC_STACK_INVALID_PARAM; diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c index 44a2135fb..4cd74f429 100755 --- a/resource/csdk/stack/src/ocresource.c +++ b/resource/csdk/stack/src/ocresource.c @@ -29,7 +29,7 @@ #ifdef WITH_STRING_H #include #endif -#ifdef WITH_STRINGS_H +#ifdef WITH_STRING_H #include #endif @@ -45,13 +45,8 @@ #include "secureresourcemanager.h" #include "cacommon.h" #include "cainterface.h" -#include "rdpayload.h" #include "ocpayload.h" -#ifdef WITH_RD -#include "rd_server.h" -#endif - #ifdef ROUTING_GATEWAY #include "routingmanager.h" #endif @@ -617,102 +612,6 @@ OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCRes return OCDoResponse(&response); } -#ifdef WITH_RD -static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType, - OCResource **payload, OCDevAddr *devAddr) -{ - OCResourceCollectionPayload *repPayload; - if (!payload) - { - return OC_STACK_ERROR; - } - if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK) - { - if (!repPayload) - { - return OC_STACK_ERROR; - } - OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource))); - if (!ptr) - { - return OC_STACK_NO_MEMORY; - } - - ptr->uri = OICStrdup(repPayload->setLinks->href); - if (!ptr->uri) - { - return OC_STACK_NO_MEMORY; - } - OCStringLL *rt = repPayload->setLinks->rt; - while (rt) - { - OCResourceType *temp = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType)); - if(!temp) - { - OICFree(ptr->uri); - return OC_STACK_NO_MEMORY; - } - temp->next = NULL; - temp->resourcetypename = OICStrdup(rt->value); - if (!ptr->rsrcType) - { - ptr->rsrcType = temp; - } - else - { - OCResourceType *type = ptr->rsrcType; - while (type->next) - { - type = type->next; - } - type->next = temp; - } - rt = rt->next; - } - - OCStringLL *itf = repPayload->setLinks->itf; - while (itf) - { - OCResourceInterface *temp = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface)); - if (!temp) - { - OICFree(ptr->uri); - - return OC_STACK_NO_MEMORY; - } - temp->next = NULL; - temp->name = OICStrdup(itf->value); - if (!ptr->rsrcInterface) - { - ptr->rsrcInterface = temp; - } - else - { - OCResourceInterface *type = ptr->rsrcInterface; - while (type->next) - { - type = type->next; - } - type->next = temp; - } - itf = itf->next; - } - - ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap; - - OCFreeCollectionResource(repPayload); - *payload = ptr; - return OC_STACK_OK; - } - else - { - OIC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \ - on the resource directory"); - } - return OC_STACK_ERROR; -} -#endif - static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource) { if (!request || !resource) @@ -816,42 +715,6 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource bool foundResourceAtRD = false; for (;resource && discoveryResult == OC_STACK_OK; resource = resource->next) { -#ifdef WITH_RD - if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0) - { - OCResource *resource1 = NULL; - OCDevAddr devAddr; - discoveryResult = checkResourceExistsAtRD(interfaceQuery, - resourceTypeQuery, &resource1, &devAddr); - if (discoveryResult != OC_STACK_OK) - { - break; - } - discoveryResult = BuildVirtualResourceResponse(resource1, - discPayload, &devAddr, true); - if (payload) - { - discPayload->baseURI = OICStrdup(devAddr.addr); - } - OICFree(resource1->uri); - for (OCResourceType *rsrcRt = resource1->rsrcType, *rsrcRtNext = NULL; rsrcRt; ) - { - rsrcRtNext = rsrcRt->next; - OICFree(rsrcRt->resourcetypename); - OICFree(rsrcRt); - rsrcRt = rsrcRtNext; - } - - for (OCResourceInterface *rsrcPtr = resource1->rsrcInterface, *rsrcNext = NULL; rsrcPtr; ) - { - rsrcNext = rsrcPtr->next; - OICFree(rsrcPtr->name); - OICFree(rsrcPtr); - rsrcPtr = rsrcNext; - } - foundResourceAtRD = true; - } -#endif if (!foundResourceAtRD && includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery)) { discoveryResult = BuildVirtualResourceResponse(resource, diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index d3e892240..a0bf25e8c 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -4766,3 +4766,61 @@ bool OCResultToSuccess(OCStackResult ocResult) return false; } } + +#if defined(RD_CLIENT) || defined(RD_SERVER) +OCStackResult OCBindResourceInsToResource(OCResourceHandle handle, uint8_t ins) +{ + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + + OCResource *resource = NULL; + + resource = findResource((OCResource *) handle); + if (!resource) + { + OIC_LOG(ERROR, TAG, "Resource not found"); + return OC_STACK_ERROR; + } + + resource->ins = ins; + + return OC_STACK_OK; +} + +OCResourceHandle OCGetResourceHandleAtUri(const char *uri) +{ + if (!uri) + { + OIC_LOG(ERROR, TAG, "Resource uri is NULL"); + return NULL; + } + + OCResource *pointer = headResource; + + while (pointer) + { + if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0) + { + OIC_LOG_V(DEBUG, TAG, "Found Resource %s", uri); + return pointer; + } + pointer = pointer->next; + } + return NULL; +} + +OCStackResult OCGetResourceIns(OCResourceHandle handle, uint8_t *ins) +{ + OCResource *resource = NULL; + + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(ins, ERROR, OC_STACK_INVALID_PARAM); + + resource = findResource((OCResource *) handle); + if (resource) + { + *ins = resource->ins; + return OC_STACK_OK; + } + return OC_STACK_ERROR; +} +#endif diff --git a/resource/csdk/stack/src/oicresourcedirectory.c b/resource/csdk/stack/src/oicresourcedirectory.c new file mode 100644 index 000000000..a0c72bffa --- /dev/null +++ b/resource/csdk/stack/src/oicresourcedirectory.c @@ -0,0 +1,109 @@ +//****************************************************************** +// +// 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 "oicresourcedirectory.h" + +#include "rdpayload.h" +#include "oic_malloc.h" +#include "oic_string.h" +#include "octypes.h" +#include "ocstack.h" +#include "ocpayload.h" +#include "rdpayload.h" +#include "ocresource.h" +#include "payload_logging.h" + +#define TAG "OIC_RI_RESOURCE_DIRECTORY" + +#ifdef RD_CLIENT +OCStackResult OCRDPublish(const char *host, OCConnectivityType connectivityType, + OCResourceHandle resourceHandles[], uint8_t nHandles, + OCCallbackData *cbData, OCQualityOfService qos) +{ + // Validate input parameters + if (!host || !cbData || !cbData->cb) + { + return OC_STACK_INVALID_CALLBACK; + } + + OCResourceHandle *pubResHandle = resourceHandles; + uint8_t nPubResHandles = nHandles; + + // if resource handles is null, "/oic/p" and "/oic/d" resource will be published to RD. + if (!pubResHandle && !nPubResHandles) + { + OCResourceHandle defaultResHandles[OIC_RD_DEFAULT_RESOURCE] = { 0 }; + + // get "/oic/d" resource handle from stack. + defaultResHandles[0] = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI); + // get "/oic/p" resource handle from stack. + defaultResHandles[1] = OCGetResourceHandleAtUri(OC_RSRVD_PLATFORM_URI); + + pubResHandle = defaultResHandles; + nPubResHandles = OIC_RD_DEFAULT_RESOURCE; + } + + char targetUri[MAX_URI_LENGTH] = { 0 }; + snprintf(targetUri, MAX_URI_LENGTH, "%s%s?rt=%s", host, + OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH); + OIC_LOG_V(DEBUG, TAG, "Target URI: %s", targetUri); + + OCPayload *rdPayload = (OCPayload *) OCRDPublishPayloadCreate(pubResHandle, nPubResHandles, + OIC_RD_PUBLISH_TTL); + if (!rdPayload) + { + OIC_LOG_V(ERROR, TAG, "Failed to create RD Payload"); + return OC_STACK_NO_MEMORY; + } + + OIC_LOG(DEBUG, TAG, "Create RD payload successfully"); + + return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)rdPayload, + connectivityType, qos, cbData, NULL, 0); +} + +OCStackResult OCRDDelete(const char *host, OCConnectivityType connectivityType, + OCResourceHandle resourceHandles[], uint8_t nHandles, + OCCallbackData *cbData, OCQualityOfService qos) +{ + // Validate input parameters + if (!host || !cbData || !cbData->cb) + { + return OC_STACK_INVALID_CALLBACK; + } + + const unsigned char *id = (const unsigned char *) OCGetServerInstanceIDString(); + + char targetUri[MAX_URI_LENGTH] = { 0 }; + snprintf(targetUri, MAX_URI_LENGTH, "%s%s?di=%s", host, OC_RSRVD_RD_URI, id); + + char queryParam[MAX_URI_LENGTH] = { 0 }; + for (uint8_t j = 0; j < nHandles; j++) + { + OCResource *handle = (OCResource *) resourceHandles[j]; + snprintf(queryParam, MAX_URI_LENGTH, "&ins=%d", handle->ins); + } + + OICStrcatPartial(targetUri, sizeof(targetUri), queryParam, strlen(queryParam)); + OIC_LOG_V(DEBUG, TAG, "Target URI: %s", targetUri); + + return OCDoResource(NULL, OC_REST_DELETE, targetUri, NULL, NULL, connectivityType, + qos, cbData, NULL, 0); +} +#endif diff --git a/resource/csdk/stack/src/rdpayload.c b/resource/csdk/stack/src/rdpayload.c index de381532c..3cffbced4 100644 --- a/resource/csdk/stack/src/rdpayload.c +++ b/resource/csdk/stack/src/rdpayload.c @@ -31,7 +31,7 @@ #define CBOR_ROOT_ARRAY_LENGTH 1 static int64_t OCTagsPayloadToCbor(OCTagsPayload *tags, CborEncoder *setMap); -static int64_t OCLinksPayloadToCbor(OCLinksPayload *rtPtr, CborEncoder *setMap); +static int64_t OCLinksPayloadToCbor(OCLinksPayload *links, CborEncoder *setMap); static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, const char *value); static int64_t ConditionalAddIntToMap(CborEncoder *map, const char *tags, const uint64_t *value); static int64_t AddStringLLToMap(CborEncoder *map, const char *tag, const OCStringLL *value); @@ -40,10 +40,13 @@ static CborError OCLinksCborToPayload(CborValue *linksArray, OCLinksPayload **li static CborError FindStringInMap(const CborValue *map, const char *tags, char **value); static CborError FindIntInMap(const CborValue *map, const char *tags, uint64_t *value); static CborError FindStringLLInMap(const CborValue *linksMap, const char *tag, OCStringLL **links); +static OCStackResult CreateStringLL(uint8_t numElements, OCResourceHandle handle, + const char* (*getValue)(OCResourceHandle handle, uint8_t i), + OCStringLL **stringLL); int64_t OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t *outPayload, size_t *size) { - int64_t cborEncoderResult = CborErrorIO; + int64_t cborEncoderResult = CborNoError; int flags = 0; CborEncoder encoder; VERIFY_PARAM_NON_NULL(TAG, rdPayload, "Invalid input parameter rdPayload"); @@ -76,21 +79,18 @@ int64_t OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t *outPayload, siz } else if (rdPayload->rdPublish) { - CborEncoder colArray; - cborEncoderResult |= cbor_encoder_create_array(&encoder, &colArray, CborIndefiniteLength); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create collection array"); + CborEncoder collMap; + cborEncoderResult |= cbor_encoder_create_map(&encoder, &collMap, CborIndefiniteLength); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create collection map"); OCResourceCollectionPayload *rdPublish = rdPayload->rdPublish; - while (rdPublish) - { - cborEncoderResult |= OCTagsPayloadToCbor(rdPublish->tags, &colArray); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding tags payload"); - cborEncoderResult |= OCLinksPayloadToCbor(rdPublish->setLinks, &colArray); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding setLinks payload"); - rdPublish = rdPublish->next; - } - cborEncoderResult |= cbor_encoder_close_container(&encoder, &colArray); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing collection array"); + cborEncoderResult |= OCTagsPayloadToCbor(rdPublish->tags, &collMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding tags payload"); + cborEncoderResult |= OCLinksPayloadToCbor(rdPublish->setLinks, &collMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding setLinks payload"); + + cborEncoderResult |= cbor_encoder_close_container(&encoder, &collMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing collection map"); } else { @@ -119,97 +119,89 @@ exit: static int64_t OCTagsPayloadToCbor(OCTagsPayload *tags, CborEncoder *setMap) { - CborEncoder tagsMap; int64_t cborEncoderResult = CborNoError; - cborEncoderResult |= cbor_encoder_create_map(setMap, &tagsMap, CborIndefiniteLength); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create tags map"); - cborEncoderResult |= ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DEVICE_NAME, tags->n.deviceName); + cborEncoderResult |= ConditionalAddTextStringToMap(setMap, OC_RSRVD_DEVICE_NAME, + tags->n.deviceName); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DEVICE_NAME in tags map"); - cborEncoderResult |= ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DEVICE_ID, - (char *)tags->di.id); + cborEncoderResult |= ConditionalAddTextStringToMap(setMap, OC_RSRVD_DEVICE_ID, + (char *)tags->di.id); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DEVICE_ID in tags map"); - cborEncoderResult |= ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_RTS, tags->rts); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_RTS in tags map"); - - cborEncoderResult |= ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_DREL, tags->drel); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_DREL in tags map"); - - cborEncoderResult |= ConditionalAddTextStringToMap(&tagsMap, OC_RSRVD_BASE_URI, tags->baseURI); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_BASE_URI in tags map"); - - { - uint64_t value = tags->bitmap; - cborEncoderResult |= ConditionalAddIntToMap(&tagsMap, OC_RSRVD_BITMAP, &value); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_BITMAP in tags map"); - - value = tags->port; - cborEncoderResult |= ConditionalAddIntToMap(&tagsMap, OC_RSRVD_HOSTING_PORT, &value); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_HOSTING_PORT in tags map"); - - value = tags->ins; - cborEncoderResult |= ConditionalAddIntToMap(&tagsMap, OC_RSRVD_INS, &value); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_INS in tags map"); - - value = tags->ttl; - cborEncoderResult |= ConditionalAddIntToMap(&tagsMap, OC_RSRVD_TTL, &value); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TTL in tags map"); - } - - cborEncoderResult |= cbor_encoder_close_container(setMap, &tagsMap); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to close container"); - + cborEncoderResult |= ConditionalAddIntToMap(setMap, OC_RSRVD_DEVICE_TTL, &tags->ttl); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TTL in tags map"); exit: return cborEncoderResult; } -static int64_t OCLinksPayloadToCbor(OCLinksPayload *rtPtr, CborEncoder *setMap) +static int64_t OCLinksPayloadToCbor(OCLinksPayload *links, CborEncoder *setMap) { CborEncoder linksArray; int64_t cborEncoderResult = CborNoError; + cborEncoderResult |= cbor_encode_text_string(setMap, OC_RSRVD_LINKS, + sizeof(OC_RSRVD_LINKS) - 1); + cborEncoderResult |= cbor_encoder_create_array(setMap, &linksArray, CborIndefiniteLength); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create Links array"); - while (rtPtr) + while (links) { CborEncoder linksMap; cborEncoderResult |= cbor_encoder_create_map(&linksArray, &linksMap, CborIndefiniteLength); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create Links map"); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create links map"); - cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_HREF, rtPtr->href); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_HREF in Links map"); + cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_HREF, links->href); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_HREF in links map"); - cborEncoderResult|= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_REL, rtPtr->rel); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_REL in Links map"); + cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_REL, links->rel); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_REL in links map"); - cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_TITLE, rtPtr->title); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TITLE in Links map"); + cborEncoderResult |= AddStringLLToMap(&linksMap, OC_RSRVD_RESOURCE_TYPE, links->rt); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_RT in links map"); - cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_URI, rtPtr->uri); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_URI in Links map"); + cborEncoderResult |= AddStringLLToMap(&linksMap, OC_RSRVD_INTERFACE, links->itf); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_ITF in links map"); - cborEncoderResult |= AddStringLLToMap(&linksMap, OC_RSRVD_RESOURCE_TYPE, rtPtr->rt); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_RT in Links map"); + // Policy + CborEncoder policyMap; + cborEncoderResult |= cbor_encode_text_string(&linksMap, OC_RSRVD_POLICY, + sizeof(OC_RSRVD_POLICY) - 1); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding policy tag to links map"); + cborEncoderResult |= cbor_encoder_create_map(&linksMap, &policyMap, CborIndefiniteLength); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding policy map to links map"); - cborEncoderResult |= AddStringLLToMap(&linksMap, OC_RSRVD_INTERFACE, rtPtr->itf); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_ITF in Links map"); + // Bitmap + cborEncoderResult |= cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP, + sizeof(OC_RSRVD_BITMAP) - 1); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding bitmap tag to policy map"); + cborEncoderResult |= cbor_encode_uint(&policyMap, links->p); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding bitmap value to policy map"); - cborEncoderResult |= AddStringLLToMap(&linksMap, OC_RSRVD_MEDIA_TYPE, rtPtr->mt); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_MT in Links map"); + cborEncoderResult |= cbor_encoder_close_container(&linksMap, &policyMap); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing policy map"); - { - uint64_t value = rtPtr->ins; - cborEncoderResult |= ConditionalAddIntToMap(&linksMap, OC_RSRVD_INS, &value); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_INS in Links map"); - } + cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_TITLE, links->title); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TITLE in links map"); + + cborEncoderResult |= ConditionalAddTextStringToMap(&linksMap, OC_RSRVD_URI, links->anchor); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_URI in links map"); + cborEncoderResult |= ConditionalAddIntToMap(&linksMap, OC_RSRVD_INS, (uint64_t *) &links->ins); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_INS in links map"); + + cborEncoderResult |= ConditionalAddIntToMap(&linksMap, OC_RSRVD_TTL, &links->ttl); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_TTL in links map"); + + cborEncoderResult |= AddStringLLToMap(&linksMap, OC_RSRVD_MEDIA_TYPE, links->type); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add OC_RSRVD_MT in links map"); + + // Finsihed encoding a resource, close the map. cborEncoderResult |= cbor_encoder_close_container(&linksArray, &linksMap); - VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing Links map"); + VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing links map"); - rtPtr = rtPtr->next; + links = links->next; } cborEncoderResult |= cbor_encoder_close_container(setMap, &linksArray); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing links array"); @@ -229,40 +221,33 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay ret = OC_STACK_MALFORMED_RESPONSE; - if (cbor_value_is_array(rdCBORPayload)) + if (cbor_value_is_map(rdCBORPayload)) { - OCLinksPayload *linksPayload = NULL; + // rdCBORPayload is already inside the main root map. OCTagsPayload *tagsPayload = NULL; + OCLinksPayload *linksPayload = NULL; + + cborFindResult = OCTagsCborToPayload(rdCBORPayload, &tagsPayload); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed parsing tags payload."); + + cborFindResult = OCLinksCborToPayload(rdCBORPayload, &linksPayload); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed parsing links payload."); + + // Move from tags payload to links array. + cborFindResult = cbor_value_advance(rdCBORPayload); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing rdCborPayload."); - while (cbor_value_is_container(rdCBORPayload)) - { - // enter tags map - CborValue tags; - cborFindResult = cbor_value_enter_container(rdCBORPayload, &tags); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed entering tags container."); - - cborFindResult= OCTagsCborToPayload(&tags, &tagsPayload); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed parsing tags payload."); - OCTagsLog(DEBUG, tagsPayload); - - cborFindResult = OCLinksCborToPayload(&tags, &linksPayload); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed parsing links payload."); - OCLinksLog(DEBUG, linksPayload); - - // Move from tags payload to links array. - cborFindResult = cbor_value_advance(rdCBORPayload); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing rdCborPayload."); - } rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload); VERIFY_PARAM_NON_NULL(TAG, rdPayload->rdPublish, "Failed allocating rdPayload->rdPublish"); } + // TODO: This logic needs to be modified to check the payload type exactly.. else if (cbor_value_is_map(rdCBORPayload)) { rdPayload->rdDiscovery = (OCRDDiscoveryPayload *)OICCalloc(1, sizeof(OCRDDiscoveryPayload)); VERIFY_PARAM_NON_NULL(TAG, rdPayload->rdDiscovery, "Failed allocating discoveryPayload"); cborFindResult = FindStringInMap(rdCBORPayload, OC_RSRVD_DEVICE_NAME, - &rdPayload->rdDiscovery->n.deviceName); + &rdPayload->rdDiscovery->n.deviceName); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding OC_RSRVD_DEVICE_NAME."); char *deviceId = NULL; cborFindResult = FindStringInMap(rdCBORPayload, OC_RSRVD_DEVICE_ID, &deviceId); @@ -335,14 +320,15 @@ static CborError FindStringLLInMap(const CborValue *linksMap, const char *tag, O VERIFY_PARAM_NON_NULL(TAG, llPtr, "Failed allocating OCStringLL"); *links = llPtr; } - else if(llPtr) + else if (llPtr) { while (llPtr->next) { llPtr = llPtr->next; } llPtr->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); - VERIFY_PARAM_NON_NULL(TAG, llPtr->next, "Failed allocating OCStringLL->next"); + llPtr = llPtr->next; + VERIFY_PARAM_NON_NULL(TAG, llPtr, "Failed allocating OCStringLL->next"); } cborFindResult = cbor_value_dup_text_string(&rtVal, &(llPtr->value), &len, NULL); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed duplicating value"); @@ -363,16 +349,10 @@ static CborError OCTagsCborToPayload(CborValue *tagsMap, OCTagsPayload **tagsPay OCTagsPayload *tags = (OCTagsPayload *)OICCalloc(1, sizeof(OCTagsPayload)); VERIFY_PARAM_NON_NULL(TAG, tags, "Failed allocating tags"); - if (cbor_value_is_map(tagsMap)) + cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DEVICE_NAME, &tags->n.deviceName); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding deviceName"); + { - cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DEVICE_NAME, &tags->n.deviceName); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding deviceName"); - cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DREL, &tags->drel); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding drel"); - cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_RTS, &tags->rts); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rts"); - cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_BASE_URI, &tags->baseURI); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding baseURI"); char *deviceId = NULL; cborFindResult = FindStringInMap(tagsMap, OC_RSRVD_DEVICE_ID, &deviceId); if (deviceId) @@ -381,27 +361,11 @@ static CborError OCTagsCborToPayload(CborValue *tagsMap, OCTagsPayload **tagsPay OICFree(deviceId); } VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding deviceId"); - { - uint64_t value = 0; - cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_HOSTING_PORT, &value); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding port"); - tags->port = value; - value = 0; - cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_BITMAP, &value); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding bitmap"); - tags->bitmap = value; - value = 0; - cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_INS, &value); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ins"); - tags->ins = value; - value = 0; - cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_TTL, &value); - tags->ttl = value; - } - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ttl"); - cborFindResult = cbor_value_advance(tagsMap); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing bitmap"); } + + cborFindResult = FindIntInMap(tagsMap, OC_RSRVD_DEVICE_TTL, &tags->ttl); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ttl"); + *tagsPayload = tags; return cborFindResult; @@ -410,11 +374,17 @@ exit: return cborFindResult; } -static CborError OCLinksCborToPayload(CborValue *linksArray, OCLinksPayload **linksPayload) +static CborError OCLinksCborToPayload(CborValue *links, OCLinksPayload **linksPayload) { - CborValue linksMap; OCLinksPayload *setLinks = NULL; - CborError cborFindResult = cbor_value_enter_container(linksArray, &linksMap); + CborValue linksMap; + CborValue linksArray; + CborError cborFindResult = CborErrorOutOfMemory; + + cborFindResult = cbor_value_map_find_value(links, OC_RSRVD_LINKS, &linksArray); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding links array"); + + cborFindResult = cbor_value_enter_container(&linksArray, &linksMap); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed entering links map container"); while (cbor_value_is_map(&linksMap)) @@ -428,28 +398,36 @@ static CborError OCLinksCborToPayload(CborValue *linksArray, OCLinksPayload **li cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_REL, &setLinks->rel); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rel value"); + cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_RESOURCE_TYPE, &setLinks->rt); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rt value"); + + cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_INTERFACE, &setLinks->itf); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding itf value"); + + // Policy + CborValue policyMap; + cborFindResult = cbor_value_map_find_value(&linksMap, OC_RSRVD_POLICY, &policyMap); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "to find policy tag"); + + // Bitmap + cborFindResult = FindIntInMap(&policyMap, OC_RSRVD_BITMAP, (uint64_t *) &setLinks->p); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding bitmap value"); + cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_TITLE, &setLinks->title); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding title value"); - cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_URI, &setLinks->uri); + cborFindResult = FindStringInMap(&linksMap, OC_RSRVD_URI, &setLinks->anchor); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding uri value"); - cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_RESOURCE_TYPE, &setLinks->rt); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding rt value"); + cborFindResult = FindIntInMap(&linksMap, OC_RSRVD_INS, (uint64_t *) &setLinks->ins); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ins value"); - cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_INTERFACE, &setLinks->itf); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding itf value"); + cborFindResult = FindIntInMap(&linksMap, OC_RSRVD_TTL, &setLinks->ttl); + VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ttl"); - cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_MEDIA_TYPE, &setLinks->mt); + cborFindResult = FindStringLLInMap(&linksMap, OC_RSRVD_MEDIA_TYPE, &setLinks->type); VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding mt value"); - { - uint64_t value = 0; - cborFindResult = FindIntInMap(&linksMap, OC_RSRVD_INS, &value); - VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding ins value"); - setLinks->ins = value; - } - if (!*linksPayload) { *linksPayload = setLinks; @@ -506,6 +484,7 @@ static int64_t AddStringLLToMap(CborEncoder *map, const char *tag, const OCStrin { CborEncoder array; int64_t cborEncoderResult = CborNoError; + cborEncoderResult |= cbor_encode_text_string(map, tag, strlen(tag)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed encoding string tag name"); cborEncoderResult |= cbor_encoder_create_array(map, &array, CborIndefiniteLength); @@ -532,6 +511,143 @@ exit: return rdPayload; } +#ifdef RD_CLIENT +OCRDPayload *OCRDPublishPayloadCreate(OCResourceHandle resourceHandles[], uint8_t nHandles, + uint64_t ttl) +{ + OCTagsPayload *tagsPayload = NULL; + OCLinksPayload *linksPayload = NULL; + OCStringLL *rt = NULL; + OCStringLL *itf = NULL; + OCStringLL *mt = NULL; + OCResourceProperty p = OC_RES_PROP_NONE; + uint8_t ins = 0; + + OCRDPayload *rdPayload = OCRDPayloadCreate(); + if (!rdPayload) + { + return NULL; + } + + const unsigned char *id = (const unsigned char *) OCGetServerInstanceIDString(); + tagsPayload = OCCopyTagsResources(NULL, id, ttl); + if (!tagsPayload) + { + goto exit; + } + + for (uint8_t j = 0; j < nHandles; j++) + { + OCResourceHandle handle = resourceHandles[j]; + if (handle) + { + rt = NULL; + itf = NULL; + mt = NULL; + ins = 0; + const char *uri = OCGetResourceUri(handle); + uint8_t numElement = 0; + if (OC_STACK_OK == OCGetNumberOfResourceTypes(handle, &numElement)) + { + OCStackResult res = CreateStringLL(numElement, handle, OCGetResourceTypeName, &rt); + if (OC_STACK_OK != res || !rt) + { + goto exit; + } + } + + if (OC_STACK_OK == OCGetNumberOfResourceInterfaces(handle, &numElement)) + { + OCStackResult res = CreateStringLL(numElement, handle, OCGetResourceInterfaceName, + &itf); + if (OC_STACK_OK != res || !itf) + { + goto exit; + } + } + + p = OCGetResourceProperties(handle); + p = (OCResourceProperty) ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)); + + OCStackResult res = OCGetResourceIns(handle, &ins); + if (OC_STACK_OK != res) + { + goto exit; + } + + mt = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); + if (!mt) + { + goto exit; + } + mt->value = OICStrdup(DEFAULT_MESSAGE_TYPE); + if (!mt->value) + { + goto exit; + } + + if (!linksPayload) + { + linksPayload = OCCopyLinksResources(uri, NULL, rt, itf, p, NULL, + NULL, ins, ttl, mt);; + if (!linksPayload) + { + goto exit; + } + } + else + { + OCLinksPayload *temp = linksPayload; + while (temp->next) + { + temp = temp->next; + } + temp->next = OCCopyLinksResources(uri, NULL, rt, itf, p, NULL, + NULL, ins, ttl, mt); + if (!temp->next) + { + goto exit; + } + } + OCFreeOCStringLL(rt); + OCFreeOCStringLL(itf); + OCFreeOCStringLL(mt); + } + } + + rdPayload->rdPublish = OCCopyCollectionResource(tagsPayload, linksPayload); + if (!rdPayload->rdPublish) + { + goto exit; + } + + return rdPayload; + +exit: + if (rt) + { + OCFreeOCStringLL(rt); + } + if (itf) + { + OCFreeOCStringLL(itf); + } + if (mt) + { + OCFreeOCStringLL(mt); + } + if (tagsPayload) + { + OCFreeTagsResource(tagsPayload); + } + if (linksPayload) + { + OCFreeLinksResource(linksPayload); + } + OCRDPayloadDestroy(rdPayload); + return NULL; +} +#endif OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(const char *deviceName, const char *id, int biasFactor) { OCRDDiscoveryPayload *discoveryPayload = (OCRDDiscoveryPayload *)OICCalloc(1, sizeof(OCRDDiscoveryPayload)); @@ -574,35 +690,31 @@ void OCRDPayloadDestroy(OCRDPayload *payload) if (payload->rdPublish) { - for (OCResourceCollectionPayload *col = payload->rdPublish; col; ) + OCResourceCollectionPayload *col = payload->rdPublish; + + if (col->setLinks) { - if (col->setLinks) - { - OCFreeLinksResource(col->setLinks); - } + OCFreeLinksResource(col->setLinks); + } - if (col->tags) - { - OCFreeTagsResource(col->tags); - } - OCResourceCollectionPayload *temp = col->next; - OICFree(col); - col = temp; + if (col->tags) + { + OCFreeTagsResource(col->tags); } + OICFree(col); } OICFree(payload); } -OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char *id, const char *baseURI, - uint8_t bitmap, uint16_t port, uint8_t ins, const char *rts,const char *drel, uint32_t ttl) +OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char *id, uint64_t ttl) { OCTagsPayload *tags = (OCTagsPayload *)OICCalloc(1, sizeof(OCTagsPayload)); if (!tags) { return NULL; } - if (deviceName) + if (deviceName) { tags->n.deviceName = OICStrdup(deviceName); if (!tags->n.deviceName) @@ -614,33 +726,6 @@ OCTagsPayload* OCCopyTagsResources(const char *deviceName, const unsigned char * { OICStrcpy((char*)tags->di.id, MAX_IDENTITY_SIZE, (char *)id); } - if (baseURI) - { - tags->baseURI = OICStrdup(baseURI); - if (!tags->baseURI) - { - goto memory_allocation_failed; - } - } - tags->bitmap = bitmap; - tags->port = port; - tags->ins = ins; - if (rts) - { - tags->rts = OICStrdup(rts); - if (!tags->rts) - { - goto memory_allocation_failed; - } - } - if (drel) - { - tags->drel = OICStrdup(drel); - if (!tags->drel) - { - goto memory_allocation_failed; - } - } tags->ttl = ttl; return tags; @@ -650,8 +735,10 @@ memory_allocation_failed: return NULL; } -OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringLL *itf, - const char *rel, bool obs, const char *title, const char *uri, uint8_t ins, OCStringLL *mt) +OCLinksPayload* OCCopyLinksResources(const char *href, const char *rel, OCStringLL *rt, + OCStringLL *itf, uint8_t p, const char *title, + const char *anchor, uint8_t ins, uint64_t ttl, + OCStringLL *mt) { OCLinksPayload *links = (OCLinksPayload *)OICCalloc(1, sizeof(OCLinksPayload)); if (!links) @@ -667,6 +754,14 @@ OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringL goto memory_allocation_failed; } } + if (rel) + { + links->rel = OICStrdup(rel); + if (!links->rel) + { + goto memory_allocation_failed; + } + } if (rt) { links->rt = CloneOCStringLL(rt); @@ -683,15 +778,7 @@ OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringL goto memory_allocation_failed; } } - if (rel) - { - links->rel = OICStrdup(rel); - if (!links->rel) - { - goto memory_allocation_failed; - } - } - links->obs = obs; + links->p = p; if (title) { links->title = OICStrdup(title); @@ -700,19 +787,20 @@ OCLinksPayload* OCCopyLinksResources(const char *href, OCStringLL *rt, OCStringL goto memory_allocation_failed; } } - if (uri) + if (anchor) { - links->uri = OICStrdup(uri); - if (!links->uri) + links->anchor = OICStrdup(anchor); + if (!links->anchor) { goto memory_allocation_failed; } } links->ins = ins; + links->ttl = ttl; if (mt) { - links->mt = CloneOCStringLL(mt); - if (!links->mt) + links->type = CloneOCStringLL(mt); + if (!links->type) { goto memory_allocation_failed; } @@ -742,21 +830,21 @@ exit: return pl; } -void OCFreeLinksResource(OCLinksPayload *payload) +void OCFreeLinksResource(OCLinksPayload *links) { - if (!payload) + if (!links) { return; } - OICFree(payload->href); - OCFreeOCStringLL(payload->rt); - OCFreeOCStringLL(payload->itf); - OICFree(payload->rel); - OICFree(payload->title); - OICFree(payload->uri); - OCFreeOCStringLL(payload->mt); - OCFreeLinksResource(payload->next); - OICFree(payload); + OICFree(links->href); + OICFree(links->rel); + OCFreeOCStringLL(links->rt); + OCFreeOCStringLL(links->itf); + OICFree(links->title); + OICFree(links->anchor); + OCFreeOCStringLL(links->type); + OCFreeLinksResource(links->next); + OICFree(links); } void OCFreeTagsResource(OCTagsPayload *payload) @@ -765,10 +853,7 @@ void OCFreeTagsResource(OCTagsPayload *payload) { return; } - OICFree(payload->n.deviceName); - OICFree(payload->baseURI); - OICFree(payload->rts); - OICFree(payload->drel); + OICFree(payload->n.deviceName);; OICFree(payload); } @@ -786,99 +871,52 @@ void OCFreeCollectionResource(OCResourceCollectionPayload *payload) { OCFreeLinksResource(payload->setLinks); } - OCFreeCollectionResource(payload->next); OICFree(payload); } -void OCTagsLog(const LogLevel level, const OCTagsPayload *tags) +static OCStackResult CreateStringLL(uint8_t numElements, OCResourceHandle handle, + const char* (*getValue)(OCResourceHandle handle, uint8_t i), + OCStringLL **stringLL) { - if (tags) + for (uint8_t i = 0; i < numElements; ++i) { - if (tags->n.deviceName) - { - OIC_LOG_V(level, TAG, " Device Name : %s ",tags->n.deviceName); - } - if (tags->baseURI) + const char *value = getValue(handle, i); + OIC_LOG_V(ERROR, TAG, "value: %s", value); + if (!*stringLL) { - OIC_LOG_V(level, TAG, " Base URI : %s ",tags->baseURI); - } - OIC_LOG_V(level, TAG, " Device ID : %s ",tags->di.id); - OIC_LOG_V(level, TAG, " Bitmap : %d ",tags->bitmap); - OIC_LOG_V(level, TAG, " Port : %d ",tags->port); - OIC_LOG_V(level, TAG, " Ins : %d ",tags->ins); - OIC_LOG_V(level, TAG, " Ttl : %d ",tags->ttl); - - if (tags->rts) - { - OIC_LOG_V(level, TAG, " RTS : %s ",tags->rts); - } - if (tags->drel) - { - OIC_LOG_V(level, TAG, " DREL : %s ",tags->drel); - } - } - else - { - (void) level; - } -} - -void OCLinksLog(const LogLevel level, const OCLinksPayload *links) -{ - while (links) - { - if (links->href) - { - OIC_LOG_V(level, TAG, " href: %s ",links->href); - } - OIC_LOG(level, TAG, " RT: "); - OCStringLL *rt = links->rt; - while (rt) - { - if (rt->value) + *stringLL = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); + if (!*stringLL) { - OIC_LOG_V(level, TAG, " %s", rt->value); + OIC_LOG(ERROR, TAG, "Failed allocating memory."); + return OC_STACK_NO_MEMORY; } - rt = rt->next; - } - OIC_LOG(level, TAG, " IF: "); - OCStringLL *itf = links->itf; - while (itf) - { - if (itf->value) + (*stringLL)->value = OICStrdup(value); + if (!(*stringLL)->value) { - OIC_LOG_V(level, TAG, " %s", itf->value); + OIC_LOG(ERROR, TAG, "Failed copying to OCStringLL."); + return OC_STACK_NO_MEMORY; } - itf = itf->next; } - OIC_LOG(level, TAG, " MT: "); - OCStringLL *mt = links->mt; - while (mt) + else { - if (mt->value) + OCStringLL *cur = *stringLL; + while (cur->next) { - OIC_LOG_V(level, TAG, " %s", mt->value); + cur = cur->next; + } + cur->next = (OCStringLL *)OICCalloc(1, sizeof(OCStringLL)); + if (!cur->next) + { + OIC_LOG(ERROR, TAG, "Failed allocating memory."); + return OC_STACK_NO_MEMORY; + } + cur->next->value = OICStrdup(value); + if (!cur->next->value) + { + OIC_LOG(ERROR, TAG, "Failed copying to OCStringLL."); + return OC_STACK_NO_MEMORY; } - mt = mt->next; - } - OIC_LOG_V(level, TAG, " INS: %d", links->ins); - OIC_LOG_V(level, TAG, " OBS: %d", links->obs); - if (links->rel) - { - OIC_LOG_V(level, TAG, " REL: %s", links->rel); - } - if (links->title) - { - OIC_LOG_V(level, TAG, " TITLE: %s", links->title); - } - if (links->uri) - { - OIC_LOG_V(level, TAG, " URI: %s", links->uri); } - links = links->next; - } - if (!links) - { - (void) level; } + return OC_STACK_OK; } diff --git a/resource/csdk/stack/test/rdtests.cpp b/resource/csdk/stack/test/rdtests.cpp new file mode 100644 index 000000000..38dbd846c --- /dev/null +++ b/resource/csdk/stack/test/rdtests.cpp @@ -0,0 +1,262 @@ +//****************************************************************** +// +// 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. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +extern "C" +{ + #include "rdpayload.h" + #include "oicresourcedirectory.h" + #include "ocstack.h" + #include "ocstackinternal.h" + #include "logger.h" + #include "oic_malloc.h" +} + +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include + +#include +#include + +#include "gtest_helper.h" + +using namespace std; + +namespace itst = iotivity::test; + +#define DEFAULT_CONTEXT_VALUE 0x99 + +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- +static const char TAG[] = "RDTests"; + +std::chrono::seconds const SHORT_TEST_TIMEOUT = std::chrono::seconds(5); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- +static OCStackApplicationResult handlePublishCB(__attribute__((unused))void *ctx, + __attribute__((unused)) OCDoHandle handle, + __attribute__((unused)) + OCClientResponse *clientResponse) +{ + OIC_LOG(DEBUG, TAG, "Successfully published resources."); + + return OC_STACK_DELETE_TRANSACTION; +} + +static OCStackApplicationResult handleDeleteCB(__attribute__((unused))void *ctx, + __attribute__((unused)) OCDoHandle handle, + __attribute__((unused)) + OCClientResponse *clientResponse) +{ + OIC_LOG(DEBUG, TAG, "Successfully delete resources."); + + return OC_STACK_DELETE_TRANSACTION; +} + +//----------------------------------------------------------------------------- +// Entity handler +//----------------------------------------------------------------------------- +OCEntityHandlerResult rdEntityHandler(OCEntityHandlerFlag /*flag*/, + OCEntityHandlerRequest * /*entityHandlerRequest*/, + void* /*callbackParam*/) +{ + OIC_LOG(INFO, TAG, "Entering entityHandler"); + + return OC_EH_OK; +} + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +class RDTests : public testing::Test { + protected: + virtual void SetUp() + { + OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER); + } + + virtual void TearDown() + { + OCStop(); + } +}; + +TEST_F(RDTests, CreateRDPayload) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", + "oic.if.baseline", "/a/light", rdEntityHandler, + NULL, OC_DISCOVERABLE | OC_OBSERVABLE)); + + // Create RD Publish Payload. + OCRDPayload *rdPayload = (OCRDPayload *) OCRDPublishPayloadCreate(&handle, 1, 86400); + EXPECT_TRUE(rdPayload != NULL); + + // Cleanup. + OCRDPayloadDestroy(rdPayload); +} + +TEST_F(RDTests, ConvertParseRDPayload) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", + "oic.if.baseline", "/a/light", rdEntityHandler, + NULL, OC_DISCOVERABLE | OC_OBSERVABLE)); + + // Create RD Publish Payload. + OCRDPayload *rdPayload = (OCRDPayload *) OCRDPublishPayloadCreate(&handle, 1, 86400); + EXPECT_TRUE(rdPayload != NULL); + + if (rdPayload) + { + // Convert RD Publish Payload to CBOR. + size_t curSize = 255; + uint8_t *outPayload = (uint8_t *)OICCalloc(1, curSize); + OCRDPayloadToCbor(rdPayload, outPayload, &curSize); + + // Parse CBOR back to RD Publish Payload. + CborParser parser; + CborValue rootValue; + cbor_parser_init(outPayload, curSize, 0, &parser, &rootValue); + + OCRDPayload *rdPayload = NULL; + EXPECT_EQ(OC_STACK_OK, OCRDCborToPayload(&rootValue, (OCPayload**) &rdPayload)); + + // Cleanup. + OICFree(outPayload); + } + OCRDPayloadDestroy(rdPayload); +} + +TEST_F(RDTests, RDPublishResourceNullAddr) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + EXPECT_EQ(OC_STACK_INVALID_IP, OCRDPublish(0, CT_ADAPTER_IP, nullptr, 0, 0, OC_LOW_QOS)); +} + +TEST_F(RDTests, RDPublishResourceNullCB) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + EXPECT_EQ(OC_STACK_INVALID_CALLBACK, OCRDPublish("127.0.0.1", CT_ADAPTER_IP, nullptr, + 0, 0, OC_LOW_QOS)); +} + +TEST_F(RDTests, RDPublishResource) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCCallbackData cbData; + cbData.cb = &handlePublishCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + + OCResourceHandle handle; + + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", + "oic.if.baseline", "/a/light", rdEntityHandler, + NULL, (OC_DISCOVERABLE | OC_OBSERVABLE))); + + EXPECT_EQ(OC_STACK_OK, OCRDPublish("127.0.0.1", CT_ADAPTER_IP, &handle, + 1, &cbData, OC_LOW_QOS)); +} + +TEST_F(RDTests, RDPublishMultipleResources) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCCallbackData cbData; + cbData.cb = &handlePublishCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + + OCResourceHandle handles[2]; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light", + "oic.if.baseline", "/a/light", rdEntityHandler, + NULL, (OC_DISCOVERABLE | OC_OBSERVABLE))); + + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light", + "oic.if.baseline", "/a/light2", rdEntityHandler, + NULL, (OC_DISCOVERABLE | OC_OBSERVABLE))); + + EXPECT_EQ(OC_STACK_OK, OCRDPublish("127.0.0.1", CT_ADAPTER_IP, handles, + 2, &cbData, OC_LOW_QOS)); +} + +TEST_F(RDTests, RDDeleteResourceNullAddr) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + EXPECT_EQ(OC_STACK_INVALID_IP, OCRDDelete(0, CT_ADAPTER_IP, nullptr, 0, 0, OC_LOW_QOS)); +} + +TEST_F(RDTests, RDDeleteResourceNullCB) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + EXPECT_EQ(OC_STACK_INVALID_CALLBACK, OCRDDelete("127.0.0.1", CT_ADAPTER_IP, nullptr, + 0, 0, OC_LOW_QOS)); +} + +TEST_F(RDTests, RDDeleteAllResource) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCCallbackData cbData; + cbData.cb = &handleDeleteCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + + EXPECT_EQ(OC_STACK_OK, OCRDDelete("127.0.0.1", CT_ADAPTER_IP, nullptr, 0, &cbData, + OC_LOW_QOS)); +} + +TEST_F(RDTests, RDDeleteSpecificResource) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCCallbackData cbData; + cbData.cb = &handleDeleteCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + + OCResourceHandle handle; + + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", + "oic.if.baseline", "/a/light", rdEntityHandler, + NULL, OC_DISCOVERABLE | OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_OK, OCRDDelete("127.0.0.1", CT_ADAPTER_IP, &handle, + 1, &cbData, OC_LOW_QOS)); +} diff --git a/resource/examples/SConscript b/resource/examples/SConscript index c85806d3a..ba49690ee 100644 --- a/resource/examples/SConscript +++ b/resource/examples/SConscript @@ -79,6 +79,12 @@ if examples_env.get('WITH_CLOUD'): if target_os in ['msys_nt', 'windows']: examples_env.AppendUnique(LIBS = ['Comctl32', 'Gdi32', 'User32']) +if examples_env.get('LOGGING'): + examples_env.AppendUnique(CPPDEFINES = ['TB_LOG']) + +if 'CLIENT' in examples_env.get('RD_MODE'): + examples_env.AppendUnique(CPPDEFINES = ['RD_CLIENT']) + def make_single_file_cpp_program(program_name): return examples_env.Program(program_name, program_name + ".cpp") @@ -103,7 +109,12 @@ if target_os not in ['windows', 'msys_nt']: 'groupserver', 'groupclient', 'lightserver', - 'threadingsample', + 'threadingsample' + ] + +if 'CLIENT' in examples_env.get('RD_MODE'): + example_names += [ + 'rdclient' ] examples = map(make_single_file_cpp_program, example_names) diff --git a/resource/examples/rdclient.cpp b/resource/examples/rdclient.cpp new file mode 100644 index 000000000..9dd075047 --- /dev/null +++ b/resource/examples/rdclient.cpp @@ -0,0 +1,280 @@ +//****************************************************************** +// +// 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 "OCPlatform.h" +#include "OCApi.h" + +#include +#include + +using namespace std; +using namespace OC; + +string rdAddress; +OCConnectivityType connectivityType = CT_ADAPTER_TCP; + +ResourceHandles m_publishedResourceHandles; + +static void onDelete(const int& eCode); +static void onPublish(const OCRepresentation& rep, const int& eCode); + +class Resource +{ + +public: + std::string m_resourceUri; + OCResourceHandle m_resourceHandle; + +public: + /// This function internally calls registerResource API. + void registerResource() + { + string resourceURI; + string resourceTypeName; + string resourceInterface; + + std::cout <<" resourceURI: "; + std::cin >> resourceURI; + std::cout <<" resourceTypeName: "; + std::cin >> resourceTypeName; + std::cout <<" resourceInterface: "; + std::cin >> resourceInterface; + + m_resourceUri = resourceURI; + + OCPlatform::registerResource(m_resourceHandle, resourceURI, resourceTypeName, + resourceInterface, + nullptr, + OC_DISCOVERABLE); + + m_publishedResourceHandles.push_back(m_resourceHandle); + cout << "registerResource is called." << endl; + } + + void updateResource() + { + cout << " 1:: add resource type\n"; + cout << " 2:: add resource interface\n"; + + int selectedMenu; + std::cin >> selectedMenu; + + string inputString; + switch (selectedMenu) + { + case 1: + std::cout << "Add Resource Type" << std::endl; + std::cout <<" resourceTypeName: "; + std::cin >> inputString; + OCPlatform::bindTypeToResource(m_resourceHandle, inputString); + break; + case 2: + std::cout << "Add Resource Interface" << std::endl; + std::cout <<" resourceInterface: "; + std::cin >> inputString; + OCPlatform::bindInterfaceToResource(m_resourceHandle, inputString); + break; + default: + cout << "Invalid option" << endl; + return; + } + } + + void publishResource() + { + /* + * Publish Resource of Resource-Server to RD. + */ + + OCStackResult result = OCPlatform::publishResourceToRD(rdAddress, connectivityType, + m_publishedResourceHandles, + &onPublish); + if (OC_STACK_OK != result) + { + cout << "Resource publish was unsuccessful\n"; + } + } + + void deleteResource() + { + /* + * Delete Resource with Resource Handle. + * Don't need to include resource handle, + * if resource-server want to delete all resources from RD. + * Ex.) OCPlatform::deleteResourceFromRD(rdAddress, connectivityType, &onDelete); + */ + OCStackResult result = OCPlatform::deleteResourceFromRD(rdAddress, connectivityType, + m_publishedResourceHandles, + &onDelete); + if (OC_STACK_OK != result) + { + cout << "Resource delete was unsuccessful\n"; + } + } +}; + +void onDelete(const int& eCode) +{ + cout << "Received Delete Resource Response From RD\n"; + try + { + if (OC_STACK_RESOURCE_DELETED == eCode) + { + cout << "Resource delete was successful\n"; + } + else + { + std::cout << "onDelete Response error: " << eCode << std::endl; + std::exit(-1); + } + } + catch(std::exception& e) + { + std::cout << "Exception: " << e.what() << " in onDelete" << std::endl; + } +} + +void onPublish(const OCRepresentation& rep, const int& eCode) +{ + cout << endl <<"Received Publish Resource Response From RD\n"; + + try + { + if (OC_STACK_RESOURCE_CREATED == eCode) + { + cout << "=========== Published Resource ===========" << endl; + if (rep.hasAttribute("di")) + { + std::cout << " di: " << rep.getValue("di") << std::endl; + } + + // Published Resource is included as the child resource. + std::vector children = rep.getChildren(); + + for (auto oit = children.begin(); oit != children.end(); ++oit) + { + std::string m_href; + oit->getValue("href", m_href); + cout << " href : " << m_href << "\n"; + + cout << " resource type : \n"; + for(const std::string& type : oit->getResourceTypes()) + { + cout << " " << type << "\n"; + } + + cout << " resource interface : \n"; + for(const std::string& type : oit->getResourceInterfaces()) + { + cout << " " << type << "\n"; + } + + int m_ins; + oit->getValue("ins", m_ins); + cout << " ins : " << m_ins << "\n"; + } + cout << "=========================================" << endl; + } + else + { + std::cout << "onPublish Response error: " << eCode << std::endl; + std::exit(-1); + } + } + catch(std::exception& e) + { + std::cout << "Exception: " << e.what() << " in onPublish" << std::endl; + } +} + +static void printUsage() +{ + std::cout<<"Usage: rdserver \n"; +} + +int main(int argc, char* argv[]) +{ + ostringstream requestURI; + + if (argc == 2) + { + rdAddress = argv[1]; + } + else + { + printUsage(); + return -1; + } + + PlatformConfig config + { OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos }; + + try + { + OCPlatform::Configure(config); + + int selectedMenu; + bool isRun = true; + + std::cout << "Register resources" << std::endl; + Resource myResource; + myResource.registerResource(); + + while (isRun) + { + cout << "================= MENU =================" << endl; + cout << "0 :: Quit" << endl; + cout << "1 :: UPDATE RESOURCE" << endl; + cout << "2 :: PUBLISH RESOURCE TO RD" << endl; + cout << "3 :: DELETE RESOURCE FROM RD" << endl; + cout << "========================================" << endl; + std::cin >> selectedMenu; + + switch (selectedMenu) + { + case 0: + isRun = false; + break; + case 1: + std::cout << "Update resources" << std::endl; + myResource.updateResource(); + break; + case 2: + std::cout << "Publish resources to RD" << std::endl; + myResource.publishResource(); + break; + case 3: + std::cout << "Delete resources from RD" << std::endl; + myResource.deleteResource(); + break; + default: + cout << "Invalid option" << endl; + } + + } + } + catch (OCException& e) + { + oclog() << "Exception in main: "<< e.what(); + } + + return 0; +} + diff --git a/resource/include/IServerWrapper.h b/resource/include/IServerWrapper.h index 62f878aca..f4223924a 100644 --- a/resource/include/IServerWrapper.h +++ b/resource/include/IServerWrapper.h @@ -74,6 +74,19 @@ namespace OC virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) = 0; virtual OCStackResult sendResponse(const std::shared_ptr pResponse) = 0; +#ifdef RD_CLIENT + virtual OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback& callback, + OCQualityOfService qos) = 0; + + virtual OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback& callback, + OCQualityOfService qos) = 0; +#endif }; } diff --git a/resource/include/InProcServerWrapper.h b/resource/include/InProcServerWrapper.h index 2e04e58c4..ad578ddbc 100644 --- a/resource/include/InProcServerWrapper.h +++ b/resource/include/InProcServerWrapper.h @@ -28,6 +28,22 @@ namespace OC { +#ifdef RD_CLIENT + namespace ServerCallbackContext + { + struct PublishContext + { + PublishResourceCallback callback; + PublishContext(PublishResourceCallback cb) : callback(cb){} + }; + + struct DeleteContext + { + DeleteResourceCallback callback; + DeleteContext(DeleteResourceCallback cb) : callback(cb){} + }; + } +#endif class InProcServerWrapper : public IServerWrapper { public: @@ -68,6 +84,19 @@ namespace OC virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler); virtual OCStackResult sendResponse(const std::shared_ptr pResponse); +#ifdef RD_CLIENT + virtual OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback& callback, + OCQualityOfService qos); + + virtual OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback& callback, + OCQualityOfService qos); +#endif private: void processFunc(); std::thread m_processThread; diff --git a/resource/include/OCApi.h b/resource/include/OCApi.h index 1188db1b3..0af772758 100644 --- a/resource/include/OCApi.h +++ b/resource/include/OCApi.h @@ -213,18 +213,21 @@ namespace OC Observe, ObserveAll }; - // - // Typedef for header option vector - // OCHeaderOption class is in HeaderOption namespace + + // Typedef for list of resource handles. + typedef std::vector ResourceHandles; + + // Typedef for header option vector. + // OCHeaderOption class is in HeaderOption namespace. typedef std::vector HeaderOptions; - // Typedef for query parameter map + // Typedef for query parameter map. typedef std::map QueryParamsMap; // Typedef for query parameter map with Vector typedef std::map< std::string, std::vector > QueryParamsList; - // Typedef for list of observation IDs + // Typedef for list of observation IDs. typedef std::vector ObservationIds; enum class ObserveAction @@ -297,7 +300,11 @@ namespace OC typedef std::function)> MQCreateTopicCallback; +#ifdef RD_CLIENT + typedef std::function PublishResourceCallback; + typedef std::function DeleteResourceCallback; +#endif } // namespace OC #endif diff --git a/resource/include/OCPlatform.h b/resource/include/OCPlatform.h index f5e969295..78742bf31 100644 --- a/resource/include/OCPlatform.h +++ b/resource/include/OCPlatform.h @@ -715,6 +715,99 @@ namespace OC OCConnectivityType connectivityType, PostCallback cloudConnectHandler); #endif // WITH_CLOUD +#ifdef RD_CLIENT + /** + * API for Virtual Resource("/oic/d" and "/oic/p") Publish to Resource Directory. + * @note This API applies to resource server side only. + * + * @param host Host IP Address of a service to direct resource publish query. + * @param connectivityType ::OCConnectivityType type of connectivity. + * @param callback Handles callbacks, success states and failure states. + * + * @return Returns ::OC_STACK_OK if success. + */ + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + PublishResourceCallback callback); + + /** + * API for Resource Publish to Resource Directory. + * @note This API applies to resource server side only. + * + * @param host Host IP Address of a service to direct resource publish query. + * @param connectivityType ::OCConnectivityType type of connectivity. + * @param resourceHandle resource handle of the resource. + * @param callback Handles callbacks, success states and failure states. + * + * @return Returns ::OC_STACK_OK if success. + */ + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback); + + /** + * @overload + * + * @param host Host IP Address of a service to direct resource publish query. + * @param connectivityType ::OCConnectivityType type of connectivity. + * @param resourceHandle resource handle of the resource. + * @param callback function to callback with published resources. + * @param QoS the quality of communication + * @see publishResourceToRD(const std::string&, OCConnectivityType, OCResourceHandle, + * uint8_t, PublishResourceCallback) + */ + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback, QualityOfService QoS); + + /** + * API for published resource delete from Resource Directory. + * @note This API applies to resource server side only. + * + * @param host Host IP Address of a service to direct resource delete query. + * @param connectivityType ::OCConnectivityType type of connectivity. + * @param callback Handles callbacks, success states and failure states. + * + * @return Returns ::OC_STACK_OK if success. + */ + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + DeleteResourceCallback callback); + + /** + * @overload + * + * @param host Host IP Address of a service to direct resource delete query. + * @param connectivityType ::OCConnectivityType type of connectivity. + * @param resourceHandle resource handle of the resource. + * @param callback function to callback with published resources. + * @param QoS the quality of communication + * @see publishResourceToRD(const std::string&, OCConnectivityType, OCResourceHandle, + * uint8_t, PublishResourceCallback) + */ + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback); + + /** + * @overload + * + * @param host Host IP Address of a service to direct resource delete query. + * @param connectivityType ::OCConnectivityType type of connectivity. + * @param resourceHandle resource handle of the resource. + * @param callback function to callback with published resources. + * @param QoS the quality of communication + * @see publishResourceToRD(const std::string&, OCConnectivityType, OCResourceHandle, + * uint8_t, PublishResourceCallback) + */ + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback, QualityOfService QoS); +#endif } } diff --git a/resource/include/OCPlatform_impl.h b/resource/include/OCPlatform_impl.h index 7897c46c1..b3d1aa35d 100644 --- a/resource/include/OCPlatform_impl.h +++ b/resource/include/OCPlatform_impl.h @@ -238,7 +238,31 @@ namespace OC const std::vector& resourceTypes, const std::vector& interfaces); OCStackResult sendResponse(const std::shared_ptr pResponse); - +#ifdef RD_CLIENT + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback); + + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback, QualityOfService qos); + + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + DeleteResourceCallback callback); + + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback); + + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback, QualityOfService qos); +#endif std::weak_ptr csdkLock(); OCStackResult findDirectPairingDevices(unsigned short waittime, diff --git a/resource/include/OCRepresentation.h b/resource/include/OCRepresentation.h index be9a11783..c07974a6c 100644 --- a/resource/include/OCRepresentation.h +++ b/resource/include/OCRepresentation.h @@ -66,7 +66,9 @@ namespace OC void setPayload(const OCPlatformPayload* rep); void setPayload(const OCRepPayload* rep); - +#ifdef RD_CLIENT + void setPayload(const OCRDPayload* rep); +#endif OCRepPayload* getPayload() const; const std::vector& representations() const; @@ -464,6 +466,9 @@ namespace OC template T payload_array_helper_copy(size_t index, const OCRepPayloadValue* pl); void setPayload(const OCRepPayload* payload); +#ifdef RD_CLIENT + void setPayload(const OCLinksPayload* payload); +#endif void setPayloadArray(const OCRepPayloadValue* pl); void getPayloadArray(OCRepPayload* payload, const OCRepresentation::AttributeItem& item) const; diff --git a/resource/include/StringConstants.h b/resource/include/StringConstants.h index 0f3e3977a..44e117899 100644 --- a/resource/include/StringConstants.h +++ b/resource/include/StringConstants.h @@ -124,6 +124,7 @@ namespace OC static const char DUPLICATE_UUID[] = "Duplicate UUID in DB"; static const char INCONSISTENT_DB[] = "Data in provisioning DB is inconsistent"; static const char AUTHENTICATION_FAILURE[] = "Authentication failure"; + static const char PUBLISH_RESOURCE_FAILED[] = "Publish Resource failure"; } namespace Error diff --git a/resource/src/InProcServerWrapper.cpp b/resource/src/InProcServerWrapper.cpp index 2fd1c19c1..bd7639d6e 100644 --- a/resource/src/InProcServerWrapper.cpp +++ b/resource/src/InProcServerWrapper.cpp @@ -37,6 +37,10 @@ #include #include +#ifdef RD_CLIENT +#include +#endif + using namespace std; using namespace OC; @@ -595,7 +599,149 @@ namespace OC return result; } } +#ifdef RD_CLIENT + OCRepresentation parseRDResponseCallback(OCClientResponse* clientResponse) + { + if (nullptr == clientResponse->payload || + PAYLOAD_TYPE_RD != clientResponse->payload->type) + { + return OCRepresentation(); + } + + MessageContainer oc; + oc.setPayload(clientResponse->payload); + + std::vector::const_iterator it = oc.representations().begin(); + if (it == oc.representations().end()) + { + return OCRepresentation(); + } + // first one is considered the root, everything else is considered a child of this one. + OCRepresentation root = *it; + root.setDevAddr(clientResponse->devAddr); + root.setUri(clientResponse->resourceUri); + ++it; + + std::for_each(it, oc.representations().end(), + [&root](const OCRepresentation& repItr) + {root.addChild(repItr);}); + return root; + + } + + OCStackApplicationResult publishResourceToRDCallback(void* ctx, OCDoHandle /*handle*/, + OCClientResponse* clientResponse) + { + ServerCallbackContext::PublishContext* context = + static_cast(ctx); + + try + { + // Update resource unique id in stack. + if (clientResponse) + { + if (clientResponse->payload) + { + OCRDPayload *rdPayload = (OCRDPayload *) clientResponse->payload; + OCLinksPayload *links = rdPayload->rdPublish->setLinks; + + while (links) + { + OCResourceHandle handle = OCGetResourceHandleAtUri(links->href); + OCBindResourceInsToResource(handle, links->ins); + links = links->next; + } + + } + } + + OCRepresentation rep = parseRDResponseCallback(clientResponse); + std::thread exec(context->callback, rep, clientResponse->result); + exec.detach(); + } + catch (OC::OCException& e) + { + oclog() <<"Exception in publishResourceToRDCallback, ignoring response: " + <(ctx), + publishResourceToRDCallback, + [](void* c) + {delete static_cast(c);} + ); + + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + if (cLock) + { + std::lock_guard lock(*cLock); + result = OCRDPublish(host.c_str(), connectivityType, &resourceHandles[0], + resourceHandles.size(), &cbdata, qos); + } + + if (OC_STACK_OK != result) + { + throw OCException(OC::Exception::PUBLISH_RESOURCE_FAILED, result); + } + return result; + } + + OCStackApplicationResult deleteResourceFromRDCallback(void* ctx, OCDoHandle /*handle*/, + OCClientResponse* clientResponse) + { + ServerCallbackContext::DeleteContext* context = + static_cast(ctx); + + std::thread exec(context->callback, clientResponse->result); + exec.detach(); + return OC_STACK_DELETE_TRANSACTION; + } + + OCStackResult InProcServerWrapper::deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback& callback, + OCQualityOfService qos) + { + ServerCallbackContext::DeleteContext* ctx = + new ServerCallbackContext::DeleteContext(callback); + OCCallbackData cbdata( + static_cast(ctx), + deleteResourceFromRDCallback, + [](void* c) + {delete static_cast(c);} + ); + + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + if (cLock) + { + std::lock_guard lock(*cLock); + result = OCRDDelete(host.c_str(), connectivityType, &resourceHandles[0], + resourceHandles.size(), &cbdata, qos); + } + + if (OC_STACK_OK != result) + { + throw OCException(OC::Exception::PUBLISH_RESOURCE_FAILED, result); + } + return result; + } +#endif InProcServerWrapper::~InProcServerWrapper() { if(m_processThread.joinable()) diff --git a/resource/src/OCPlatform.cpp b/resource/src/OCPlatform.cpp index 913f6583c..8373b2384 100644 --- a/resource/src/OCPlatform.cpp +++ b/resource/src/OCPlatform.cpp @@ -343,6 +343,65 @@ namespace OC connectivityType, cloudConnectHandler); } #endif // WITH_CLOUD +#ifdef RD_CLIENT + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + PublishResourceCallback callback) + { + ResourceHandles resourceHandles; + return OCPlatform_impl::Instance().publishResourceToRD(host, connectivityType, + resourceHandles, + callback); + } + + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback) + { + return OCPlatform_impl::Instance().publishResourceToRD(host, connectivityType, + resourceHandles, + callback); + } + + OCStackResult publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback, QualityOfService QoS) + { + return OCPlatform_impl::Instance().publishResourceToRD(host, connectivityType, + resourceHandles, + callback, QoS); + } + + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + DeleteResourceCallback callback) + { + ResourceHandles resourceHandles; + return OCPlatform_impl::Instance().deleteResourceFromRD(host, connectivityType, + resourceHandles, callback); + } + + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback) + { + return OCPlatform_impl::Instance().deleteResourceFromRD(host, connectivityType, + resourceHandles, callback); + } + + OCStackResult deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback, QualityOfService QoS) + { + return OCPlatform_impl::Instance().deleteResourceFromRD(host, connectivityType, + resourceHandles, callback, + QoS); + } +#endif } // namespace OCPlatform } //namespace OC diff --git a/resource/src/OCPlatform_impl.cpp b/resource/src/OCPlatform_impl.cpp index f5817c66f..4c89788a3 100644 --- a/resource/src/OCPlatform_impl.cpp +++ b/resource/src/OCPlatform_impl.cpp @@ -399,7 +399,47 @@ namespace OC return checked_guard(m_server, &IServerWrapper::sendResponse, pResponse); } +#ifdef RD_CLIENT + OCStackResult OCPlatform_impl::publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback) + { + return publishResourceToRD(host, connectivityType, resourceHandles, + callback, m_cfg.QoS); + } + + OCStackResult OCPlatform_impl::publishResourceToRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + PublishResourceCallback callback, + QualityOfService qos) + { + return checked_guard(m_server, &IServerWrapper::publishResourceToRD, + host, connectivityType, resourceHandles, callback, + static_cast(qos)); + } + OCStackResult OCPlatform_impl::deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback) + { + return deleteResourceFromRD(host, connectivityType, resourceHandles, callback, + m_cfg.QoS); + } + + OCStackResult OCPlatform_impl::deleteResourceFromRD(const std::string& host, + OCConnectivityType connectivityType, + ResourceHandles& resourceHandles, + DeleteResourceCallback callback, + QualityOfService qos) + { + return checked_guard(m_server, &IServerWrapper::deleteResourceFromRD, + host, connectivityType, resourceHandles, callback, + static_cast(qos)); + } +#endif std::weak_ptr OCPlatform_impl::csdkLock() { return m_csdkLock; diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp index 06b208381..476d72b8c 100644 --- a/resource/src/OCRepresentation.cpp +++ b/resource/src/OCRepresentation.cpp @@ -59,6 +59,11 @@ namespace OC case PAYLOAD_TYPE_PLATFORM: setPayload(reinterpret_cast(rep)); break; +#ifdef RD_CLIENT + case PAYLOAD_TYPE_RD: + setPayload(reinterpret_cast(rep)); + break; +#endif default: throw OC::OCException("Invalid Payload type in setPayload"); break; @@ -150,7 +155,7 @@ namespace OC void MessageContainer::setPayload(const OCRepPayload* payload) { const OCRepPayload* pl = payload; - while(pl) + while (pl) { OCRepresentation cur; cur.setPayload(pl); @@ -159,7 +164,29 @@ namespace OC this->addRepresentation(cur); } } +#ifdef RD_CLIENT + void MessageContainer::setPayload(const OCRDPayload* payload) + { + OCRepresentation rep; + rep[OC_RSRVD_DEVICE_ID] = (payload->rdPublish->tags->di.id) ? + std::string(reinterpret_cast(payload->rdPublish->tags->di.id)) : + std::string(); + rep[OC_RSRVD_DEVICE_NAME] = (payload->rdPublish->tags->n.deviceName) ? + std::string(payload->rdPublish->tags->n.deviceName) : + std::string(); + this->addRepresentation(rep); + const OCLinksPayload* pl = payload->rdPublish->setLinks; + while (pl) + { + OCRepresentation cur; + cur.setPayload(pl); + + pl = pl->next; + this->addRepresentation(cur); + } + } +#endif OCRepPayload* MessageContainer::getPayload() const { OCRepPayload* root = nullptr; @@ -657,7 +684,43 @@ namespace OC val = val->next; } } +#ifdef RD_CLIENT + void OCRepresentation::setPayload(const OCLinksPayload* pl) + { + if (pl->href) + { + setValue(OC_RSRVD_HREF, pl->href); + } + if (pl->rel) + { + setValue(OC_RSRVD_REL, pl->rel); + } + OCStringLL* ll = pl->rt; + while (ll) + { + addResourceType(ll->value); + ll = ll->next; + } + ll = pl->itf; + while (ll) + { + addResourceInterface(ll->value); + ll = ll->next; + } + setValue(OC_RSRVD_POLICY, pl->p); + setValue(OC_RSRVD_INS, pl->ins); + setValue(OC_RSRVD_TTL, pl->ttl); + if (pl->title) + { + setValue(OC_RSRVD_TITLE, pl->title); + } + if (pl->anchor) + { + setValue(OC_RSRVD_URI, pl->anchor); + } + } +#endif void OCRepresentation::addChild(const OCRepresentation& rep) { m_children.push_back(rep); diff --git a/resource/src/SConscript b/resource/src/SConscript index 32ff64bd8..c5f10d252 100644 --- a/resource/src/SConscript +++ b/resource/src/SConscript @@ -80,6 +80,11 @@ if target_os in ['msys_nt', 'windows']: if oclib_env.get('WITH_CLOUD'): oclib_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD']) +if 'CLIENT' in oclib_env.get('RD_MODE'): + oclib_env.AppendUnique(CPPDEFINES = ['RD_CLIENT']) +if 'SERVER' in oclib_env.get('RD_MODE'): + oclib_env.AppendUnique(CPPDEFINES = ['RD_SERVER']) + ###################################################################### # Source files and Targets ###################################################################### diff --git a/service/SConscript b/service/SConscript index 114be6e2b..7d8f1ac36 100755 --- a/service/SConscript +++ b/service/SConscript @@ -47,9 +47,9 @@ if target_os not in ['arduino','darwin', 'ios', 'windows']: if target_os in ['linux'] and env.get('SIMULATOR', False): SConscript('simulator/SConscript') -# Build resource directory project -if env.get('WITH_RD') == '1': - SConscript('resource-directory/SConscript') + # Build resource directory project + #if env.get('WITH_RD') == '1': + #SConscript('resource-directory/SConscript') # Build EasySetup module if target_os in ['arduino', 'android', 'linux','tizen']: