From 8ad37e362aaf0aba5e20552e0bd54780d49c3d34 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 6 Oct 2014 10:50:47 -0700 Subject: [PATCH] Make exception and error handling more consistent through the top-level API. Following up on Sudarshan's comments. Change-Id: I8e19a89952f5235abbab43f1eb266604b5a4f1ac --- README | 113 ------------ examples/ocicuc/Makefile | 9 +- include/OCException.h | 57 ++---- include/OCResource.h | 1 + include/OCUtilities.h | 53 +++++- makefile | 7 +- src/OCException.cpp | 80 +++++++++ src/OCPlatform.cpp | 452 ++++++++++++++++------------------------------- src/OCResource.cpp | 311 +++++++++++++------------------- src/OCUtilities.cpp | 61 ++++++- 10 files changed, 493 insertions(+), 651 deletions(-) delete mode 100644 README create mode 100644 src/OCException.cpp diff --git a/README b/README deleted file mode 100644 index 22129e5..0000000 --- a/README +++ /dev/null @@ -1,113 +0,0 @@ -****************************************************************** - - Copyright 2014 Intel Mobile Communications GmbH 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. - --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -=============================================================================== -== UB Stack & TB Stack == -=============================================================================== - -The OIC-RESOURCE repository contains two SDKs with underlying code -(i.e. "stack"). The two SDKs are referred to as "UB SDK" (or "C++ SDK") and "TB -SDK" (or "C SDK"). The associated stacks are referred to as "UB Stack" (or "C++ -Stack") and "TB Stack" (or "C Stack"). The UB Stack requires that the TB Stack -is built under it. - -For a list of artifact locations for all possible build processes in the -OIC-RESOURCE repository, please refer to: -/artifact_output_locations.txt. - -=============================================================================== - -The UB Stack is intended ONLY for Linux Ubuntu 12.04 operating system. -To build UB Stack, please follow these requirements: -- GCC compiler version is 4.6.1 -- Pre-install the "gnu-libc" libraries package. -- The OIC-UTILITIES repository must be a sibling directory to the OIC-RESOURCE - repository. - -The TB Stack is intended ONLY for Linux Ubuntu 12.04, Arduino ATMega 2560 with -Arduino Framework 1.0.5, and Arduino Due with Arduino Framework 1.5.7. -Tip: Use Cutecom in Ubuntu 12.04 to view logs from Arduino ATMega 2560 and -Arduino Due. - -To build TB Stack, please follow these requirements for Linux Ubuntu 12.04: -- GCC compiler version is 4.6.1 -- Pre-install the "gnu-libc" libraries package. -- The OIC-UTILITIES repository must be a cousin directory to the OIC-RESOURCE - repository. -To build TB Stack, please follow these requirements for Arduino ATMega 2560: -- AVR-GCC compiler version is 4.5.3 -- Unzip the Time Library from here to your Arduino Directory Structure: - http://playground.arduino.cc/code/time -- The OIC-UTILITIES repository must be a cousin directory to the OIC-RESOURCE - repository. -- Apply 2 patches from OIC-UTILITIES/tb/ to your Arduino Directory Structure. - -At this time, build instructions have not been written for the Arduino ATMega -2560 with WiFi Shield, Arduino Due with Ethernet Shield, and Arduino Due with -WiFi Shield. These instructions will be included very soon (as the build -server(s) verifies and utilizes the new build script "buildScript.mk"). - -=============================================================================== - -Instructions for Common Build Processes: - -NOTE: 'GNU Make' is required to utilize the build script at location: -/buildScript.mk. - -- All Modules (TB Stack, TB Unit Tests, TB Examples, UB Stack, UB Examples) for -Linux & Arduino Mega 2560: - - make -f buildScript.mk all - -- All UB Stack Modules in Release & Debug (TB Stack, UB Stack, UB Examples) for -Linux: - - make -f buildScript.mk linux_ub - -- All Modules, without OCICUC, in Release & Debug (TB Stack, TB Unit Tests, -TB Examples, UB Stack, UB Examples) for linux: - - make -f buildScript.mk linux - -- All Modules, Including OCICUC, in Release & Debug (TB Stack, TB Unit Tests, -TB Examples, UB Stack, UB Examples, UB OCICUC) for linux: -(This will be what is used on the Build Server(s) to limit regression.) - - make -f buildScript.mk all_dev - -- All UB Stack Modules, Including OCICUC, in Release & Debug (TB Stack, -UB Stack, UB Examples, UB OCICUC) for linux: - - make -f buildScript.mk linux_ub_dev - -- All TB Stack Modules in Release & Debug (TB Stack, TB Unit Tests, -TB Examples) for Linux: - - make -f buildScript.mk linux_tb - -- All TB Stack Modules in Release & Debug (TB Stack, TB Unit Tests, -TB Examples) for Arduino ATMega 2560: - - make -f buildScript.mk arduinomega - -- Clean All: - - make -f buildScript.mk clean - diff --git a/examples/ocicuc/Makefile b/examples/ocicuc/Makefile index 88bce11..cc83bd0 100644 --- a/examples/ocicuc/Makefile +++ b/examples/ocicuc/Makefile @@ -24,6 +24,10 @@ PLATFORM:=linux OCLIB=../.. OCLIB_LIB=../../$(BUILD)/obj/liboc.a +BOOST_BASE=/usr/local/boost +BOOST_INC=$(BOOST_BASE)/include +BOOST_LIB=$(BOOST_BASE)/lib + CXX_FLAGS.debug := -g3 -O0 CXX_FLAGS.release := -O3 @@ -31,6 +35,7 @@ CXX_FLAGS:=-Werror -Wall -std=c++0x -ggdb $(CXX_FLAGS.$(BUILD)) -pthread # There's probably nicer Makefile magic for this, but hopefully it will suffice: CXX_INC=-I$(OCLIB)/include \ + -I$(BOOST_INC) \ -I../../include/ \ -I../../oc_logger/include/ \ -I../../csdk/stack/include \ @@ -39,7 +44,6 @@ CXX_INC=-I$(OCLIB)/include \ -I../../csdk/logger/include BOOST_LIBS=-lboost_program_options -#BOOST_LIBS=/usr/local/boost/lib/libboost_program_options.a # for boost_1_55 lib LIB_OC_LOGGER:=../../oc_logger/lib/oc_logger.a @@ -74,8 +78,7 @@ small_example: small_example.o driver.o utility.o clean: rm -f *.o $(APPS) - cd ../../ && $(MAKE) clean_cpp_sdk clean_apps: - rm -f *.o $(APPS) + rm -f server client monoprocess diff --git a/include/OCException.h b/include/OCException.h index 5aad87c..459f2d8 100644 --- a/include/OCException.h +++ b/include/OCException.h @@ -25,53 +25,24 @@ #include namespace OC { -typedef std::runtime_error reflection_exception; - class OCException : public std::runtime_error { public: - OCException(const std::string& msg, OCStackResult reason = OC_STACK_ERROR): std::runtime_error(msg), m_reason(reason) {} - std::string reason() + OCException(const std::string& msg, OCStackResult reason = OC_STACK_ERROR) + : std::runtime_error(msg), + m_reason(reason) + {} + + static std::string reason(const OCStackResult sr); + + std::string reason() const + { + return reason(m_reason); + } + + std::string reason(const OC::OCException& e) const { - switch(m_reason) - { - case OC_STACK_OK: - return "No Error"; - case OC_STACK_INVALID_URI: - return "Invalid URI"; - case OC_STACK_INVALID_IP: - return "Invalid IP"; - case OC_STACK_INVALID_PORT: - return "Invalid Port"; - case OC_STACK_INVALID_CALLBACK: - return "Invalid Callback"; - case OC_STACK_INVALID_METHOD: - return "Invalid Method"; - case OC_STACK_INVALID_QUERY: - return "Invalid Query"; - case OC_STACK_INVALID_PARAM: - return "Invalid Param"; - case OC_STACK_INVALID_OBSERVE_PARAM: - return "Invalid Observe Param"; - case OC_STACK_NO_MEMORY: - return "No Memory"; - case OC_STACK_COMM_ERROR: - return "Communication Error"; - case OC_STACK_NOTIMPL: - return "Not Implemented"; - case OC_STACK_NO_RESOURCE: - return "Resource Not Found"; - case OC_STACK_RESOURCE_ERROR: - return "Resource Error"; - case OC_STACK_SLOW_RESOURCE: - return "Slow Resource"; - case OC_STACK_NO_OBSERVERS: - return "No Observers"; - case OC_STACK_ERROR: - return "General Fault"; - default: - return "Unknown Error"; - } + return e.reason(); } private: diff --git a/include/OCResource.h b/include/OCResource.h index a399825..3cc765f 100644 --- a/include/OCResource.h +++ b/include/OCResource.h @@ -53,6 +53,7 @@ namespace OC { friend class OCPlatform; friend class InProcClientWrapper; + public: typedef std::shared_ptr Ptr; /** diff --git a/include/OCUtilities.h b/include/OCUtilities.h index 6d4f6b1..35a6383 100644 --- a/include/OCUtilities.h +++ b/include/OCUtilities.h @@ -20,13 +20,15 @@ #ifndef _INTEL_OCUTILITIES_H_ #define _INTEL_OCUTILITIES_H_ -#endif #include #include #include +#include #include +#include "OCException.h" + namespace OC { namespace Utilities { @@ -48,3 +50,52 @@ namespace OC { } } + +/* The C++11 standard unfortunately forgot to provide make_unique<>! However, if we're +using C++14 or later, we want to take the standard library's implementation: */ +#if defined(__cplusplus) && __cplusplus < 201300 +namespace OC { + + template + std::unique_ptr make_unique(XS&& ...xs) + { + return std::unique_ptr(new T(std::forward(xs)...)); + } + +} // namespace OC +#else + using std::make_unique; +#endif + +namespace OC { + + using OC::make_unique; + + /* Examine an OCStackResult, and either forward its value or raise an exception: */ + OCStackResult result_guard(const OCStackResult r); + + /* Check for a nullptr, and throw an exception if we see one; otherwise, return the + result of the function call: */ + template + auto nil_guard(PtrT&& p, FnT&& fn, ParamTs&& ...params) -> OCStackResult + { + if(nullptr == p) + { + throw OCException("nullptr at nil_guard()", OC_STACK_INVALID_PARAM); + } + + // Note that although parameters are being forwarded, std::bind() will make a single copy: + return std::bind(fn, p, std::forward(params)...)(); + } + + /* Check for nullptr and forward the result of an OC function call on success; raise + an exception on failure or exceptional result: */ + template + auto checked_guard(PtrT&& p, FnT&& fn, ParamTs&& ...params) -> OCStackResult + { + return result_guard(nil_guard(p, fn, std::forward(params)...)); + } + +} // namespace OC + +#endif diff --git a/makefile b/makefile index e3098d9..f93c3c8 100644 --- a/makefile +++ b/makefile @@ -70,8 +70,8 @@ cpp_sdk: prep_dirs c_sdk liboc.a examples: liboc.a cd examples && $(MAKE) apps "BUILD=$(BUILD)" -liboc.a: OCPlatform.o OCResource.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o - ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o +liboc.a: OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o + ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o OCPlatform.o: src/OCPlatform.cpp $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform.cpp $(CXX_INC) @@ -79,6 +79,9 @@ OCPlatform.o: src/OCPlatform.cpp OCResource.o: src/OCResource.cpp $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCResource.cpp $(CXX_INC) +OCException.o: src/OCException.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCException.cpp $(CXX_INC) + OCUtilities.o: src/OCUtilities.cpp $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCUtilities.cpp $(CXX_INC) diff --git a/src/OCException.cpp b/src/OCException.cpp new file mode 100644 index 0000000..39010f8 --- /dev/null +++ b/src/OCException.cpp @@ -0,0 +1,80 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH 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 "OCException.h" + +std::string OC::OCException::reason(const OCStackResult sr) +{ + switch(sr) + { + case OC_STACK_OK: + return "No Error"; + case OC_STACK_INVALID_URI: + return "Invalid URI"; + case OC_STACK_INVALID_IP: + return "Invalid IP"; + case OC_STACK_INVALID_PORT: + return "Invalid Port"; + case OC_STACK_INVALID_CALLBACK: + return "Invalid Callback"; + case OC_STACK_INVALID_METHOD: + return "Invalid Method"; + case OC_STACK_INVALID_QUERY: + return "Invalid Query"; + case OC_STACK_INVALID_PARAM: + return "Invalid Parameter"; + case OC_STACK_INVALID_OBSERVE_PARAM: + return "Invalid Observe Parameter"; + case OC_STACK_NO_MEMORY: + return "No Memory"; + case OC_STACK_COMM_ERROR: + return "Communication Error"; + case OC_STACK_NOTIMPL: + return "Not Implemented"; + case OC_STACK_NO_RESOURCE: + return "Resource Not Found"; + case OC_STACK_RESOURCE_ERROR: + return "Resource Error"; + case OC_STACK_SLOW_RESOURCE: + return "Slow Resource"; + case OC_STACK_NO_OBSERVERS: + return "No Observers"; + case OC_STACK_OBSERVER_NOT_FOUND: + return "Stack observer not found"; + case OC_STACK_OBSERVER_NOT_ADDED: + return "Stack observer not added"; + case OC_STACK_OBSERVER_NOT_REMOVED: + return "Stack observer not removed"; +#ifdef WITH_PRESENCE + case OC_STACK_PRESENCE_STOPPED: + return "Stack presence stopped"; + case OC_STACK_PRESENCE_DO_NOT_HANDLE: + return "Stack presence should not be handled"; +#endif + case OC_STACK_INVALID_OPTION: + return "Invalid option"; + + case OC_STACK_ERROR: + return "General Fault"; + } + + return "Unknown Error"; +} + diff --git a/src/OCPlatform.cpp b/src/OCPlatform.cpp index dd8d877..16e4dce 100644 --- a/src/OCPlatform.cpp +++ b/src/OCPlatform.cpp @@ -29,344 +29,202 @@ //********************************************************************* #include +#include +#include + +#include "ocstack.h" #include "OCPlatform.h" #include "OCApi.h" #include "OCException.h" +#include "OCUtilities.h" #include "oc_logger.hpp" namespace OC { - OCPlatform::OCPlatform(const PlatformConfig& config) - : m_log_stream(std::move(oc_log_stream {oc_make_ostream_logger})), - m_cfg(config) - { - init(m_cfg); - } +void OCPlatform::init(const PlatformConfig& config) +{ + switch(config.mode) + { + case ModeType::Server: + m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config); + break; + + case ModeType::Client: + m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config); + break; + + case ModeType::Both: + m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config); + m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config); + break; + } +} + +OCPlatform::OCPlatform(const PlatformConfig& config) + : m_log_stream { std::move(oc_log_stream {oc_make_ostream_logger}) }, + m_cfg { config }, + m_WrapperInstance { make_unique() }, + m_csdkLock { make_shared() } +{ + init(m_cfg); +} + +OCPlatform::OCPlatform(const PlatformConfig& config, OC::oc_log_stream& log_target) + : m_log_stream { log_target }, + m_cfg { config }, + m_WrapperInstance { make_unique() }, + m_csdkLock { make_shared() } +{ + init(m_cfg); +} - OCPlatform::OCPlatform(const PlatformConfig& config, OC::oc_log_stream& log_target) - : m_log_stream(log_target), - m_cfg(config) - { - init(m_cfg); - } +OCPlatform::~OCPlatform(void) +{ +} - OCPlatform::~OCPlatform(void) - { - } +OCStackResult OCPlatform::setDefaultDeviceEntityHandler(EntityHandler entityHandler) +{ + return checked_guard(m_server, &IServerWrapper::setDefaultDeviceEntityHandler, + entityHandler); +} - OCStackResult OCPlatform::notifyAllObservers(OCResourceHandle resourceHandle) - { - return OCNotifyAllObservers(resourceHandle); - } +OCStackResult OCPlatform::notifyAllObservers(OCResourceHandle resourceHandle) +{ + return result_guard(OCNotifyAllObservers(resourceHandle)); +} - OCStackResult OCPlatform::notifyListOfObservers( - OCResourceHandle resourceHandle, - ObservationIds& observationIds, - const std::shared_ptr pResponse) +OCStackResult OCPlatform::notifyListOfObservers(OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr pResponse) +{ + if(!pResponse) { - OCStackResult result = OC_STACK_ERROR; - - if(pResponse) - { - try - { - std::string payload = pResponse->getPayload(); - unsigned char *pBuffer = new unsigned char[payload.length()+1]; - strncpy((char*)pBuffer, payload.c_str(), payload.length() + 1); - - // TODO Logging - printf("\tGoing from stack for List of Observers: Payload: %s\n", (char*)pBuffer); - - result = OCNotifyListOfObservers(resourceHandle, &observationIds[0], - observationIds.size(), pBuffer); - - delete(pBuffer); - } - catch(std::exception e) // TODO : define our own exception - { - throw e; - } - } - return result; + return result_guard(OC_STACK_ERROR); } - void OCPlatform::init(const PlatformConfig& config) - { - m_csdkLock = make_shared(); - std::unique_ptr wrapperInstance(new WrapperFactory()); - m_WrapperInstance = std::move(wrapperInstance); - - if(config.mode == ModeType::Server) - { - // Call server wrapper init - m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config); - } - else if(config.mode == ModeType::Client) - { - // Call client wrapper init - m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config); - } - else - { - // This must be both server and client - m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config); - m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config); - } - } + std::string payload(pResponse->getPayload()); - OCResource::Ptr OCPlatform::constructResourceObject(const std::string& host, const std::string& uri, - bool isObservable, const std::vector& resourceTypes, - const std::vector& interfaces) - { - if(m_client) - { - return std::shared_ptr(new OCResource(m_client, host, uri, isObservable, resourceTypes, interfaces)); - } - - else - { - return std::shared_ptr(); - } - } + return result_guard( + OCNotifyListOfObservers(resourceHandle, + &observationIds[0], observationIds.size(), + reinterpret_cast(const_cast(payload.c_str())))); +} - OCStackResult OCPlatform::findResource(const std::string& host, const std::string& resourceName, - FindCallback resourceHandler) +OCResource::Ptr OCPlatform::constructResourceObject(const std::string& host, const std::string& uri, + bool isObservable, const std::vector& resourceTypes, + const std::vector& interfaces) +{ + if(!m_client) { - if(m_client) - { - return m_client->ListenForResource(host, resourceName, resourceHandler); - } - return OC_STACK_ERROR; + return std::shared_ptr(); } + return std::shared_ptr(new OCResource(m_client, host, uri, isObservable, resourceTypes, interfaces)); +} - OCStackResult OCPlatform::registerResource(OCResourceHandle& resourceHandle, - std::string& resourceURI, - const std::string& resourceTypeName, - const std::string& resourceInterface, - EntityHandler entityHandler, - uint8_t resourceProperty) - { - OCStackResult result = OC_STACK_ERROR; - - if(m_server) - { - try{ - result = m_server->registerResource(resourceHandle, resourceURI, resourceTypeName, resourceInterface, entityHandler, resourceProperty); - } - catch(std::exception e) // TODO: define our own expception. - { - throw e; - } - } - - return result; - } - - OCStackResult OCPlatform::setDefaultDeviceEntityHandler(EntityHandler entityHandler) - { - OCStackResult result = OC_STACK_ERROR; - - if(m_server) - { - try{ - result = m_server->setDefaultDeviceEntityHandler(entityHandler); - } - catch(std::exception e) // TODO: define our own expception. - { - throw e; - } - } - return result; - } +OCStackResult OCPlatform::findResource(const std::string& host, const std::string& resourceName, + FindCallback resourceHandler) +{ + return checked_guard(m_client, &IClientWrapper::ListenForResource, + host, resourceName, resourceHandler); +} - OCStackResult OCPlatform::unregisterResource(const OCResourceHandle& resourceHandle) const - { - OCStackResult result = OC_STACK_ERROR; - if(m_server) - { - result = m_server->unregisterResource(resourceHandle); - } - return result; - } +OCStackResult OCPlatform::registerResource(OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler entityHandler, + uint8_t resourceProperty) +{ + return checked_guard(m_server, &IServerWrapper::registerResource, + ref(resourceHandle), resourceURI, resourceTypeName, resourceInterface, entityHandler, resourceProperty); +} +OCStackResult OCPlatform::unregisterResource(const OCResourceHandle& resourceHandle) const +{ + return checked_guard(m_server, &IServerWrapper::unregisterResource, + resourceHandle); +} +OCStackResult OCPlatform::unbindResource(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) +{ + return result_guard(OCUnBindResource(ref(collectionHandle), ref(resourceHandle))); +} - OCStackResult OCPlatform::unbindResource(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) +OCStackResult OCPlatform::unbindResources(const OCResourceHandle collectionHandle, const std::vector& resourceHandles) +{ + for(const auto& h : resourceHandles) { - OCStackResult result = OC_STACK_ERROR; - - try { - result = OCUnBindResource(collectionHandle, resourceHandle); - } - catch(std::exception e) // TODO: define our own expception. - { - throw e; - } - - return result; - } + OCStackResult r; - OCStackResult OCPlatform::unbindResources(const OCResourceHandle collectionHandle, const std::vector& resourceHandles) - { - OCStackResult result = OC_STACK_ERROR; - - try { - - for(const OCResourceHandle& handle : resourceHandles) - { - result = OCUnBindResource(collectionHandle, handle); - - if(result != OC_STACK_OK) - { - // TODO Should we unbind the previous successful ones? - // TODO should we return which are succesful - // Currently just returns with any failure - return result; - } - } - } - catch(std::exception e) // TODO : define our own exception - { - throw e; - } - - return result; + if(OC_STACK_OK != (r = result_guard(OCUnBindResource(collectionHandle, h)))) + { + return r; + } } - OCStackResult OCPlatform::bindResource(const OCResourceHandle collectionHandle, const OCResourceHandle resourceHandle) - { - OCStackResult result = OC_STACK_ERROR; - - try { - result = OCBindResource(collectionHandle, resourceHandle); - } - catch(std::exception e) // TODO : define our own exception - { - throw e; - } + return OC_STACK_OK; +} - return result; - } +OCStackResult OCPlatform::bindResource(const OCResourceHandle collectionHandle, const OCResourceHandle resourceHandle) +{ + return result_guard(OCBindResource(collectionHandle, resourceHandle)); +} - OCStackResult OCPlatform::bindResources(const OCResourceHandle collectionHandle, const std::vector& resourceHandles) +OCStackResult OCPlatform::bindResources(const OCResourceHandle collectionHandle, const std::vector& resourceHandles) +{ + for(const auto& h : resourceHandles) { - OCStackResult result = OC_STACK_ERROR; - - try { - - for(const OCResourceHandle& handle : resourceHandles) - { - result = OCBindResource(collectionHandle, handle); - - if(result != OC_STACK_OK) - { - // TODO Should we unbind the previous successful ones? - // TODO should we return which are succesful - // Currently just returns with any failure - return result; - } - } - } - catch(std::exception e) // TODO : define our own exception - { - throw e; - } - - return result; - } + OCStackResult r; - OCStackResult OCPlatform::bindTypeToResource(const OCResourceHandle& resourceHandle, - const std::string& resourceTypeName) const - { - OCStackResult result = OC_STACK_ERROR; - if(m_server) - { - try - { - result = m_server->bindTypeToResource(resourceHandle, resourceTypeName); - } - catch (OCException& e) - { - log() << "Caught an exception..." << endl; - log() << "\tMessage: " << e.what() << endl; - log() << "\t Reason: " << e.reason() << endl; - } - } - return result; + if(OC_STACK_OK != (r = result_guard(OCBindResource(collectionHandle, h)))) + { + return r; + } } - OCStackResult OCPlatform::bindInterfaceToResource(const OCResourceHandle& resourceHandle, - const std::string& resourceInterfaceName) const - { - OCStackResult result = OC_STACK_ERROR; - if(m_server) - { - try - { - result = m_server->bindInterfaceToResource(resourceHandle, resourceInterfaceName); - } - catch (OCException& e) - { - log() << "Caught an exception..." << endl; - log() << "\tMessage: " << e.what() << endl; - log() << "\t Reason: " << e.reason() << endl; - } - } - return result; + return OC_STACK_OK; +} - } +OCStackResult OCPlatform::bindTypeToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) const +{ + return checked_guard(m_server, &IServerWrapper::bindTypeToResource, + resourceHandle, resourceTypeName); +} - OCStackResult OCPlatform::startPresence(const unsigned int announceDurationSeconds) - { - if(m_server) - { - return m_server->startPresence(announceDurationSeconds); - } - else - { - return OC_STACK_ERROR; - } - } +OCStackResult OCPlatform::bindInterfaceToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) const +{ + return checked_guard(m_server, &IServerWrapper::bindInterfaceToResource, + resourceHandle, resourceInterfaceName); +} - OCStackResult OCPlatform::stopPresence() - { - if(m_server) - { - return m_server->stopPresence(); - } - else - { - return OC_STACK_ERROR; - } - } +OCStackResult OCPlatform::startPresence(const unsigned int announceDurationSeconds) +{ + return checked_guard(m_server, &IServerWrapper::startPresence, + announceDurationSeconds); +} - OCStackResult OCPlatform::subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, - SubscribeCallback presenceHandler) - { - if(m_client) - { - return m_client->SubscribePresence(&presenceHandle, host, presenceHandler); - } - else - { - return OC_STACK_ERROR; - } - } +OCStackResult OCPlatform::stopPresence() +{ + return checked_guard(m_server, &IServerWrapper::stopPresence); +} - OCStackResult OCPlatform::unsubscribePresence(OCPresenceHandle presenceHandle) - { - if(m_client) - { - return m_client->UnsubscribePresence(presenceHandle); - } - else - { - return OC_STACK_ERROR; - } - } +OCStackResult OCPlatform::subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, + SubscribeCallback presenceHandler) +{ + return checked_guard(m_client, &IClientWrapper::SubscribePresence, + &presenceHandle, host, presenceHandler); +} + +OCStackResult OCPlatform::unsubscribePresence(OCPresenceHandle presenceHandle) +{ + return checked_guard(m_client, &IClientWrapper::UnsubscribePresence, + ref(presenceHandle)); +} } //namespace OC diff --git a/src/OCResource.cpp b/src/OCResource.cpp index a1f6353..e9b2730 100644 --- a/src/OCResource.cpp +++ b/src/OCResource.cpp @@ -19,218 +19,155 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "OCResource.h" +#include "OCUtilities.h" namespace OC { - OCResource::OCResource(std::weak_ptr clientWrapper, const std::string& host, - const std::string& uri, bool observable, const std::vector& resourceTypes, - const std::vector& interfaces) : - m_clientWrapper(clientWrapper), m_uri(uri), m_host(host), m_isObservable(observable), - m_isCollection(false), m_resourceTypes(resourceTypes), m_interfaces(interfaces), - m_observeHandle(nullptr) + +using OC::nil_guard; +using OC::result_guard; +using OC::checked_guard; + +OCResource::OCResource(std::weak_ptr clientWrapper, const std::string& host, + const std::string& uri, bool observable, const std::vector& resourceTypes, + const std::vector& interfaces) + : m_clientWrapper(clientWrapper), m_uri(uri), m_host(host), m_isObservable(observable), + m_isCollection(false), m_resourceTypes(resourceTypes), m_interfaces(interfaces), + m_observeHandle(nullptr) +{ + m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE) + != m_interfaces.end(); + + if (m_uri.empty() || + resourceTypes.empty() || + interfaces.empty()|| + m_clientWrapper.expired()) { - m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE) - != m_interfaces.end(); - - if (m_uri.empty() || resourceTypes.empty() - || interfaces.empty()|| m_clientWrapper.expired()) - { - throw ResourceInitException(m_uri.empty(), resourceTypes.empty(), - interfaces.empty(), m_clientWrapper.expired()); - } + throw ResourceInitException(m_uri.empty(), resourceTypes.empty(), + interfaces.empty(), m_clientWrapper.expired()); } - - OCResource::~OCResource() +} + +OCResource::~OCResource() +{ +} + +OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap, + GetCallback attributeHandler) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetResourceRepresentation, + m_host, m_uri, queryParametersMap, attributeHandler); +} + +OCStackResult OCResource::get(const std::string& resourceType, + const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, + GetCallback attributeHandler) +{ + QueryParamsMap mapCpy(queryParametersMap); + + if(!resourceType.empty()) { + mapCpy["rt"]=resourceType; } - OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap, - GetCallback attributeHandler) + if(!resourceInterface.empty()) { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - return cw->GetResourceRepresentation(m_host, m_uri, queryParametersMap, attributeHandler); - } - else - { - return OC_STACK_ERROR; - } + mapCpy["if"]= resourceInterface; } - OCStackResult OCResource::get(const std::string& resourceType, - const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, - GetCallback attributeHandler) + return result_guard(get(mapCpy, attributeHandler)); +} + +OCStackResult OCResource::put(const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, PutCallback attributeHandler) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutResourceRepresentation, + m_host, m_uri, rep, queryParametersMap, attributeHandler); +} + +OCStackResult OCResource::put(const std::string& resourceType, + const std::string& resourceInterface, const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, + PutCallback attributeHandler) +{ + QueryParamsMap mapCpy(queryParametersMap); + + if(!resourceType.empty()) + { + mapCpy["rt"]=resourceType; + } + + if(!resourceInterface.empty()) + { + mapCpy["if"]=resourceInterface; + } + + return result_guard(put(rep, mapCpy, attributeHandler)); +} + +OCStackResult OCResource::post(const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, PostCallback attributeHandler) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation, + m_host, m_uri, rep, queryParametersMap, attributeHandler); +} + +OCStackResult OCResource::post(const std::string& resourceType, + const std::string& resourceInterface, const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, + PostCallback attributeHandler) +{ + QueryParamsMap mapCpy(queryParametersMap); + + if(!resourceType.empty()) { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - QueryParamsMap mapCpy(queryParametersMap); - - if(!resourceType.empty()) - { - mapCpy["rt"]=resourceType; - } - if(!resourceInterface.empty()) - { - mapCpy["if"]= resourceInterface; - } - - return get(mapCpy, attributeHandler); - } - else - { - return OC_STACK_ERROR; - } + mapCpy["rt"]=resourceType; } - OCStackResult OCResource::put(const OCRepresentation& rep, - const QueryParamsMap& queryParametersMap, PutCallback attributeHandler) + if(!resourceInterface.empty()) { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - return cw->PutResourceRepresentation(m_host, m_uri, rep, queryParametersMap, - attributeHandler); - } - else - { - return OC_STACK_ERROR; - } + mapCpy["if"]=resourceInterface; } + return result_guard(post(rep, mapCpy, attributeHandler)); +} - OCStackResult OCResource::put(const std::string& resourceType, - const std::string& resourceInterface, const OCRepresentation& rep, - const QueryParamsMap& queryParametersMap, - PutCallback attributeHandler) +OCStackResult OCResource::observe(ObserveType observeType, + const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler) +{ + if(m_observeHandle != nullptr) { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - QueryParamsMap mapCpy(queryParametersMap); - - if(!resourceType.empty()) - { - mapCpy["rt"]=resourceType; - } - if(!resourceInterface.empty()) - { - mapCpy["if"]=resourceInterface; - } - - return put(rep, mapCpy, attributeHandler); - } - else - { - return OC_STACK_ERROR; - } + return result_guard(OC_STACK_INVALID_PARAM); } - OCStackResult OCResource::post(const OCRepresentation& rep, - const QueryParamsMap& queryParametersMap, PostCallback attributeHandler) - { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - return cw->PostResourceRepresentation(m_host, m_uri, rep, queryParametersMap, - attributeHandler); - } - else - { - return OC_STACK_ERROR; - } - } + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource, + observeType, &m_observeHandle, m_host, + m_uri, queryParametersMap, observeHandler); +} - OCStackResult OCResource::post(const std::string& resourceType, - const std::string& resourceInterface, const OCRepresentation& rep, - const QueryParamsMap& queryParametersMap, - PostCallback attributeHandler) +OCStackResult OCResource::cancelObserve() +{ + if(m_observeHandle == nullptr) { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - QueryParamsMap mapCpy(queryParametersMap); - - if(!resourceType.empty()) - { - mapCpy["rt"]=resourceType; - } - if(!resourceInterface.empty()) - { - mapCpy["if"]=resourceInterface; - } - - return post(rep, mapCpy, attributeHandler); - } - else - { - return OC_STACK_ERROR; - } + return result_guard(OC_STACK_INVALID_PARAM); } + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::CancelObserveResource, + m_observeHandle, m_host, m_uri); +} - OCStackResult OCResource::observe(ObserveType observeType, - const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler) - { - if(m_observeHandle != nullptr) - { - return OC_STACK_INVALID_PARAM; - } - else - { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - return cw->ObserveResource(observeType, &m_observeHandle, m_host, - m_uri, queryParametersMap, observeHandler); - } - else - { - return OC_STACK_ERROR; - } - } - } +std::string OCResource::host() const +{ + return m_host; +} - OCStackResult OCResource::cancelObserve() - { - if(m_observeHandle == nullptr) - { - return OC_STACK_INVALID_PARAM; - } - else - { - auto cw = m_clientWrapper.lock(); - - if(cw) - { - OCStackResult ret = cw->CancelObserveResource(m_observeHandle, m_host, m_uri); - m_observeHandle = nullptr; - return ret; - } - else - { - return OC_STACK_ERROR; - } - } - } +std::string OCResource::uri() const +{ + return m_uri; +} + +bool OCResource::isObservable() const +{ + return m_isObservable; +} - std::string OCResource::host() const - { - return m_host; - } - std::string OCResource::uri() const - { - return m_uri; - } - bool OCResource::isObservable() const - { - return m_isObservable; - } } // namespace OC diff --git a/src/OCUtilities.cpp b/src/OCUtilities.cpp index 0e98ae5..1162522 100644 --- a/src/OCUtilities.cpp +++ b/src/OCUtilities.cpp @@ -18,19 +18,22 @@ // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include + #include "OCUtilities.h" -#include -#include + #include + #include +#include +#include + extern "C" { #include // libcoap #include // libcoap } -#include - -namespace OC{ +namespace OC { // Helper function to escape special character. std::string escapeString(const std::string& value) @@ -164,3 +167,51 @@ OC::Utilities::QueryParamsKeyVal OC::Utilities::getQueryParams(const std::string } return qp; } + +namespace OC { + +OCStackResult result_guard(const OCStackResult r) +{ + std::ostringstream os; + + switch(r) + { + default: + os << "result_guard(): unhandled exception: " << OCException::reason(r); + throw OCException(os.str(), r); + + /* Exceptional conditions: */ + case OC_STACK_NO_MEMORY: + case OC_STACK_COMM_ERROR: + case OC_STACK_NOTIMPL: + case OC_STACK_INVALID_URI: + case OC_STACK_INVALID_QUERY: + case OC_STACK_INVALID_IP: + case OC_STACK_INVALID_PORT: + case OC_STACK_INVALID_CALLBACK: + case OC_STACK_INVALID_METHOD: + case OC_STACK_INVALID_PARAM: + case OC_STACK_INVALID_OBSERVE_PARAM: + throw OCException(os.str(), r); + + /* Non-exceptional failures or success: */ + case OC_STACK_OK: + case OC_STACK_NO_RESOURCE: + case OC_STACK_RESOURCE_ERROR: + case OC_STACK_SLOW_RESOURCE: + case OC_STACK_NO_OBSERVERS: + case OC_STACK_OBSERVER_NOT_FOUND: + case OC_STACK_OBSERVER_NOT_ADDED: + case OC_STACK_OBSERVER_NOT_REMOVED: +#ifdef WITH_PRESENCE + case OC_STACK_PRESENCE_STOPPED: + case OC_STACK_PRESENCE_DO_NOT_HANDLE: +#endif + + break; + } + + return r; +} + +} // namespace OC -- 2.7.4