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
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)
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#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
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#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
//-----------------------------------------------------------------------------
// 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
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;
/**
} 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);
//-----------------------------------------------------------------------------
--- /dev/null
+//******************************************************************
+//
+// 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";
+}
--- /dev/null
+//******************************************************************
+//
+// 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));
+}
+
+
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)
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
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) {
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 */
--- /dev/null
+//******************************************************************
+//
+// 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;
+}
+
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#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;} }
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
}
}
-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;
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;
{
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)) {
}
}
}
- OC_LOG(INFO, MOD_NAME, PCF("Observer node not found!!"));
+ OC_LOG(INFO, TAG, PCF("Observer node not found!!"));
return NULL;
}
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);
}
#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;
"/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];
}
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)
{
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)
{
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;
+}
+
+
+++ /dev/null
-//******************************************************************
-//
-// 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;
-}
-
-
-
//-----------------------------------------------------------------------------
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocserverrequest.h"
#include "ocresource.h"
#include "occlientcb.h"
#include "ocobserve.h"
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;
}
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
// 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);