From 665e53266629fc851a7d4df4ee5dbe9e05acc932 Mon Sep 17 00:00:00 2001 From: Sashi Penta Date: Wed, 24 Sep 2014 18:48:57 -0700 Subject: [PATCH] 1. Default device entity handler implementation in Cpp Stack. 2. Addressed review comments. Change-Id: I8745b604d62d9c2e49fce1cedb3af185ae2f5f5b --- examples/fridgeclient.cpp | 38 +++++++--- examples/fridgeserver.cpp | 47 +++++++++++- examples/simpleclientserver.cpp | 2 +- include/IServerWrapper.h | 4 +- include/InProcServerWrapper.h | 4 +- include/OCApi.h | 2 +- include/OCPlatform.h | 43 +++++++---- include/OutOfProcServerWrapper.h | 24 ++++-- src/InProcServerWrapper.cpp | 159 +++++++++++++++++++++++++++++---------- src/OCPlatform.cpp | 28 +++++-- 10 files changed, 268 insertions(+), 83 deletions(-) diff --git a/examples/fridgeclient.cpp b/examples/fridgeclient.cpp index 8c4c55b..85ced90 100644 --- a/examples/fridgeclient.cpp +++ b/examples/fridgeclient.cpp @@ -83,6 +83,8 @@ class ClientFridge "/door/left", false, doorTypes, ifaces); OCResource::Ptr rightdoor = m_platform.constructResourceObject(resource->host(), "/door/right", false, doorTypes, ifaces); + OCResource::Ptr randomdoor = m_platform.constructResourceObject(resource->host(), + "/door/random", false, doorTypes, ifaces); light->get(QueryParamsMap(), GetCallback( std::bind(&ClientFridge::getResponse, this, "Fridge Light", PH::_1, @@ -96,6 +98,10 @@ class ClientFridge std::bind(&ClientFridge::getResponse, this, "Right Door", PH::_1, PH::_2, rightdoor, 3) )); + randomdoor->get(QueryParamsMap(), GetCallback( + std::bind(&ClientFridge::getResponse, this, "Random Door", PH::_1, + PH::_2, randomdoor, 4) + )); } // Note that resourceName, resource, and getId are all bound via the std::bind mechanism. @@ -113,18 +119,30 @@ class ClientFridge switch(getId) { case 1: - bool isOn; - rep.getValue("on",isOn); - std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"< request, + std::shared_ptr response) + { + if(request) + { + if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + if(request->getRequestType() == "GET") + { + if(response) + { + std::cout<<"Default Entity Handler: Get Request"<setErrorCode(200); + response->setResourceRepresentation(get(), ""); + } + } + else + { + std::cout <<"Default Entity Handler: unsupported request type " + << request->getRequestType() << std::endl; + } + } + else + { + std::cout << "Default Entity Handler: unsupported request flag" <)> FindCallback; - typedef std::function, const std::shared_ptr)> RegisterCallback; + typedef std::function, const std::shared_ptr)> EntityHandler; typedef std::function SubscribeCallback; typedef std::function GetCallback; typedef std::function PutCallback; diff --git a/include/OCPlatform.h b/include/OCPlatform.h index 40848e1..365bc09 100644 --- a/include/OCPlatform.h +++ b/include/OCPlatform.h @@ -154,10 +154,23 @@ namespace OC std::string& resourceURI, const std::string& resourceTypeName, const std::string& resourceInterface, - RegisterCallback entityHandler, + EntityHandler entityHandler, uint8_t resourceProperty); /** + * Set default device entity handler + * + * @param entityHandler - entity handler to handle requests for + * any undefined resources or default actions. + * if NULL is passed it removes the device default entity handler. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler); + + /** * This API unregisters a resource with the server * NOTE: This API applies to server side only. * @@ -176,13 +189,13 @@ namespace OC * * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
- * NOTE: bindResource must be used only after the both collection resource and + * NOTE: bindResource must be used only after the both collection resource and * resource to add under a collections are created and respective handles obtained
* Example:
* Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
* Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
* Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);
- * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".
+ * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".
*/ OCStackResult bindResource(const OCResourceHandle collectionHandle, const OCResourceHandle resourceHandle); @@ -194,7 +207,7 @@ namespace OC * * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
- * NOTE: bindResources must be used only after the both collection resource and + * NOTE: bindResources must be used only after the both collection resource and * list of resources to add under a collection are created and respective handles obtained
* Example:
* Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
@@ -214,7 +227,7 @@ namespace OC * * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
- * NOTE: unbindResource must be used only after the both collection resource and + * NOTE: unbindResource must be used only after the both collection resource and * resource to unbind from a collection are created and respective handles obtained
* Example
* Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
@@ -232,9 +245,9 @@ namespace OC * @param resourceHandleList List of resource handles to be unbound from the collection resource * * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * + * * NOTE: OCStackResult is defined in ocstack.h.
- * NOTE: unbindResources must be used only after the both collection resource and + * NOTE: unbindResources must be used only after the both collection resource and * list of resources resource to unbind from a collection are created and respective handles obtained.
* Example
* Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
@@ -268,7 +281,7 @@ namespace OC const std::string& resourceInterfaceName) const; public: - /** + /** * Start Presence announcements. * * @param ttl - time to live @@ -300,14 +313,14 @@ namespace OC * stopped (potentially more to be added later). * * @param presenceHandle - a handle object that can be used to identify this subscription - * request. It can be used to unsubscribe from these events in the future. + * request. It can be used to unsubscribe from these events in the future. * It will be set upon successful return of this method. * @param host - The IP address/addressable name of the server to subscribe to. * @param presenceHandler - callback function that will receive notifications/subscription events * * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
*/ - OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, SubscribeCallback presenceHandler); /** @@ -326,15 +339,15 @@ namespace OC * Creates a resource proxy object so that get/put/observe functionality * can be used without discovering the object in advance. Note that the * consumer of this method needs to provide all of the details required to - * correctly contact and observe the object. If the consumer lacks any of - * this information, they should discover the resource object normally. + * correctly contact and observe the object. If the consumer lacks any of + * this information, they should discover the resource object normally. * Additionally, you can only create this object if OCPlatform was initialized * to be a Client or Client/Server. Otherwise, this will return an empty * shared ptr. * - * @param host - a string containing a resolvable host address of the server - * holding the resource. Currently this should be in the format - * coap://address:port, though in the future, we expect this to + * @param host - a string containing a resolvable host address of the server + * holding the resource. Currently this should be in the format + * coap://address:port, though in the future, we expect this to * change to //address:port * * @param uri - the rest of the resource's URI that will permit messages to be diff --git a/include/OutOfProcServerWrapper.h b/include/OutOfProcServerWrapper.h index c190e6c..9de3401 100644 --- a/include/OutOfProcServerWrapper.h +++ b/include/OutOfProcServerWrapper.h @@ -37,7 +37,7 @@ namespace OC std::string& resourceURI, const std::string& resourceTypeName, const std::string& resourceInterface, - RegisterCallback& entityHandler, + EntityHandler& entityHandler, uint8_t resourceProperty) { @@ -47,31 +47,43 @@ namespace OC virtual OCStackResult unregisterResource( const OCResourceHandle& resourceHandle) - { //Not implemented yet + { + //Not implemented yet return OC_STACK_ERROR; } virtual OCStackResult bindTypeToResource( const OCResourceHandle& resourceHandle, const std::string& resourceTypeName) - { //Not implemented yet + { + //Not implemented yet return OC_STACK_NOTIMPL; } virtual OCStackResult bindInterfaceToResource( const OCResourceHandle& resourceHandle, const std::string& resourceInterfaceName) - { //Not implemented yet + { + //Not implemented yet return OC_STACK_NOTIMPL; } virtual OCStackResult startPresence(const unsigned int seconds) - { //Not implemented yet + { + //Not implemented yet return OC_STACK_NOTIMPL; } virtual OCStackResult stopPresence() - { //Not implemented yet + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + + + virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) + { + //Not implemented yet return OC_STACK_NOTIMPL; } }; diff --git a/src/InProcServerWrapper.cpp b/src/InProcServerWrapper.cpp index 5bd2604..3d2e511 100644 --- a/src/InProcServerWrapper.cpp +++ b/src/InProcServerWrapper.cpp @@ -37,28 +37,20 @@ #include using namespace std; +using namespace OC; -std::map entityHandlerMap; +std::map entityHandlerMap; +EntityHandler defaultDeviceEntityHandler = 0; -void defaultEntityHandler(const OC::OCResourceRequest::Ptr request, const OC::OCResourceResponse::Ptr response) +void formResourceRequest(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest, + std::shared_ptr pRequest) { - // TODO: 1) why is this ever even possible? 2) throw exception? - std::clog << "Error: defaultEntityHandler() invoked" << std::endl; -} - -OCEntityHandlerResult EntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *entityHandlerRequest ) -{ - auto pRequest = std::make_shared(); - auto pResponse = std::make_shared(); - - // TODO Utility to convert from C to C++ (every). - if(flag & OC_INIT_FLAG) { - // TODO We can fill the common data (resource Handle, etc.. ) - // init time. pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag); } + if(flag & OC_REQUEST_FLAG) { pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag); @@ -90,6 +82,7 @@ OCEntityHandlerResult EntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerReq } } } + if(flag & OC_OBSERVE_FLAG) { pRequest->setRequestHandlerFlag( @@ -102,42 +95,116 @@ OCEntityHandlerResult EntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerReq pRequest->setObservationInfo(observationInfo); } } +} - // Finding the corresponding CPP Application entityHandler for a given resource - auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource); +void processResourceResponse(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest, + std::shared_ptr pResponse) +{ + if(flag & OC_REQUEST_FLAG) + { + // TODO we could use const reference + std::string payLoad; - if(entityHandlerEntry != entityHandlerMap.end()) { - // Call CPP Application Entity Handler - // TODO CPP Application also should return OC_EH_OK or OC_EH_ERROR - if(entityHandlerEntry->second) + if(pResponse) { - entityHandlerEntry->second(pRequest, pResponse); + payLoad = pResponse->getPayload(); + } + else + { + // TODO throw appropriate runtime error + std::clog << "Response is NULL" << endl; + } + + if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen) + { + strncpy((char*)entityHandlerRequest->resJSONPayload, + payLoad.c_str(), + entityHandlerRequest->resJSONPayloadLen); } else { - std::clog << "C stack should not call again for parent resource" << std::endl; + // TODO throw appropriate runtime error + std::clog << "Payload is larger than the PayloadLen" << endl; } } - else { - std::clog << "No entity handler found." << std::endl; + +} + +OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest) +{ + // TODO we need to have a better way of logging (with various levels of logging) + std::clog << "\nIn Default device entity handler wrapper: " << endl; + + if(NULL == entityHandlerRequest) + { + std::clog << "Entity handler request is NULL." << endl; return OC_EH_ERROR; } - if(flag & OC_REQUEST_FLAG) + auto pRequest = std::make_shared(); + auto pResponse = std::make_shared(); + + formResourceRequest(flag, entityHandlerRequest, pRequest); + + if(defaultDeviceEntityHandler) { - // TODO we could use const reference - std::string payLoad = pResponse->getPayload(); + defaultDeviceEntityHandler(pRequest, pResponse); + } + else + { + std::clog << "Default device entity handler was not set." << endl; + return OC_EH_ERROR; + } - if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen) + processResourceResponse(flag, entityHandlerRequest, pResponse); + + return OC_EH_OK; +} + + +OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest ) +{ + // TODO we need to have a better way of logging (with various levels of logging) + std::clog << "\nIn entity handler wrapper: " << endl; + + if(NULL == entityHandlerRequest) + { + std::clog << "Entity handler request is NULL." << endl; + return OC_EH_ERROR; + } + + auto pRequest = std::make_shared(); + auto pResponse = std::make_shared(); + + formResourceRequest(flag, entityHandlerRequest, pRequest); + + + // Finding the corresponding CPP Application entityHandler for a given resource + auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource); + + if(entityHandlerEntry != entityHandlerMap.end()) + { + // Call CPP Application Entity Handler + // TODO CPP Application also should return OC_EH_OK or OC_EH_ERROR + if(entityHandlerEntry->second) { - strncpy((char*)entityHandlerRequest->resJSONPayload, payLoad.c_str(), entityHandlerRequest->resJSONPayloadLen); + entityHandlerEntry->second(pRequest, pResponse); } else { - // TODO throw appropriate runtime error - // cout << "Payload is larger than the PayloadLen" << endl; + std::clog << "C stack should not call again for parent resource\n"; } } + else + { + std::clog << "No entity handler found." << endl; + return OC_EH_ERROR; + } + + processResourceResponse(flag, entityHandlerRequest, pResponse); return OC_EH_OK; } @@ -165,9 +232,6 @@ namespace OC OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType); - // Setting default entity Handler - entityHandlerMap[(OCResourceHandle) 0] = defaultEntityHandler; - if(OC_STACK_OK != result) { throw InitializeException("Error Initializing Stack", result); @@ -202,11 +266,11 @@ namespace OC std::string& resourceURI, const std::string& resourceTypeName, const std::string& resourceInterface, - RegisterCallback& eHandler, + EntityHandler& eHandler, uint8_t resourceProperties) { - OCStackResult result; + OCStackResult result = OC_STACK_ERROR; auto cLock = m_csdkLock.lock(); @@ -220,7 +284,7 @@ namespace OC resourceTypeName.c_str(), // const char * resourceTypeName resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this resourceURI.c_str(), // const char * uri - EntityHandler, // OCEntityHandler entityHandler + EntityHandlerWrapper, // OCEntityHandler entityHandler resourceProperties // uint8_t resourceProperties ); } @@ -252,6 +316,25 @@ namespace OC return result; } + OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler(EntityHandler entityHandler) + { + OCStackResult result = OC_STACK_ERROR; + + defaultDeviceEntityHandler = entityHandler; + + if(entityHandler) + { + result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper); + } + else + { + // If Null passed we unset + result = OCSetDefaultDeviceEntityHandler(NULL); + } + + return result; + } + OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle) { auto cLock = m_csdkLock.lock(); diff --git a/src/OCPlatform.cpp b/src/OCPlatform.cpp index 77f4428..dd8d877 100644 --- a/src/OCPlatform.cpp +++ b/src/OCPlatform.cpp @@ -146,10 +146,10 @@ namespace OC std::string& resourceURI, const std::string& resourceTypeName, const std::string& resourceInterface, - RegisterCallback entityHandler, + EntityHandler entityHandler, uint8_t resourceProperty) { - OCStackResult result = OC_STACK_OK; + OCStackResult result = OC_STACK_ERROR; if(m_server) { @@ -165,6 +165,22 @@ namespace OC 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::unregisterResource(const OCResourceHandle& resourceHandle) const { @@ -181,7 +197,7 @@ namespace OC OCStackResult OCPlatform::unbindResource(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) { - OCStackResult result = OC_STACK_OK; + OCStackResult result = OC_STACK_ERROR; try { result = OCUnBindResource(collectionHandle, resourceHandle); @@ -196,7 +212,7 @@ namespace OC OCStackResult OCPlatform::unbindResources(const OCResourceHandle collectionHandle, const std::vector& resourceHandles) { - OCStackResult result = OC_STACK_OK; + OCStackResult result = OC_STACK_ERROR; try { @@ -223,7 +239,7 @@ namespace OC OCStackResult OCPlatform::bindResource(const OCResourceHandle collectionHandle, const OCResourceHandle resourceHandle) { - OCStackResult result = OC_STACK_OK; + OCStackResult result = OC_STACK_ERROR; try { result = OCBindResource(collectionHandle, resourceHandle); @@ -238,7 +254,7 @@ namespace OC OCStackResult OCPlatform::bindResources(const OCResourceHandle collectionHandle, const std::vector& resourceHandles) { - OCStackResult result = OC_STACK_OK; + OCStackResult result = OC_STACK_ERROR; try { -- 2.7.4