diff --git a/bridging/common/SConscript b/bridging/common/SConscript index bb77d6b96f..452aec2fc2 100644 --- a/bridging/common/SConscript +++ b/bridging/common/SConscript @@ -55,7 +55,7 @@ mpmcommon_env.PrependUnique(CPPPATH=[ if target_os not in ['windows']: mpmcommon_env.AppendUnique( - CXXFLAGS=['-std=c++0x', '-Wall', '-Wextra', '-Werror', '-fpic']) + CXXFLAGS=['-std=c++0x', '-Wall', '-Wextra', '-fpic']) mpmcommon_env['LINKFLAGS'] = maskFlags(mpmcommon_env['LINKFLAGS']) diff --git a/resource/csdk/include/octypes.h b/resource/csdk/include/octypes.h index 89280de3f0..e2e49a62b2 100644 --- a/resource/csdk/include/octypes.h +++ b/resource/csdk/include/octypes.h @@ -1447,6 +1447,13 @@ typedef enum PAYLOAD_TYPE_INTROSPECTION } OCPayloadType; +/** Enum to describe payload interface interface.*/ +typedef enum +{ + PAYLOAD_NON_BATCH_INTERFACE, + PAYLOAD_BATCH_INTERFACE +} OCPayloadInterfaceType; + /** * A generic struct representing a payload returned from a resource operation * @@ -1526,6 +1533,7 @@ typedef struct OCRepPayloadValue typedef struct OCRepPayload { OCPayload base; + OCPayloadInterfaceType ifType; char* uri; OCStringLL* types; OCStringLL* interfaces; diff --git a/resource/csdk/resource-directory/samples/rd_publishingClient.cpp b/resource/csdk/resource-directory/samples/rd_publishingClient.cpp index ee9c01ec8a..be76861d14 100644 --- a/resource/csdk/resource-directory/samples/rd_publishingClient.cpp +++ b/resource/csdk/resource-directory/samples/rd_publishingClient.cpp @@ -22,20 +22,20 @@ #include #include #include +#include +#include +#include #include "oic_string.h" #include "rd_client.h" -/// This example is using experimental API, so there is no guarantee of support for future release, -/// nor any there any guarantee that breaking changes will not occur across releases. -/// logging part is not critical but convenient for developer -#include "experimental/payload_logging.h" - -#define TAG ("RD_PublishClient") #define DEFAULT_CONTEXT_VALUE 0x99 OCResourceHandle handles[2]; -std::ostringstream rdAddress; +std::string rdAddress; +std::mutex mutex; +std::condition_variable cond; +int in = 0; OCStackResult registerLocalResources() { @@ -74,11 +74,11 @@ void printHelp() { std::cout << std::endl; std::cout << "********************************************" << std::endl; - std::cout << "* method Type : 1 - Discover RD *" << std::endl; - std::cout << "* method Type : 2 - Publish *" << std::endl; - std::cout << "* method Type : 3 - Update *" << std::endl; - std::cout << "* method Type : 4 - Delete *" << std::endl; - std::cout << "* method Type : 5 - Status *" << std::endl; + std::cout << "* method Type : 1 - Discover RD *" << std::endl; + std::cout << "* method Type : 2 - Publish *" << std::endl; + std::cout << "* method Type : 3 - Update *" << std::endl; + std::cout << "* method Type : 4 - Delete *" << std::endl; + std::cout << "* method Type : 99 - Exit *" << std::endl; std::cout << "********************************************" << std::endl; std::cout << std::endl; } @@ -88,9 +88,11 @@ static OCStackApplicationResult handleDiscoveryCB(__attribute__((unused))void *c __attribute__((unused)) OCClientResponse *clientResponse) { - OIC_LOG(DEBUG, TAG, "Successfully found RD."); - rdAddress << clientResponse->devAddr.addr << ":" << clientResponse->devAddr.port; - std::cout << "RD Address is : " << rdAddress.str() << std::endl; + std::cout << "Successfully found RD." << std::endl; + std::ostringstream oss; + oss << clientResponse->devAddr.addr << ":" << clientResponse->devAddr.port; + rdAddress = oss.str(); + std::cout << "RD Address is : " << rdAddress << std::endl; return OC_STACK_DELETE_TRANSACTION; } @@ -99,17 +101,127 @@ static OCStackApplicationResult handlePublishCB(__attribute__((unused))void *ctx __attribute__((unused)) OCClientResponse *clientResponse) { - OIC_LOG(DEBUG, TAG, "Successfully published resources."); + std::cout << "Successfully published resources." << std::endl; return OC_STACK_DELETE_TRANSACTION; } -int main(void) +static OCStackApplicationResult handleUpdateCB(__attribute__((unused))void *ctx, + __attribute__((unused)) OCDoHandle handle, + __attribute__((unused)) + OCClientResponse *clientResponse) +{ + std::cout << "Successfully updated resources." << std::endl; + return OC_STACK_DELETE_TRANSACTION; +} + +static OCStackApplicationResult handleDeleteCB(__attribute__((unused))void *ctx, + __attribute__((unused)) OCDoHandle handle, + __attribute__((unused)) + OCClientResponse *clientResponse) +{ + std::cout << "Successfully deleted resources." << std::endl; + return OC_STACK_DELETE_TRANSACTION; +} + +static void ocThread() +{ + OCStackResult result; + bool run = true; + while (run) + { + std::unique_lock lock(mutex); + if (cond.wait_for(lock, std::chrono::milliseconds(100)) == std::cv_status::no_timeout) + { + switch (in) + { + case 1: + { + OCCallbackData cbData; + cbData.cb = &handleDiscoveryCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + result = OCRDDiscover(nullptr, CT_ADAPTER_IP, &cbData, OC_LOW_QOS); + if (OC_STACK_OK != result) + { + std::cout << "OCRDDiscover Failed " << result << std::endl; + } + break; + } + case 2: + { + OCCallbackData cbData; + cbData.cb = &handlePublishCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + result = OCRDPublish(nullptr, rdAddress.c_str(), CT_ADAPTER_IP, handles, + 2, OIC_RD_PUBLISH_TTL, &cbData, OC_LOW_QOS); + if (OC_STACK_OK != result) + { + std::cout << "OCRDPublish Failed " << result << std::endl; + } + break; + } + case 3: + { + /* Update the TTL */ + OCCallbackData cbData; + cbData.cb = &handleUpdateCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + result = OCRDPublish(nullptr, rdAddress.c_str(), CT_ADAPTER_IP, handles, + 2, OIC_RD_PUBLISH_TTL, &cbData, OC_LOW_QOS); + if (OC_STACK_OK != result) + { + std::cout << "OCRDPublish Failed " << result << std::endl; + } + break; + } + case 4: + { + /* Delete all resources */ + OCCallbackData cbData; + cbData.cb = &handleDeleteCB; + cbData.cd = NULL; + cbData.context = (void*) DEFAULT_CONTEXT_VALUE; + result = OCRDDelete(nullptr, rdAddress.c_str(), CT_ADAPTER_IP, NULL, + 0, &cbData, OC_LOW_QOS); + if (OC_STACK_OK != result) + { + std::cout << "OCRDDelete Failed " << result << std::endl; + } + break; + } + case 99: + run = false; + break; + default: + std::cout << "Invalid input, please try again" << std::endl; + break; + } + printHelp(); + } + result = OCProcess(); + if (OC_STACK_OK != result) + { + std::cout << "OCProcess Failed " << result << std::endl; + break; + } + } +} + +int main() { std::cout << "Initializing IoTivity Platform" << std::endl; OCStackResult result = OCInit(NULL, 0, OC_CLIENT_SERVER); if (OC_STACK_OK != result) { - std::cout << "OCInit Failed" << result << std::endl; + std::cout << "OCInit Failed " << result << std::endl; + return -1; + } + result = OCStopMulticastServer(); + if (OC_STACK_OK != result) + { + std::cout << "OCStopMulticastServer Failed " << result << std::endl; return -1; } @@ -121,15 +233,12 @@ int main(void) return -1; } + printHelp(); + + std::thread t(ocThread); + while (1) { - if (handles[0] == NULL || handles[1] == NULL) - { - continue; - } - printHelp(); - - int in = 0; std::cin >> in; if (std::cin.fail()) @@ -140,34 +249,14 @@ int main(void) continue; } - switch ((int)in) + cond.notify_one(); + + if (in == 99) { - case 1: - { - OCCallbackData cbData; - cbData.cb = &handleDiscoveryCB;; - cbData.cd = NULL; - cbData.context = (void*) DEFAULT_CONTEXT_VALUE; - OCRDDiscover(nullptr, CT_ADAPTER_IP, &cbData, OC_LOW_QOS); - break; - } - case 2: - { - OCCallbackData cbData; - cbData.cb = &handlePublishCB; - cbData.cd = NULL; - cbData.context = (void*) DEFAULT_CONTEXT_VALUE; - std::string address = rdAddress.str(); - OCRDPublish(nullptr, address.c_str(), CT_ADAPTER_IP, handles, - 2, OIC_RD_PUBLISH_TTL, &cbData, OC_LOW_QOS); - break; - } - case 3: - break; - default: - std::cout << "Invalid input, please try again" << std::endl; - break; + break; } } + + t.join(); return 0; } diff --git a/resource/csdk/resource-directory/samples/rd_queryClient.cpp b/resource/csdk/resource-directory/samples/rd_queryClient.cpp index d1ecf7c601..90547290e4 100644 --- a/resource/csdk/resource-directory/samples/rd_queryClient.cpp +++ b/resource/csdk/resource-directory/samples/rd_queryClient.cpp @@ -36,11 +36,11 @@ OCStackApplicationResult foundResource(void* ctx, OCClientResponse *clientResponse) { (void)handle; - (void) ctx; + (void)ctx; if (clientResponse == NULL) { std::cout << "foundResource received NULL clientResponse" << std::endl; - return OC_STACK_DELETE_TRANSACTION; + return OC_STACK_DELETE_TRANSACTION; } std::cout << "Found resource response." << std::endl; @@ -102,5 +102,10 @@ int main(void) sendRequest = true; } } + if (OCProcess() != OC_STACK_OK) + { + std::cout << "OCStack process error" << std::endl; + return -1; + } } } diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h index 40b9edb906..8be42063c4 100644 --- a/resource/csdk/stack/include/ocpayload.h +++ b/resource/csdk/stack/include/ocpayload.h @@ -114,6 +114,8 @@ void OC_CALL OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child); bool OC_CALL OCRepPayloadSetUri(OCRepPayload* payload, const char* uri); +bool OC_CALL OCRepPayloadSetInterfaceType(OCRepPayload* payload, OCPayloadInterfaceType type); + bool OC_CALL OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType); bool OC_CALL OCRepPayloadAddInterface(OCRepPayload* payload, const char* iface); diff --git a/resource/csdk/stack/octbstack_product.def b/resource/csdk/stack/octbstack_product.def index 56021c5597..b8407970e0 100644 --- a/resource/csdk/stack/octbstack_product.def +++ b/resource/csdk/stack/octbstack_product.def @@ -120,6 +120,7 @@ OCRepPayloadSetPropStringAsOwner OCRepPayloadSetStringArray OCRepPayloadSetStringArrayAsOwner OCRepPayloadSetUri +OCRepPayloadSetInterfaceType OCResourcePayloadAddNewEndpoint OCResourcePayloadAddStringLL OCSecurityPayloadCreate diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp index 4b939a0612..3dd5f20084 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp @@ -211,6 +211,7 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag, { OCRepPayloadSetUri(payload, gRoomResourceUri); + OCRepPayloadSetInterfaceType(payload, PAYLOAD_BATCH_INTERFACE); OCRepPayload *tempPayload = OCRepPayloadCreate(); OCRepPayloadSetUri(tempPayload, gLightResourceUri); diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index a0c3b05fec..6e34b565d7 100644 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -85,6 +85,7 @@ OCRepPayload* OC_CALL OCRepPayloadCreate(void) return NULL; } + payload->ifType = PAYLOAD_NON_BATCH_INTERFACE; payload->base.type = PAYLOAD_TYPE_REPRESENTATION; return payload; @@ -495,6 +496,17 @@ bool OC_CALL OCRepPayloadSetUri(OCRepPayload* payload, const char* uri) return payload->uri != NULL; } +bool OC_CALL OCRepPayloadSetInterfaceType(OCRepPayload* payload, OCPayloadInterfaceType type) +{ + if (!payload) + { + return false; + } + + payload->ifType = type; + return true; +} + bool OC_CALL OCRepPayloadIsNull(const OCRepPayload* payload, const char* name) { OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name); @@ -1622,6 +1634,7 @@ OCRepPayload* OC_CALL OCRepPayloadBatchClone(const OCRepPayload* repPayload) } clone->types = CloneOCStringLL(repPayload->types); + clone->ifType = repPayload->ifType; clone->interfaces = CloneOCStringLL(repPayload->interfaces); clone->values = OCRepPayloadValueClone(repPayload->values); OCRepPayloadSetPropObjectAsOwner(newPayload, OC_RSRVD_REPRESENTATION, clone); diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index 11891b2c0f..ac06847711 100644 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -942,13 +942,19 @@ static int64_t OCConvertRepPayload(OCRepPayload *payload, uint8_t *outPayload, s cbor_encoder_init(&encoder, outPayload, *size, 0); + int isBatch = 0; + if (payload != NULL && payload->ifType == PAYLOAD_BATCH_INTERFACE) + { + isBatch = 1; + } + size_t arrayCount = 0; for (OCRepPayload *temp = payload; temp; temp = temp->next) { arrayCount++; } CborEncoder rootArray; - if (arrayCount > 1) + if (arrayCount > 1 || isBatch) { err |= cbor_encoder_create_array(&encoder, &rootArray, arrayCount); VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed adding rep root map"); @@ -957,7 +963,7 @@ static int64_t OCConvertRepPayload(OCRepPayload *payload, uint8_t *outPayload, s while (payload != NULL && (err == CborNoError)) { CborEncoder rootMap; - err |= cbor_encoder_create_map(((arrayCount == 1)? &encoder: &rootArray), + err |= cbor_encoder_create_map(((arrayCount == 1 && !isBatch)? &encoder: &rootArray), &rootMap, CborIndefiniteLength); VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed creating root map"); @@ -965,12 +971,12 @@ static int64_t OCConvertRepPayload(OCRepPayload *payload, uint8_t *outPayload, s VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed setting rep payload"); // Close main array - err |= cbor_encoder_close_container(((arrayCount == 1) ? &encoder: &rootArray), + err |= cbor_encoder_close_container(((arrayCount == 1 && !isBatch) ? &encoder: &rootArray), &rootMap); VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed closing root map"); payload = payload->next; } - if (arrayCount > 1) + if (arrayCount > 1 || isBatch) { err |= cbor_encoder_close_container(&encoder, &rootArray); VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed closing root array"); diff --git a/resource/csdk/stack/src/ocserverrequest.c b/resource/csdk/stack/src/ocserverrequest.c index 65bf85a6bc..d1224e61e6 100644 --- a/resource/csdk/stack/src/ocserverrequest.c +++ b/resource/csdk/stack/src/ocserverrequest.c @@ -877,6 +877,7 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse) if(!serverResponse->payload) { + OCRepPayloadSetInterfaceType(newPayload, PAYLOAD_BATCH_INTERFACE); serverResponse->payload = (OCPayload *)newPayload; } else diff --git a/resource/include/OCRepresentation.h b/resource/include/OCRepresentation.h index 561bea4343..d7b079cd1e 100644 --- a/resource/include/OCRepresentation.h +++ b/resource/include/OCRepresentation.h @@ -102,6 +102,10 @@ namespace OC OCRepPayload* getPayload() const; + void setInterfaceType(const InterfaceType&); + + InterfaceType getInterfaceType() const; + void addChild(const OCRepresentation&); void clearChildren(); @@ -448,10 +452,6 @@ namespace OC // based on the interface type configured in ResourceResponse. // This allows ResourceResponse to set it, so that the save function // doesn't serialize things that it isn't supposed to serialize. - void setInterfaceType(InterfaceType ift) - { - m_interfaceType = ift; - } // class used to wrap the 'prop' feature of the save/load class Prop diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp index b3dc5b2fc6..970a2fb160 100644 --- a/resource/src/OCRepresentation.cpp +++ b/resource/src/OCRepresentation.cpp @@ -83,6 +83,10 @@ namespace OC if (!root) { root = r.getPayload(); + if (r.getInterfaceType() == InterfaceType::BatchParent) + { + root->ifType = PAYLOAD_BATCH_INTERFACE; + } } else { @@ -389,6 +393,16 @@ namespace OC return root; } + void OCRepresentation::setInterfaceType(const InterfaceType& ift) + { + m_interfaceType = ift; + } + + InterfaceType OCRepresentation::getInterfaceType() const + { + return m_interfaceType; + } + size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH]) { if (dimensions[0] == 0)