Default entity handler outline for collection resources
authorclairiky <chanchala.roy.lairikyengbam@intel.com>
Tue, 19 Aug 2014 02:19:48 +0000 (19:19 -0700)
committerclairiky <chanchala.roy.lairikyengbam@intel.com>
Tue, 19 Aug 2014 02:19:48 +0000 (19:19 -0700)
Added GET for LL and def for default entity handler.

This commit has Sachin's and Chanchala'a changes.
This is GET (LL and B) and PUT (B) working from C apps. New JSON format is
also implemented.

Jesse's review incorporated and tabs removed.

Change-Id: I9d27612d545fdeda1798a5b8c01953a260cfdbef

14 files changed:
csdk/makefile
csdk/stack/include/internal/occollection.h [moved from csdk/stack/include/internal/ocserverrequest.h with 51% similarity]
csdk/stack/include/internal/ocresource.h
csdk/stack/include/internal/ocstackinternal.h
csdk/stack/include/ocstack.h
csdk/stack/samples/SimpleClientServer/occlientcoll.cpp [new file with mode: 0644]
csdk/stack/samples/SimpleClientServer/ocservercoll.cpp [new file with mode: 0644]
csdk/stack/samples/linux/SimpleClientServer/makefile
csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp
csdk/stack/src/occollection.c [new file with mode: 0644]
csdk/stack/src/ocobserve.c
csdk/stack/src/ocresource.c
csdk/stack/src/ocserverrequest.c [deleted file]
csdk/stack/src/ocstack.c

index dc4e25f..e8c403a 100644 (file)
@@ -83,9 +83,9 @@ OCCOAP_SOURCES                += $(OCCOAP_SRC)/occoaphelper.c
 
 OCTBSTACK_SOURCES      := $(OCTBSTACK_SRC)/ocstack.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occlientcb.c
-OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocserverrequest.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocresource.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocobserve.c
+OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occollection.c
 
 SOURCES                        := $(CJSON_SOURCES)
 SOURCES                        += $(OCCOAP_SOURCES)
similarity index 51%
rename from csdk/stack/include/internal/ocserverrequest.h
rename to csdk/stack/include/internal/occollection.h
index 937e289..d1a9e4b 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#ifndef OC_SERVER_REQUEST_H
-#define OC_SERVER_REQUEST_H
+#ifndef OC_COLLECTION_H
+#define OC_COLLECTION_H
 
-#define OC_RSRVD_OC             "oc"
-#define OC_RSRVD_PAYLOAD        "payload"
-#define OC_RSRVD_HREF           "href"
-#define OC_RSRVD_RESOURCE_TYPE  "rt"
-#define OC_RSRVD_INTERFACE      "if"
-#define OC_RSRVD_OBSERVABLE     "obs"
-#define OC_RESOURCE_OBSERVABLE   1
+#include "ocstack.h"
+#include "ocresource.h"
 
-typedef enum {
-    STACK_RES_DISCOVERY_NOFILTER = 0,
-    STACK_RES_DISCOVERY_IF_FILTER,
-    STACK_RES_DISCOVERY_RT_FILTER
-} StackQueryTypes;
+OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
+                                              OCEntityHandlerRequest *entityHandlerRequest);
 
-OCStackResult ProcessResourceDiscoverReq (OCEntityHandlerRequest *request,
-                                 uint8_t filterOn, char *filterValue);
-
-OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query,
-                                uint8_t *filterOn, char **filterValue);
-#endif //OC_SERVER_REQUEST_H
+#endif //OC_COLLECTION_H
index 8aac9df..03d195c 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+#ifndef OC_RESOURCE_H
+#define OC_RESOURCE_H
+
 #include "ocstack.h"
 #include "ocstackinternal.h"
 
+#define OC_RSRVD_OC                     "oc"
+#define OC_RSRVD_PAYLOAD                "payload"
+#define OC_RSRVD_HREF                   "href"
+#define OC_RSRVD_RESOURCE_TYPE          "rt"
+#define OC_RSRVD_INTERFACE              "if"
+#define OC_RSRVD_DEFAULT                "oc.mi.def"
+#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
+#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
+#define OC_RSRVD_OBSERVABLE             "obs"
+
+#define OC_JSON_PREFIX                     "{\"oc\":["
+#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
+#define OC_JSON_SUFFIX                     "]}"
+#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
+#define OC_JSON_SEPARATOR                  ','
+
+#define OC_RESOURCE_OBSERVABLE   1
+
+typedef enum {
+    STACK_RES_DISCOVERY_NOFILTER = 0,
+    STACK_RES_DISCOVERY_IF_FILTER,
+    STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+typedef enum {
+    OC_RESOURCE_VIRTUAL = 0,
+    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_NOT_SPECIFIED
+} ResourceHandling;
+
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * request);
+
 const char * GetVirtualResourceUri( OCVirtualResources resource);
 OCResource *FindResourceByUri(const char* resourceUri);
 uint8_t IsVirtualResource(const char* resourceUri);
 
+OCStackResult DetermineResourceHandling (OCRequest *request,
+                                         ResourceHandling *handling,
+                                         OCResource **resource);
+
+OCStackResult
+BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request);
+
+OCEntityHandlerResult
+BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest);
+
+OCStackResult
+BuildDiscoveryResponse(OCResource *resourcePtr, uint8_t filterOn,
+                        char *filterValue, char * out, uint16_t *remaining);
+
+#endif //OC_RESOURCE_H
index fb6d2d5..2291cc1 100644 (file)
@@ -51,6 +51,14 @@ struct rsrc_t;
 //-----------------------------------------------------------------------------
 // Typedefs
 //-----------------------------------------------------------------------------
+
+// IF here stands for Interface
+typedef enum {
+    STACK_IF_DEFAULT = 0,
+    STACK_IF_LL,
+    STACK_IF_BATCH
+} OCStackIfTypes;
+
 typedef struct resourcetype_t {
     struct resourcetype_t *next; // linked list; for multiple types on resource
 
index 1f2b51a..fe43cb6 100644 (file)
@@ -54,7 +54,7 @@ typedef enum {
     OC_WELL_KNOWN_URI= 0,    // "/oc/core"
     OC_DEVICE_URI,           // "/oc/core/d"
     OC_RESOURCE_TYPES_URI,   // "/oc/core/d/type"
-    OC_MAX_RESOURCES         // Max items in the list
+    OC_MAX_VIRTUAL_RESOURCES         // Max items in the list
 } OCVirtualResources;
 
 /**
@@ -194,10 +194,19 @@ typedef struct {
 } OCCallbackData;
 
 /**
+ * Possible returned values from entity handler
+ */
+typedef enum {
+    OC_EH_OK = 0,
+    OC_EH_ERROR
+} OCEntityHandlerResult;
+
+/**
  * Application server implementations must implement this callback to consume requests OTA.
- * TODO: Need a clear explanation that the Entity handler callback needs to fill in the data inside the OCEntityHandlerRequest and then simply return from the callback.
+ * Entity handler callback needs to fill the resPayload of the entityHandlerRequest.
  */
-typedef OCStackResult (*OCEntityHandler) (OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest);
+typedef OCEntityHandlerResult (*OCEntityHandler)
+(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest);
 
 
 //-----------------------------------------------------------------------------
diff --git a/csdk/stack/samples/SimpleClientServer/occlientcoll.cpp b/csdk/stack/samples/SimpleClientServer/occlientcoll.cpp
new file mode 100644 (file)
index 0000000..7d98020
--- /dev/null
@@ -0,0 +1,334 @@
+//******************************************************************
+//
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <ocstack.h>
+#include <iostream>
+#include <sstream>
+
+const char *getResult(OCStackResult result);
+std::string getIPAddrTBServer(OCClientResponse * clientResponse);
+std::string getPortTBServer(OCClientResponse * clientResponse);
+std::string getQueryStrForGetPut(unsigned  const char * responsePayload);
+
+#define TAG PCF("occlient")
+#define CTX_VAL 0x99
+#ifndef MAX_LENGTH_IPv4_ADDR
+#define MAX_LENGTH_IPv4_ADDR 16
+#endif
+
+#define MAX_TEST_CASES 5
+
+static int UNICAST_DISCOVERY = 0;
+static int TEST_CASE = 0;
+static std::string putPayload = "{\"state\":\"off\",\"power\":\"0\"}";
+
+// The handle for the observe registration
+OCDoHandle gObserveDoHandle;
+// After this crosses a threshold client deregisters for further observations
+int gNumNotifies = 1;
+
+int gQuitFlag = 0;
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+    if (signum == SIGINT) {
+        gQuitFlag = 1;
+    }
+}
+
+// Forward Declaration
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
+int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse);
+int InitObserveRequest(OCClientResponse * clientResponse);
+int InitPutRequest(OCClientResponse * clientResponse);
+int InitGetRequest(OCClientResponse * clientResponse);
+int InitDiscovery();
+
+void PrintUsage()
+{
+    OC_LOG(INFO, TAG, "Usage : occlient <Unicast Discovery> <Test Case>");
+    OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources");
+    OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources and Initiate Get Request");
+    OC_LOG(INFO, TAG, "Test Case 3 : Discover Resources and Initiate Get/Put Requests");
+    OC_LOG(INFO, TAG, "Test Case 4 : Discover Resources and Initiate Observe Requests");
+    OC_LOG(INFO, TAG, "Test Case 5 : Discover Resources and Initiate Get Request for a resource which is unavailable");
+}
+
+OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
+    if(clientResponse) {}
+    if(ctx == (void*)CTX_VAL) {
+        OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
+        OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
+    }
+
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
+    OC_LOG_V(INFO, TAG, "StackResult: %s",
+            getResult(clientResponse->result));
+    if(ctx == (void*)CTX_VAL) {
+        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+        if(clientResponse->sequenceNumber == 0) {
+            OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
+            OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
+        }
+        else {
+            OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumNotifies);
+            OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
+            gNumNotifies++;
+            if (gNumNotifies == 3)
+            {
+                if (OCCancel (gObserveDoHandle) != OC_STACK_OK){
+                    OC_LOG(ERROR, TAG, "Observe cancel error");
+                }
+            }
+        }
+    }
+    InitPutRequest(clientResponse);
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+        OCClientResponse * clientResponse) {
+    uint8_t remoteIpAddr[4];
+    uint16_t remotePortNu;
+
+    OC_LOG(INFO, TAG,
+            "Entering discoveryReqCB (Application Layer CB)");
+    OC_LOG_V(INFO, TAG, "StackResult: %s",
+            getResult(clientResponse->result));
+
+    if (ctx == (void*) CTX_VAL) {
+        OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
+    }
+
+    OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
+            remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+    OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
+    printf(">>>>>>>>>>>>>From Printf %s\n", clientResponse->resJSONPayload);
+#if 0
+    OC_LOG_V(INFO, TAG,
+            "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
+            clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
+            remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
+#endif
+
+    InitGetRequest(clientResponse);
+
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+
+int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+    std::ostringstream getQuery;
+    getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource";
+    cbData.cb = getReqCB;
+    cbData.context = (void*)CTX_VAL;
+    ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+    return ret;
+}
+
+
+int InitObserveRequest(OCClientResponse * clientResponse)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+    std::ostringstream obsReg;
+    obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
+    cbData.cb = getReqCB;
+    cbData.context = (void*)CTX_VAL;
+    OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
+    ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+    else
+    {
+        gObserveDoHandle = handle;
+    }
+    return ret;
+}
+
+
+int InitPutRequest(OCClientResponse * clientResponse)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+    //* Make a PUT query*/
+    std::ostringstream getQuery;
+    getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) <<
+    "/a/sroom?if=oc.mi.b";
+    // getQueryStrForGetPut(clientResponse->resJSONPayload);
+    cbData.cb = putReqCB;
+    cbData.context = (void*)CTX_VAL;
+    OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
+    ret = OCDoResource(&handle, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(), OC_NON_CONFIRMABLE, &cbData);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+    return ret;
+}
+
+
+int InitGetRequest(OCClientResponse * clientResponse)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+
+    uint8_t remoteIpAddr[4];
+    uint16_t remotePortNu;
+
+    OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
+            remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+    OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
+
+    //* Make a GET query*/
+    std::ostringstream getQuery;
+    getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) <<
+    //"/a/sroom?if=oc.mi.def";
+    //"/a/sroom?if=oc.mi.ll";
+    "/a/sroom?if=oc.mi.b";
+
+    std::cout << "Get Query: " << getQuery.str() << std::endl;
+
+    cbData.cb = getReqCB;
+    cbData.context = (void*)CTX_VAL;
+    ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+    return ret;
+}
+
+#define TEST_APP_UNICAST_DISCOVERY_QUERY                  PCF("coap://0.0.0.0:5683/oc/core")
+int InitDiscovery()
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+    /* Start a discovery query*/
+    char szQueryUri[64] = { 0 };
+
+    //strcpy(szQueryUri, "coap://224.0.1.187:5683/oc/core");//?rt=core.sroom");
+    strcpy(szQueryUri, "coap://0.0.0.0:5683/oc/core");
+
+    cbData.cb = discoveryReqCB;
+    cbData.context = (void*)CTX_VAL;
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+    return ret;
+}
+
+int main(int argc, char* argv[]) {
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = USE_RANDOM_PORT;
+    uint8_t ifname[] = "eth0";
+
+    /*Get Ip address on defined interface and initialize coap on it with random port number
+     * this port number will be used as a source port in all coap communications*/
+    if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+                               sizeof(addr)) == ERR_SUCCESS)
+    {
+        OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr);
+        paddr = addr;
+    }
+
+    /* Initialize OCStack*/
+    if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    InitDiscovery();
+
+    // Break from loop with Ctrl+C
+    OC_LOG(INFO, TAG, "Entering occlient main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag) {
+
+        if (OCProcess() != OC_STACK_OK) {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+
+        sleep(3);
+    }
+    OC_LOG(INFO, TAG, "Exiting occlient main loop...");
+
+    if (OCStop() != OC_STACK_OK) {
+        OC_LOG(ERROR, TAG, "OCStack stop error");
+    }
+
+    return 0;
+}
+
+std::string getIPAddrTBServer(OCClientResponse * clientResponse) {
+    if(!clientResponse) return "";
+    if(!clientResponse->addr) return "";
+    uint8_t a, b, c, d = 0;
+    if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return "";
+
+    char ipaddr[16] = {'\0'};
+    snprintf(ipaddr,  sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); // ostringstream not working correctly here, hence snprintf
+    //printf("IP address string of the TB server = %s\n", *out_ipaddr);
+    return std::string (ipaddr);
+}
+
+
+std::string getPortTBServer(OCClientResponse * clientResponse){
+    if(!clientResponse) return "";
+    if(!clientResponse->addr) return "";
+    uint16_t p = 0;
+    if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return "";
+    std::ostringstream ss;
+    ss << p;
+    return ss.str();
+}
+
+std::string getQueryStrForGetPut(unsigned  const char * responsePayload){
+    std::string jsonPayload(reinterpret_cast<char*>(const_cast<unsigned char*>(responsePayload)));
+
+    return "/a/sroom";
+}
diff --git a/csdk/stack/samples/SimpleClientServer/ocservercoll.cpp b/csdk/stack/samples/SimpleClientServer/ocservercoll.cpp
new file mode 100644 (file)
index 0000000..7010e49
--- /dev/null
@@ -0,0 +1,267 @@
+//******************************************************************
+//
+// 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <ocstack.h>
+#include <logger.h>
+
+const char *getResult(OCStackResult result);
+
+#define TAG PCF("ocservercontainer")
+
+int gQuitFlag = 0;
+int gLEDUnderObservation = 0;
+void createResources();
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+static LEDResource LED;
+
+// TODO : hard coded for now, change after Sprint4
+const char rspGetLed[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"color\":\"yellow\"}}";
+// TODO : Needs to be changed to retrieve current status of led and return that in response
+const char rspPutLed[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"color\":\"off\"}}";
+const char rspFailureLed[] = "{\"href\":\"/a/led\",\"rep\":{\"error\":\"LED_OP_FAIL\"}}";
+
+
+// TODO : hard coded for now, change after Sprint4
+const char rspGetFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"on\",\"speed\":10}}";
+// TODO : Needs to be changed to retrieve current status of fan and return that in response
+const char rspPutFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"off\",\"speed\":0}}";
+const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}";
+
+static OCEntityHandlerResult
+HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char* errStr)
+{
+    OCEntityHandlerResult ret = OC_EH_ERROR;
+
+    if (strlen(opStr) < ehRequest->resJSONPayloadLen)
+    {
+        strncpy((char*)ehRequest->resJSONPayload, opStr, ehRequest->resJSONPayloadLen);
+    }
+    else if (strlen(errStr) < ehRequest->resJSONPayloadLen)
+    {
+        strncpy((char*)ehRequest->resJSONPayload, errStr, ehRequest->resJSONPayloadLen);
+        ret = OC_EH_ERROR;
+    }
+    return ret;
+}
+
+static void
+PrintReceivedMsgInfo(OCEntityHandlerFlag flag, const OCEntityHandlerRequest * ehRequest )
+{
+    const char* typeOfMessage;
+
+    switch (flag) {
+        case OC_INIT_FLAG:
+            typeOfMessage = "OC_INIT_FLAG";
+            break;
+        case OC_REQUEST_FLAG:
+            typeOfMessage = "OC_REQUEST_FLAG";
+            break;
+        case OC_OBSERVE_FLAG:
+            typeOfMessage = "OC_OBSERVE_FLAG";
+            break;
+        default:
+            typeOfMessage = "UNKNOWN";
+    }
+
+    OC_LOG_V(INFO, TAG, "Receiving message type: %s, method %s",
+             typeOfMessage,
+             (ehRequest->method == OC_REST_GET) ? "OC_REST_GET" : "OC_REST_PUT" );
+}
+
+OCEntityHandlerResult OCEntityHandlerLedCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+    OCEntityHandlerResult ret = OC_EH_ERROR;
+
+    OC_LOG_V(INFO, TAG, "Callback for Led");
+    PrintReceivedMsgInfo(flag, ehRequest );
+
+    if(ehRequest && flag == OC_REQUEST_FLAG)
+    {
+        if(OC_REST_GET == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspGetLed, rspFailureLed);
+        }
+        if(OC_REST_PUT == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspPutLed, rspFailureLed);
+        }
+    }
+    else if (ehRequest && flag == OC_OBSERVE_FLAG)
+    {
+        gLEDUnderObservation = 1;
+    }
+
+    return ret;
+}
+
+OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+    OCEntityHandlerResult ret = OC_EH_OK;
+
+    OC_LOG_V(INFO, TAG, "Callback for Fan");
+    PrintReceivedMsgInfo(flag, ehRequest );
+
+    if(ehRequest && flag == OC_REQUEST_FLAG)
+    {
+        if(OC_REST_GET == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspGetFan, rspFailureFan);
+        }
+        if(OC_REST_PUT == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspPutFan, rspFailureFan);
+        }
+    }
+    else if (ehRequest && flag == OC_OBSERVE_FLAG)
+    {
+        gLEDUnderObservation = 1;
+    }
+
+    return ret;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+    if (signum == SIGINT) {
+        gQuitFlag = 1;
+    }
+}
+
+void *ChangeLEDRepresentation (void *param)
+{
+    (void)param;
+    OCStackResult result = OC_STACK_ERROR;
+
+    while (1 && !gQuitFlag)
+    {
+        sleep(10);
+        LED.power += 5;
+        if (gLEDUnderObservation)
+        {
+     OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power);
+            result = OCNotifyObservers (LED.handle);
+            if (OC_STACK_NO_OBSERVERS == result)
+            {
+                gLEDUnderObservation = 0;
+            }
+        }
+    }
+    return NULL;
+}
+
+int main() {
+    printf("hello world from main\n");
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = 5683;
+    uint8_t ifname[] = "eth0";
+    pthread_t threadId;
+
+    /*Get Ip address on defined interface and initialize coap on it with random port number
+     * this port number will be used as a source port in all coap communications*/
+    if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+                               sizeof(addr)) == ERR_SUCCESS)
+    {
+        OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+        paddr = addr;
+    }
+
+    if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * Declare and create the example resource: LED
+     */
+    createResources();
+
+    /*
+     * Create a thread for changing the representation of the LED
+     */
+    pthread_create (&threadId, NULL, ChangeLEDRepresentation, (void *)NULL);
+
+    // Break from loop with Ctrl-C
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag) {
+        if (OCProcess() != OC_STACK_OK) {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+        sleep(3);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK) {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+void createResources() {
+    LED.state = false;
+    OCResourceHandle room;
+    OCStackResult res = OCCreateResource(&room,
+            "core.sroom",
+            "oc.mi.ll",
+            "/a/sroom",
+            NULL,
+            OC_DISCOVERABLE);
+    OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
+
+    OCResourceHandle light;
+    res = OCCreateResource(&light,
+            "core.light",
+            "oc.mi.def",
+            "/a/led",
+            OCEntityHandlerLedCb,
+            OC_DISCOVERABLE|OC_OBSERVABLE);
+    OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
+
+    OCResourceHandle fan;
+    res = OCCreateResource(&fan,
+            "core.fan",
+            "oc.mi.def",
+            "/a/fan",
+            OCEntityHandlerFanCb,
+            OC_DISCOVERABLE|OC_OBSERVABLE);
+    OC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res));
+
+    res = OCBindResource(room, light);
+    OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
+
+    res = OCBindResource(room, fan);
+    OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
+}
+
+
index fd17daf..70fb748 100644 (file)
@@ -41,12 +41,14 @@ CC_FLAGS.release    := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-e
 LDLIBS         += -loctbstack -lpthread
 CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS)
 
-SOURCES     := occlient.cpp ocserver.cpp common.cpp
+SOURCES     := occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp
 
 OBJECTS:= $(patsubst %.c, $(OBJ_DIR)/%.o, $(SOURCES))
 
 PROGRAMS       += ocserver
 PROGRAMS       += occlient
+PROGRAMS       += ocservercoll
+PROGRAMS       += occlientcoll
 
 all:   prep_dirs $(OBJECTS) $(PROGRAMS)
 
@@ -60,9 +62,15 @@ $(OBJ_DIR)/%.o: %.cpp
 ocserver: $(OBJ_DIR)/ocserver.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+ocservercoll: $(OBJ_DIR)/ocservercoll.o $(OBJ_DIR)/common.o
+       $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
 occlient: $(OBJ_DIR)/occlient.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+occlientcoll: $(OBJ_DIR)/occlientcoll.o $(OBJ_DIR)/common.o
+       $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
 .PHONY: clean
 
 clean: legacy_clean
index a76b1bb..18a0e50 100644 (file)
@@ -44,11 +44,11 @@ typedef struct LEDRESOURCE{
 static LEDResource LED;
 
 // TODO: hard coded for now, change after Sprint4
-static unsigned char responsePayloadGet[] = "{\"oc\": {\"payload\": {\"state\" : \"on\",\"power\" : \"10\"}}}";
-static unsigned char responsePayloadPut[] = "{\"oc\": {\"payload\": {\"state\" : \"off\",\"power\" : \"0\"}}}";
+const char responsePayloadGet[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+const char responsePayloadPut[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"power\":0}}";
 static uint16_t OC_WELL_KNOWN_PORT = 5683;
 
-OCStackResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) {
+OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) {
     const char* typeOfMessage;
 
     switch (flag) {
@@ -67,23 +67,17 @@ OCStackResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest
     OC_LOG_V(INFO, TAG, "Receiving message type: %s", typeOfMessage);
     if(entityHandlerRequest && flag == OC_REQUEST_FLAG){ //[CL]
     if(OC_REST_GET == entityHandlerRequest->method)
-            //entityHandlerRequest->resJSONPayload = reinterpret_cast<unsigned char*>(const_cast<unsigned char*> (responsePayloadGet.c_str()));
-            entityHandlerRequest->resJSONPayload = responsePayloadGet;
+            strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadGet, entityHandlerRequest->resJSONPayloadLen);
         if(OC_REST_PUT == entityHandlerRequest->method) {
-            //std::cout << std::string(reinterpret_cast<const char*>(entityHandlerRequest->reqJSONPayload)) << std::endl;
             OC_LOG_V(INFO, TAG, "PUT JSON payload from client: %s", entityHandlerRequest->reqJSONPayload);
-            //entityHandlerRequest->resJSONPayload = reinterpret_cast<unsigned char*>(const_cast<char*> (responsePayloadPut.c_str()));
-            entityHandlerRequest->resJSONPayload = responsePayloadPut;
-            //responsePayloadGet = responsePayloadPut; // just a bad hack!
+            strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadPut, entityHandlerRequest->resJSONPayloadLen);
             }
 
     } else if (entityHandlerRequest && flag == OC_OBSERVE_FLAG) {
         gLEDUnderObservation = 1;
     }
 
-    //OC_LOG_V(INFO, TAG, "/nReceiving message type:/n/t %s. /n/nWith request:/n/t %s", typeOfMessage, request);
-
-    return OC_STACK_OK;
+    return OC_EH_OK;
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
diff --git a/csdk/stack/src/occollection.c b/csdk/stack/src/occollection.c
new file mode 100644 (file)
index 0000000..95942b2
--- /dev/null
@@ -0,0 +1,322 @@
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#define _POSIX_C_SOURCE 200112L
+#include <string.h>
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocresource.h"
+#include "logger.h"
+#include "debug.h"
+#include "cJSON.h"
+/// Module Name
+#define TAG PCF("occollection")
+
+#define NUM_PARAM_IN_QUERY  2
+
+static OCStackResult
+ValidateQuery (const unsigned char *query, OCResourceHandle *resource,
+                             OCStackIfTypes *ifParam, char **rtParam)
+{
+    uint8_t numFields = 0, numParam;
+
+    //TODO: Query and URL validation is being done for virtual resource case
+    // using ValidateUrlQuery function. We should be able to merge it with this
+    // function.
+    OC_LOG_V(INFO, TAG, PCF("Entering ValidateQuery"));
+
+    if (!query)
+        return OC_STACK_ERROR;
+
+    if (!(*query))
+    {
+        // Query string is empty
+        OC_LOG_V(INFO, TAG, PCF("Empty query string, use default IF and RT"));
+        *ifParam = STACK_IF_DEFAULT;
+        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+        return OC_STACK_OK;
+    }
+
+    // Break the query string to validate it and determine IF and RT parameters
+    // Validate there are atmost 2 parameters in string and that one is 'if' and other 'rt'
+    char *endStr, *ifPtr = NULL, *rtPtr = NULL;
+    char *token = strtok_r ((char *)query, "&", &endStr);
+
+    // External loop breaks query string into fields using the & separator
+    while (token != NULL)
+    {
+        numFields++;
+        char *endToken;
+        char *innerToken = strtok_r (token, "=", &endToken);
+        numParam = 0;
+        // Internal loop parses the field to extract values (parameters) assigned to each field
+        while (innerToken != NULL)
+        {
+
+            numParam++;
+            if (strcmp (innerToken, OC_RSRVD_INTERFACE) == 0)
+            {
+                // Determine the value of IF parameter
+                innerToken = strtok_r (NULL, "=", &endToken);
+                ifPtr = innerToken;
+            } else if (strcmp (innerToken, OC_RSRVD_RESOURCE_TYPE) == 0) {
+                // Determine the value of RT parameter
+                innerToken = strtok_r (NULL, "=", &endToken);
+                rtPtr = innerToken;
+            } else {
+                innerToken = strtok_r (NULL, "=", &endToken);
+            }
+        }
+        if (numParam != 2)
+        {
+            // Query parameter should be of the form if=<string>. String should not have & or =
+            return OC_STACK_INVALID_QUERY;
+        }
+        token = strtok_r (NULL, "&", &endStr);
+    }
+    if (numFields > NUM_PARAM_IN_QUERY)
+    {
+        // M1 release supports one IF value, one RT value and no other params
+        return OC_STACK_INVALID_QUERY;
+    }
+
+    if (!ifPtr)
+    {
+        // IF not specified in query, use default IF
+        *ifParam = STACK_IF_DEFAULT;
+    }
+    else
+    {
+        if (strcmp (ifPtr, OC_RSRVD_DEFAULT) == 0)
+            *ifParam = STACK_IF_DEFAULT;
+        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_LL) == 0)
+            *ifParam = STACK_IF_LL;
+        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_BATCH) == 0)
+            *ifParam = STACK_IF_BATCH;
+        else
+        {
+            return OC_STACK_ERROR;
+        }
+    }
+
+    if (!rtPtr)
+    {
+        // RT not specified in query. Use the first resource type for the resource as default.
+        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+    }
+    else
+    {
+        *rtParam = rtPtr;
+    }
+    OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s\n", *ifParam, *rtParam);
+
+    // TODO: Validate that the resource supports specified IF param
+    // TODO: Validate that the resource supports specified RT param
+    return OC_STACK_OK;
+}
+static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandlerRequest *ehRequest)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    cJSON *resObj;
+    char *jsonStr;
+    uint16_t jsonLen;
+
+    OC_LOG_V(INFO, TAG, PCF("Entering BuildRootResourceJSON\n"));
+    resObj = cJSON_CreateObject();
+    if (resource)
+    {
+        cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri));
+    }
+    jsonStr = cJSON_PrintUnformatted (resObj);
+    jsonLen = strlen(jsonStr);
+    if (jsonLen < ehRequest->resJSONPayloadLen)
+    {
+        strcpy((char*)ehRequest->resJSONPayload, jsonStr);
+        ehRequest->resJSONPayloadLen -= jsonLen;
+        ehRequest->resJSONPayload += jsonLen;
+        ret = OC_STACK_OK;
+    }
+
+    if (ehRequest->resJSONPayloadLen >= (sizeof(OC_JSON_SEPARATOR) + 1))
+    {
+        *ehRequest->resJSONPayload = OC_JSON_SEPARATOR;
+        ehRequest->resJSONPayload++;
+        ehRequest->resJSONPayloadLen--;
+        ret = OC_STACK_OK;
+    }
+
+    cJSON_Delete (resObj);
+    free (jsonStr);
+
+    return ret;
+}
+
+
+static OCStackResult
+BuildCollectionJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest,
+                       uint8_t filterOn, char *filterValue)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    ret = BuildRootResourceJSON(resource, ehRequest);
+
+    unsigned char* buffer = ehRequest->resJSONPayload;
+    uint16_t remaining = ehRequest->resJSONPayloadLen;
+    if (ret == OC_STACK_OK)
+    {
+        for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        {
+            OCResource* temp = resource->rsrcResources[i];
+            if (temp)
+            {
+                //TODO ("Proper Error handling");
+                ret = BuildDiscoveryResponse(temp, filterOn, filterValue, (char*)buffer, &remaining);
+                if (ret != OC_STACK_OK)
+                {
+                    break;
+                }
+
+                buffer += strlen((char*)buffer);
+                if (resource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
+                {
+                    *buffer = OC_JSON_SEPARATOR;
+                    buffer++;
+                    remaining--;
+                }
+            }
+            else
+            {
+                break;
+            }
+        }
+        ehRequest->resJSONPayload = buffer;
+        ehRequest->resJSONPayloadLen = remaining;
+    }
+
+    return ret;
+}
+
+
+static OCStackResult
+BuildCollectionBatchJSONResponse(OCEntityHandlerFlag flag,
+                OCResource *resource, OCEntityHandlerRequest *ehRequest)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    ret = BuildRootResourceJSON(resource, ehRequest);
+    if (ret == OC_STACK_OK)
+    {
+        for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        {
+            OCResource* temp = resource->rsrcResources[i];
+            if (temp)
+            {
+                //TODO ("Proper Error handling");
+                ret = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
+                unsigned char* buffer = ehRequest->resJSONPayload;
+                ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen - strlen((char*)buffer);
+
+                buffer += strlen((char*)buffer);
+                ehRequest->resJSONPayload = buffer;
+                if ( resource->rsrcResources[i+1] && ehRequest->resJSONPayloadLen > sizeof(OC_JSON_SEPARATOR) )
+                {
+                    *buffer = OC_JSON_SEPARATOR;
+                    buffer++;
+                    ehRequest->resJSONPayload = buffer;
+                    ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen - 1;
+                }
+            }
+            else
+            {
+               break;
+            }
+        }
+    }
+    return ret;
+}
+
+
+OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
+                                              OCEntityHandlerRequest *ehRequest)
+{
+    OCStackResult result;
+    OCStackIfTypes ifQueryParam;
+    char *rtQueryParam;
+
+    OC_LOG(INFO, TAG, "DefaultCollectionEntityHandler\n");
+
+    if (flag != OC_REQUEST_FLAG)
+        return OC_STACK_ERROR;
+
+    result = ValidateQuery ((const unsigned char *)ehRequest->query,
+                            ehRequest->resource, &ifQueryParam, &rtQueryParam);
+
+    if (result != OC_STACK_OK)
+        return result;
+
+    if ((ehRequest->method != OC_REST_GET) &&
+        (ehRequest->method != OC_REST_PUT))
+        return OC_STACK_ERROR;
+
+    if (ehRequest->method == OC_REST_GET)
+    {
+        switch (ifQueryParam)
+        {
+            case STACK_IF_DEFAULT:
+                // Get attributes of collection resource and properties of contined resource
+                // M1 release does not support attributes for collection resource, so the GET
+                // operation is same as the GET on LL interface.
+
+                OC_LOG(INFO, TAG, "STACK_IF_DEFAULT\n");
+                return BuildCollectionJSONResponse( ehRequest->resource,
+                             ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+
+            case STACK_IF_LL:
+                OC_LOG(INFO, TAG, "STACK_IF_LL\n");
+                return BuildCollectionJSONResponse( ehRequest->resource,
+                             ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+
+            case STACK_IF_BATCH:
+                OC_LOG(INFO, TAG, "STACK_IF_BATCH\n");
+                return BuildCollectionBatchJSONResponse(flag, ehRequest->resource, ehRequest);
+
+            default:
+                return OC_STACK_ERROR;
+        }
+    } else if (ehRequest->method == OC_REST_PUT) {
+        switch (ifQueryParam)
+        {
+            case STACK_IF_DEFAULT:
+                // M1 release does not support PUT on default interface
+                return OC_STACK_ERROR;
+
+            case STACK_IF_LL:
+                // LL interface only supports GET
+                return OC_STACK_ERROR;
+
+            case STACK_IF_BATCH:
+                return BuildCollectionBatchJSONResponse(flag, ehRequest->resource, ehRequest);
+
+            default:
+                return OC_STACK_ERROR;
+        }
+    }
+    return result;
+}
+
index 1d54cd6..66d9865 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#include <string.h>
 #include "ocstack.h"
 #include "ocstackinternal.h"
 #include "ocobserve.h"
+#include "ocresource.h"
 #include "occoap.h"
 #include "utlist.h"
 #include "debug.h"
+#include <string.h>
 
-// Module Name
-#define MOD_NAME PCF("ocobserve")
-
-#define TAG  PCF("OCStackObserve")
+#define TAG  PCF("ocbserve")
 
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
 
@@ -61,9 +59,9 @@ OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
         if (OC_STACK_OK == result)
         {
             // Add subscriber to the server observation list
-            result = AddObserver ((const char*)(request->resourceUrl), (const char *)(ehReq->query), 
+            result = AddObserver ((const char*)(request->resourceUrl), (const char *)(ehReq->query),
                                    obs->token->token, obs->token->tokenLength, obs->subAddr, resource);
-        } 
+        }
         return result;
     } else if (strcmp ((char *)obs->option, OC_RESOURCE_OBSERVE_DEREGISTER) == 0) {
         // Deregister observation
@@ -76,16 +74,16 @@ OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
     }
 }
 
-OCStackResult SendObserverNotification (OCResourceHandle handle, OCResource *resPtr) 
+OCStackResult SendObserverNotification (OCResourceHandle handle, OCResource *resPtr)
 {
     uint8_t numObs = 0;
     OCStackResult result;
     ObserveResourceServer *obsRes = serverObsList;
     OCEntityHandlerRequest entityHandlerReq;
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
-    /* 
+    unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 } ;
+    /*
      * TODO: In the current releast all observes are set as non-confirmable since the
-     * entity handler does not have a way to specify the message QoS - add a parameter. 
+     * entity handler does not have a way to specify the message QoS - add a parameter.
      * Sending all observes NON does not confirm with the observe draft (ver14).
      */
     OCQualityOfService qos = OC_NON_CONFIRMABLE;
@@ -108,13 +106,14 @@ OCStackResult SendObserverNotification (OCResourceHandle handle, OCResource *res
             entityHandlerReq.resJSONPayload = bufRes;
             entityHandlerReq.resJSONPayloadLen = MAX_RESPONSE_LENGTH;
             // Even if entity handler for a resource is not successful we continue calling
-            // entity handler for other resources 
-            result = resPtr->entityHandler (OC_REQUEST_FLAG, &entityHandlerReq);
-            if (OC_STACK_OK == result)
+            // entity handler for other resources
+            if ( BuildObsJSONResponse((OCResource *)handle, &entityHandlerReq)
+                    == OC_EH_OK)
             {
+                result = OC_STACK_OK;
                 OCCoAPSendMessage (obsRes->addr, result, qos, obsRes->token,
                                    (const char *)entityHandlerReq.resJSONPayload,
-                                    resPtr->sequenceNum);
+                                   resPtr->sequenceNum);
             }
         }
         obsRes = obsRes->next;
@@ -172,9 +171,9 @@ ObserveResourceServer* GetObserver (const uint8_t *token, const size_t tokenLeng
 {
     ObserveResourceServer *out = NULL;
 
-    if(token) 
+    if(token)
     {
-        LL_FOREACH (serverObsList, out) 
+        LL_FOREACH (serverObsList, out)
         {
             if((out->token->tokenLength == tokenLength) &&
                (memcmp(out->token->token, token, tokenLength) == 0)) {
@@ -182,7 +181,7 @@ ObserveResourceServer* GetObserver (const uint8_t *token, const size_t tokenLeng
             }
         }
     }
-    OC_LOG(INFO, MOD_NAME, PCF("Observer node not found!!"));
+    OC_LOG(INFO, TAG, PCF("Observer node not found!!"));
     return NULL;
 }
 
@@ -203,11 +202,11 @@ OCStackResult DeleteObserver (uint8_t *token, size_t tokenLength)
     return OC_STACK_ERROR;
 }
 
-void DeleteObserverList() 
+void DeleteObserverList()
 {
     ObserveResourceServer *out;
     ObserveResourceServer *tmp;
-    LL_FOREACH_SAFE (serverObsList, out, tmp) 
+    LL_FOREACH_SAFE (serverObsList, out, tmp)
     {
         DeleteObserver (out->token->token, out->token->tokenLength);
     }
index 6e2816e..984f564 100644 (file)
 #include "ocstack.h"
 #include "ocstackinternal.h"
 #include "ocresource.h"
+#include "ocobserve.h"
+#include "occollection.h"
 #include "logger.h"
 #include "debug.h"
+#include "cJSON.h"
 
 /// Module Name
 #define TAG PCF("ocresource")
+#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
+             TAG, PCF(#arg " is NULL")); return (retVal); } }
 
 extern OCResource *headResource;
 
@@ -36,10 +41,176 @@ static const char * VIRTUAL_RSRCS[] = {
        "/oc/core/types/d",
 };
 
+//-----------------------------------------------------------------------------
+// Default resource entity handler function
+//-----------------------------------------------------------------------------
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest * request) {
+    TODO ("Implement me!!!!");
+    // TODO:  remove silence unused param warnings
+    (void) flag;
+    (void) request;
+    return  OC_STACK_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
+}
+
+static OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query,
+                                uint8_t *filterOn, char **filterValue)
+{
+    char *filterParam;
+
+    OC_LOG_V(INFO, TAG, PCF("Entering ValidateUrlQuery"));
+    if (!url)
+        return OC_STACK_INVALID_URI;
+
+    if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0) {
+        *filterOn = STACK_RES_DISCOVERY_NOFILTER;
+        if (query && *query) {
+            filterParam = strtok ((char *)query, "=");
+            *filterValue = strtok (NULL, " ");
+            if (!(*filterValue)) {
+                return OC_STACK_INVALID_QUERY;
+            } else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0) {
+                // Resource discovery with interface filter
+                *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
+            } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) {
+                // Resource discovery with resource type filter
+                *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
+            } else {
+                // Other filter types not supported
+                return OC_STACK_INVALID_QUERY;
+            }
+        }
+    } else {
+        // Other URIs not yet supported
+        return OC_STACK_INVALID_URI;
+    }
+    OC_LOG_V(INFO, TAG, PCF("Exiting ValidateUrlQuery"));
+    return OC_STACK_OK;
+}
+
+
+OCStackResult BuildDiscoveryResponse(OCResource *resourcePtr, uint8_t filterOn,
+                            char *filterValue, char * out, uint16_t *remaining)
+{
+    OCResourceType *resourceTypePtr;
+    OCResourceInterface *interfacePtr;
+    cJSON *resObj, *propObj, *rtArray;
+    char *jsonStr;
+    uint8_t encodeRes = 0;
+    OCStackResult ret = OC_STACK_OK;
+    uint16_t jsonLen;
+
+    OC_LOG_V(INFO, TAG, PCF("Entering BuildDiscoveryResponse"));
+    resObj = cJSON_CreateObject();
+
+    if (resourcePtr)
+    {
+        encodeRes = 0;
+        if (filterOn == STACK_RES_DISCOVERY_RT_FILTER) {
+            resourceTypePtr = resourcePtr->rsrcType;
+            while (resourceTypePtr) {
+                if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0) {
+                    encodeRes = 1;
+                    break;
+                }
+                resourceTypePtr = resourceTypePtr->next;
+            }
+        } else if (filterOn == STACK_RES_DISCOVERY_IF_FILTER) {
+            interfacePtr = resourcePtr->rsrcInterface;
+            while (interfacePtr) {
+                if (strcmp (interfacePtr->name, filterValue) == 0) {
+                    encodeRes = 1;
+                    break;
+                }
+                interfacePtr = interfacePtr->next;
+            }
+        } else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) {
+            encodeRes = 1;
+        } else {
+            //TODO: Unsupported query filter
+            return OC_STACK_INVALID_QUERY;
+        }
+
+        if (encodeRes) {
+            // Add URIs
+            cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
+
+            cJSON_AddItemToObject (resObj, "prop", propObj = cJSON_CreateObject());
+            // Add resource types
+            cJSON_AddItemToObject (propObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
+            resourceTypePtr = resourcePtr->rsrcType;
+            while (resourceTypePtr) {
+                cJSON_AddItemToArray (rtArray,
+                                      cJSON_CreateString(resourceTypePtr->resourcetypename));
+                resourceTypePtr = resourceTypePtr->next;
+            }
+            // Add interface types
+            cJSON_AddItemToObject (propObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
+            interfacePtr = resourcePtr->rsrcInterface;
+            while (interfacePtr) {
+                cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
+                interfacePtr = interfacePtr->next;
+            }
+            // If resource is observable, set observability flag.
+            // Resources that are not observable will not have the flag.
+            if (resourcePtr->resourceProperties & OC_OBSERVABLE) {
+                cJSON_AddItemToObject (propObj, OC_RSRVD_OBSERVABLE,
+                                       cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE));
+            }
+        }
+    }
+    jsonStr = cJSON_PrintUnformatted (resObj);
+    jsonLen = strlen(jsonStr);
+    if (jsonLen < *remaining)
+    {
+        strcpy(out, jsonStr);
+        *remaining = *remaining - jsonLen;
+    }
+    else
+    {
+        ret = OC_STACK_ERROR;
+    }
+    cJSON_Delete (resObj);
+    free (jsonStr);
+
+
+    OC_LOG_V(INFO, TAG, PCF("Exiting BuildDiscoveryResponse"));
+    return ret;
+}
+
+
+OCEntityHandlerResult
+BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest)
+{
+    OCEntityHandlerResult ret = OC_EH_ERROR;
+    unsigned char* saveJSONPayLoadPtr = ehRequest->resJSONPayload;
+
+    if (ehRequest->resJSONPayloadLen > OC_JSON_PREFIX_LEN)
+    {
+        strcpy((char*)ehRequest->resJSONPayload, OC_JSON_PREFIX);
+        ehRequest->resJSONPayloadLen -= OC_JSON_PREFIX_LEN;
+        ehRequest->resJSONPayload += OC_JSON_PREFIX_LEN;
+    }
+
+    ret = resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
+
+    ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
+            strlen((char*)ehRequest->resJSONPayload);
+    ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
+
+    if (ehRequest->resJSONPayloadLen > OC_JSON_SUFFIX_LEN)
+    {
+        strcpy((char*)ehRequest->resJSONPayload, OC_JSON_SUFFIX);
+    }
+    ehRequest->resJSONPayload = saveJSONPayLoadPtr;
+    return ret;
+}
+
+
 TODO ("Does it make sense to make this method as inline")
 const char * GetVirtualResourceUri( OCVirtualResources resource)
 {
-    if (resource < OC_MAX_RESOURCES)
+    if (resource < OC_MAX_VIRTUAL_RESOURCES)
     {
         return VIRTUAL_RSRCS[resource];
     }
@@ -49,7 +220,7 @@ const char * GetVirtualResourceUri( OCVirtualResources resource)
 
 uint8_t IsVirtualResource(const char* resourceUri)
 {
-    for (int i = 0; i < OC_MAX_RESOURCES; i++)
+    for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
     {
         if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
         {
@@ -59,6 +230,17 @@ uint8_t IsVirtualResource(const char* resourceUri)
     return 0;
 }
 
+uint8_t IsCollectionResource (OCResource *resource)
+{
+    for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+    {
+        if (resource->rsrcResources[i])
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
 
 OCResource *FindResourceByUri(const char* resourceUri)
 {
@@ -73,3 +255,243 @@ OCResource *FindResourceByUri(const char* resourceUri)
     return NULL;
 }
 
+
+OCStackResult DetermineResourceHandling (OCRequest *request,
+                                         ResourceHandling *handling,
+                                         OCResource **resource)
+{
+
+    OC_LOG(INFO, TAG, "Entering DetermineResourceHandling");
+
+    // Check if virtual resource
+    if (IsVirtualResource((const char*)request->resourceUrl))
+    {
+        *handling = OC_RESOURCE_VIRTUAL;
+        *resource = headResource;
+        return OC_STACK_OK;
+    }
+    if (NULL == request->resourceUrl || (strlen((const char*)(request->resourceUrl)) == 0))
+    {
+        // Resource URL not specified
+        *handling = OC_RESOURCE_NOT_SPECIFIED;
+        return OC_STACK_OK;
+    }
+    else
+    {
+        OCResource *resourcePtr = NULL;
+        resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
+        *resource = resourcePtr;
+        if (!resourcePtr)
+        {
+            // Resource does not exist
+            return OC_STACK_NO_RESOURCE;
+        }
+
+        if (IsCollectionResource (resourcePtr))
+        {
+            // Collection resource
+            if (resourcePtr->entityHandler != defaultResourceEHandler)
+            {
+                *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
+                return OC_STACK_OK;
+            } else {
+                *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
+                return OC_STACK_OK;
+            }
+        } else {
+            // Resource not a collection
+            if (resourcePtr->entityHandler != defaultResourceEHandler)
+            {
+                *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
+                return OC_STACK_OK;
+            } else {
+                *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
+                return OC_STACK_OK;
+            }
+        }
+    }
+}
+
+
+static OCStackResult
+HandleVirtualResource (OCRequest *request, OCResource* resource)
+{
+    OCStackResult result;
+    char *filterValue = NULL;
+    uint8_t filterOn;
+    uint16_t remaining;
+    unsigned char *buffer;
+
+    OC_LOG(INFO, TAG, "Entering HandleVirtualResource");
+
+    result = ValidateUrlQuery (request->resourceUrl,
+            request->entityHandlerRequest->query, &filterOn,
+            &filterValue);
+
+    if (result == OC_STACK_OK)
+    {
+        remaining = request->entityHandlerRequest->resJSONPayloadLen;
+        buffer = request->entityHandlerRequest->resJSONPayload;
+        while( resource)
+        {
+            result = BuildDiscoveryResponse(resource, filterOn, filterValue,
+                                            (char*)buffer, &remaining);
+            if (result != OC_STACK_OK)
+            {
+                break;
+            }
+            buffer += strlen((char*)buffer);
+            if ( resource->next && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1) )
+            {
+                *buffer = OC_JSON_SEPARATOR;
+                buffer++;
+                remaining--;
+            }
+            resource = resource->next;
+        }
+    }
+
+    if (result == OC_STACK_OK)
+    {
+        request->entityHandlerRequest->resJSONPayloadLen = remaining;
+        request->entityHandlerRequest->resJSONPayload = buffer;
+    }
+
+    return result;
+}
+
+
+static OCStackResult
+HandleResourceWithEntityHandler (OCRequest *request,
+                                 OCResource *resource,
+                                 uint8_t collectionResource)
+{
+    OCStackResult result = OC_STACK_OK;
+    OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+
+    OC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
+
+    ehRequest->resource = (OCResourceHandle)resource;
+    // status code from entity handler is ignored unless observe call
+    resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
+
+    if (request->observe != NULL)
+    {
+        if (!collectionResource)
+            result = ProcessObserveRequest (resource, request);
+        else
+            // Observation on collection resources not supported in M1
+            result = OC_STACK_ERROR;
+    }
+
+    if (result == OC_STACK_OK)
+    {
+        ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
+            strlen((char*)ehRequest->resJSONPayload);
+        ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
+    }
+
+    return result;
+}
+
+
+static OCStackResult
+HandleCollectionResourceDefaultEntityHandler (OCRequest *request,
+                                              OCResource *resource)
+{
+    request->entityHandlerRequest->resource = (OCResourceHandle)resource;
+    return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, request->entityHandlerRequest));
+}
+
+
+OCStackResult
+BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request)
+{
+    OCStackResult ret = OC_STACK_OK;
+
+    // save the response payload pointer, this pointer will be moved as
+    // different entity handlers will be called
+    unsigned char* saveJSONPayLoadPtr = request->entityHandlerRequest->resJSONPayload;
+    unsigned char* buffer = saveJSONPayLoadPtr;
+    uint16_t remaining = request->entityHandlerRequest->resJSONPayloadLen;
+
+    // add suffix in payload
+    if (remaining > OC_JSON_PREFIX_LEN)
+    {
+        strcpy((char*)buffer, OC_JSON_PREFIX);
+        remaining -= OC_JSON_PREFIX_LEN;
+        buffer += OC_JSON_PREFIX_LEN;
+    }
+
+    // move the entity handler payload pointer and update
+    // remaining valid bytes to fill data
+    request->entityHandlerRequest->resJSONPayload = buffer;
+    request->entityHandlerRequest->resJSONPayloadLen = remaining;
+
+    switch (resHandling)
+    {
+        case OC_RESOURCE_VIRTUAL:
+            {
+                ret = HandleVirtualResource (request, resource);
+                break;
+            }
+
+        case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
+            {
+                OC_LOG_V(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
+                return OC_STACK_ERROR;
+            }
+
+        case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
+            {
+                ret = HandleResourceWithEntityHandler (request, resource, 0);
+                break;
+            }
+        case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
+            {
+                ret = HandleResourceWithEntityHandler (request, resource, 1);
+                break;
+            }
+
+        case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
+            {
+                ret = HandleCollectionResourceDefaultEntityHandler (request,
+                        resource);
+                break;
+            }
+
+        case OC_RESOURCE_NOT_SPECIFIED:
+            // TODO: This is a special case. In M1 this occurs only for observation
+            // delete since OCCancel (on the client) only takes OCDoHandle param.
+            // TODO: Remove comments below before release - only for code review
+            // OPEN: We had decided to revisit the OCDoHandle logic for this sprint. If it
+            // changes and URI is passed this special case will not be needed.
+            OC_LOG_V(INFO, TAG, PCF("OC_RESOURCE_NOT_SPECIFIED"));
+            if (request->observe != NULL)
+            {
+                ret = ProcessObserveRequest (resource, request);
+            }
+            break;
+
+        default:
+            {
+                OC_LOG_V(INFO, TAG, PCF("Invalid Resource Determination"));
+                return OC_STACK_ERROR;
+            }
+    }
+
+    remaining = request->entityHandlerRequest->resJSONPayloadLen;
+
+    if (remaining > OC_JSON_SUFFIX_LEN)
+    {
+        strcpy((char*)request->entityHandlerRequest->resJSONPayload, OC_JSON_SUFFIX);
+    }
+
+    // update payload pointer with it's original location and original length
+    request->entityHandlerRequest->resJSONPayload = saveJSONPayLoadPtr;
+    request->entityHandlerRequest->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
+
+    return ret;
+}
+
+
diff --git a/csdk/stack/src/ocserverrequest.c b/csdk/stack/src/ocserverrequest.c
deleted file mode 100644 (file)
index 6c3c4d1..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-//******************************************************************
-//
-// 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 <string.h>
-#include "ocstack.h"
-#include "ocresource.h"
-#include "ocstackinternal.h"
-#include "ocserverrequest.h"
-#include "debug.h"
-#include "cJSON.h"
-
-// Module Name
-#define MOD_NAME PCF("ocserverrequest")
-
-#define TAG  PCF("OCStackServerRequest")
-
-#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
-             TAG, PCF(#arg " is NULL")); return (retVal); } }
-
-extern OCResource *headResource;
-
-OCStackResult ProcessResourceDiscoverReq (OCEntityHandlerRequest *request,
-                                 uint8_t filterOn, char *filterValue)
-{
-    OCResource *resourcePtr = headResource;
-    OCResourceType *resourceTypePtr;
-    OCResourceInterface *interfacePtr;
-    cJSON *ocObj, *pLoadObj, *resArray, *resObj, *rtArray;
-    char *jsonStr;
-    uint8_t encodeRes = 0;
-    OCStackResult ret = OC_STACK_OK;
-
-    OC_LOG(INFO, TAG, PCF("Entering ProcessResourceDiscoverReq"));
-    ocObj = cJSON_CreateObject();
-    cJSON_AddItemToObject (ocObj, OC_RSRVD_OC, pLoadObj = cJSON_CreateObject());
-    cJSON_AddItemToObject (pLoadObj, OC_RSRVD_PAYLOAD, resArray = cJSON_CreateArray());
-
-    while (resourcePtr)
-    {
-        encodeRes = 0;
-        if (filterOn == STACK_RES_DISCOVERY_RT_FILTER) {
-            resourceTypePtr = resourcePtr->rsrcType;
-            while (resourceTypePtr) {
-                if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0) {
-                    encodeRes = 1;
-                    break;
-                }
-                resourceTypePtr = resourceTypePtr->next;
-            }
-        } else if (filterOn == STACK_RES_DISCOVERY_IF_FILTER) {
-            interfacePtr = resourcePtr->rsrcInterface;
-            while (interfacePtr) {
-                if (strcmp (interfacePtr->name, filterValue) == 0) {
-                    encodeRes = 1;
-                    break;
-                }
-                interfacePtr = interfacePtr->next;
-            }
-        } else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) {
-            encodeRes = 1;
-        } else {
-            //TODO: Unsupported query filter
-            return OC_STACK_INVALID_QUERY;
-        }
-
-        if (encodeRes) {
-            cJSON_AddItemToArray (resArray, resObj = cJSON_CreateObject());
-            // Add URIs
-            cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
-            // Add resource types
-            cJSON_AddItemToObject (resObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
-            resourceTypePtr = resourcePtr->rsrcType;
-            while (resourceTypePtr) {
-                cJSON_AddItemToArray (rtArray,
-                                      cJSON_CreateString(resourceTypePtr->resourcetypename));
-                resourceTypePtr = resourceTypePtr->next;
-            }
-            // Add interface types
-            cJSON_AddItemToObject (resObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
-            interfacePtr = resourcePtr->rsrcInterface;
-            while (interfacePtr) {
-                cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
-                interfacePtr = interfacePtr->next;
-            }
-            // If resource is observable, set observability flag.
-            // Resources that are not observable will not have the flag.
-            if (resourcePtr->resourceProperties & OC_OBSERVABLE) {
-                cJSON_AddItemToObject (resObj, OC_RSRVD_OBSERVABLE,
-                                       cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE));
-            }
-        }
-        resourcePtr = resourcePtr->next;
-    }
-    jsonStr = cJSON_PrintUnformatted (ocObj);
-    if (strlen(jsonStr) < request->resJSONPayloadLen)
-    {
-        strncpy((char *)request->resJSONPayload, jsonStr, request->resJSONPayloadLen);
-    }
-    else
-    {
-        ret = OC_STACK_ERROR;
-    }
-    cJSON_Delete (ocObj);
-    free (jsonStr);
-
-    OC_LOG(INFO, TAG, PCF("Exiting ProcessResourceDiscoverReq"));
-    return ret;
-}
-
-OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query,
-                                uint8_t *filterOn, char **filterValue)
-{
-    char *filterParam;
-
-    OC_LOG(INFO, TAG, PCF("Entering ValidateUrlQuery"));
-    if (!url)
-        return OC_STACK_INVALID_URI;
-
-    if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0) {
-        *filterOn = STACK_RES_DISCOVERY_NOFILTER;
-        if (query && *query) {
-            filterParam = strtok ((char *)query, "=");
-            *filterValue = strtok (NULL, " ");
-            if (!(*filterValue)) {
-                return OC_STACK_INVALID_QUERY;
-            } else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0) {
-                // Resource discovery with interface filter
-                *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
-            } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) {
-                // Resource discovery with resource type filter
-                *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
-            } else {
-                // Other filter types not supported
-                return OC_STACK_INVALID_QUERY;
-            }
-        }
-    } else {
-        // Other URIs not yet supported
-        return OC_STACK_INVALID_URI;
-    }
-    OC_LOG(INFO, TAG, PCF("Exiting ValidateUrlQuery"));
-    return OC_STACK_OK;
-}
-
-
-
index 8137eb5..5cd4b09 100644 (file)
@@ -24,7 +24,6 @@
 //-----------------------------------------------------------------------------
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocserverrequest.h"
 #include "ocresource.h"
 #include "occlientcb.h"
 #include "ocobserve.h"
@@ -60,45 +59,19 @@ OCResource *headResource = NULL;
 OCStackResult HandleStackRequests(OCRequest * request) {
     OC_LOG(INFO, TAG, PCF("Entering OCStackHandleReceiveRequest (OCStack Layer)"));
 
-    char *filterValue;
-    uint8_t filterOn;
-    OCStackResult result;
+    OCStackResult result = OC_STACK_ERROR;
+    ResourceHandling resHandling;
+    OCResource *resource;
 
     VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
 
-    if (IsVirtualResource((const char*)request->resourceUrl))
-    {
-        result = ValidateUrlQuery(request->resourceUrl,
-                                  request->entityHandlerRequest->query, &filterOn,
-                                  &filterValue);
+    result = DetermineResourceHandling (request, &resHandling, &resource);
 
-        if (result == OC_STACK_OK)
-        {
-            result = ProcessResourceDiscoverReq(request->entityHandlerRequest,
-                                                filterOn,
-                                                filterValue);
-        }
-    }
-    else
+    if (result == OC_STACK_OK)
     {
-        OCResource* resource = FindResourceByUri((const char*)request->resourceUrl);
-        if (resource)
-        {
-            request->entityHandlerRequest->resource = (OCResourceHandle)resource;
-            result = resource->entityHandler(OC_REQUEST_FLAG, request->entityHandlerRequest);
-        }
-        else
-        {
-            OC_LOG(INFO, TAG, PCF("Resource Not found"));
-            result = OC_STACK_NO_RESOURCE;
-        }
-        if (request->observe != NULL)
-        {
-            result = ProcessObserveRequest (resource, request);
-        }
+        result = BuildJSONResponse(resHandling, resource, request);
     }
-
     return result;
 }
 
@@ -174,17 +147,6 @@ static void deleteResourceElements(OCResource *resource);
 static int deleteResource(OCResource *resource);
 static void deleteAllResources();
 
-//-----------------------------------------------------------------------------
-// Default resource entity handler function
-//-----------------------------------------------------------------------------
-OCStackResult defaultResourceEHandler(OCEntityHandlerFlag flag,
-        OCEntityHandlerRequest * request) {
-    TODO ("Implement me!!!!");
-    // TODO:  remove silence unused param warnings
-    (void) flag;
-    (void) request;
-    return OC_STACK_OK;
-}
 
 //-----------------------------------------------------------------------------
 // Public APIs
@@ -1028,7 +990,7 @@ OCStackResult OCBindResourceHandler(OCResourceHandle handle,
 
     // Validate parameters
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
+    //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
 
     // Use the handle to find the resource in the resource linked list
     resource = findResource((OCResource *)handle);