X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=service%2Fresource-encapsulation%2Fsrc%2FserverBuilder%2Fsrc%2FRCSResourceObject.cpp;h=cecfb1d577faf49d65d74cde842ed6588cd997dd;hb=bdec944c51c8e0063b6ee0890170e828ac8f2b96;hp=e0f2abb94d2dfc4ad0031fc0f02496b826f6419f;hpb=6848338aebbe9c639e4e2bb01065e5ccff34092b;p=platform%2Fupstream%2Fiotivity.git diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp index e0f2abb..cecfb1d 100644 --- a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp +++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp @@ -18,21 +18,25 @@ // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#include +#include "RCSResourceObject.h" -#include #include -#include - -#include -#include -#include -#include -#include - -#include -#include +#include "RequestHandler.h" +#include "AssertUtils.h" +#include "AtomicHelper.h" +#include "ResourceAttributesConverter.h" +#include "ResourceAttributesUtils.h" +#include "RCSRequest.h" +#include "RCSRepresentation.h" +#include "InterfaceHandler.h" + +#include "logger.h" +#include "OCPlatform.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif #define LOG_TAG "RCSResourceObject" namespace @@ -54,11 +58,9 @@ namespace return base & ~target; } - template - OCEntityHandlerResult sendResponse(RCSResourceObject& resource, - std::shared_ptr< OC::OCResourceRequest > ocRequest, RESPONSE&& response) + OCEntityHandlerResult sendResponse(const std::shared_ptr< OC::OCResourceRequest >& ocRequest, + const std::shared_ptr< OC::OCResourceResponse >& ocResponse) { - auto ocResponse = response.getHandler()->buildResponse(resource); ocResponse->setRequestHandle(ocRequest->getRequestHandle()); ocResponse->setResourceHandle(ocRequest->getResourceHandle()); @@ -71,14 +73,14 @@ namespace } catch (const OC::OCException& e) { - OC_LOG_V(WARNING, LOG_TAG, "Error (%s)", e.what()); + OIC_LOG_V(WARNING, LOG_TAG, "Error (%s)", e.what()); } return OC_EH_ERROR; } RCSResourceAttributes getAttributesFromOCRequest( - std::shared_ptr< OC::OCResourceRequest > request) + const std::shared_ptr< OC::OCResourceRequest >& request) { return ResourceAttributesConverter::fromOCRepresentation( request->getResourceRepresentation()); @@ -86,12 +88,12 @@ namespace template< typename HANDLER, typename RESPONSE = typename std::decay::type::result_type > - RESPONSE invokeHandler(RCSResourceAttributes& attrs, - std::shared_ptr< OC::OCResourceRequest > ocRequest, HANDLER&& handler) + RESPONSE invokeHandler(RCSResourceAttributes& attrs, const RCSRequest& request, + std::shared_ptr< HANDLER > handler) { - if (handler) + if (handler && *handler) { - return handler(RCSRequest{ ocRequest->getResourceUri() }, attrs); + return (*handler)(request, attrs); } return RESPONSE::defaultAction(); @@ -100,8 +102,9 @@ namespace typedef void (RCSResourceObject::* AutoNotifyFunc) (bool, RCSResourceObject::AutoNotifyPolicy) const; - std::function createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc, - const RCSResourceObject& resourceObject, const RCSResourceAttributes& resourceAttributes, + std::function createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc, + const RCSResourceObject& resourceObject, + const RCSResourceAttributes& resourceAttributes, RCSResourceObject::AutoNotifyPolicy autoNotifyPolicy) { if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::UPDATED) @@ -120,22 +123,66 @@ namespace } return {}; } -} // unnamed namespace + void insertValue(std::vector& container, std::string value) + { + if (value.empty()) return; + + if (std::find(container.begin(), container.end(), value) == container.end()) + { + container.push_back(std::move(value)); + } + } + +} // unnamed namespace namespace OIC { namespace Service { - RCSResourceObject::Builder::Builder(const std::string& uri, const std::string& type, - const std::string& interface) : - m_uri{ uri }, - m_type{ type }, - m_interface{ interface }, + RCSResourceObject::Builder::Builder(std::string uri, std::string type, + std::string interface) : + m_uri{ std::move(uri) }, + m_types{ std::move(type) }, + m_interfaces{ }, + m_defaultInterface{ interface }, m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE }, m_resourceAttributes{ } { + addInterface(interface); + addInterface(BASELINE_INTERFACE); + + if (m_defaultInterface.empty()) + { + m_defaultInterface = BASELINE_INTERFACE; + } + } + + RCSResourceObject::Builder& RCSResourceObject::Builder::addInterface(std::string interface) + { + insertValue(m_interfaces, std::move(interface)); + return *this; + } + + RCSResourceObject::Builder& RCSResourceObject::Builder::addType(std::string type) + { + insertValue(m_types, std::move(type)); + return *this; + } + + RCSResourceObject::Builder& RCSResourceObject::Builder::setDefaultInterface( + std::string interface) + { + if (std::find(m_interfaces.begin(), m_interfaces.end(), interface) == + m_interfaces.end()) + { + throw RCSBadRequestException{"The interface should be added, first."}; + } + + m_defaultInterface = std::move(interface); + + return *this; } RCSResourceObject::Builder& RCSResourceObject::Builder::setDiscoverable( @@ -152,6 +199,12 @@ namespace OIC return *this; } + RCSResourceObject::Builder& RCSResourceObject::Builder::setSecureFlag( + bool secureFlag) + { + m_properties = ::makePropertyFlags(m_properties, OC_SECURE, secureFlag); + return *this; + } RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes( const RCSResourceAttributes& attrs) { @@ -171,50 +224,82 @@ namespace OIC OCResourceHandle handle{ nullptr }; RCSResourceObject::Ptr server { - new RCSResourceObject{ m_properties, std::move(m_resourceAttributes) } }; + new RCSResourceObject{ m_uri, m_properties, std::move(m_resourceAttributes) } }; OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler, - server.get(), std::placeholders::_1) }; + std::weak_ptr< RCSResourceObject >{ server }, std::placeholders::_1) }; typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&, const std::string&, const std::string&, OC::EntityHandler, uint8_t); invokeOCFunc(static_cast(OC::OCPlatform::registerResource), - handle, m_uri, m_type, m_interface, entityHandler, m_properties); + handle, m_uri, m_types[0], m_interfaces[0], entityHandler, m_properties); + + std::for_each(m_interfaces.begin() + 1, m_interfaces.end(), + [&handle](const std::string& interfaceName){ + invokeOCFunc(OC::OCPlatform::bindInterfaceToResource, handle, interfaceName); + }); - server->m_resourceHandle = handle; + std::for_each(m_types.begin() + 1, m_types.end(), + [&handle](const std::string& typeName){ + invokeOCFunc(OC::OCPlatform::bindTypeToResource, handle, typeName); + }); + + server->init(handle, m_interfaces, m_types, m_defaultInterface); return server; } - RCSResourceObject::RCSResourceObject(uint8_t properties, RCSResourceAttributes&& attrs) : - m_properties { properties }, + RCSResourceObject::RCSResourceObject(const std::string& uri, + uint8_t properties, RCSResourceAttributes&& attrs) : + m_properties{ properties }, + m_uri{ uri }, + m_interfaces{ }, + m_types{ }, + m_defaultInterface{ }, m_resourceHandle{ }, m_resourceAttributes{ std::move(attrs) }, m_getRequestHandler{ }, m_setRequestHandler{ }, - m_autoNotifyPolicy { AutoNotifyPolicy::UPDATED }, - m_setRequestHandlerPolicy { SetRequestHandlerPolicy::NEVER }, - m_keyAttributesUpdatedListeners{ }, + m_autoNotifyPolicy{ AutoNotifyPolicy::UPDATED }, + m_setRequestHandlerPolicy{ SetRequestHandlerPolicy::NEVER }, + m_attributeUpdatedListeners{ }, m_lockOwner{ }, m_mutex{ }, - m_mutexKeyAttributeUpdate{ } + m_mutexAttributeUpdatedListeners{ } { m_lockOwner.reset(new AtomicThreadId); } + void RCSResourceObject::init(OCResourceHandle handle, + const std::vector< std::string >& interfaces, + const std::vector< std::string >& types, + const std::string& defaultInterface) + { + m_resourceHandle = handle; + m_interfaces = interfaces; + m_types = types; + m_defaultInterface = defaultInterface; + + for (const auto& itf : interfaces) + { + m_interfaceHandlers.insert({ itf, getDefaultInterfaceHandler(itf, + m_defaultInterface) }); + } + } + RCSResourceObject::~RCSResourceObject() { if (m_resourceHandle) { try { - OC::OCPlatform::unregisterResource(m_resourceHandle); + invokeOCFunc(OC::OCPlatform::unregisterResource, m_resourceHandle); } catch (...) { - OC_LOG(WARNING, LOG_TAG, "Failed to unregister resource."); + OIC_LOG(WARNING, LOG_TAG, "Failed to unregister resource."); } } } @@ -337,12 +422,12 @@ namespace OIC void RCSResourceObject::setGetRequestHandler(GetRequestHandler h) { - m_getRequestHandler = std::move(h); + m_getRequestHandler = std::make_shared< GetRequestHandler >(std::move(h)); } void RCSResourceObject::setSetRequestHandler(SetRequestHandler h) { - m_setRequestHandler = std::move(h); + m_setRequestHandler = std::make_shared< SetRequestHandler >(std::move(h)); } void RCSResourceObject::notify() const @@ -357,22 +442,26 @@ namespace OIC void RCSResourceObject::addAttributeUpdatedListener(const std::string& key, AttributeUpdatedListener h) { - std::lock_guard lock(m_mutexKeyAttributeUpdate); - m_keyAttributesUpdatedListeners[key] = std::move(h); + std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners); + + m_attributeUpdatedListeners[key] = + std::make_shared< AttributeUpdatedListener >(std::move(h)); } void RCSResourceObject::addAttributeUpdatedListener(std::string&& key, AttributeUpdatedListener h) { - std::lock_guard lock(m_mutexKeyAttributeUpdate); - m_keyAttributesUpdatedListeners[std::move(key)] = std::move(h); + std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners); + + m_attributeUpdatedListeners[std::move(key)] = + std::make_shared< AttributeUpdatedListener >(std::move(h)); } bool RCSResourceObject::removeAttributeUpdatedListener(const std::string& key) { - std::lock_guard lock(m_mutexKeyAttributeUpdate); + std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners); - return m_keyAttributesUpdatedListeners.erase(key) != 0; + return m_attributeUpdatedListeners.erase(key) != 0; } bool RCSResourceObject::testValueUpdated(const std::string& key, @@ -402,6 +491,78 @@ namespace OIC return m_setRequestHandlerPolicy; } + void RCSResourceObject::bindResource(const RCSResourceObject::Ptr& resource) + { + if (!resource || resource.get() == this) + { + throw RCSInvalidParameterException("The resource is invalid!"); + } + + invokeOCFunc(OC::OCPlatform::bindResource, + m_resourceHandle, resource->m_resourceHandle); + + std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources }; + m_boundResources.push_back(resource); + } + + void RCSResourceObject::unbindResource(const RCSResourceObject::Ptr& resource) + { + if (!resource || resource.get() == this) + { + throw RCSInvalidParameterException("The resource is invalid!"); + } + + invokeOCFunc(OC::OCPlatform::unbindResource, + m_resourceHandle, resource->m_resourceHandle); + + std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources }; + m_boundResources.erase(std::find(m_boundResources.begin(), m_boundResources.end(), + resource)); + } + + std::vector< RCSResourceObject::Ptr > RCSResourceObject::getBoundResources() const + { + std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources }; + return m_boundResources; + } + + std::string RCSResourceObject::getUri() const + { + return m_uri; + } + + std::string RCSResourceObject::getDefaultInterface() const + { + return m_defaultInterface; + } + + std::vector< std::string > RCSResourceObject::getInterfaces() const + { + return m_interfaces; + } + + std::vector< std::string > RCSResourceObject::getTypes() const + { + return m_types; + } + + RCSRepresentation RCSResourceObject::getRepresentation(const RCSRequest& request) const + { + if (request.getOCRequest()->getRequestType() == "GET") + { + return findInterfaceHandler( + request.getInterface()).getGetResponseBuilder()(request, *this); + } + + if (request.getOCRequest()->getRequestType() == "POST") + { + return findInterfaceHandler( + request.getInterface()).getSetResponseBuilder()(request, *this); + } + + throw RCSBadRequestException{ "Unsupported request type!" }; + } + void RCSResourceObject::autoNotify(bool isAttributesChanged) const { autoNotify(isAttributesChanged, m_autoNotifyPolicy); @@ -418,9 +579,14 @@ namespace OIC } OCEntityHandlerResult RCSResourceObject::entityHandler( - std::shared_ptr< OC::OCResourceRequest > request) + const std::weak_ptr< RCSResourceObject >& weakRes, + const std::shared_ptr< OC::OCResourceRequest >& request) { - OC_LOG(WARNING, LOG_TAG, "entityHandler"); + auto resource = weakRes.lock(); + + if (!resource) return OC_EH_ERROR; + + OIC_LOG(WARNING, LOG_TAG, "entityHandler"); if (!request) { return OC_EH_ERROR; @@ -428,24 +594,26 @@ namespace OIC try { + RCSRequest rcsRequest{ resource, request }; + if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag) { - return handleRequest(request); + return resource->handleRequest(rcsRequest); } if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag) { - return handleObserve(request); + return resource->handleObserve(rcsRequest); } } catch (const std::exception& e) { - OC_LOG_V(WARNING, LOG_TAG, "Failed to handle request : %s", e.what()); + OIC_LOG_V(WARNING, LOG_TAG, "Failed to handle request : %s", e.what()); throw; } catch (...) { - OC_LOG(WARNING, LOG_TAG, "Failed to handle request."); + OIC_LOG(WARNING, LOG_TAG, "Failed to handle request."); throw; } @@ -453,16 +621,20 @@ namespace OIC } OCEntityHandlerResult RCSResourceObject::handleRequest( - std::shared_ptr< OC::OCResourceRequest > request) + const RCSRequest& request) { - assert(request != nullptr); + if (request.getInterface() != "" && + m_interfaceHandlers.find(request.getInterface()) == m_interfaceHandlers.end()) + { + return OC_EH_ERROR; + } - if (request->getRequestType() == "GET") + if (request.getOCRequest()->getRequestType() == "GET") { return handleRequestGet(request); } - if (request->getRequestType() == "PUT") + if (request.getOCRequest()->getRequestType() == "POST") { return handleRequestSet(request); } @@ -470,54 +642,78 @@ namespace OIC return OC_EH_ERROR; } - OCEntityHandlerResult RCSResourceObject::handleRequestGet( - std::shared_ptr< OC::OCResourceRequest > request) + OCEntityHandlerResult RCSResourceObject::handleRequestGet(const RCSRequest& request) { - assert(request != nullptr); + if (!findInterfaceHandler(request.getInterface()).isGetSupported()) + { + return OC_EH_ERROR; + } - auto attrs = getAttributesFromOCRequest(request); + auto attrs = getAttributesFromOCRequest(request.getOCRequest()); - return sendResponse(*this, request, invokeHandler(attrs, request, m_getRequestHandler)); + auto response = invokeHandler(attrs, request, m_getRequestHandler); + + if (response.isSeparate()) return OC_EH_SLOW; + + return sendResponse(request, response, + findInterfaceHandler(request.getInterface()).getGetResponseBuilder()); } - OCEntityHandlerResult RCSResourceObject::handleRequestSet( - std::shared_ptr< OC::OCResourceRequest > request) + bool RCSResourceObject::applyAcceptanceMethod( + const RCSSetResponse& response, const RCSResourceAttributes& requestAttrs) { - assert(request != nullptr); - - auto attrs = getAttributesFromOCRequest(request); - auto response = invokeHandler(attrs, request, m_setRequestHandler); auto requestHandler = response.getHandler(); assert(requestHandler != nullptr); - AttrKeyValuePairs replaced = requestHandler->applyAcceptanceMethod( - response.getAcceptanceMethod(), *this, attrs); + RCSResourceAttributes result; - OC_LOG_V(WARNING, LOG_TAG, "replaced num %d", replaced.size()); + auto replaced = requestHandler->applyAcceptanceMethod(response.getAcceptanceMethod(), + *this, requestAttrs); + + OIC_LOG_V(WARNING, LOG_TAG, "replaced num %zu", replaced.size()); for (const auto& attrKeyValPair : replaced) { - std::lock_guard lock(m_mutexKeyAttributeUpdate); + std::shared_ptr< AttributeUpdatedListener > foundListener; + { + std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners); + + auto it = m_attributeUpdatedListeners.find(attrKeyValPair.first); + if (it != m_attributeUpdatedListeners.end()) + { + foundListener = it->second; + } + } - auto keyAttrListener = m_keyAttributesUpdatedListeners.find(attrKeyValPair.first); - if(keyAttrListener != m_keyAttributesUpdatedListeners.end()) + if (foundListener) { - keyAttrListener-> second(attrKeyValPair.second, attrs[attrKeyValPair.first]); + (*foundListener)(attrKeyValPair.second, requestAttrs.at(attrKeyValPair.first)); } } - try + return !replaced.empty(); + } + + OCEntityHandlerResult RCSResourceObject::handleRequestSet(const RCSRequest& request) + { + if (!findInterfaceHandler(request.getInterface()).isSetSupported()) { - autoNotify(!replaced.empty(), m_autoNotifyPolicy); - return sendResponse(*this, request, response); - } catch (const PlatformException& e) { - OC_LOG(ERROR, LOG_TAG, e.what()); return OC_EH_ERROR; } + + auto attrs = getAttributesFromOCRequest(request.getOCRequest()); + + auto response = invokeHandler(attrs, request, m_setRequestHandler); + + if (response.isSeparate()) return OC_EH_SLOW; + + autoNotify(applyAcceptanceMethod(response, attrs), m_autoNotifyPolicy); + + return sendResponse(request, response, + findInterfaceHandler(request.getInterface()).getSetResponseBuilder()); } - OCEntityHandlerResult RCSResourceObject::handleObserve( - std::shared_ptr< OC::OCResourceRequest >) + OCEntityHandlerResult RCSResourceObject::handleObserve(const RCSRequest&) { if (!isObservable()) { @@ -527,6 +723,43 @@ namespace OIC return OC_EH_OK; } + InterfaceHandler RCSResourceObject::findInterfaceHandler( + const std::string& interfaceName) const + { + auto it = m_interfaceHandlers.find(interfaceName); + + if (it != m_interfaceHandlers.end()) return it->second; + + assert(m_interfaceHandlers.find(m_defaultInterface) != m_interfaceHandlers.end()); + + return m_interfaceHandlers.find(m_defaultInterface)->second; + } + + template + OCEntityHandlerResult RCSResourceObject::sendResponse( + const RCSRequest& request, const RESPONSE& response, + const RESPONSE_BUILDER& resBuilder) + { + auto reqHandler = response.getHandler(); + auto ocResponse = std::make_shared< OC::OCResourceResponse >(); + + ocResponse->setResponseResult(OC_EH_OK); + ocResponse->setErrorCode(reqHandler->getErrorCode()); + + if (reqHandler->hasCustomRepresentation()) + { + ocResponse->setResourceRepresentation(reqHandler->getRepresentation()); + } + else + { + ocResponse->setResourceRepresentation( + RCSRepresentation::toOCRepresentation(resBuilder(request, *this))); + } + + return ::sendResponse(request.getOCRequest(), ocResponse); + } + + RCSResourceObject::LockGuard::LockGuard(const RCSResourceObject::Ptr ptr) : m_resourceObject(*ptr), m_autoNotifyPolicy{ ptr->getAutoNotifyPolicy() }, @@ -562,9 +795,9 @@ namespace OIC init(); } - RCSResourceObject::LockGuard::~LockGuard() + RCSResourceObject::LockGuard::~LockGuard() noexcept(false) { - if (m_autoNotifyFunc) m_autoNotifyFunc(); + if (!std::uncaught_exception() && m_autoNotifyFunc) m_autoNotifyFunc(); if (m_isOwningLock) { @@ -585,7 +818,7 @@ namespace OIC m_resourceObject, m_resourceObject.m_resourceAttributes, m_autoNotifyPolicy); } - RCSResourceObject::WeakGuard::WeakGuard( + RCSResourceObject::WeakGuard::WeakGuard( const RCSResourceObject& resourceObject) : m_isOwningLock{ false }, m_resourceObject(resourceObject)