From d6deb32c7109e909041e9d93a298940e1a55180c Mon Sep 17 00:00:00 2001 From: Habib Virji Date: Thu, 27 Oct 2016 16:29:10 +0100 Subject: [PATCH] [IOT-1386] Update ins value after deleting resource from rd - Support multiple ins query for deleting resource. - Reset ins value of deleted resource. - Enable RD build in all platforms. - https://jira.iotivity.org/browse/IOT-1386 Change-Id: If7f19f63592ccfa6d298561da5ad173b0965d32c Signed-off-by: Habib Virji Reviewed-on: https://gerrit.iotivity.org/gerrit/12183 Tested-by: jenkins-iotivity --- cloud/samples/client/SConscript | 2 +- examples/OICMiddle/SConscript | 7 +- resource/SConscript | 7 +- resource/csdk/SConscript | 4 - resource/csdk/octbstack_product.def | 3 + resource/csdk/resource-directory/SConscript | 21 ++-- .../csdk/resource-directory/include/rd_client.h | 4 + .../csdk/resource-directory/include/rd_server.h | 4 + .../resource-directory/src/internal/rd_database.c | 3 +- resource/csdk/resource-directory/src/rd_client.c | 24 +++- .../csdk/stack/include/internal/ocstackinternal.h | 14 +++ resource/csdk/stack/src/ocstack.c | 128 ++++++++++++++++++++- resource/examples/SConscript | 5 + resource/src/InProcServerWrapper.cpp | 29 +---- resource/src/SConscript | 13 +-- resource/unittests/SConscript | 4 + 16 files changed, 205 insertions(+), 67 deletions(-) diff --git a/cloud/samples/client/SConscript b/cloud/samples/client/SConscript index aadd7a4..3f9ae58 100644 --- a/cloud/samples/client/SConscript +++ b/cloud/samples/client/SConscript @@ -43,7 +43,7 @@ cc_sample_app_env.AppendUnique(CPPPATH = [ cc_sample_app_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-Wextra', '-std=c++0x', '-pthread']) cc_sample_app_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) cc_sample_app_env.AppendUnique(RPATH = [env.get('BUILD_DIR')]) -cc_sample_app_env.PrependUnique(LIBS = ['oc', 'octbstack', 'pthread']) +cc_sample_app_env.PrependUnique(LIBS = ['oc', 'octbstack', 'pthread', 'resource_directory']) cc_sample_app_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD', 'RD_CLIENT']) diff --git a/examples/OICMiddle/SConscript b/examples/OICMiddle/SConscript index 05b3aae..b2b981b 100644 --- a/examples/OICMiddle/SConscript +++ b/examples/OICMiddle/SConscript @@ -27,6 +27,7 @@ lib_env = env.Clone() SConscript('#resource/third_party_libs.scons', 'lib_env') examples_env = lib_env.Clone() +rd_mode = lib_env.get('RD_MODE') ###################################################################### # Build flags @@ -72,6 +73,9 @@ if target_os in ['darwin', 'ios']: if env.get('WITH_CLOUD'): examples_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD']) +if 'CLIENT' in rd_mode or 'SERVER' in rd_mode: + examples_env.AppendUnique(LIBS = ['resource_directory']) + ###################################################################### # Source files and Targets ###################################################################### @@ -79,6 +83,3 @@ OICMiddle = examples_env.Program('OICMiddle', ['OICMiddle.cpp', 'Client.cpp', 'L Alias("examples", [OICMiddle]) env.AppendTarget('examples') - - - diff --git a/resource/SConscript b/resource/SConscript index 4b09744..0cce7d5 100644 --- a/resource/SConscript +++ b/resource/SConscript @@ -27,6 +27,7 @@ Import('env') target_os = env.get('TARGET_OS') src_dir = env.get('SRC_DIR') +rd_mode = env.get('RD_MODE') # Build C Common dependencies SConscript('c_common/SConscript') @@ -47,10 +48,8 @@ if env.get('ROUTING') in ['GW', 'EP']: # Build Routing SConscript('csdk/routing/SConscript') -if target_os in ['linux', 'android']: - rd_mode = env.get('RD_MODE') - if 'CLIENT' in rd_mode or 'SERVER' in rd_mode: - SConscript('csdk/resource-directory/SConscript') +if 'CLIENT' in rd_mode or 'SERVER' in rd_mode: + SConscript('csdk/resource-directory/SConscript') # Build libocsrm SConscript('csdk/security/SConscript') diff --git a/resource/csdk/SConscript b/resource/csdk/SConscript index 0de9e79..cf0a48c 100644 --- a/resource/csdk/SConscript +++ b/resource/csdk/SConscript @@ -171,10 +171,6 @@ if 'CLIENT' in rd_mode or 'SERVER' in rd_mode: liboctbstack_env.AppendUnique(CPPDEFINES = ['RD_CLIENT']) if 'SERVER' in rd_mode: liboctbstack_env.AppendUnique(CPPDEFINES = ['RD_SERVER']) - if target_os in ['linux', 'android']: - liboctbstack_env.Prepend(LIBS = ['resource_directory']) - liboctbstack_env.PrependUnique(CPPPATH = [env.get('BUILD_DIR') + 'resource/csdk/resource-directory/include']) - liboctbstack_env.PrependUnique(LIBPATH = [env.get('BUILD_DIR') + 'resource/csdk/resource-directory/include']) if with_tcp == True: liboctbstack_src.append(OCTBSTACK_SRC + 'oickeepalive.c') diff --git a/resource/csdk/octbstack_product.def b/resource/csdk/octbstack_product.def index 4b226b0..b782f23 100644 --- a/resource/csdk/octbstack_product.def +++ b/resource/csdk/octbstack_product.def @@ -58,6 +58,7 @@ OCGetResourceInterfaceName OCGetResourceProperties OCGetResourceTypeName OCGetResourceUri +OCGetResourceIns OCGetServerInstanceIDString OCInit OCInit1 @@ -88,6 +89,7 @@ OCRepPayloadSetPropBool OCRepPayloadSetPropDouble OCRepPayloadSetPropByteString OCRepPayloadSetPropInt +OCRepPayloadSetPropObjectArray OCRepPayloadSetPropObjectArrayAsOwner OCRepPayloadSetPropObjectAsOwner OCRepPayloadSetPropString @@ -101,6 +103,7 @@ OCSetPlatformInfo OCStartPresence OCStop OCStopPresence +OCStopMulticastServer OCUnBindResource OCSetHeaderOption OCGetHeaderOption diff --git a/resource/csdk/resource-directory/SConscript b/resource/csdk/resource-directory/SConscript index ff0b2ee..44413f4 100755 --- a/resource/csdk/resource-directory/SConscript +++ b/resource/csdk/resource-directory/SConscript @@ -35,25 +35,22 @@ rd_mode = env.get('RD_MODE') ###################################################################### # Build flags ###################################################################### -rd_env.AppendUnique(CPPPATH = ['include', 'src/internal', '../stack/include']) +rd_env.AppendUnique(CPPPATH = ['include', 'src/internal', '../stack/include', '../../oc_logger/include']) if 'CLIENT' in rd_mode: rd_env.AppendUnique(CPPDEFINES = ['RD_CLIENT']) if 'SERVER' in rd_mode: rd_env.AppendUnique(CPPDEFINES = ['RD_SERVER']) -rd_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'coap']) +rd_env.AppendUnique(LIBPATH = [rd_env.get('BUILD_DIR')]) +rd_env.AppendUnique(LIBS = ['octbstack']) if target_os not in ['windows']: rd_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-Wextra']) -if target_os in ['linux']: - rd_env.AppendUnique(LIBS = ['pthread']) - if target_os == 'android': rd_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) rd_env.AppendUnique(LIBS = ['gnustl_static']) - if not env.get('RELEASE'): rd_env.AppendUnique(LIBS = ['log']) @@ -67,23 +64,25 @@ else: ###################################################################### RD_SRC_DIR = 'src/' rd_src = [] + if 'SERVER' in rd_mode: rd_src += [ - RD_SRC_DIR + 'internal/rd_database.c', - RD_SRC_DIR + 'rd_server.c', - ] + RD_SRC_DIR + 'internal/rd_database.c', + RD_SRC_DIR + 'rd_server.c', + ] if target_os not in ['tizen'] : rd_src += [ '../../../extlibs/sqlite3/sqlite3.c' ] + if 'CLIENT' in rd_mode: rd_src += [RD_SRC_DIR + 'rd_client.c',] -if target_os in ['tizen'] : +if target_os in ['tizen']: rdsdk = rd_env.SharedLibrary('resource_directory', rd_src) else : rdsdk = rd_env.StaticLibrary('resource_directory', rd_src) - rd_env.InstallTarget(rdsdk, 'resource_directory') rd_env.UserInstallTargetLib(rdsdk, 'resource_directory') + if 'CLIENT' in rd_mode: rd_env.UserInstallTargetHeader('include/rd_client.h', 'service/resource-directory', 'rd_client.h') diff --git a/resource/csdk/resource-directory/include/rd_client.h b/resource/csdk/resource-directory/include/rd_client.h index 1e622ad..2b4a582 100644 --- a/resource/csdk/resource-directory/include/rd_client.h +++ b/resource/csdk/resource-directory/include/rd_client.h @@ -28,6 +28,8 @@ extern "C" { #endif // __cplusplus +#ifdef RD_CLIENT + #define OIC_RD_PUBLISH_TTL 86400 #define OIC_RD_DEFAULT_RESOURCE 2 @@ -124,6 +126,8 @@ OCStackResult OCRDDeleteWithDeviceId(const char *host, const unsigned char *id, OCResourceHandle *resourceHandles, uint8_t nHandles, OCCallbackData *cbData, OCQualityOfService qos); +#endif + #ifdef __cplusplus } #endif // __cplusplus diff --git a/resource/csdk/resource-directory/include/rd_server.h b/resource/csdk/resource-directory/include/rd_server.h index 32ef331..8554904 100644 --- a/resource/csdk/resource-directory/include/rd_server.h +++ b/resource/csdk/resource-directory/include/rd_server.h @@ -28,6 +28,8 @@ extern "C" { #endif // __cplusplus +#ifdef RD_SERVER + /** * This function creates resource /oic/rd. * @@ -58,6 +60,8 @@ OCStackResult OCRDStop(); OCStackResult OCRDCheckPublishedResource(const char *interfaceType, const char *resourceType, OCDiscoveryPayload **payload); +#endif + #ifdef __cplusplus } #endif // __cplusplus diff --git a/resource/csdk/resource-directory/src/internal/rd_database.c b/resource/csdk/resource-directory/src/internal/rd_database.c index c16cec8..8653da8 100644 --- a/resource/csdk/resource-directory/src/internal/rd_database.c +++ b/resource/csdk/resource-directory/src/internal/rd_database.c @@ -401,7 +401,8 @@ static OCStackResult appendStringLL(OCStringLL **type, const unsigned char *valu } else { - for (OCStringLL *tmp = *type; tmp->next; tmp = tmp->next); + OCStringLL *tmp = *type; + for (; tmp->next; tmp = tmp->next); tmp->next = temp; } return OC_STACK_OK; diff --git a/resource/csdk/resource-directory/src/rd_client.c b/resource/csdk/resource-directory/src/rd_client.c index c63b749..bf3597d 100644 --- a/resource/csdk/resource-directory/src/rd_client.c +++ b/resource/csdk/resource-directory/src/rd_client.c @@ -19,6 +19,8 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "rd_client.h" +#include + #include "oic_malloc.h" #include "oic_string.h" #include "octypes.h" @@ -125,9 +127,14 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id, } OCRepPayloadSetPropInt(rdPayload, OC_RSRVD_DEVICE_TTL, OIC_RD_PUBLISH_TTL); - const OCRepPayload *linkArr[nPubResHandles]; - size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nPubResHandles, 0, 0}; + OCRepPayload **linkArr = OICCalloc(nPubResHandles, sizeof(OCRepPayload *)); + if (!linkArr) + { + OCRepPayloadDestroy(rdPayload); + return OC_STACK_NO_MEMORY; + } + size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nPubResHandles, 0, 0}; for (uint8_t j = 0; j < nPubResHandles; j++) { OCResourceHandle handle = pubResHandle[j]; @@ -152,7 +159,7 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id, OIC_LOG_V(DEBUG, TAG, "value: %s", value); rt[i] = OICStrdup(value); } - OCRepPayloadSetStringArray(link, OC_RSRVD_RESOURCE_TYPE, (const char **)rt, rtDim); + OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_RESOURCE_TYPE, rt, rtDim); } numElement = 0; @@ -166,7 +173,7 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id, OIC_LOG_V(DEBUG, TAG, "value: %s", value); itf[i] = OICStrdup(value); } - OCRepPayloadSetStringArray(link, OC_RSRVD_INTERFACE, (const char **)itf, ifDim); + OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_INTERFACE, itf, ifDim); } uint8_t ins = 0; @@ -178,7 +185,7 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id, size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0}; char **mediaType = (char **)OICMalloc(sizeof(char *) * 1); mediaType[0] = OICStrdup(DEFAULT_MESSAGE_TYPE); - OCRepPayloadSetStringArray(link, OC_RSRVD_MEDIA_TYPE, (const char **)mediaType, + OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_MEDIA_TYPE, mediaType, mtDim); OCResourceProperty p = OCGetResourceProperties(handle); @@ -194,6 +201,12 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id, OCRepPayloadSetPropObjectArray(rdPayload, OC_RSRVD_LINKS, linkArr, dimensions); OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload); + for (uint8_t i = 0; i < nPubResHandles; i++) + { + OCRepPayloadDestroy(linkArr[i]); + } + OICFree(linkArr); + return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)rdPayload, connectivityType, qos, cbData, NULL, 0); } @@ -252,5 +265,4 @@ OCStackResult OCRDDeleteWithDeviceId(const char *host, const unsigned char *id, return OCDoResource(NULL, OC_REST_DELETE, targetUri, NULL, NULL, connectivityType, qos, cbData, NULL, 0); } - #endif diff --git a/resource/csdk/stack/include/internal/ocstackinternal.h b/resource/csdk/stack/include/internal/ocstackinternal.h index da45393..ba22bf0 100644 --- a/resource/csdk/stack/include/internal/ocstackinternal.h +++ b/resource/csdk/stack/include/internal/ocstackinternal.h @@ -299,6 +299,20 @@ void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out); */ uint32_t GetTicks(uint32_t milliSeconds); +#if defined(RD_CLIENT) || defined(RD_SERVER) +/** + * This function binds an resource unique ins value to the resource. This can be only called + * when stack is received response from resource-directory. + * + * @param requestUri URI of the resource. + * @param response Response from queries to remote servers. + * + * @return ::OC_STACK_OK on success, some other value upon failure. + */ +OCStackResult OCUpdateResourceInsWithResponse(const char *requestUri, + const OCClientResponse *response); +#endif + #ifdef __cplusplus } #endif // __cplusplus diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index 5e792d6..95e9720 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -1443,6 +1443,14 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp } else { +#ifdef RD_CLIENT + // if request uri is '/oic/rd', update ins value of resource. + char *targetUri = strstr(cbNode->requestUri, OC_RSRVD_RD_URI); + if (targetUri) + { + OCUpdateResourceInsWithResponse(cbNode->requestUri, &response); + } +#endif OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context, cbNode->handle, &response); @@ -4854,6 +4862,116 @@ OCStackResult OCBindResourceInsToResource(OCResourceHandle handle, uint8_t ins) return OC_STACK_OK; } +OCStackResult OCUpdateResourceInsWithResponse(const char *requestUri, + const OCClientResponse *response) +{ + // Validate input parameters + VERIFY_NON_NULL(requestUri, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(response, ERROR, OC_STACK_INVALID_PARAM); + + char *targetUri = (char *) OICMalloc(strlen(requestUri) + 1); + if (!targetUri) + { + return OC_STACK_NO_MEMORY; + } + strncpy(targetUri, requestUri, strlen(requestUri) + 1); + + if (response->result == OC_STACK_RESOURCE_CHANGED) // publish message + { + OIC_LOG(DEBUG, TAG, "update the ins of published resource"); + + char rdPubUri[MAX_URI_LENGTH] = { 0 }; + snprintf(rdPubUri, MAX_URI_LENGTH, "%s?rt=%s", OC_RSRVD_RD_URI, + OC_RSRVD_RESOURCE_TYPE_RDPUBLISH); + + if (strcmp(rdPubUri, targetUri) == 0) + { + // Update resource unique id in stack. + if (response) + { + if (response->payload) + { + OCRepPayload *rdPayload = (OCRepPayload *) response->payload; + OCRepPayload **links = NULL; + size_t dimensions[MAX_REP_ARRAY_DEPTH]; + if (OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, + &links, dimensions)) + { + size_t i = 0; + for (; i < dimensions[0]; i++) + { + char *uri = NULL; + if (OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri)) + { + OCResourceHandle handle = OCGetResourceHandleAtUri(uri); + int64_t ins = 0; + if (OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins)) + { + OCBindResourceInsToResource(handle, ins); + } + } + } + } + } + } + } + } + else if (response->result == OC_STACK_RESOURCE_DELETED) // delete message + { + OIC_LOG(DEBUG, TAG, "update the ins of deleted resource with 0"); + + uint8_t numResources = 0; + OCGetNumberOfResources(&numResources); + + char *ins = strstr(targetUri, OC_RSRVD_INS); + if (!ins) + { + for (uint8_t i = 0; i < numResources; i++) + { + OCResourceHandle resHandle = OCGetResourceHandle(i); + if (resHandle) + { + OCBindResourceInsToResource(resHandle, 0); + } + } + } + else + { + const char *token = "&"; + char *iterTokenPtr = NULL; + char *start = strtok_r(targetUri, token, &iterTokenPtr); + + while (start != NULL) + { + char *query = start; + query = strstr(query, OC_RSRVD_INS); + if (query) + { + uint8_t queryIns = atoi(query + 4); + for (uint8_t i = 0; i < numResources; i++) + { + OCResourceHandle resHandle = OCGetResourceHandle(i); + if (resHandle) + { + uint8_t resIns = 0; + OCGetResourceIns(resHandle, &resIns); + if (queryIns && queryIns == resIns) + { + OCBindResourceInsToResource(resHandle, 0); + break; + } + } + } + } + start = strtok_r(NULL, token, &iterTokenPtr); + } + } + } + + OICFree(targetUri); + return OC_STACK_OK; +} + OCResourceHandle OCGetResourceHandleAtUri(const char *uri) { if (!uri) @@ -4891,9 +5009,10 @@ OCStackResult OCGetResourceIns(OCResourceHandle handle, uint8_t *ins) } return OC_STACK_ERROR; } +#endif OCStackResult OCSetHeaderOption(OCHeaderOption* ocHdrOpt, size_t* numOptions, uint16_t optionID, - void* optionData, size_t optionDataLength) + void* optionData, size_t optionDataLength) { if (!ocHdrOpt) { @@ -4930,8 +5049,10 @@ OCStackResult OCSetHeaderOption(OCHeaderOption* ocHdrOpt, size_t* numOptions, ui return OC_STACK_OK; } -OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, uint16_t optionID, - void* optionData, size_t optionDataLength, uint16_t* receivedDataLength) + +OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, + uint16_t optionID, void* optionData, size_t optionDataLength, + uint16_t* receivedDataLength) { if (!ocHdrOpt || !numOptions) { @@ -4970,7 +5091,6 @@ OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, uin } return OC_STACK_OK; } -#endif void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled) { diff --git a/resource/examples/SConscript b/resource/examples/SConscript index e25cabf..8075f9e 100644 --- a/resource/examples/SConscript +++ b/resource/examples/SConscript @@ -28,6 +28,8 @@ lib_env = thread_env.Clone() SConscript('#resource/third_party_libs.scons', 'lib_env') examples_env = lib_env.Clone() target_os = examples_env.get('TARGET_OS') +rd_mode = examples_env.get('RD_MODE') + ###################################################################### # Build flags ###################################################################### @@ -79,6 +81,9 @@ if target_os in ['msys_nt', 'windows']: if examples_env.get('LOGGING'): examples_env.AppendUnique(CPPDEFINES = ['TB_LOG']) +if 'CLIENT' in rd_mode or 'SERVER' in rd_mode: + examples_env.AppendUnique(LIBS = ['resource_directory']) + def make_single_file_cpp_program(program_name): return examples_env.Program(program_name, program_name + ".cpp") diff --git a/resource/src/InProcServerWrapper.cpp b/resource/src/InProcServerWrapper.cpp index 88ea41f..0235fda 100644 --- a/resource/src/InProcServerWrapper.cpp +++ b/resource/src/InProcServerWrapper.cpp @@ -641,30 +641,9 @@ namespace OC try { - // Update resource unique id in stack. - if (clientResponse) - { - if (clientResponse->payload) - { - OCRepPayload *rdPayload = (OCRepPayload *) clientResponse->payload; - OCRepPayload **links = NULL; - - size_t dimensions[MAX_REP_ARRAY_DEPTH]; - OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, &links, dimensions); - for(size_t i = 0; i < dimensions[0]; i++) - { - char *uri = NULL; - OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri); - OCResourceHandle handle = OCGetResourceHandleAtUri(uri); - int64_t ins = 0; - OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins); - OCBindResourceInsToResource(handle, ins); - } - } - OCRepresentation rep = parseRDResponseCallback(clientResponse); - std::thread exec(context->callback, rep, clientResponse->result); - exec.detach(); - } + OCRepresentation rep = parseRDResponseCallback(clientResponse); + std::thread exec(context->callback, rep, clientResponse->result); + exec.detach(); } catch (OC::OCException& e) { @@ -672,7 +651,7 @@ namespace OC <