integrated coapuriparser
authorAniket Pingley <aniket.pingley@intel.com>
Fri, 15 Aug 2014 21:29:33 +0000 (14:29 -0700)
committerAniket Pingley <aniket.pingley@intel.com>
Mon, 18 Aug 2014 17:57:39 +0000 (10:57 -0700)
fixed the crash occuring when freeing memory in OCUtilities.cpp
added a temporary patch in OCUtilities.cpp after discussion with Sudarshan
made changes to makefile and OCUtilities.h as per Bill and Joey's comments.

Change-Id: I53f838bf6cd2e78d5a9c9eadfeb982d29bde54cb

OCLib/InProcServerWrapper.cpp
OCLib/OCUtilities.cpp [new file with mode: 0644]
csdk/libcoap [new symlink]
include/OCResourceRequest.h
include/OCUtilities.h [new file with mode: 0644]
makefile

index 6f1edf9..6f5f3a6 100644 (file)
@@ -34,6 +34,7 @@
 #include <OCResourceResponse.h>
 #include <ocstack.h>
 #include <OCApi.h>
+#include <OCUtilities.h>
 
 
 using namespace OC::OCReflect;
@@ -68,6 +69,13 @@ OCStackResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * e
 
             if(entityHandlerRequest)
             {
+                if(entityHandlerRequest->query)
+                {
+                    std::string querystr(reinterpret_cast<char*>(entityHandlerRequest->query));
+                    OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr);
+                    if(qp.size() > 0)
+                        pRequest->setQueryParams(qp);
+                }
                 if(OC_REST_GET == entityHandlerRequest->method)
                 {
                     // TODO @SASHI Why strings : "GET"??
@@ -137,7 +145,7 @@ namespace OC
                             :m_csdkLock(csdkLock)
     {
         OCMode initType;
-        
+
         if(cfg.mode == ModeType::Server)
         {
             initType = OC_SERVER;
@@ -205,7 +213,7 @@ namespace OC
         cout << "\tResource Interface: " << resourceInterface << endl;
 
         auto cLock = m_csdkLock.lock();
-        
+
         if(cLock)
         {
             std::lock_guard<std::mutex> lock(*cLock);
@@ -245,7 +253,7 @@ namespace OC
         cout << "\tTypeName: " << resourceTypeName  << endl;
 
         auto cLock = m_csdkLock.lock();
-        OCStackResult result; 
+        OCStackResult result;
         if(cLock)
         {
             std::lock_guard<std::mutex> lock(*cLock);
@@ -296,7 +304,7 @@ namespace OC
             m_threadRun = false;
             m_processThread.join();
         }
-        
+
         OCStop();
     }
 }
diff --git a/OCLib/OCUtilities.cpp b/OCLib/OCUtilities.cpp
new file mode 100644 (file)
index 0000000..e11c97f
--- /dev/null
@@ -0,0 +1,131 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation 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 "OCUtilities.h"
+#include <algorithm>
+#include <iterator>
+#include <boost/algorithm/string.hpp>
+#include <sstream>
+extern "C" {
+#include <uri.h>    // libcoap
+#include <option.h> // libcoap
+}
+
+// [TODO] remove this function
+// this function is just a temporary patch for Sudarshan
+// it seems that the C stack is parsing and giving out the query separately.
+// the entire URI need not be parsed
+static OC::Utilities::QueryParamsKeyVal tempPatch(const std::string& _uri)
+{
+    OC::Utilities::QueryParamsKeyVal qp;
+    if(_uri.empty())
+    {
+        return qp;
+    }
+
+    std::vector<std::string> queryparams;
+    boost::split(queryparams, _uri, boost::is_any_of("&"));
+
+    for(std::vector<std::string>::iterator it = queryparams.begin(); it != queryparams.end(); ++it)
+    {
+        std::vector<std::string> keyval;
+        boost::split(keyval, *it, boost::is_any_of("="));
+        if(2 == keyval.size())
+        {
+            qp[keyval.at(0)] = keyval.at(1);
+        }
+    }
+
+    return qp;
+}
+
+// implementation can be split into two functions if needed
+// uses do{}while(0) to avoid returning from multiple locations
+OC::Utilities::QueryParamsKeyVal OC::Utilities::getQueryParams(const std::string& _uri)
+{
+
+    // this is a temporary fix. [TODO] remove this after permanent fix
+    return tempPatch(_uri);
+
+    OC::Utilities::QueryParamsKeyVal qp;
+    unsigned char *bufptr = nullptr; // don't delete via bufptr
+    unsigned char *bufptrToDelete = nullptr; // bufptr may be incremented. need this one to keep track.
+    do // while(0)
+    {
+        if(_uri.empty())
+        {
+            break;
+        }
+
+        coap_uri_t coapuri = {0};
+        unsigned char* uristr = reinterpret_cast<unsigned char*>(const_cast<char*>(_uri.c_str()));
+
+        if(coap_split_uri(uristr, _uri.length(), &coapuri) < 0)
+        {
+            break;
+        }
+
+        size_t buflen = 2048; // this is big enough buffer. [TODO] may want to downsize it. I have seen that the size may have to be greater than coap.query.length, which is counterintuitve but there may be a bug in coap uri parser.
+        bufptrToDelete = bufptr = new (std::nothrow) unsigned char[buflen](); // why heap? will need it for incrementing the pointer in the logic below
+
+        if(!bufptr)
+        {
+            break;
+        }
+
+        int segments = -1;
+        if((segments = coap_split_query(coapuri.query.s, coapuri.query.length, bufptr, &buflen)) < 0)
+        {
+            break;
+        }
+
+        // coap uri parser has weird api. its not straighforward to understand what the coap function calls below do.
+        // coap uri parser lacks ability to split the key value pair in query params. that will be done in getQueryParams() function
+        std::vector<std::string> queryparams;
+        while(segments--)
+        {
+            queryparams.push_back(std::string (reinterpret_cast<char*>(coap_opt_value(bufptr)), coap_opt_length(bufptr)));
+            bufptr += coap_opt_size(bufptr);
+        }
+
+        if(queryparams.empty())
+        {
+            break;
+        }
+
+        //[TODO] use foreach
+        for(std::vector<std::string>::iterator it = queryparams.begin(); it != queryparams.end(); ++it)
+        {
+            std::vector<std::string> keyval;
+            boost::split(keyval, *it, boost::is_any_of("="));
+            if(2 == keyval.size())
+            {
+                qp[keyval.at(0)] = keyval.at(1);
+            }
+        }
+    }
+    while(0);
+
+    if(bufptrToDelete)
+    {
+        delete [] bufptrToDelete;
+    }
+    return qp;
+}
diff --git a/csdk/libcoap b/csdk/libcoap
new file mode 120000 (symlink)
index 0000000..ec55e69
--- /dev/null
@@ -0,0 +1 @@
+libcoap-4.1.1
\ No newline at end of file
index f5d497e..cd784b1 100644 (file)
@@ -18,9 +18,9 @@
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/// @file OCResourceRequest.h 
+/// @file OCResourceRequest.h
 
-/// @brief  This file contains the declaration of classes and its members related to 
+/// @brief  This file contains the declaration of classes and its members related to
 ///         ResourceRequest.
 
 #ifndef __OCRESOURCEREQUEST_H
@@ -42,7 +42,7 @@ namespace OC
         typedef std::shared_ptr<OCResourceRequest> Ptr;
 
         /**
-        *  Virtual destructor 
+        *  Virtual destructor
         */
         virtual ~OCResourceRequest(void)
         {
@@ -53,7 +53,7 @@ namespace OC
         *  @return std::string request type. This could be 'GET'/'PUT'/'POST'/'DELETE'
         */
         std::string getRequestType() const {return m_requestType;}
-        
+
         /**
         *  Retrieves the query parameters from the request
         *  @return std::string query parameters in the request
@@ -61,10 +61,10 @@ namespace OC
         const QueryParamsMap& getQueryParameters() const {return m_queryParameters;}
 
         /**
-        *  Retrieves the request handler flag type. This can be either INIT flag or REQUEST flag or OBSERVE flag. 
-        *  NOTE: 
+        *  Retrieves the request handler flag type. This can be either INIT flag or REQUEST flag or OBSERVE flag.
+        *  NOTE:
         *  INIT indicates that the vendor's entity handler should go and perform initialization operations
-        *  REQUEST indicates that it is a request of certain type (GET/PUT/POST/DELETE) and entity handler needs to perform 
+        *  REQUEST indicates that it is a request of certain type (GET/PUT/POST/DELETE) and entity handler needs to perform
         *  corresponding operations
         *  OBSERVE indicates that the request is of type Observe and entity handler needs to perform corresponding operations
         *  @return std::string type of request flag
@@ -84,21 +84,21 @@ namespace OC
         AttributeMap m_attributeMap;
 
     public:
-        // TODO: This is not a public API for app developers. 
-        // This function will not be exposed in future 
+        // TODO: This is not a public API for app developers.
+        // This function will not be exposed in future
         void setRequestType(const std::string& requestType)
         {
             m_requestType = requestType;
         }
 
-        // TODO: This is not a public API for app developers. 
+        // TODO: This is not a public API for app developers.
         // This function will not be exposed in future
         void setPayload(const std::string& requestPayload)
         {
             // TODO: The following JSON Parse implementation should be seperated into utitilites
             // and used wherever required.
             // e.g. parse(std::string& payload, Attributemap& attributeMap)
-            
+
             std::stringstream requestStream;
             requestStream << requestPayload;
             boost::property_tree::ptree root;
@@ -117,14 +117,14 @@ namespace OC
             }
         }
 
-        // TODO: This is not a public API for app developers. 
+        // TODO: This is not a public API for app developers.
         // This function will not be exposed in future
         void setQueryParams(QueryParamsMap& queryParams)
         {
-
+            m_queryParameters = queryParams;
         }
 
-        // TODO: This is not a public API for app developers. 
+        // TODO: This is not a public API for app developers.
         // This function will not be exposed in future
         void setRequestHandlerFlag(RequestHandlerFlag requestHandlerFlag)
         {
diff --git a/include/OCUtilities.h b/include/OCUtilities.h
new file mode 100644 (file)
index 0000000..92acc3a
--- /dev/null
@@ -0,0 +1,50 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _INTEL_OCUTILITIES_H_
+#define _INTEL_OCUTILITIES_H_
+#endif
+
+#include <map>
+#include <vector>
+#include <memory>
+#include <exception>
+
+namespace OC {
+    namespace Utilities {
+
+        typedef std::map<std::string, std::string> QueryParamsKeyVal;
+        /*
+         * @brief Helper function to get query parameter from a URI
+         * @remarks      Its okay to return a copy of the container.\
+         *               The size is not expected to be huge.
+         * @remarks      Temporary: The URI must strictly have\
+         *               coap as the protocol in the fully qualified URI\
+         *               e.g., coap://1.2.3.4:5657/foo?bar=0)
+         * @remarks      If a separate class for URI parser is needed,\
+         *               please talk to Erich Keane.
+         * @todo         If more URI elements need to be parsed,\
+         *               please move the common parsing logic to a
+         *               different function
+         */
+        QueryParamsKeyVal getQueryParams(const std::string& uri);
+
+    }
+}
index 8698701..18675a9 100644 (file)
--- a/makefile
+++ b/makefile
@@ -16,6 +16,7 @@ CXX_INC         += -I./csdk/stack/include
 CXX_INC          += -I./csdk/ocsocket/include
 CXX_INC          += -I./csdk/ocrandom/include
 CXX_INC          += -I./csdk/logger/include
+CXX_INC          += -I./csdk/libcoap
 
 # Force metatargets to build:
 .PHONY: prep_dirs c_sdk simpleserver simpleclient simpleclientserver
@@ -42,8 +43,8 @@ simpleclient: OCLib.a
 simpleclientserver: OCLib.a
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(SAMPLES_OUT_DIR)/$@ examples/simpleclientserver.cpp $(CXX_INC) $(OBJ_DIR)/OCLib.a csdk/$(BUILD)/liboctbstack.a
 
-OCLib.a: OCPlatform.o OCResource.o OCReflect.o InProcServerWrapper.o InProcClientWrapper.o
-       ar -cvq $(OBJ_DIR)/OCLib.a $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCReflect.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o
+OCLib.a: OCPlatform.o OCResource.o OCReflect.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o
+       ar -cvq $(OBJ_DIR)/OCLib.a $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCReflect.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o
 
 OCReflect.o: OCLib/OCReflect.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c OCLib/OCReflect.cpp $(CXX_INC)
@@ -54,6 +55,9 @@ OCPlatform.o: OCLib/OCPlatform.cpp
 OCResource.o: OCLib/OCResource.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c OCLib/OCResource.cpp $(CXX_INC)
 
+OCUtilities.o: OCLib/OCUtilities.cpp
+       $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c OCLib/OCUtilities.cpp $(CXX_INC)
+
 InProcServerWrapper.o: OCLib/InProcServerWrapper.cpp
        $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c OCLib/InProcServerWrapper.cpp $(CXX_INC)