IOT 1819: Return URI of new resource in option header.
authorSoemin Tjong <stjong@microsoft.com>
Tue, 25 Apr 2017 06:33:57 +0000 (23:33 -0700)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Tue, 13 Jun 2017 18:44:18 +0000 (18:44 +0000)
https://tools.ietf.org/html/rfc7252#section-5.8.2 specifies that the URI
of a new resource created by a server is returned in Location-Path
option.

Change-Id: I358d8ee127a598c2f2fdb8f101413eebbf100a89
Signed-off-by: Soemin Tjong <stjong@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19245
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
14 files changed:
resource/IPCA/src/callback.cpp
resource/IPCA/src/inc/callback.h
resource/IPCA/src/ocfframework.cpp
resource/IPCA/unittests/IPCAElevatorClient.cpp
resource/IPCA/unittests/IPCAElevatorClient.h
resource/IPCA/unittests/ipcatestdata.h
resource/IPCA/unittests/ipcaunittests.cpp
resource/IPCA/unittests/mockOC.cpp
resource/IPCA/unittests/testelevatorserver.cpp
resource/IPCA/unittests/testelevatorserver.h
resource/csdk/connectivity/api/cacommon.h
resource/csdk/include/octypes.h
resource/csdk/stack/src/ocserverrequest.c
resource/src/InProcServerWrapper.cpp

index a7c9b2d..5d42e82 100644 (file)
@@ -778,7 +778,11 @@ void Callback::GetCallback(IPCAStatus status, const OCRepresentation& rep, Callb
     RemoveCallbackInfo(cbInfo->mapKey);
 }
 
-void Callback::SetCallback(IPCAStatus status, const OCRepresentation& rep, CallbackInfo::Ptr cbInfo)
+void Callback::SetCallback(
+                    IPCAStatus status,
+                    const OCRepresentation& rep,
+                    CallbackInfo::Ptr cbInfo,
+                    std::string newResourcePath)
 {
     if ((cbInfo->app != m_app) || (SetCallbackInProgress(cbInfo->mapKey) == false))
     {
@@ -790,8 +794,7 @@ void Callback::SetCallback(IPCAStatus status, const OCRepresentation& rep, Callb
         cbInfo->createResourceCallback(
                     status,
                     const_cast<void*>(cbInfo->callbackContext),
-                    NULL, /* tbd: no info on new resource URI. */
-                          /* See https://jira.iotivity.org/browse/IOT-1819 */
+                    newResourcePath.c_str(),
                     (IPCAPropertyBagHandle)&rep);
     }
     else
index ea5d1a4..ab326d6 100644 (file)
@@ -174,7 +174,8 @@ class Callback
         // resource->put() callback.
         void SetCallback(IPCAStatus status,
                 const OC::OCRepresentation& rep,
-                CallbackInfo::Ptr cbInfo);
+                CallbackInfo::Ptr cbInfo,
+                std::string newResourcePath);
 
         // resource->observe() callback.
         void ObserveCallback(IPCAStatus status,
index 3b7df97..13851af 100644 (file)
@@ -1008,7 +1008,19 @@ void OCFFramework::OnPostPut(const HeaderOptions& headerOptions,
                         const int eCode,
                         CallbackInfo::Ptr callbackInfo)
 {
-    OC_UNUSED(headerOptions);
+    std::string newResourcePath;
+    if (headerOptions.size())
+    {
+        // Pass LOCATION_PATH_OPTION_ID to the app.
+        for (auto header : headerOptions)
+        {
+            if (header.getOptionID() == HeaderOption::LOCATION_PATH_OPTION_ID)
+            {
+                newResourcePath = header.getOptionData();
+                break;
+            }
+        }
+    }
 
     IPCAStatus status = MapOCStackResultToIPCAStatus((OCStackResult)eCode);
 
@@ -1018,7 +1030,7 @@ void OCFFramework::OnPostPut(const HeaderOptions& headerOptions,
 
     for (const auto& callback : callbackSnapshot)
     {
-        callback->SetCallback(status, rep, callbackInfo);
+        callback->SetCallback(status, rep, callbackInfo, newResourcePath);
     }
 }
 
index a7db669..8585f49 100644 (file)
@@ -242,6 +242,16 @@ void IPCAElevatorClient::CreateResourceRelativePath()
     IPCAPropertyBagDestroy(propertyBagHandle);
 }
 
+void IPCAElevatorClient::CreateResourceLongRelativePath()
+{
+    IPCAPropertyBagHandle propertyBagHandle;
+    ASSERT_EQ(IPCA_OK, IPCAPropertyBagCreate(&propertyBagHandle));
+
+    CreateElevatorResource(ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH_LONG, propertyBagHandle);
+
+    IPCAPropertyBagDestroy(propertyBagHandle);
+}
+
 void IPCAElevatorClient::DeleteResource()
 {
     DeleteElevatorResource();
index dc3a55d..3cad611 100644 (file)
@@ -38,7 +38,8 @@ public:
     void GetTargetFloor(int* targetFloor, bool* result);
     void SetTargetFloor(int targetFloor, bool* result);
     void CreateResourceRelativePath();
-    const char* GetNewResourceURI() { return m_newResourcePath.c_str(); }
+    void CreateResourceLongRelativePath();
+    const char* GetNewResourcePath() { return m_newResourcePath.c_str(); }
     void CreateResouceExplicitPath();
     void DeleteResource();
 
index 67a66b7..7688ead 100644 (file)
@@ -39,6 +39,7 @@
 #define ELEVATOR_CO_PRIVATE_INTERFACE   "my.private.if"\r
 \r
 #define ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH       "/ipca/new/resource/relative"\r
+#define ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH_LONG  "/ipca/new/resource/relative/long"\r
 #define ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH_TYPE  "x.ipca.test.elevator.create.resource.relative"\r
 #define ELEVATOR_RESOURCE_NEW_RESOURCE_PATH          "/ipca/new/resource/relative/1"\r
 \r
index 927a8f4..39eafdf 100644 (file)
@@ -570,10 +570,15 @@ TEST_F(IPCAElevatorClient, SuccessfullyCreateAndDeleteResources)
         CreateResourceRelativePath();
         afterCreateCount = g_testElevator1.GetRelativePathResourceCreateCount();
         ASSERT_EQ(beforeCreateCount + 1, afterCreateCount);
-        // @todo: when IOT-1819 is resolved.
-        // EXPECT_STREQ(ELEVATOR_RESOURCE_NEW_RESOURCE_PATH, GetNewResourceURI());
+        EXPECT_STREQ(ELEVATOR_RESOURCE_NEW_RESOURCE_PATH, GetNewResourcePath());
     }
 
+    // Create new resource that results in resource with long resource path.
+    beforeCreateCount = g_testElevator1.GetRelativePathResourceCreateCount();
+    CreateResourceLongRelativePath();
+    afterCreateCount = g_testElevator1.GetRelativePathResourceCreateCount();
+    ASSERT_EQ(beforeCreateCount, afterCreateCount); // resource should not be created.
+
     // Delete resource
     size_t beforeDeleteCount, afterDeleteCount;
     for (int i = 0 ; i < 3 ; i++)
index b629db7..2e92703 100644 (file)
@@ -470,6 +470,24 @@ OCStackResult OCPlatform::sendResponse(const std::shared_ptr<OCResourceResponse>
             {\r
                 ocResult = OC_STACK_OK;\r
             }\r
+\r
+            // Add path of new resource in the header option.\r
+            std::string newResourcePath = pResponse->getNewResourceUri();\r
+            if (!newResourcePath.empty())\r
+            {\r
+                // MAX_URI_LENGTH is the URI limit of OCEntityHandlerResponse.resourceUri in\r
+                // inProcServerWrapper.cpp.\r
+                if (newResourcePath.length() > MAX_URI_LENGTH)\r
+                {\r
+                    return OC_STACK_ERROR;\r
+                }\r
+\r
+                HeaderOption::OCHeaderOption headerOption(\r
+                                                HeaderOption::LOCATION_PATH_OPTION_ID,\r
+                                                newResourcePath);\r
+                serverHeaderOptions.push_back(headerOption);\r
+            }\r
+\r
             std::thread postCallbackThread(pendingRequest->postCallback,\r
                             serverHeaderOptions,\r
                             ocRep,\r
index 1b1e8ad..2c8de51 100644 (file)
@@ -21,6 +21,7 @@
 #include "OCApi.h"
 #include "testelevatorserver.h"
 #include "ipcatestdata.h"
+#include "OCException.h"
 
 using namespace OC;
 using namespace std::placeholders;
@@ -199,6 +200,7 @@ OCEntityHandlerResult ElevatorServer::ElevatorEntityHandler(
 
                     ehResult = OC_EH_OK;
                 }
+                else
                 if (resourceUri.compare(ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH) == 0)
                 {
                     m_relativePathResourceCreateCount++;
@@ -214,6 +216,52 @@ OCEntityHandlerResult ElevatorServer::ElevatorEntityHandler(
                     OCPlatform::sendResponse(pResponse);
                     ehResult = OC_EH_OK;
                 }
+                else
+                if (resourceUri.compare(ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH_LONG) == 0)
+                {
+                    // long resource path.
+                    char newResourcePath[2048];
+                    memset(newResourcePath, 'x', 2047);
+                    newResourcePath[2047] = '\0';
+
+                    m_relativePathResourceCreateCount++;
+
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
+                    pResponse->setNewResourceUri(newResourcePath);
+                    pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+
+                    try
+                    {
+                        // Send the response.
+                        if (OCPlatform::sendResponse(pResponse) != OC_STACK_OK)
+                        {
+                            m_relativePathResourceCreateCount--;
+                            ehResult = OC_EH_INTERNAL_SERVER_ERROR;
+                        }
+                        else
+                        {
+                            ehResult = OC_EH_OK;
+                        }
+                    }
+                    catch(OCException& e)
+                    {
+                        // The stack returns OC_STACK_INVALID_URI when the new resource path
+                        // exceeds MAX_URI_LENGTH.
+                        if (e.code() == OC_STACK_INVALID_URI)
+                        {
+                            // The resource is not created.
+                            m_relativePathResourceCreateCount--;
+                            ehResult = OC_EH_INTERNAL_SERVER_ERROR;
+                        }
+                        else
+                        {
+                            throw e;
+                        }
+                    }
+
+                }
 
             }
             else if (requestType == OC::PlatformCommands::PUT)
@@ -445,6 +493,20 @@ bool ElevatorServer::Start(std::string& elevatorName)
             return false;
         }
 
+        std::string createRelativeResourcePathLong(ELEVATOR_RESOURCE_CREATE_RELATIVE_PATH_LONG);
+        result = OCPlatform::registerResource(
+                                    m_elevatorCreateRelativeResourceLong,
+                                    createRelativeResourcePathLong,
+                                    createRelativeResourceType,
+                                    DEFAULT_INTERFACE,
+                                    std::bind(&ElevatorServer::ElevatorEntityHandler, this, _1),
+                                    OC_DISCOVERABLE | OC_OBSERVABLE);
+
+        if (result != OC_STACK_OK)
+        {
+            return false;
+        }
+
         std::string deleteResourcePath(ELEVATOR_RESOURCE_DELETE_PATH);
         std::string deleteResourceType(ELEVATOR_RESOURCE_DELETE_TYPE);
         result = OCPlatform::registerResource(
@@ -484,6 +546,9 @@ void ElevatorServer::Stop()
         OCPlatform::unregisterResource(m_elevatorCreateRelativeResource);
         m_elevatorCreateRelativeResource = nullptr;
 
+        OCPlatform::unregisterResource(m_elevatorCreateRelativeResourceLong);
+        m_elevatorCreateRelativeResourceLong = nullptr;
+
         OCPlatform::unregisterResource(m_elevatorDeleteResource);
         m_elevatorDeleteResource = nullptr;
 
index 9cf13eb..579874b 100644 (file)
-/* *****************************************************************
- *
- * Copyright 2017 Microsoft
- *
- *
- * 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 _ELEVATOR_SERVER_H
-#define _ELEVATOR_SERVER_H
-
-#include <string>
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-using namespace OC;
-
-typedef enum
-{
-    Stopped = 0,
-    Up,
-    Down
-} ElevatorDirection;
-
-class ElevatorServer
-{
-public:
-    ElevatorServer();
-    ~ElevatorServer();
-
-    // Start stop the thread processing the elevator movement.  Also register/unregister the
-    // elevator from IoTivity.
-    bool Start(std::string& elevatorName);
-    void Stop();
-
-    // Target floor is set by caller.
-    void SetTargetFloor(int floor);
-    int GetTargetFloor();
-
-    // Current floor is set by elevator.
-    int GetCurrentFloor();
-    ElevatorDirection GetElevatorDirection();
-
-    size_t GetRelativePathResourceCreateCount() { return m_relativePathResourceCreateCount; }
-    size_t GetExplicitPathResourceCreateCount() { return m_explicitPathResourceCreateCount; }
-    size_t GetDeleteResourceCount() { return m_deleteResourceCount; }
-    size_t GetIncorrectInterfaceCount() { return m_IncorrectInterfaceCount; }
-
-private:
-    // List of observers, when client app calls resource->Observer().
-    ObservationIds m_observers;
-
-    // Send notification to observers when property values change.
-    void NotifyObservers(std::string propertyName, int value);
-
-    // Elevator has one resource.
-    OCResourceHandle m_elevatorResourceHandle;            // The elevator resource.
-    OCResourceHandle m_elevatorCOResourceHandle;          // CO resource.
-    OCResourceHandle m_elevatorMaintenanceHandle;
-    OCResourceHandle m_elevatorCreateRelativeResource;    // Resource that handles pretent create.
-    OCResourceHandle m_elevatorDeleteResource;            // Resource that handles pretend delete.
-
-    int m_targetFloor;    // where elevator needs to be.
-    int m_currentFloor;   // where elevator is.
-    ElevatorDirection m_direction;    // current direction of the elevator.
-
-    // Thread moving the elevator.
-    std::thread m_engineThread;
-    bool m_isRunning;
-    static void Engine(ElevatorServer* elevator);
-
-    // Move current floor to target floor.
-    void MoveElevator();
-
-    // Helper function to send response for a request.
-    OCStackResult SendResponse(std::shared_ptr<OCResourceRequest> request,
-                               OCEntityHandlerResult result = OC_EH_OK);
-    OCStackResult SendMaintenanceResponse(std::shared_ptr<OCResourceRequest> request);
-
-    // OCF callback for this elevator.
-    OCEntityHandlerResult ElevatorEntityHandler(std::shared_ptr<OCResourceRequest> request);
-
-    // Elevator device details.
-    std::string m_name;
-
-    // Elevator platform details.
-    std::string m_platformID;
-    std::string m_modelNumber;
-    std::string m_platformVersion;
-    std::string m_serialNumber;
-    std::string m_specVersion;
-    std::string m_defaultLanguage;
-    std::string m_manufacturerName;
-    std::string m_manufacturerUrl;
-    std::string m_dateOfManufacture;
-    std::string m_operatingSystemVersion;
-    std::string m_hardwareVersion;
-    std::string m_firmwareVersion;
-    std::string m_supportUrl;
-    std::string m_systemTime;
-
-    // Elevator new resource request count.
-    size_t m_relativePathResourceCreateCount;
-    size_t m_explicitPathResourceCreateCount;
-
-    // Elevator delete resource count.
-    size_t m_deleteResourceCount;
-
-    // Number of times entity handler is called with incorrect resource interface.
-    size_t m_IncorrectInterfaceCount;
-};
-
-#endif // _ELEVATOR_SERVER_H
+/* *****************************************************************\r
+ *\r
+ * Copyright 2017 Microsoft\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ ******************************************************************/\r
+\r
+#ifndef _ELEVATOR_SERVER_H\r
+#define _ELEVATOR_SERVER_H\r
+\r
+#include <string>\r
+#include "OCPlatform.h"\r
+#include "OCApi.h"\r
+\r
+using namespace OC;\r
+\r
+typedef enum\r
+{\r
+    Stopped = 0,\r
+    Up,\r
+    Down\r
+} ElevatorDirection;\r
+\r
+class ElevatorServer\r
+{\r
+public:\r
+    ElevatorServer();\r
+    ~ElevatorServer();\r
+\r
+    // Start stop the thread processing the elevator movement.  Also register/unregister the\r
+    // elevator from IoTivity.\r
+    bool Start(std::string& elevatorName);\r
+    void Stop();\r
+\r
+    // Target floor is set by caller.\r
+    void SetTargetFloor(int floor);\r
+    int GetTargetFloor();\r
+\r
+    // Current floor is set by elevator.\r
+    int GetCurrentFloor();\r
+    ElevatorDirection GetElevatorDirection();\r
+\r
+    size_t GetRelativePathResourceCreateCount() { return m_relativePathResourceCreateCount; }\r
+    size_t GetExplicitPathResourceCreateCount() { return m_explicitPathResourceCreateCount; }\r
+    size_t GetDeleteResourceCount() { return m_deleteResourceCount; }\r
+    size_t GetIncorrectInterfaceCount() { return m_IncorrectInterfaceCount; }\r
+\r
+private:\r
+    // List of observers, when client app calls resource->Observer().\r
+    ObservationIds m_observers;\r
+\r
+    // Send notification to observers when property values change.\r
+    void NotifyObservers(std::string propertyName, int value);\r
+\r
+    // Elevator has one resource.\r
+    OCResourceHandle m_elevatorResourceHandle;            // The elevator resource.\r
+    OCResourceHandle m_elevatorCOResourceHandle;          // CO resource.\r
+    OCResourceHandle m_elevatorMaintenanceHandle;\r
+    OCResourceHandle m_elevatorCreateRelativeResource;     // Resource that handles pretend create.\r
+    OCResourceHandle m_elevatorCreateRelativeResourceLong; // Resource that handles pretend create.\r
+    OCResourceHandle m_elevatorDeleteResource;             // Resource that handles pretend delete.\r
+\r
+    int m_targetFloor;    // where elevator needs to be.\r
+    int m_currentFloor;   // where elevator is.\r
+    ElevatorDirection m_direction;    // current direction of the elevator.\r
+\r
+    // Thread moving the elevator.\r
+    std::thread m_engineThread;\r
+    bool m_isRunning;\r
+    static void Engine(ElevatorServer* elevator);\r
+\r
+    // Move current floor to target floor.\r
+    void MoveElevator();\r
+\r
+    // Helper function to send response for a request.\r
+    OCStackResult SendResponse(std::shared_ptr<OCResourceRequest> request,\r
+                               OCEntityHandlerResult result = OC_EH_OK);\r
+    OCStackResult SendMaintenanceResponse(std::shared_ptr<OCResourceRequest> request);\r
+\r
+    // OCF callback for this elevator.\r
+    OCEntityHandlerResult ElevatorEntityHandler(std::shared_ptr<OCResourceRequest> request);\r
+\r
+    // Elevator device details.\r
+    std::string m_name;\r
+\r
+    // Elevator platform details.\r
+    std::string m_platformID;\r
+    std::string m_modelNumber;\r
+    std::string m_platformVersion;\r
+    std::string m_serialNumber;\r
+    std::string m_specVersion;\r
+    std::string m_defaultLanguage;\r
+    std::string m_manufacturerName;\r
+    std::string m_manufacturerUrl;\r
+    std::string m_dateOfManufacture;\r
+    std::string m_operatingSystemVersion;\r
+    std::string m_hardwareVersion;\r
+    std::string m_firmwareVersion;\r
+    std::string m_supportUrl;\r
+    std::string m_systemTime;\r
+\r
+    // Elevator new resource request count.\r
+    size_t m_relativePathResourceCreateCount;\r
+    size_t m_explicitPathResourceCreateCount;\r
+\r
+    // Elevator delete resource count.\r
+    size_t m_deleteResourceCount;\r
+\r
+    // Number of times entity handler is called with incorrect resource interface.\r
+    size_t m_IncorrectInterfaceCount;\r
+};\r
+\r
+#endif // _ELEVATOR_SERVER_H\r
index 6e256a1..d62d2a8 100644 (file)
@@ -128,7 +128,7 @@ extern "C"
 #define CA_OPTION_URI_QUERY 15
 #define CA_OPTION_ACCEPT 17
 #define CA_OPTION_LOCATION_QUERY 20
-        
+
 /**
  * @def UUID_PREFIX
  * @brief uuid prefix in certificate subject field
@@ -452,6 +452,15 @@ typedef enum
 } CAPayloadFormat_t;
 
 /**
+ * Option ID of header option. The values match CoAP option types in pdu.h.
+ */
+typedef enum
+{
+    CA_HEADER_OPTION_ID_LOCATION_PATH = 8,
+    CA_HEADER_OPTION_ID_LOCATION_QUERY = 20
+} CAHeaderOptionId_t;
+
+/**
  * Header options structure to be filled.
  *
  * This structure is used to hold header information.
index 9c24106..a0733d4 100644 (file)
@@ -1713,7 +1713,7 @@ typedef struct
     /** An array of the vendor specific header options the entity handler wishes to use in response.*/
     OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
 
-    /** URI of new resource that entity handler might create.*/
+    /** Resource path of new resource that entity handler might create.*/
     char resourceUri[MAX_URI_LENGTH];
 
     /** Server sets to true for persistent response buffer,false for non-persistent response buffer*/
index d007710..38d65ae 100644 (file)
@@ -579,6 +579,12 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions;
     }
 
+    // Path of new resource is returned in options as location-path.
+    if (ehResponse->resourceUri[0] != '\0')
+    {
+        responseInfo.info.numOptions++;
+    }
+
     if(responseInfo.info.numOptions > 0)
     {
         responseInfo.info.options = (CAHeaderOption_t *)
@@ -618,6 +624,30 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
             memcpy(optionsPointer, ehResponse->sendVendorSpecificHeaderOptions,
                             sizeof(OCHeaderOption) *
                             ehResponse->numSendVendorSpecificHeaderOptions);
+
+            // Advance the optionPointer by the number of vendor options.
+            optionsPointer += ehResponse->numSendVendorSpecificHeaderOptions;
+        }
+
+        // Return new resource as location-path option.
+        // https://tools.ietf.org/html/rfc7252#section-5.8.2.
+        if (ehResponse->resourceUri[0] != '\0')
+        {
+            if ((strlen(ehResponse->resourceUri) + 1) > CA_MAX_HEADER_OPTION_DATA_LENGTH)
+            {
+                OIC_LOG(ERROR, TAG,
+                    "New resource path must be less than CA_MAX_HEADER_OPTION_DATA_LENGTH");
+                OICFree(responseInfo.info.options);
+                return OC_STACK_INVALID_URI;
+            }
+
+            optionsPointer->protocolID = CA_COAP_ID;
+            optionsPointer->optionID = CA_HEADER_OPTION_ID_LOCATION_PATH;
+            OICStrcpy(
+                optionsPointer->optionData,
+                sizeof(optionsPointer->optionData),
+                ehResponse->resourceUri);
+            optionsPointer->optionLength = (uint16_t)strlen(optionsPointer->optionData) + 1;
         }
     }
     else
index 30ada5c..b8d5d40 100644 (file)
@@ -616,6 +616,8 @@ namespace OC
         else
         {
             OCEntityHandlerResponse response;
+            memset(&response, 0, sizeof(response));
+
 //            OCRepPayload* payLoad = pResponse->getPayload();
             HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
 
@@ -661,9 +663,17 @@ namespace OC
 
             if(OC_EH_RESOURCE_CREATED == response.ehResult)
             {
-                pResponse->getNewResourceUri().copy(response.resourceUri,
-                        sizeof (response.resourceUri) - 1);
-                response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
+                // Do not truncate if new resource uri is too long, return failure.
+                if (pResponse->getNewResourceUri().length() > (sizeof(response.resourceUri) - 1))
+                {
+                    return OC_STACK_INVALID_URI;
+                }
+                else
+                {
+                    pResponse->getNewResourceUri().copy(response.resourceUri,
+                            sizeof(response.resourceUri) - 1);
+                    response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
+                }
             }
 
             if(cLock)