Implement slow response feature.
authorDoug Hudson <douglas.hudson@intel.com>
Thu, 4 Dec 2014 21:37:22 +0000 (16:37 -0500)
committerDoug Hudson <douglas.hudson@intel.com>
Thu, 4 Dec 2014 21:37:22 +0000 (16:37 -0500)
This feature allows a resource entity handler to provide a "slow response"
to a client request.  That is, if a request is received but the server cannot
respond immediately (e.g. response data is not available), the server can
instead respond at a later time.  The same API is used for both immediate
and slow responses.

Updated collection's batch interface to aggregate responses of local resources
contained in the collection.  Note that the aggregate response only applies
to local resources, not remote resources.

This feature introduces a new C API, OCDoResponse and a new C++ API,
OCPlatform::sendResponse.  The C++ modifications also include a change to
the the signature of the applications entity handler.

Change-Id: Ic33ab0c7ff52481bed86e9a77319baa3813dd6cd
Signed-off-by: Doug Hudson <douglas.hudson@intel.com>
Signed-off-by: Yamin Al-Mousa <yamin.s.al-mousa@intel.com>
Signed-off-by: Sashi Penta <sashi.kumar.penta@intel.com>
Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
Signed-off-by: Sudarshan Prasad <sudarshan.prasad@intel.com>
Signed-off-by: Erich Keane <erich.keane@intel.com>
74 files changed:
resource/buildScript.mk
resource/csdk/SConscript
resource/csdk/libcoap-4.1.1/block.h
resource/csdk/libcoap-4.1.1/net.c
resource/csdk/libcoap-4.1.1/net.h
resource/csdk/libcoap-4.1.1/pdu.h
resource/csdk/libcoap-4.1.1/sec/netdtls.c
resource/csdk/makefile
resource/csdk/occoap/include/occoap.h
resource/csdk/occoap/include/occoaphelper.h
resource/csdk/occoap/src/occoap.c
resource/csdk/occoap/src/occoaphelper.c
resource/csdk/stack/include/internal/occollection.h
resource/csdk/stack/include/internal/ocobserve.h
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocserverrequest.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/common.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/makefile
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h
resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.h
resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/common.cpp
resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/secure/ocserverbasicops.h
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocobserve.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c [new file with mode: 0644]
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/arduino/makefile
resource/csdk/stack/test/makefile
resource/csdk/stack/test/stacktests.cpp
resource/examples/fridgeserver.cpp
resource/examples/garageserver.cpp
resource/examples/ocicuc/light_resource.cpp
resource/examples/ocicuc/light_resource.hpp
resource/examples/presenceclient.cpp
resource/examples/presenceserver.cpp
resource/examples/roomserver.cpp
resource/examples/simpleclient.cpp
resource/examples/simpleclientHQ.cpp
resource/examples/simpleclientserver.cpp
resource/examples/simpleserver.cpp
resource/examples/simpleserverHQ.cpp
resource/examples/threadingsample.cpp
resource/include/IServerWrapper.h
resource/include/InProcServerWrapper.h
resource/include/OCApi.h
resource/include/OCPlatform.h
resource/include/OCPlatform_impl.h
resource/include/OCResourceRequest.h
resource/include/OCResourceResponse.h
resource/include/OutOfProcServerWrapper.h
resource/include/StringConstants.h
resource/src/InProcServerWrapper.cpp
resource/src/OCException.cpp
resource/src/OCPlatform.cpp
resource/src/OCPlatform_impl.cpp
resource/src/OCUtilities.cpp
resource/unittests/tests.cpp

index bb53325..64afad1 100644 (file)
@@ -167,10 +167,12 @@ linux_tb_examples_all: linux_tb_stack_release linux_tb_examples_debug
 linux_tb_examples_release: linux_tb_stack_release
        @echo "=====BUILD TB SAMPLE APPS FOR LINUX - RELEASE - <oic-resource>/csdk/stack/samples/linux/SimpleClientServer/release/====="
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=release"
+       $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=release"
 
 linux_tb_examples_debug: linux_tb_stack_debug
        @echo "=====BUILD TB SAMPLE APPS FOR LINUX - DEBUG - <oic-resource>/csdk/stack/samples/linux/SimpleClientServer/debug/====="
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=debug"
+       $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=debug"
 
 ###############################################################################
 ####      UB Stack (& TB Stack as prerequisite) - Linux Only               ####
@@ -483,6 +485,7 @@ linux_clean:
        -rm -rf -C csdk/linux
        $(MAKE) -C csdk/stack/test/linux "clean"
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean"
+       $(MAKE) -C csdk/stack/samples/linux/secure "clean"
        $(MAKE) -C . "clean"
 
 ###############################################################################
@@ -513,6 +516,7 @@ clean:
        $(MAKE) -C csdk "clean" "deepclean"
        $(MAKE) -C csdk/stack/test/linux "clean"
        $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean"
+       $(MAKE) -C csdk/stack/samples/linux/secure "clean"
        $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "clean"
        $(MAKE) -C . "clean"
        $(MAKE) -C unittests/ "clean"
index f8cc634..d47f3e0 100644 (file)
@@ -53,6 +53,7 @@ liboctbstack_src = [
        OCTBSTACK_SRC + 'occlientcb.c',
        OCTBSTACK_SRC + 'ocresource.c',
        OCTBSTACK_SRC + 'ocobserve.c',
+       OCTBSTACK_SRC + 'ocserverrequest.c',
        OCTBSTACK_SRC + 'occollection.c',
        ]
 
index 283ba69..ee2d5a9 100644 (file)
@@ -3,12 +3,16 @@
  * Copyright (C) 2010--2012,2014 Olaf Bergmann <bergmann@tzi.org>
  *
  * This file is part of the CoAP library libcoap. Please see
- * README for terms of use. 
+ * README for terms of use.
  */
 
 #ifndef _COAP_BLOCK_H_
 #define _COAP_BLOCK_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "option.h"
 #include "encode.h"
 #include "pdu.h"
 #endif
 
 /**
- * Structure of Block options. 
+ * Structure of Block options.
  */
 typedef struct {
-  unsigned int num:20;         /**< block number */
-  unsigned int m:1;            /**< 1 if more blocks follow, 0 otherwise */
-  unsigned int szx:3;          /**< block size */
+  unsigned int num:20;  /**< block number */
+  unsigned int m:1;     /**< 1 if more blocks follow, 0 otherwise */
+  unsigned int szx:3;   /**< block size */
 } coap_block_t;
 
 /**
- * Returns the value of the least significant byte of a Block option @p opt. 
+ * Returns the value of the least significant byte of a Block option @p opt.
  * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST
  * returns @c NULL.
  */
@@ -87,7 +91,7 @@ coap_opt_block_set_m(coap_opt_t *block_opt, int m) {
  * value @c 1. Otherwise, @c 0 is returned.
  *
  * @param pdu   The pdu to search for option @p type.
- * @param type  The option to search for (must be COAP_OPTION_BLOCK1 or 
+ * @param type  The option to search for (must be COAP_OPTION_BLOCK1 or
  *              COAP_OPTION_BLOCK2)
  * @param block The block structure to initilize.
  * @return @c 1 on success, @c 0 otherwise.
@@ -101,9 +105,9 @@ int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block);
  * space is required. The actual length of the resource is specified
  * in @p data_length.
  *
- * This function may change *block to reflect the values written to 
+ * This function may change *block to reflect the values written to
  * @p pdu. As the function takes into consideration the remaining space
- * @p pdu, no more options should be added after coap_write_block_opt() 
+ * @p pdu, no more options should be added after coap_write_block_opt()
  * has returned.
  *
  * @param block      The block structure to use. On return, this object
@@ -117,9 +121,9 @@ int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block);
  * @return @c 1 on success, or a negative value on error.
  */
 int coap_write_block_opt(coap_block_t *block, unsigned short type,
-                        coap_pdu_t *pdu, size_t data_length);
+                         coap_pdu_t *pdu, size_t data_length);
 
-/** 
+/**
  * Adds the @p block_num block of size 1 << (@p block_szx + 4) from
  * source @p data to @p pdu.
  *
@@ -131,7 +135,11 @@ int coap_write_block_opt(coap_block_t *block, unsigned short type,
  * @return @c 1 on success, @c 0 otherwise.
  */
 int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data,
-                  unsigned int block_num, unsigned char block_szx);
+                   unsigned int block_num, unsigned char block_szx);
 /**@}*/
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _COAP_BLOCK_H_ */
index eb1f1eb..4fce8f9 100644 (file)
@@ -716,7 +716,7 @@ coap_tid_t coap_send(coap_context_t *context,
     else
     {
         node->timeout = MAX_MULTICAST_DELAY_SEC * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8);
-        node->delayedResponse = 1;
+        node->delayedResNeeded = 1;
     }
 
     if (flag & SEND_SECURE_PORT) {
@@ -857,7 +857,7 @@ int coap_read(coap_context_t *ctx, int sockfd) {
 
   coap_address_t src, dst;
   coap_queue_t *node;
-  unsigned char delayRes = 0;
+  unsigned char delayedResNeeded = 0;
 
 #ifdef WITH_CONTIKI
     pbuf = uip_appdata;
@@ -876,7 +876,7 @@ int coap_read(coap_context_t *ctx, int sockfd) {
 
   // Set the delayed response flag for responding to multicast requests
   if (sockfd == ctx->sockfd_wellknown && bytes_read > 0) {
-      delayRes = 1;
+      delayedResNeeded = 1;
   }
 #if defined(WITH_DTLS)
   // Perform the DTLS decryption if packet is coming on secure port
@@ -949,7 +949,7 @@ int coap_read(coap_context_t *ctx, int sockfd) {
     }
 
     //set the delayed response flag
-    node->delayedResponse = delayRes;
+    node->delayedResNeeded = delayedResNeeded;
 
     //set the secure flag on the received packet
 #if defined(WITH_DTLS)
@@ -1612,7 +1612,6 @@ handle_locally(coap_context_t *context __attribute__ ((unused)),
 
         if (ctx->timer_configured)
         {
-            printf("clearing\n");
             sys_untimeout(coap_retransmittimer_execute, (void*)ctx);
             ctx->timer_configured = 0;
         }
@@ -1636,8 +1635,6 @@ handle_locally(coap_context_t *context __attribute__ ((unused)),
                  * */
                 delay = 0;
             }
-
-            printf("scheduling for %d ticks\n", delay);
             sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx);
             ctx->timer_configured = 1;
         }
index 81f8031..cec3f0a 100644 (file)
@@ -51,12 +51,16 @@ extern "C" {
 #include "coap_time.h"
 
 typedef enum {
-    SEND_NOW            = (1 << 0), /*Flag used when sending non-confirmable, ACK and RESET coap pdus*/
-    SEND_NOW_CON        = (1 << 1), /*Flag used when sending confirmable coap pdu*/
-    SEND_DELAYED        = (1 << 2), /*Flag used to delay the transmission of coap pdu*/
-    SEND_RETX           = (1 << 3), /*Flag used to retransmit a confirmable pdu*/
-    SEND_SECURE_PORT    = (1 << 4)  /*Flag used to indicate that PDU needs to
-                                      be transmitted on secure port */
+    SEND_NOW            = (1 << 0), // Flag used when sending non-confirmable,
+                                    // ACK and RESET coap pdus, Automatically set in SendCoAPPdu
+                                    // Do not use in upper stack APIs
+    SEND_NOW_CON        = (1 << 1), // Flag used when sending confirmable coap pdu,
+                                    // Automatically set in SendCoAPPdu,
+                                    // Do not use in upper stack APIs
+    SEND_DELAYED        = (1 << 2), // Flag used to delay the transmission of coap pdu
+    SEND_RETX           = (1 << 3), // Flag used to retransmit a confirmable pdu
+    SEND_SECURE_PORT    = (1 << 4)  // Flag used to indicate that PDU needs to
+                                    // be transmitted on secure port
 } coap_send_flags_t;
 
 struct coap_queue_t;
@@ -74,7 +78,7 @@ typedef struct coap_queue_t {
 
   coap_pdu_t *pdu;      /**< the CoAP PDU to send */
 
-  unsigned char delayedResponse;  /**< delayed response flag */
+  unsigned char delayedResNeeded;  /**< delayed response flag */
   unsigned char secure;      /**< rx/tx will use secure channel (DTLS) */
 } coap_queue_t;
 
index 7428e63..8b76776 100644 (file)
@@ -80,6 +80,7 @@ extern "C" {
 #define COAP_OPTION_LOCATION_QUERY 20 /* E, String,   0-255 B, (none) */
 #define COAP_OPTION_PROXY_URI    35 /* C, String, 1-1034 B, (none) */
 #define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
+#define COAP_OPTION_SIZE2        28 /* E, uint, 0-4 B, (none) */
 #define COAP_OPTION_SIZE1        60 /* E, uint, 0-4 B, (none) */
 
 /* option types from draft-ietf-coap-observe-09 */
@@ -343,7 +344,7 @@ int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data);
  * This function returns the number of bytes written or @c 0 on error.
  */
 size_t coap_add_option(coap_pdu_t *pdu, unsigned short type,
-                      unsigned int len, const unsigned char *data);
+                       unsigned int len, const unsigned char *data);
 
 /**
  * Adds option of given type to pdu that is passed as first
@@ -353,7 +354,7 @@ size_t coap_add_option(coap_pdu_t *pdu, unsigned short type,
  * written before the PDU can be sent, or @c NULL on error.
  */
 unsigned char *coap_add_option_later(coap_pdu_t *pdu, unsigned short type,
-                     unsigned int len);
+                                     unsigned int len);
 
 /**
  * Adds given data to the pdu that is passed as first parameter. Note
index b15ed99..a097f4c 100644 (file)
@@ -123,7 +123,7 @@ static int coap_cache_pdu(coap_context_t *ctx,
 
     if (existing_node) {
         node->timeout = existing_node->timeout;
-        node->delayedResponse = existing_node->delayedResponse;
+        node->delayedResNeeded = existing_node->delayedResNeeded;
     }
 
     // Add the node in cachedqueue list
@@ -163,7 +163,7 @@ static void save_cached_con_pdu(coap_context_t *ctx,
         node->t = (now - ctx->sendqueue_basetime) + node->timeout;
     }
 
-    node->delayedResponse = 0;
+    node->delayedResNeeded = 0;
     node->next = NULL;
     coap_insert_node(&ctx->sendqueue, node);
 }
index d05756a..3fb7b52 100644 (file)
@@ -133,6 +133,7 @@ OCTBSTACK_SOURCES   := $(OCTBSTACK_SRC)/ocstack.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occlientcb.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocresource.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocobserve.c
+OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocserverrequest.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occollection.c
 
 SOURCES                        := $(CJSON_SOURCES)
index 512ef74..31ab9f0 100644 (file)
@@ -70,6 +70,16 @@ OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode);
 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
         const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions);
 
+/**
+ * Send a response to a request.
+ *
+ * @param response - pointer to OCServerProtocolResponse that contains all request and
+ *                   response info necessary to send the response to the client
+ * @return
+ *     OC_STACK_OK               - No errors; Success
+ *     OC_STACK_ERROR            - Error sending response
+ */
+OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response);
 
 /**
  * Stop the CoAP client or server processing
@@ -94,15 +104,6 @@ OCStackResult OCProcessCoAP();
 void OCGenerateCoAPToken(OCCoAPToken * token);
 
 /**
- * Initiate sending of CoAP messages. Example: server uses it to send observe messages
- *
- * @return 0 - success, else - TBD error
- */
-OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
-        OCQualityOfService qos, OCCoAPToken * token,
-        unsigned char *payload, OCResource *resPtr, uint32_t maxAge);
-
-/**
  * Retrieve the end-point info where resource is being hosted.
  * Currently, this method only provides the IP port with which the socket
  * is bound. This internal method may be extended in future to retrieve
index b0999de..7be3e30 100644 (file)
@@ -68,31 +68,19 @@ coap_list_t *
 CreateNewOptionNode(unsigned short key, unsigned int length,
         unsigned char *data);
 
-// Internal function to create OCRequest struct at the server from a received coap pdu
-OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
-        unsigned char * uriBuf, OCObserveReq * observeReq,
-        OCEntityHandlerRequest * entityHandlerRequest,
-        uint8_t secure);
-
-// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
-        OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
-        unsigned char * queryBuf, unsigned char *newResUriBuf);
-
 // Internal function to retrieve Uri and Query from received coap pdu
 OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
-        unsigned char * queryBuf, uint8_t * * observeOptionLoc,
-        uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
-        OCHeaderOption * rcvVendorSpecificHeaderOptions,
-        uint8_t * numRcvVendorSpecificHeaderOptions);
+        unsigned char * queryBuf, uint32_t * observeOption,
+        uint32_t * maxAgeOption,
+        uint8_t * numVendorSpecificHeaderOptions,
+        OCHeaderOption * vendorSpecificHeaderOptions,
+        coap_block_t * block1, coap_block_t * block2,
+        uint16_t * size1, uint16_t * size2,
+        unsigned char * payload);
 
 // Internal function to retrieve a Token from received coap pdu
 void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken);
 
-// Internal function to create OCObserveReq at the server
-OCStackResult FormOCObserveReq(OCObserveReq ** observeReqLoc, uint32_t obsOption,
-            OCDevAddr * remote, OCCoAPToken * rcvdToken);
-
 // Internal function to create OCResponse struct at the client from a received coap pdu
 OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
         uint8_t TTL, OCClientResponse * clientResponse);
@@ -107,7 +95,7 @@ void HandleSendQueue(coap_context_t * gCoAPCtx);
 
 // Internal function to form the standard response option list
 OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
-        uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
+        uint32_t * addMaxAge, uint32_t * observeOptionPtr,
         uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
         uint8_t queryLength, unsigned char * query, OCHeaderOption * vendorSpecificHeaderOptions,
         uint8_t numVendorSpecificHeaderOptions);
index ee8cb3a..87d28fe 100644 (file)
 #include <limits.h>
 #include <ctype.h>
 
-//-----------------------------------------------------------------------------
+//=============================================================================
 // Macros
-//-----------------------------------------------------------------------------
+//=============================================================================
 #define TAG    PCF("OCCoAP")
 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} }
 
 //=============================================================================
+// Defines
+//=============================================================================
+#define COAP_BLOCK_FILL_VALUE   (0xFF)
+
+//=============================================================================
 // Private Variables
 //=============================================================================
 
@@ -71,25 +76,27 @@ static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
 
     // silence warnings
     (void) ctx;
-
-    OCStackResult result = OC_STACK_OK;
-    OCCoAPToken sentToken;
-    uint8_t * observeOption = NULL;
     coap_pdu_t * sentPdu = sentQueue->pdu;
+    OCStackResult result = OC_STACK_ERROR;
+    uint32_t observationOption = OC_OBSERVE_NO_OPTION;
+    // {{0}} to eliminate warning for known compiler bug 53119
+    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
+    OCCoAPToken sentToken = {{0}};
 
-    // fill the buffers of Uri and Query
-    result = ParseCoAPPdu(sentPdu, NULL, NULL, &observeOption, NULL, NULL, NULL, NULL);
+    result = ParseCoAPPdu(sentPdu, NULL, NULL, &observationOption, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL, NULL);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // fill OCCoAPToken structure
     RetrieveOCCoAPToken(sentPdu, &sentToken);
 
-    if(msgType == COAP_MESSAGE_RST){
-        // now the observer should be deleted
+    if(msgType == COAP_MESSAGE_RST)
+    {
         if(myStackMode != OC_CLIENT)
         {
-            result = OCObserverStatus(&sentToken, OC_OBSERVER_NOT_INTERESTED);
-            if(result == OC_STACK_OK){
+            result = OCStackFeedBack(&sentToken, OC_OBSERVER_NOT_INTERESTED);
+            if(result == OC_STACK_OK)
+            {
                 OC_LOG_V(DEBUG, TAG,
                         "Received RST, removing all queues associated with Token %d bytes",
                         sentToken.tokenLength);
@@ -98,18 +105,19 @@ static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
                         sentToken.tokenLength);
             }
         }
-    }else if(observeOption && msgType == COAP_MESSAGE_ACK){
+    }
+    else if(observationOption != OC_OBSERVE_NO_OPTION && msgType == COAP_MESSAGE_ACK)
+    {
         OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength);
         OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
         // now the observer is still interested
         if(myStackMode != OC_CLIENT)
         {
-            OCObserverStatus(&sentToken, OC_OBSERVER_STILL_INTERESTED);
+            OCStackFeedBack(&sentToken, OC_OBSERVER_STILL_INTERESTED);
         }
     }
-
-    exit:
-        OCFree(observeOption);
+exit:
+    return;
 }
 
 //This function is called back by libcoap when a request is received
@@ -118,6 +126,18 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
 {
     // silence warnings
     (void) ctx;
+    OCServerProtocolRequest protocolRequest;
+    memset(&protocolRequest, 0, sizeof(OCServerProtocolRequest));
+    coap_block_t rcvdBlock1;
+    coap_block_t rcvdBlock2;
+    memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
+    memset(&rcvdBlock2, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
+    uint16_t rcvdSize1 = 0;
+    coap_pdu_t * rcvdPdu = rcvdRequest->pdu;
+    coap_pdu_t * sendPdu = NULL;
+    coap_send_flags_t sendFlag;
+    OCStackResult result = OC_STACK_ERROR;
+    OCStackResult requestResult = OC_STACK_ERROR;
 
     if(myStackMode == OC_CLIENT)
     {
@@ -125,181 +145,139 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
         return;
     }
 
-    OCStackResult result = OC_STACK_ERROR;
-    OCStackResult responseResult = OC_STACK_ERROR;
-    OCRequest * request = NULL;
-    OCEntityHandlerRequest entityHandlerRequest;
-    OCCoAPToken rcvdToken;
-    OCObserveReq * rcvdObsReq = NULL;
-    coap_pdu_t * sendPdu = NULL;
-    coap_list_t *optList = NULL;
-    uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
-    uint32_t maxAge = 0x2ffff;
-    OCMethod ocMethod;
-
-    unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
-    unsigned char rcvdQuery[MAX_QUERY_LENGTH] = { 0 };
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 };
-    unsigned char newResourceUri[MAX_RESPONSE_LENGTH] = { 0 };
-    uint8_t * rcvObserveOption = NULL;
-    unsigned char * bufReqPayload = NULL;
-    uint32_t observeOption = OC_RESOURCE_NO_OBSERVE;
-    coap_send_flags_t sendFlag;
-    memset(&entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
-
-    coap_pdu_t * recvPdu = rcvdRequest->pdu;
-
-    // fill the buffers of Uri and Query
-    result = ParseCoAPPdu(recvPdu, rcvdUri, rcvdQuery, &rcvObserveOption, NULL, &bufReqPayload,
-            entityHandlerRequest.rcvdVendorSpecificHeaderOptions,
-            &(entityHandlerRequest.numRcvdVendorSpecificHeaderOptions));
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-    if(rcvObserveOption){
-        observeOption = (uint32_t)(*rcvObserveOption);
-    }
+    protocolRequest.observationOption = OC_OBSERVE_NO_OPTION;
+    protocolRequest.qos = (rcvdPdu->hdr->type == COAP_MESSAGE_CON) ?
+            OC_HIGH_QOS : OC_LOW_QOS;
+    protocolRequest.coapID = rcvdPdu->hdr->id;
+    protocolRequest.delayedResNeeded = rcvdRequest->delayedResNeeded;
+    protocolRequest.secured = rcvdRequest->secure;
 
     // fill OCCoAPToken structure
-    RetrieveOCCoAPToken(recvPdu, &rcvdToken);
+    RetrieveOCCoAPToken(rcvdPdu, &protocolRequest.requestToken);
+    OC_LOG_V(INFO, TAG, " Token received %d bytes",
+            protocolRequest.requestToken.tokenLength);
+    OC_LOG_BUFFER(INFO, TAG, protocolRequest.requestToken.token,
+            protocolRequest.requestToken.tokenLength);
+
+    // fill OCDevAddr
+    memcpy(&protocolRequest.requesterAddr, (OCDevAddr *) &rcvdRequest->remote,
+            sizeof(OCDevAddr));
+
+    // Retrieve Uri and Query from received coap pdu
+    result =  ParseCoAPPdu(rcvdPdu, protocolRequest.resourceUrl,
+            protocolRequest.query,
+            &(protocolRequest.observationOption), NULL,
+            &(protocolRequest.numRcvdVendorSpecificHeaderOptions),
+            protocolRequest.rcvdVendorSpecificHeaderOptions,
+            &rcvdBlock1, &rcvdBlock2, &rcvdSize1, NULL,
+            protocolRequest.reqJSONPayload);
+    VERIFY_SUCCESS(result, OC_STACK_OK);
 
-    switch (recvPdu->hdr->code)
+    switch (rcvdPdu->hdr->code)
     {
         case COAP_REQUEST_GET:
-            {
-                ocMethod = OC_REST_GET;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_GET;
+            break;
+        }
         case COAP_REQUEST_POST:
-            {
-                ocMethod = OC_REST_POST;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_POST;
+            break;
+        }
         case COAP_REQUEST_DELETE:
-            {
-                ocMethod = OC_REST_DELETE;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_DELETE;
+            break;
+        }
         case COAP_REQUEST_PUT:
-            {
-                ocMethod = OC_REST_PUT;
-                break;
-            }
+        {
+            protocolRequest.method = OC_REST_PUT;
+            break;
+        }
         default:
-            {
-                OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
-                         recvPdu->hdr->code);
-                goto exit;
-            }
+        {
+            OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
+                    rcvdPdu->hdr->code);
+            goto exit;
+        }
     }
 
-    // fill OCEntityHandlerRequest structure
-    result = FormOCEntityHandlerRequest(&entityHandlerRequest, ocMethod,
-                                        bufRes, bufReqPayload, rcvdQuery, newResourceUri);
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-   // fill OCObserveReq
-   result = FormOCObserveReq(&rcvdObsReq, observeOption,
-           (OCDevAddr *)&(rcvdRequest->remote), &rcvdToken);
-   VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    // fill OCRequest structure
-    result = FormOCRequest(&request, (recvPdu->hdr->type == COAP_MESSAGE_CON) ?
-            OC_HIGH_QOS : OC_LOW_QOS, rcvdUri, rcvdObsReq, &entityHandlerRequest,
-            rcvdRequest->secure);
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    OC_LOG_V(INFO, TAG, " Receveid uri:     %s", request->resourceUrl);
-    OC_LOG_V(INFO, TAG, " Receveid query:   %s", entityHandlerRequest.query);
-    OC_LOG_V(INFO, TAG, " Receveid payload: %s",
-            request->entityHandlerRequest->reqJSONPayload);
-    OC_LOG_V(INFO, TAG, " Token received %d bytes",
-            rcvdToken.tokenLength);
-    OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
-
-    // process the request
-    responseResult = HandleStackRequests(request);
-    #ifdef WITH_PRESENCE
-    if(responseResult == OC_STACK_PRESENCE_DO_NOT_HANDLE)
+    if(rcvdBlock1.szx != 7)
     {
-        goto exit;
+        protocolRequest.reqPacketSize = 1 << (rcvdBlock1.szx + 4);
+        protocolRequest.reqMorePacket = rcvdBlock1.m;
+        protocolRequest.reqPacketNum  = rcvdBlock1.num;
+    }
+    else
+    {
+        // No block1 received
+        rcvdSize1 = strlen((const char *)protocolRequest.reqJSONPayload)+1;
+        protocolRequest.reqTotalSize = rcvdSize1;
     }
-    #endif
 
-    // do not process further if received an error
-    // ex : when receive a non-secure request to a secure resource
-    if(responseResult == OC_STACK_ERROR)
+    if(rcvdBlock2.szx != 7)
     {
-        goto exit;
+        protocolRequest.resPacketSize = 1 << (rcvdBlock2.szx + 4);
+        protocolRequest.resPacketNum  = rcvdBlock2.num;
     }
 
-    OC_LOG_V(INFO, TAG, "Response from ocstack: %s",
-            request->entityHandlerRequest->resJSONPayload);
+    requestResult = HandleStackRequests(&protocolRequest);
 
-    if(rcvdObsReq)
+    if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE ||
+            requestResult == OC_STACK_OK ||
+            requestResult == OC_STACK_RESOURCE_CREATED ||
+            requestResult == OC_STACK_RESOURCE_DELETED)
     {
-        switch(rcvdObsReq->result)
-        {
-        case OC_STACK_OK:
-            observeOption = rcvdObsReq->option;
-            result = FormOptionList(&optList, &mediaType, &maxAge,
-                    sizeof(observeOption), &observeOption,
-                    NULL, 0, NULL, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
-            break;
-        case OC_STACK_OBSERVER_NOT_ADDED:
-        case OC_STACK_OBSERVER_NOT_REMOVED:
-        case OC_STACK_INVALID_OBSERVE_PARAM:
-        default:
-            result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                    0, NULL, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
-            break;
+        goto exit;
+    }
+    else if(requestResult == OC_STACK_NO_MEMORY ||
+            requestResult == OC_STACK_ERROR ||
+            requestResult == OC_STACK_NOTIMPL ||
+            requestResult == OC_STACK_NO_RESOURCE ||
+            requestResult == OC_STACK_RESOURCE_ERROR)
+    {
+        // TODO: should we send an error also when we receive a non-secured request to a secure resource?
+        // TODO: should we consider some sort of error response
+        OC_LOG(DEBUG, TAG, PCF("We should send some sort of error message"));
+        // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+        sendPdu = GenerateCoAPPdu((rcvdPdu->hdr->type == COAP_MESSAGE_CON)? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+                OCToCoAPResponseCode(requestResult), rcvdPdu->hdr->id,
+                &protocolRequest.requestToken, NULL, NULL);
+        VERIFY_NON_NULL(sendPdu);
+        coap_show_pdu(sendPdu);
+        sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
+        if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
+                sendFlag)
+                != OC_STACK_OK){
+            OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
         }
+        goto exit;
     }
-    else
+    else if(requestResult == OC_STACK_SLOW_RESOURCE)
     {
-        if (responseResult == OC_STACK_RESOURCE_CREATED)
+        if(rcvdPdu->hdr->type == COAP_MESSAGE_CON)
         {
-            result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                    strlen((char *)newResourceUri), newResourceUri, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
+            // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+            sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, rcvdPdu->hdr->id,
+                    NULL, NULL, NULL);
+            VERIFY_NON_NULL(sendPdu);
+            coap_show_pdu(sendPdu);
+
+            sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
+            if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
+                    sendFlag)
+                    != OC_STACK_OK){
+                OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
+            }
         }
         else
         {
-            result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                    0, NULL, 0, NULL,
-                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
-                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
+            goto exit;
         }
     }
-
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
-    sendPdu = GenerateCoAPPdu(
-            (rcvdRequest->pdu->hdr->type == COAP_MESSAGE_CON) ?
-                    COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
-                    OCToCoAPResponseCode(responseResult), rcvdRequest->pdu->hdr->id,
-                    &rcvdToken,
-                    request->entityHandlerRequest->resJSONPayload, optList);
-    VERIFY_NON_NULL(sendPdu);
-    coap_show_pdu(sendPdu);
-
-    sendFlag = (coap_send_flags_t)(rcvdRequest->delayedResponse ? SEND_DELAYED : 0);
-    sendFlag = (coap_send_flags_t)( sendFlag | (rcvdRequest->secure ? SEND_SECURE_PORT : 0));
-
-    if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
-         sendFlag)
-            != OC_STACK_OK){
-        OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
-    }
-
 exit:
-    OCFree(rcvObserveOption);
-    OCFree(rcvdObsReq);
-    OCFree(request);
+    return;
 }
 
 uint32_t GetTime(float afterSeconds)
@@ -315,46 +293,41 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     OCResponse * response = NULL;
     OCCoAPToken rcvdToken;
     OCClientResponse clientResponse;
+    memset(&clientResponse, 0, sizeof(OCClientResponse));
     ClientCB * cbNode = NULL;
-    unsigned char * bufRes = NULL;
-    uint8_t * rcvObserveOption = NULL;
-    uint8_t * rcvMaxAgeOption = NULL;
-    uint32_t sequenceNumber = OC_RESOURCE_NO_OBSERVE;
+    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+    uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
     uint32_t maxAge = 0;
-    char * resourceTypeName = NULL;
     OCStackResult result = OC_STACK_ERROR;
-    coap_pdu_t *sendPdu = NULL;
+    coap_pdu_t * sendPdu = NULL;
     coap_pdu_t * recvPdu = NULL;
-    uint8_t remoteIpAddr[4];
-    uint16_t remotePortNu;
-    unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
     unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
     uint8_t isObserveNotification = 0;
     #ifdef WITH_PRESENCE
+    char * resourceTypeName = NULL;
+    uint8_t remoteIpAddr[4];
+    uint16_t remotePortNu;
+    unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
     uint8_t isPresenceNotification = 0;
     uint8_t isMulticastPresence = 0;
     uint32_t lowerBound;
     uint32_t higherBound;
     char * tok = NULL;
     #endif
-    memset(&clientResponse, 0, sizeof(OCClientResponse));
+    coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
+    coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
+    uint16_t rcvdSize2 = 0;
 
     VERIFY_NON_NULL(ctx);
     VERIFY_NON_NULL(rcvdResponse);
     recvPdu = rcvdResponse->pdu;
 
-    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &rcvObserveOption, &rcvMaxAgeOption, &bufRes,
+    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
+            &clientResponse.numRcvdVendorSpecificHeaderOptions,
             clientResponse.rcvdVendorSpecificHeaderOptions,
-            &(clientResponse.numRcvdVendorSpecificHeaderOptions));
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-
-    if(rcvObserveOption){
-        sequenceNumber = *((uint32_t *) rcvObserveOption);
-    }
+            &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);
 
-    if(rcvMaxAgeOption){
-        maxAge = *((uint32_t *) rcvMaxAgeOption);
-    }
+    VERIFY_SUCCESS(result, OC_STACK_OK);
 
     OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber);
     OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge);
@@ -370,13 +343,16 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
         isPresenceNotification = 1;
         OC_LOG(INFO, TAG, PCF("Received a presence notification"));
-        tok = strtok((char *)bufRes, ":");
-        sequenceNumber = (uint32_t )atoi(tok);
+        tok = strtok((char *)bufRes, "[:]");
+        tok = strtok(NULL, "[:]");
+        VERIFY_NON_NULL(tok);
+        sequenceNumber = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
-        tok = strtok(NULL, ":");
-        maxAge = (uint32_t )atoi(tok);
+        tok = strtok(NULL, "[:]");
+        VERIFY_NON_NULL(tok);
+        maxAge = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
-        tok = strtok(NULL, ":");
+        tok = strtok(NULL, "[:]");
         bufRes[strlen((char *)bufRes)] = ':';
         if(tok) {
             resourceTypeName = (char *)OCMalloc(strlen(tok));
@@ -433,6 +409,26 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
 
     if(cbNode)
     {
+        if(!isObserveNotification)
+        {
+            #ifdef WITH_PRESENCE
+            if(!isPresenceNotification)
+            {
+            #endif
+                OC_LOG(INFO, TAG, PCF("Received a regular response"));
+                if(recvPdu->hdr->type == COAP_MESSAGE_CON)
+                {
+                    sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
+                            recvPdu->hdr->id, NULL, NULL, NULL);
+                    VERIFY_NON_NULL(sendPdu);
+                    result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
+                            sendPdu,
+                            (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
+                }
+            #ifdef WITH_PRESENCE
+            }
+            #endif
+        }
         if(isObserveNotification)
         {
             OC_LOG(INFO, TAG, PCF("Received an observe notification"));
@@ -449,7 +445,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
             if(cbNode->method == OC_REST_OBSERVE &&
                     (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
                             (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
-                                    clientResponse.sequenceNumber == MAX_SEQUENCE_NUMBER)))
+                                    clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER))))
             {
                 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
                         Ignoring Incoming:%d  Against Current:%d.",
@@ -482,6 +478,12 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                 {
                     OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
                     response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+                    if(cbNode->presence)
+                    {
+                        OCFree(cbNode->presence->timeOut);
+                        OCFree(cbNode->presence);
+                        cbNode->presence = NULL;
+                    }
                 }
                 else
                 {
@@ -575,7 +577,6 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
             }
             #endif
         }
-
         HandleStackResponses(response);
     }
     else if(!cbNode && isObserveNotification)
@@ -608,8 +609,6 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         VERIFY_SUCCESS(result, OC_STACK_OK);
     }
     exit:
-        OCFree(rcvObserveOption);
-        OCFree(rcvMaxAgeOption);
         OCFree(response);
 }
 
@@ -727,7 +726,7 @@ OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPTo
             goto exit;
         }
 
-        VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, 0, NULL,
+        VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, NULL,
                 (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
                 uri.query.s, options, numOptions), OC_STACK_OK);
 
@@ -764,7 +763,7 @@ OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPTo
         case OC_REST_CANCEL_OBSERVE:
             coapMethod = COAP_REQUEST_GET;
             observeOption = (method == OC_REST_CANCEL_OBSERVE)?
-                    OC_RESOURCE_OBSERVE_DEREGISTER:OC_RESOURCE_OBSERVE_REGISTER;
+                    OC_OBSERVE_DEREGISTER:OC_OBSERVE_REGISTER;
             coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
                         sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions);
             break;
@@ -790,60 +789,92 @@ exit:
     return ret;
 }
 
-OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
-                       OCQualityOfService qos, OCCoAPToken * token,
-                       unsigned char *payload, OCResource *resPtr, uint32_t maxAge)
+OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response)
 {
     OCStackResult result = OC_STACK_ERROR;
+    coap_pdu_t * sendPdu = NULL;
     coap_list_t *optList = NULL;
-    uint8_t coapMsgType = COAP_MESSAGE_NON;
+    uint8_t msgType = COAP_MESSAGE_NON;
     uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
-    coap_pdu_t *sendPdu;
+    uint32_t maxAge = 0x2ffff;
+    coap_send_flags_t sendFlag = (coap_send_flags_t)0;
 
-    OC_LOG(INFO, TAG, PCF("Entering OCSendCoAPNotification"));
+    //uint32_t observeOption = OC_OBSERVE_NO_OPTION;
+    //OCStackResult responseResult;
 
-    coapMsgType = OCToCoAPQoS(qos);
+    OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResponse"));
 
-    #ifdef WITH_PRESENCE
-    if(!strcmp((const char *)uri, OC_PRESENCE_URI))
+    if(response->notificationFlag && response->qos == OC_HIGH_QOS)
     {
-        result = FormOptionList(&optList, &mediaType, NULL, 0, NULL,
-                NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
+        msgType = COAP_MESSAGE_CON;
     }
-    else
+    else if(response->notificationFlag && response->qos != OC_HIGH_QOS)
     {
-    #endif
-        result = FormOptionList(&optList, &mediaType, &maxAge, sizeof(resPtr->sequenceNum),
-                &resPtr->sequenceNum, NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
-    #ifdef WITH_PRESENCE
+        msgType = COAP_MESSAGE_NON;
+    }
+    else if(!response->notificationFlag && !response->slowFlag && response->qos == OC_HIGH_QOS)
+    {
+        msgType = COAP_MESSAGE_ACK;
+    }
+    else if(!response->notificationFlag && response->slowFlag && response->qos == OC_HIGH_QOS)
+    {
+        msgType = COAP_MESSAGE_CON;
+    }
+    else if(!response->notificationFlag)
+    {
+        msgType = COAP_MESSAGE_NON;
     }
-    #endif
-    VERIFY_SUCCESS(result, OC_STACK_OK);
 
-    if(resPtr->resourceProperties == 0)
+    if(response->coapID == 0)
     {
-        result = OC_STACK_RESOURCE_DELETED;
+        response->coapID = coap_new_message_id(gCoAPCtx);
     }
 
-    sendPdu = GenerateCoAPPdu(
-            coapMsgType == COAP_MESSAGE_CON ? COAP_MESSAGE_CON : COAP_MESSAGE_NON,
-                    OCToCoAPResponseCode(result), coap_new_message_id(gCoAPCtx),
-                    token, payload, optList);
+    if (response->observationOption != OC_OBSERVE_NO_OPTION)
+    {
+        result = FormOptionList(&optList, &mediaType, &maxAge,
+                &response->observationOption, NULL,
+                strlen((char *)response->resourceUri), response->resourceUri,
+                0, NULL,
+                response->sendVendorSpecificHeaderOptions,
+                response->numSendVendorSpecificHeaderOptions);
+    }
+    else
+    {
+        result = FormOptionList(&optList, &mediaType, &maxAge,
+                NULL, NULL,
+                strlen((char *)response->resourceUri), response->resourceUri,
+                0, NULL,
+                response->sendVendorSpecificHeaderOptions,
+                response->numSendVendorSpecificHeaderOptions);
+    }
+    VERIFY_SUCCESS(result, OC_STACK_OK);
+
+    sendPdu = GenerateCoAPPdu(msgType, OCToCoAPResponseCode(response->result),
+            response->coapID, response->requestToken, (unsigned char *)response->payload,
+            optList);
+
     VERIFY_NON_NULL(sendPdu);
     coap_show_pdu(sendPdu);
 
-    // TODO : resourceProperties will determine if the packet will be send using secure port
-    if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) dstAddr, sendPdu ,
-            (coap_send_flags_t)((resPtr->resourceProperties & OC_SECURE) ? SEND_SECURE_PORT : 0) )
+    sendFlag = (coap_send_flags_t)(response->delayedResNeeded ? SEND_DELAYED : 0);
+    sendFlag = (coap_send_flags_t)( sendFlag | (response->secured ? SEND_SECURE_PORT : 0));
+
+    if (SendCoAPPdu(gCoAPCtx, (coap_address_t *) (response->requesterAddr), sendPdu, sendFlag)
             != OC_STACK_OK)
     {
-        OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
+        OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu"));
+        return OC_STACK_ERROR;
     }
+
     return OC_STACK_OK;
+
 exit:
+    OC_LOG(ERROR, TAG, PCF("Error formatting server response"));
     return OC_STACK_ERROR;
 }
 
+
 /**
  * Stop the CoAP client or server processing
  *
index ceed9dd..f1e9382 100644 (file)
@@ -24,7 +24,6 @@
 #include "occoaphelper.h"
 #include "ocstackconfig.h"
 #include "logger.h"
-#include "ocobserve.h"
 #include "coap_time.h"
 #include "ocmalloc.h"
 
@@ -81,6 +80,10 @@ uint8_t OCToCoAPResponseCode(OCStackResult result)
             ret = COAP_RESPONSE_405;
             break;
 
+        case OC_STACK_NOTIMPL :
+            ret = COAP_RESPONSE_501;
+            break;
+
         default:
             ret = COAP_RESPONSE_500;
     }
@@ -137,6 +140,10 @@ OCStackResult CoAPToOCResponseCode(uint8_t coapCode)
             ret = OC_STACK_INVALID_METHOD;
             break;
 
+        case COAP_RESPONSE_501 :
+            ret = OC_STACK_NOTIMPL;
+            break;
+
         default:
             decimal = ((coapCode >> 5) * 100) + (coapCode & 31);
             if (decimal >= 200 && decimal <= 231)
@@ -153,261 +160,171 @@ OCStackResult CoAPToOCResponseCode(uint8_t coapCode)
 
 // Retrieve Uri and Query from received coap pdu
 OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
-        unsigned char * queryBuf, uint8_t * * observeOptionLoc,
-        uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
-        OCHeaderOption * rcvVendorSpecificHeaderOptions,
-        uint8_t * numRcvVendorSpecificHeaderOptions)
+        unsigned char * queryBuf, uint32_t * observeOption,
+        uint32_t * maxAgeOption,
+        uint8_t * numVendorSpecificHeaderOptions,
+        OCHeaderOption * vendorSpecificHeaderOptions,
+        coap_block_t * block1, coap_block_t * block2,
+        uint16_t * size1, uint16_t * size2,
+        unsigned char * payload)
 {
     coap_opt_filter_t filter;
     coap_opt_iterator_t opt_iter;
     coap_opt_t *option = NULL;
-    size_t bufLen = 0;
     size_t optLen = 0;
-    uint8_t * observeOption = NULL;
-    uint8_t * maxAgeOption = NULL;
-    uint8_t optionFound = 0;
+    unsigned char * optVal = NULL;
+    size_t uriBufLen = 0;
+    size_t queryBufLen = 0;
+    unsigned char * payloadLoc = NULL;
+    size_t payloadLength = 0;
 
+    coap_option_filter_clear(filter);
     if(uriBuf)
     {
-        // parse the Uri
-        coap_option_filter_clear(filter);
         coap_option_setb(filter, COAP_OPTION_URI_PATH);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
+    }
+    if(queryBuf)
+    {
+        coap_option_setb(filter, COAP_OPTION_URI_QUERY);
+    }
+    if(observeOption)
+    {
+        coap_option_setb(filter, COAP_OPTION_OBSERVE);
+    }
+    if(maxAgeOption)
+    {
+        coap_option_setb(filter, COAP_OPTION_MAXAGE);
+    }
+    if(block1)
+    {
+        coap_option_setb(filter, COAP_OPTION_BLOCK1);
+    }
+    if(block2)
+    {
+        coap_option_setb(filter, COAP_OPTION_BLOCK2);
+    }
+    if(size1)
+    {
+        coap_option_setb(filter, COAP_OPTION_SIZE1);
+    }
+    if(size2)
+    {
+        coap_option_setb(filter, COAP_OPTION_SIZE2);
+    }
+    if(vendorSpecificHeaderOptions)
+    {
+        coap_option_setbVendor(filter);
+    }
+    if(payload)
+    {
+        coap_get_data(pdu, &payloadLength, &payloadLoc);
+        memcpy(payload, payloadLoc, payloadLength);
+    }
+    coap_option_iterator_init(pdu, &opt_iter, filter);
+
+    while ((option = coap_option_next(&opt_iter)))
+    {
+        optLen = COAP_OPT_LENGTH(option);
+        optVal = COAP_OPT_VALUE(option);
+        switch(opt_iter.type)
         {
-            optLen = COAP_OPT_LENGTH(option);
-            if (bufLen + 1 + optLen < MAX_URI_LENGTH)
+        case COAP_OPTION_URI_PATH:
+            if (uriBufLen + 1 + optLen < MAX_URI_LENGTH)
             {
                 //we still have room in the buffer
-                uriBuf[bufLen++] = '/';
-                memcpy(uriBuf + bufLen, COAP_OPT_VALUE(option), optLen);
-                bufLen += optLen;
+                uriBuf[uriBufLen++] = '/';
+                memcpy(uriBuf + uriBufLen, optVal, optLen);
+                uriBufLen += optLen;
             }
             else
             {
-                // TODO: we should check that resources do not have long uri at the resource creation
                 return OC_STACK_NO_MEMORY;
             }
-        }
-        uriBuf[bufLen] = '\0';
-    }
-
-    if(queryBuf)
-    {
-        // parse the Query
-        bufLen = 0;
-        coap_option_filter_clear(filter);
-        coap_option_setb(filter, COAP_OPTION_URI_QUERY);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
-        {
-            optLen = COAP_OPT_LENGTH(option);
-            if (bufLen + 1 + optLen < MAX_QUERY_LENGTH)
+            break;
+        case COAP_OPTION_URI_QUERY:
+            if (queryBufLen + 1 + optLen < MAX_QUERY_LENGTH)
             {
                 //we still have room in the buffer
-                memcpy(queryBuf + bufLen, COAP_OPT_VALUE(option), optLen);
-                bufLen += optLen;
-                queryBuf[bufLen++] = '&';
+                memcpy(queryBuf + queryBufLen, optVal, optLen);
+                queryBufLen += optLen;
+                queryBuf[queryBufLen++] = '&';
             }
             else
             {
-                // TODO: should it be OC_STACK_NO_MEMORY
+                // TODO: we should check that resources do not have long uri
+                // at the resource creation
                 return OC_STACK_NO_MEMORY;
             }
-        }
-        // delete last '&'
-        queryBuf[bufLen ? (bufLen - 1) : (bufLen)] = '\0';
-    }
-
-    if(observeOptionLoc)
-    {
-        optionFound = 0;
-        // parse the observe option
-        coap_option_filter_clear(filter);
-        coap_option_setb(filter, COAP_OPTION_OBSERVE);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
-        {
-            observeOption = (uint8_t *) OCMalloc(COAP_OPT_LENGTH(option));
-            if(!observeOption)
+            break;
+        case COAP_OPTION_OBSERVE:
+            memcpy(observeOption, optVal, optLen);
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the observe option %u",
+                    *observeOption);
+            break;
+        case COAP_OPTION_MAXAGE:
+            memcpy(maxAgeOption, optVal, optLen);
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the max age option %u",
+                    *maxAgeOption);
+            break;
+        case COAP_OPTION_BLOCK1:
+            block1->szx = COAP_OPT_BLOCK_SZX(option);
+            block1->num = coap_opt_block_num(option);
+            block1->m = 0;
+            if(COAP_OPT_BLOCK_MORE(option))
             {
-                return OC_STACK_NO_MEMORY;
+                block1->m = 1;
             }
-            memcpy(observeOption, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
-            optionFound = 1;
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block1 %u:%u:%u",
+                    block1->num, block1->m, block1->szx);
             break;
-        }
-        if(optionFound)
-        {
-            *observeOptionLoc = observeOption;
-        }
-        else
-        {
-            OCFree(observeOption);
-            *observeOptionLoc = NULL;
-        }
-    }
-
-
-    if(maxAgeOptionLoc)
-    {
-        optionFound = 0;
-        // parse the observe option
-        coap_option_filter_clear(filter);
-        coap_option_setb(filter, COAP_OPTION_MAXAGE);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        while ((option = coap_option_next(&opt_iter)))
-        {
-            maxAgeOption = (uint8_t *) OCMalloc(COAP_OPT_LENGTH(option));
-            if(!maxAgeOption)
+        case COAP_OPTION_BLOCK2:
+            block2->szx = COAP_OPT_BLOCK_SZX(option);
+            block2->num = coap_opt_block_num(option);
+            block2->m = 0;
+            if(COAP_OPT_BLOCK_MORE(option))
             {
-                return OC_STACK_NO_MEMORY;
+                block2->m = 1;
             }
-            memcpy(maxAgeOption, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
-            optionFound = 1;
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block2 %u:%u:%u",
+                    block1->num, block1->m, block1->szx);
             break;
-        }
-        if(optionFound)
-        {
-            *maxAgeOptionLoc = maxAgeOption;
-        }
-        else
-        {
-            OCFree(maxAgeOption);
-            *maxAgeOptionLoc = NULL;
-        }
-    }
-
-    if(rcvVendorSpecificHeaderOptions)
-    {
-        coap_option_filter_clear(filter);
-        coap_option_setbVendor(filter);
-        coap_option_iterator_init(pdu, &opt_iter, filter);
-        uint8_t i = 0;
-        while((option = coap_option_next(&opt_iter)))
-        {
-            if(i >= MAX_HEADER_OPTIONS ||
-                    COAP_OPT_LENGTH(option) > MAX_HEADER_OPTION_DATA_LENGTH)
+        case COAP_OPTION_SIZE1:
+            break;
+        case COAP_OPTION_SIZE2:
+            break;
+        default:
+            if(*numVendorSpecificHeaderOptions >= MAX_HEADER_OPTIONS ||
+                    optLen > MAX_HEADER_OPTION_DATA_LENGTH)
             {
                 return OC_STACK_NO_MEMORY;
             }
-            rcvVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
-            rcvVendorSpecificHeaderOptions[i].optionID = opt_iter.type;
-            rcvVendorSpecificHeaderOptions[i].optionLength = COAP_OPT_LENGTH(option);
-            memcpy(rcvVendorSpecificHeaderOptions[i].optionData, COAP_OPT_VALUE(option),
-                    rcvVendorSpecificHeaderOptions[i].optionLength);
-            OC_LOG_V(INFO, TAG, " Parsing option %d with", rcvVendorSpecificHeaderOptions[i].optionID);
-            OC_LOG_BUFFER(INFO, TAG, rcvVendorSpecificHeaderOptions[i].optionData,
-                    rcvVendorSpecificHeaderOptions[i].optionLength);
-            i++;
+            vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].protocolID = OC_COAP_ID;
+            vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID = opt_iter.type;
+            vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength = optLen;
+            memcpy(vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData, optVal, optLen);
+            OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing vendor specific option %u",
+                    vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID);
+            OC_LOG_BUFFER(DEBUG, TAG, vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData,
+                    vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength);
+            (*numVendorSpecificHeaderOptions)++;
         }
-
-        *numRcvVendorSpecificHeaderOptions = i;
-    }
-
-    // get the payload
-    if(payloadLoc)
-    {
-        coap_get_data(pdu, &bufLen, payloadLoc);
-    }
-
-    return OC_STACK_OK;
-}
-
-// Form the OCRequest struct
-OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
-        unsigned char * uriBuf, OCObserveReq * observeReq,
-        OCEntityHandlerRequest * entityHandlerRequest,
-        uint8_t secure)
-{
-    OCRequest * request = NULL;
-
-    // allocate it
-    request = (OCRequest *) OCMalloc(sizeof(OCRequest));
-    if (!request)
-    {
-        return OC_STACK_NO_MEMORY;
     }
 
-    // fill in qos
-    request->qos = qos;
-
-    // fill in uri
-    request->resourceUrl = uriBuf;
-
-    request->secure = secure;
-
-    // fill in observe
-    request->observe = observeReq;
-
-    // add entityHandlerRequest
-    request->entityHandlerRequest = entityHandlerRequest;
-
-    //TODO: this needs to be filled in the future
-    request->sequenceNum = 0;
-
-    *requestLoc = request;
-    return OC_STACK_OK;
-}
-
-// Form the OCObserveReq struct
-OCStackResult FormOCObserveReq(OCObserveReq ** observeReqLoc, uint32_t observeOption,
-            OCDevAddr * remote, OCCoAPToken * rcvdToken)
-{
-    OCObserveReq * observeReq;
-
-    if(observeOption == OC_RESOURCE_NO_OBSERVE)
+    if(uriBuf)
     {
-        return OC_STACK_OK;
+        uriBuf[uriBufLen] = '\0';
     }
-
-    observeReq = (OCObserveReq *)OCMalloc(sizeof(OCObserveReq));
-    if(!observeReq)
+    // delete last '&' in the query
+    if(queryBuf)
     {
-        *observeReqLoc = NULL;
-        return OC_STACK_NO_MEMORY;
+        queryBuf[queryBufLen?queryBufLen-1:queryBufLen] = '\0';
     }
 
-    observeReq->option = observeOption;
-    observeReq->subAddr = remote;
-    observeReq->token = rcvdToken;
-    observeReq->result = OC_STACK_OK;
-
-    *observeReqLoc = observeReq;
+    OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed uri is %s", uriBuf);
+    OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed query is %s", queryBuf);
     return OC_STACK_OK;
 }
 
-// Form the OCEntityHandlerRequest struct
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
-        OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
-        unsigned char * queryBuf, unsigned char *newResUriBuf)
-{
-    if (entityHandlerRequestLoc)
-    {
-        //set it to NULL for now, it will be modified in ocstack
-        entityHandlerRequestLoc->resource = NULL;
-
-        entityHandlerRequestLoc->method = method;
-
-        // fill in query
-        entityHandlerRequestLoc->query = queryBuf;
-
-        // fill payload
-        entityHandlerRequestLoc->reqJSONPayload = bufReqPayload;
-
-        entityHandlerRequestLoc->resJSONPayload = resBuf;
-        entityHandlerRequestLoc->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
-
-        entityHandlerRequestLoc->obsInfo = NULL;
-        entityHandlerRequestLoc->newResourceUri = newResUriBuf;
-
-        entityHandlerRequestLoc->numSendVendorSpecificHeaderOptions = 0;
-        return OC_STACK_OK;
-    }
-
-    return OC_STACK_INVALID_PARAM;
-}
-
 // Retrieve the token from the PDU
 void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken)
 {
@@ -448,7 +365,7 @@ OCStackResult FormOCClientResponse(OCClientResponse * clientResponse,
 }
 
 OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
-        uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
+        uint32_t * addMaxAge, uint32_t * observeOptionPtr,
         uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
         uint8_t queryLength, unsigned char * query,
         OCHeaderOption * vendorSpecificHeaderOptions,
@@ -476,10 +393,10 @@ OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
         coap_insert(optListLoc, optNode, OrderOptions);
     }
 
-    if(observeOptionLength && observeOptionPtr)
+    if(observeOptionPtr)
     {
         optNode = CreateNewOptionNode(COAP_OPTION_OBSERVE,
-                observeOptionLength, (uint8_t *)observeOptionPtr);
+                sizeof(*observeOptionPtr), (uint8_t *)observeOptionPtr);
 
         VERIFY_NON_NULL(optNode);
         coap_insert(optListLoc, optNode, OrderOptions);
@@ -715,9 +632,9 @@ OCStackResult ReTXCoAPQueue(coap_context_t * ctx, coap_queue_t * queue)
 
 OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * queue)
 {
+    //TODO: this function should change to only use OCStackFeedBack
     OCResponse * response = NULL;
     ClientCB * cbNode = NULL;
-    ResourceObserver * observer = NULL;
     OCClientResponse clientResponse;
     OCCoAPToken token;
     OCStackResult result = OC_STACK_OK;
@@ -743,21 +660,12 @@ OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * que
     HandleStackResponses(response);
 
 observation:
-    observer = GetObserverUsingToken (&token);
-    if(!observer)
-    {
-        goto exit;
-    }
-
-    result = OCObserverStatus(&token, OC_OBSERVER_FAILED_COMM);
+    result = OCStackFeedBack(&token, OC_OBSERVER_FAILED_COMM);
     if(result == OC_STACK_OK)
     {
         coap_cancel_all_messages(ctx, &queue->remote, token.token, token.tokenLength);
     }
-
-    exit:
-
-        OCFree(response);
+    OCFree(response);
     return result;
 }
 
@@ -772,7 +680,7 @@ void HandleSendQueue(coap_context_t * ctx)
     while (nextQueue && nextQueue->t <= now - ctx->sendqueue_basetime)
     {
         nextQueue = coap_pop_next( ctx );
-        if((uint8_t)nextQueue->delayedResponse)
+        if((uint8_t)nextQueue->delayedResNeeded)
         {
             OC_LOG_V(DEBUG, TAG, "Sending Delayed response TID %d",
                     nextQueue->id);
index 955b344..512ec93 100644 (file)
@@ -24,6 +24,8 @@
 #include "ocstack.h"
 #include "ocresource.h"
 
+uint8_t GetNumOfResourcesInCollection (OCResource *resource);
+
 OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                                               OCEntityHandlerRequest *entityHandlerRequest);
 
index a84bb98..ba87306 100644 (file)
 
 /* In CoAP sequence number is a 24 bit field */
 #define MAX_SEQUENCE_NUMBER              (0xFFFFFF)
-#define OC_RESOURCE_OBSERVE_REGISTER     (0)
-#define OC_RESOURCE_OBSERVE_DEREGISTER   (1)
-#define OC_RESOURCE_NO_OBSERVE           (2)
 
 #define MAX_OBSERVER_FAILED_COMM         (2)
 #define MAX_OBSERVER_NON_COUNT           (3)
 
-#define OC_OBSERVER_NOT_INTERESTED       (0)
-#define OC_OBSERVER_STILL_INTERESTED     (1)
-#define OC_OBSERVER_FAILED_COMM          (2)
-
 /* This information is stored for each registerd observer */
 typedef struct ResourceObserver {
     // Observation Identifier for request
@@ -60,12 +53,17 @@ typedef struct ResourceObserver {
     struct ResourceObserver *next;
 } ResourceObserver;
 
-OCStackResult OCObserverStatus(OCCoAPToken * token, uint8_t status);
-
-OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request);
-
-OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
-                                        OCResourceType *resourceType, OCQualityOfService qos);
+#ifdef WITH_PRESENCE
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCResourceType *resourceType, OCQualityOfService qos);
+#else
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCQualityOfService qos);
+#endif
+OCStackResult SendListObserverNotification (OCResource * resource,
+        OCObservationId  *obsIdList, uint8_t numberOfIds,
+        unsigned char *notificationJSONPayload, uint32_t maxAge,
+        OCQualityOfService qos);
 
 void DeleteObserverList();
 
index 10f7a91..62d5363 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "ocstack.h"
 #include "ocstackinternal.h"
+#include "ocserverrequest.h"
 
 #define OC_RSRVD_OC                     "oc"
 #define OC_RSRVD_PAYLOAD                "payload"
@@ -67,15 +68,12 @@ const char * GetVirtualResourceUri( OCVirtualResources resource);
 OCResource *FindResourceByUri(const char* resourceUri);
 uint8_t IsVirtualResource(const char* resourceUri);
 
-OCStackResult DetermineResourceHandling (OCRequest *request,
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
                                          ResourceHandling *handling,
                                          OCResource **resource);
 
 OCStackResult
-BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request);
-
-OCEntityHandlerResult
-BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest);
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
 
 OCStackResult
 BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
diff --git a/resource/csdk/stack/include/internal/ocserverrequest.h b/resource/csdk/stack/include/internal/ocserverrequest.h
new file mode 100644 (file)
index 0000000..e96ed51
--- /dev/null
@@ -0,0 +1,110 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_SERVER_REQUEST_H
+#define OC_SERVER_REQUEST_H
+
+#include "occoap.h"
+
+/**
+ * The signature of the internal call back functions to handle responses from entity handler
+ */
+typedef OCStackResult (* OCEHResponseHandler)(OCEntityHandlerResponse * ehResponse);
+OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse);
+OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse);
+
+// following structure will be created in occoap and passed up the stack on the server side
+typedef struct OCServerRequest {
+    // the REST method retrieved from received request PDU
+    OCMethod method;
+    // resourceUrl will be filled in occoap using the path options in received request PDU
+    unsigned char resourceUrl[MAX_URI_LENGTH];
+    // resource query send by client
+    unsigned char query[MAX_QUERY_LENGTH];
+
+    // qos is indicating if the request is CON or NON
+    OCQualityOfService qos;
+    // Observe option field
+    uint32_t observationOption;
+    OCStackResult observeResult;
+    uint8_t numResponses;
+    OCEHResponseHandler ehResponseHandler;
+    //////////////////////////////////////////////////////////
+    // IP address & port of client registered for observe   //These
+    OCDevAddr requesterAddr;                                //Members
+    // CoAP token for the observe request                   //Might
+    OCCoAPToken requestToken;                               //Be
+    // The ID of CoAP pdu                                   //Kept in
+    uint16_t coapID;                                        //CoAP
+    uint8_t delayedResNeeded;
+    uint8_t secured;
+    //////////////////////////////////////////////////////////
+    // An array of the received vendor specific header options
+    uint8_t numRcvdVendorSpecificHeaderOptions;
+    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+    uint8_t requestComplete;
+    struct OCServerRequest * next;
+    // Flag indicating slow response
+    uint8_t slowFlag;
+    uint8_t notificationFlag;
+    // reqJSON is retrieved from the payload of the received request PDU
+    unsigned char reqJSONPayload[1];
+} OCServerRequest;
+
+// following structure will be created in ocstack to aggregate responses (in future: for block transfer)
+typedef struct OCServerResponse {
+    struct OCServerResponse * next;
+    // this is the pointer to server payload data to be transferred
+    unsigned char *payload;
+    uint16_t remainingPayloadSize;
+    OCRequestHandle requestHandle;
+} OCServerResponse;
+
+OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token);
+
+OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle);
+
+OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle);
+
+OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
+        uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
+        uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
+        OCQualityOfService qos, unsigned char * query,
+        OCHeaderOption * rcvdVendorSpecificHeaderOptions,
+        unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
+        OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize);
+
+OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle);
+
+// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
+        OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
+        uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+        OCObservationId observeID);
+
+void FindAndDeleteServerRequest(OCServerRequest * serverRequest);
+
+void DeleteServerRequest(OCServerRequest * serverRequest);
+
+void FindAndDeleteServerResponse(OCServerResponse * serverResponse);
+
+void DeleteServerResponse(OCServerResponse * serverResponse);
+
+#endif //OC_SERVER_REQUEST_H
index 31844fa..713b123 100644 (file)
@@ -51,6 +51,10 @@ extern OCDeviceEntityHandler defaultDeviceHandler;
 #define OC_COAP_SCHEME "coap://"
 #define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5
 
+#define OC_OBSERVER_NOT_INTERESTED       (0)
+#define OC_OBSERVER_STILL_INTERESTED     (1)
+#define OC_OBSERVER_FAILED_COMM          (2)
+
 //-----------------------------------------------------------------------------
 // Virtual Resource Presence Attributes
 //-----------------------------------------------------------------------------
@@ -74,7 +78,8 @@ struct rsrc_t;
 typedef enum {
     STACK_IF_DEFAULT = 0,
     STACK_IF_LL,
-    STACK_IF_BATCH
+    STACK_IF_BATCH,
+    STACK_IF_INVALID
 } OCStackIfTypes;
 
 typedef struct resourcetype_t {
@@ -155,19 +160,69 @@ typedef struct {
 
 // following structure will be created in occoap and passed up the stack on the server side
 typedef struct {
+    // the REST method retrieved from received request PDU
+    OCMethod method;
     // resourceUrl will be filled in occoap using the path options in received request PDU
-    unsigned char * resourceUrl;
+    unsigned char resourceUrl[MAX_URI_LENGTH];
+    // resource query send by client
+    unsigned char query[MAX_QUERY_LENGTH];
+    // reqJSON is retrieved from the payload of the received request PDU
+    unsigned char reqJSONPayload[MAX_REQUEST_LENGTH];
     // qos is indicating if the request is CON or NON
     OCQualityOfService qos;
-    // this structure points to the information for processing observe option
-    OCObserveReq *observe;
-    // If a subscription update, this is count of observe notifications from server perspective.
-    uint32_t sequenceNum;
-    // this structure will be passed to entity handler
-    OCEntityHandlerRequest * entityHandlerRequest;
-    // Indicate whether the request arrives on a secure port
-    uint8_t secure;
-} OCRequest;
+    // Observe option field
+    uint32_t observationOption;
+    // An array of the received vendor specific header options
+    uint8_t numRcvdVendorSpecificHeaderOptions;
+    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+    //////////////////////////////////////////////////////////
+    // TODO: Consider moving these member to CoAP
+    // IP address & port of client registered for observe
+    OCDevAddr requesterAddr;
+    // CoAP token for the observe request
+    OCCoAPToken requestToken;
+    // The ID of CoAP pdu
+    uint16_t coapID;
+    uint8_t delayedResNeeded;
+    uint8_t secured;
+    //////////////////////////////////////////////////////////
+    uint8_t reqMorePacket;
+    uint32_t reqPacketNum;
+    uint16_t reqPacketSize;
+    uint32_t resPacketNum;
+    uint16_t resPacketSize;
+    uint32_t reqTotalSize;
+} OCServerProtocolRequest;
+
+typedef struct
+{
+    // qos is indicating if the request is CON or NON
+    OCQualityOfService qos;
+    // Observe option field
+    uint32_t observationOption;
+    // Allow the entity handler to pass a result with the response
+    OCStackResult result;
+    // IP address & port of client registered for observe
+    OCDevAddr *requesterAddr;
+    // CoAP token for the observe request
+    OCCoAPToken *requestToken;
+    // The ID of CoAP pdu
+    uint16_t coapID;
+    // Flag indicating that response is to be delayed before sending
+    uint8_t delayedResNeeded;
+    uint8_t secured;
+    uint8_t slowFlag;
+    uint8_t notificationFlag;
+    // this is the pointer to server payload data to be transferred
+    unsigned char *payload;
+    // size of server payload data.  Don't rely on null terminated data for size
+    uint16_t payloadSize;
+    // An array of the vendor specific header options the entity handler wishes to use in response
+    uint8_t numSendVendorSpecificHeaderOptions;
+    OCHeaderOption *sendVendorSpecificHeaderOptions;
+    // URI of new resource that entity handler might create
+    unsigned char * resourceUri;
+} OCServerProtocolResponse;
 
 // following structure will be created in occoap and passed up the stack on the client side
 typedef struct {
@@ -182,11 +237,13 @@ typedef struct {
 //-----------------------------------------------------------------------------
 // Internal function prototypes
 //-----------------------------------------------------------------------------
-
-OCStackResult HandleStackRequests(OCRequest * request);
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos);
+OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status);
+OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest);
 void HandleStackResponses(OCResponse * response);
 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
+#ifdef WITH_PRESENCE
+OCStackResult SendPresenceNotification(OCResourceType *resourceType);
+#endif
 
 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
                                             const char *resourceInterfaceName);
index 2cca35c..343a874 100644 (file)
@@ -141,6 +141,7 @@ typedef enum {
     OC_STACK_OK = 0,
     OC_STACK_RESOURCE_CREATED,
     OC_STACK_RESOURCE_DELETED,
+    OC_STACK_CONTINUE,
     /* Success status code - END HERE */
     /* Error status code - START HERE */
     OC_STACK_INVALID_URI,
@@ -159,15 +160,16 @@ typedef enum {
     OC_STACK_SLOW_RESOURCE,
     OC_STACK_NO_OBSERVERS,              /* resource has no registered observers */
     OC_STACK_OBSERVER_NOT_FOUND,
-    OC_STACK_OBSERVER_NOT_ADDED,
-    OC_STACK_OBSERVER_NOT_REMOVED,
     #ifdef WITH_PRESENCE
     OC_STACK_PRESENCE_STOPPED,
     OC_STACK_PRESENCE_TIMEOUT,
     OC_STACK_PRESENCE_DO_NOT_HANDLE,
     #endif
+    OC_STACK_VIRTUAL_DO_NOT_HANDLE,
     OC_STACK_INVALID_OPTION,
     OC_STACK_MALFORMED_RESPONSE,        /* the remote reply contained malformed data */
+    OC_STACK_PERSISTENT_BUFFER_REQUIRED,
+    OC_STACK_INVALID_REQUEST_HANDLE,
     OC_STACK_ERROR
     /* Error status code - END HERE */
 } OCStackResult;
@@ -182,6 +184,9 @@ typedef void * OCDoHandle;
  */
 typedef void * OCResourceHandle;
 
+typedef void * OCRequestHandle;
+typedef void * OCResponseHandle;
+
 /**
  * Unique identifier for each observation request. Used when observations are
  * registered or deregistering. Used by entity handler to signal specific
@@ -206,6 +211,18 @@ typedef struct {
     OCObservationId obsId;
 } OCObservationInfo;
 
+/**
+ * Possible returned values from entity handler
+ */
+typedef enum {
+    OC_EH_OK = 0,
+    OC_EH_ERROR,
+    OC_EH_RESOURCE_CREATED,
+    OC_EH_RESOURCE_DELETED,
+    OC_EH_SLOW,
+    OC_EH_FORBIDDEN
+} OCEntityHandlerResult;
+
 // following structure will be used to define the vendor specific header options to be included
 // in communication packets
 
@@ -227,28 +244,19 @@ typedef struct OCHeaderOption {
 typedef struct {
     // Associated resource
     OCResourceHandle resource;
-    // resource query send by client
-    unsigned char * query;
+    OCRequestHandle requestHandle;
     // the REST method retrieved from received request PDU
     OCMethod method;
-    // reqJSON is retrieved from the payload of the received request PDU
-    unsigned const char * reqJSONPayload;
-    // resJSON is allocated in the stack and will be used by entity handler to fill in its response
-    unsigned char * resJSONPayload;
-    // Length of maximum allowed response
-    uint16_t resJSONPayloadLen;
+    // resource query send by client
+    unsigned char * query;
     // Information associated with observation - valid only when OCEntityHandler
     // flag includes OC_OBSERVE_FLAG
-    OCObservationInfo *obsInfo;
+    OCObservationInfo obsInfo;
     // An array of the received vendor specific header options
     uint8_t numRcvdVendorSpecificHeaderOptions;
-    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
-    // An array of the vendor specific header options the entity handler wishes to use in response
-    uint8_t numSendVendorSpecificHeaderOptions;
-    OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
-    // URI of new resource that entity handler might create
-    unsigned char *newResourceUri;
-
+    OCHeaderOption * rcvdVendorSpecificHeaderOptions;
+    // reqJSON is retrieved from the payload of the received request PDU
+    unsigned char * reqJSONPayload;
 }OCEntityHandlerRequest;
 
 /**
@@ -268,6 +276,30 @@ typedef struct {
     OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
 }OCClientResponse;
 
+typedef struct
+{
+    // Request handle is passed to server via the entity handler for each incoming request.
+    // Stack assigns when request is received, server sets to indicate what request response is for
+    OCRequestHandle requestHandle;
+    // New handle for tracking block (or slow) response.  Stack assigns, server uses for subsequent calls
+    OCResponseHandle  *responseHandle;
+    // Resource handle
+    OCResourceHandle resourceHandle;
+    // Allow the entity handler to pass a result with the response
+    OCEntityHandlerResult  ehResult;
+    // this is the pointer to server payload data to be transferred
+    unsigned char *payload;
+    // size of server payload data.  I don't think we should rely on null terminated data for size
+    uint16_t payloadSize;
+    // An array of the vendor specific header options the entity handler wishes to use in response
+    uint8_t numSendVendorSpecificHeaderOptions;
+    OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+    // URI of new resource that entity handler might create
+    unsigned char resourceUri[MAX_URI_LENGTH];
+    // Server sets to true for persistent response buffer, false for non-persistent response buffer
+    uint8_t persistentBufferFlag;
+} OCEntityHandlerResponse;
+
 typedef enum {
     OC_INIT_FLAG    = (1 << 0),
     OC_REQUEST_FLAG = (1 << 1),
@@ -306,17 +338,6 @@ typedef struct {
 } OCCallbackData;
 
 /**
- * Possible returned values from entity handler
- */
-typedef enum {
-    OC_EH_OK = 0,
-    OC_EH_ERROR,
-    OC_EH_RESOURCE_CREATED,
-    OC_EH_RESOURCE_DELETED,
-    OC_EH_FORBIDDEN
-} OCEntityHandlerResult;
-
-/**
  * Application server implementations must implement this callback to consume requests OTA.
  * Entity handler callback needs to fill the resPayload of the entityHandlerRequest.
  */
@@ -739,6 +760,7 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
  * @param obsIdList - list of observation ids that need to be notified
  * @param numberOfIds - number of observation ids included in obsIdList
  * @param notificationJSONPayload - JSON encoded payload to send in notification
+ * @param qos - desired quality of service of the observation notifications
  * NOTE: The memory for obsIdList and notificationJSONPayload is managed by the
  * entity invoking the API. The maximum size of the notification is 1015 bytes
  * for non-Arduino platforms. For Arduino the maximum size is 247 bytes.
@@ -749,10 +771,36 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
  */
 OCStackResult
 OCNotifyListOfObservers (OCResourceHandle handle,
-                         OCObservationId  *obsIdList,
-                         uint8_t          numberOfIds,
-                         unsigned char    *notificationJSONPayload,
-                         OCQualityOfService qos);
+                            OCObservationId  *obsIdList,
+                            uint8_t          numberOfIds,
+                            unsigned char    *notificationJSONPayload,
+                            OCQualityOfService qos);
+
+
+/**
+ * Send a response to a request.
+ * The response can be a normal, slow, or block (i.e. a response that
+ * is too large to be sent in a single PDU and must span multiple transmissions)
+ *
+ * @param response - pointer to structure that contains response parameters
+ *
+ * @return
+ *     OC_STACK_OK    - no errors
+ */
+OCStackResult OCDoResponse(OCEntityHandlerResponse *response);
+
+/**
+ * Cancel a response.  Applies to a block response
+ *
+ * @param responseHandle - response handle set by stack in OCServerResponse after
+ *                         OCDoResponse is called
+ *
+ * @return
+ *     OC_STACK_OK               - No errors; Success
+ *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
+ */
+OCStackResult OCCancelResponse(OCResponseHandle responseHandle);
+
 
 #ifdef __cplusplus
 }
index bba1f90..52cd7d6 100644 (file)
@@ -151,42 +151,69 @@ void PrintArduinoMemoryStats()
 OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest )
 {
     OCEntityHandlerResult ehRet = OC_EH_OK;
+    OCEntityHandlerResponse response = {0};
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
     {
         OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+
         if(OC_REST_GET == entityHandlerRequest->method)
         {
-            if (strlen(responsePayloadGet) < entityHandlerRequest->resJSONPayloadLen)
+            size_t responsePayloadGetLength = strlen(responsePayloadGet);
+            if (responsePayloadGetLength < (sizeof(payload) - 1))
             {
-                strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadGet, entityHandlerRequest->resJSONPayloadLen);
+                strncpy(payload, responsePayloadGet, responsePayloadGetLength);
             }
             else
             {
                 ehRet = OC_EH_ERROR;
             }
         }
-        if(OC_REST_PUT == entityHandlerRequest->method)
+        else if(OC_REST_PUT == entityHandlerRequest->method)
         {
             //Do something with the 'put' payload
-            if (strlen(responsePayloadPut) < entityHandlerRequest->resJSONPayloadLen)
+            size_t responsePayloadPutLength = strlen(responsePayloadPut);
+            if (responsePayloadPutLength < (sizeof(payload) - 1))
             {
-                strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadPut, entityHandlerRequest->resJSONPayloadLen);
+                strncpy((char *)payload, responsePayloadPut, responsePayloadPutLength);
             }
             else
             {
                 ehRet = OC_EH_ERROR;
             }
          }
+
+        if (ehRet == OC_EH_OK)
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = entityHandlerRequest->requestHandle;
+            response.resourceHandle = entityHandlerRequest->resource;
+            response.ehResult = ehRet;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            response.numSendVendorSpecificHeaderOptions = 0;
+            memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+            memset(response.resourceUri, 0, sizeof response.resourceUri);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
+            {
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ehRet = OC_EH_ERROR;
+            }
+        }
     }
     if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
     {
-        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
             gLEDUnderObservation = 1;
         }
-        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
         {
             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
         }
index 6ce48b4..3f2b586 100644 (file)
@@ -59,8 +59,8 @@ const char *getResult(OCStackResult result) {
     case OC_STACK_NO_OBSERVERS:
         return "OC_STACK_NO_OBSERVERS";
     #ifdef WITH_PRESENCE
-    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-        return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+    case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+        return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
     case OC_STACK_PRESENCE_STOPPED:
         return "OC_STACK_PRESENCE_STOPPED";
     case OC_STACK_PRESENCE_TIMEOUT:
index fd2aaf8..07164ad 100644 (file)
@@ -38,6 +38,7 @@ OCRANDOM_DIR  = $(ROOT_DIR)/ocrandom
 OCSOCKET_DIR   = $(ROOT_DIR)/ocsocket
 LCOAP_DIR      = $(ROOT_DIR)/libcoap-4.1.1
 OCCOAP_DIR     = $(ROOT_DIR)/occoap
+OCMALLOC_DIR   = $(ROOT_DIR)/ocmalloc
 OCTBSTACK_DIR  = $(ROOT_DIR)/stack
 EXTLIBS_DIR    = $(ROOT_DIR)/../../extlibs
 CJSON_DIR      = $(EXTLIBS_DIR)/cjson
@@ -50,6 +51,7 @@ OCRANDOM_INC  = $(OCRANDOM_DIR)/include
 OCSOCKET_INC   = $(OCSOCKET_DIR)/include
 LCOAP_INC      = $(LCOAP_DIR)
 OCCOAP_INC     = $(OCCOAP_DIR)/include
+OCMALLOC_INC   = $(OCMALLOC_DIR)/include
 OCTBSTACK_INC  = $(OCTBSTACK_DIR)/include
 CJSON_INC      = $(CJSON_DIR)
 
@@ -59,6 +61,7 @@ INC_DIRS      += -I$(OCRANDOM_INC)
 INC_DIRS       += -I$(OCSOCKET_INC)
 INC_DIRS       += -I$(LCOAP_INC)
 INC_DIRS       += -I$(OCCOAP_INC)
+INC_DIRS       += -I$(OCMALLOC_INC)
 INC_DIRS       += -I$(OCTBSTACK_INC)
 INC_DIRS       += -I$(CJSON_INC)
 
@@ -72,17 +75,19 @@ CPPFLAGS    += $(CC_FLAGS.$(BUILD)) $(LDLIBS)
 
 CJSON_SOURCES          := $(CJSON_SRC)/cJSON.c
 
-SOURCES                := $(CJSON_SOURCES)
-SOURCES     += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp
+SOURCES        := $(CJSON_SOURCES)
+SOURCES        += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp ocserverslow.cpp occlientslow.cpp
 
 OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES))
 
 PROGRAMS       += ocserver
 PROGRAMS       += occlient
 PROGRAMS       += ocserverbasicops
+PROGRAMS       += ocserverslow
 PROGRAMS       += ocservercoll
 PROGRAMS       += occlientcoll
 PROGRAMS       += occlientbasicops
+PROGRAMS       += occlientslow
 
 all:   c_sdk prep_dirs $(OBJECTS) $(PROGRAMS)
 
@@ -99,6 +104,9 @@ $(OBJ_DIR)/%.o: %.cpp
 ocserver: $(OBJ_DIR)/ocserver.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+ocserverslow: $(OBJ_DIR)/ocserverslow.o $(OBJ_DIR)/common.o
+       $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
 ocserverbasicops: $(OBJ_DIR)/ocserverbasicops.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
@@ -111,6 +119,9 @@ occlient: $(OBJ_DIR)/occlient.o $(OBJ_DIR)/common.o
 occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
+occlientslow: $(OBJ_DIR)/occlientslow.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)/$@
 
index 4be565a..095647c 100644 (file)
@@ -93,7 +93,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     OCDoHandle handle;
 
     cbData.cb = cb;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, method, query.str().c_str(), 0,
@@ -119,7 +119,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
 }
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
     }
@@ -134,7 +134,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
     }
@@ -149,7 +149,7 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
 
 OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully");
     }
@@ -163,7 +163,7 @@ OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientRespo
 }
 
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
@@ -195,7 +195,7 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 }
 
 OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully");
     }
@@ -207,10 +207,9 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse
         OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumObserveNotifies);
         OC_LOG_V(INFO, TAG, "JSON = %s =============> Obs Response", clientResponse->resJSONPayload);
         gNumObserveNotifies++;
-        if (gNumObserveNotifies == 50) //large number to test observing in DELETE case.
+        if (gNumObserveNotifies == 3)  //large number to test observing in DELETE case.
         {
             if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON){
-                printf ("RESET\n");
                 if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK){
                     OC_LOG(ERROR, TAG, "Observe cancel error");
                 }
@@ -235,7 +234,7 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 }
 #ifdef WITH_PRESENCE
 OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for Presence recvd successfully");
     }
@@ -265,7 +264,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     uint8_t remoteIpAddr[4];
     uint16_t remotePortNu;
 
-    if (ctx == (void*) CTX_VAL)
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
     }
@@ -508,7 +507,7 @@ int InitDiscovery()
         strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     }
     cbData.cb = discoveryReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
index 1bc1d57..cb59cb0 100644 (file)
@@ -28,7 +28,7 @@
 // Defines
 //-----------------------------------------------------------------------------
 #define TAG "occlient"
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 #ifndef MAX_LENGTH_IPv4_ADDR
 #define MAX_LENGTH_IPv4_ADDR 16
 #endif
index 5ac6a90..7ae7d29 100644 (file)
@@ -67,7 +67,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     OCDoHandle handle;
 
     cbData.cb = cb;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, method, query.str().c_str(), 0,
@@ -84,7 +84,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
     }
@@ -99,7 +99,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 
 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
     }
@@ -115,7 +115,7 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
 
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
-    if(ctx == (void*)CTX_VAL)
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
@@ -154,7 +154,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     uint8_t remoteIpAddr[4];
     uint16_t remotePortNu;
 
-    if (ctx == (void*) CTX_VAL)
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
     }
@@ -262,7 +262,7 @@ int InitDiscovery()
         strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     }
     cbData.cb = discoveryReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
index debd8ed..6752bed 100644 (file)
@@ -27,7 +27,7 @@
 // Defines
 //-----------------------------------------------------------------------------
 #define TAG "occlientbasicops"
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 #ifndef MAX_LENGTH_IPv4_ADDR
 #define MAX_LENGTH_IPv4_ADDR 16
 #endif
index 2a93a6f..523057b 100644 (file)
@@ -33,7 +33,7 @@ std::string getPortTBServer(OCClientResponse * clientResponse);
 std::string getQueryStrForGetPut(unsigned  const char * responsePayload);
 
 #define TAG PCF("occlient")
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 #ifndef MAX_LENGTH_IPv4_ADDR
 #define MAX_LENGTH_IPv4_ADDR 16
 #endif
@@ -98,7 +98,7 @@ int InitDiscovery();
 
 void PrintUsage()
 {
-    OC_LOG(INFO, TAG, "Usage : occlient -t <Test Case>");
+    OC_LOG(INFO, TAG, "Usage : occlientcoll -t <Test Case>");
     OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources && Initiate GET Request on an"\
             "available resource using default interface.");
     OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources && Initiate GET Request on an"\
@@ -121,7 +121,7 @@ void PrintUsage()
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
     if(clientResponse) {}
-    if(ctx == (void*)CTX_VAL) {
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
         OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
     }
@@ -132,14 +132,14 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
     OC_LOG_V(INFO, TAG, "StackResult: %s",
             getResult(clientResponse->result));
-    if(ctx == (void*)CTX_VAL) {
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         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", gNumObserveNotifies);
+            OC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d", gNumObserveNotifies);
             OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
             gNumObserveNotifies++;
             if (gNumObserveNotifies == 3)
@@ -169,19 +169,18 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
     OC_LOG_V(INFO, TAG, "StackResult: %s",
             getResult(clientResponse->result));
 
-    if (ctx == (void*) CTX_VAL) {
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE) {
         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);
-#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
 
     if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
             TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
@@ -204,7 +203,7 @@ int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse)
     std::ostringstream getQuery;
     getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource";
     cbData.cb = getReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
 
     ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS,
@@ -225,7 +224,7 @@ int InitObserveRequest(OCClientResponse * clientResponse)
     std::ostringstream obsReg;
     obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
     cbData.cb = getReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     OC_LOG_V(INFO, TAG, "OBSERVE payload from client = %s ", putPayload.c_str());
 
@@ -253,7 +252,7 @@ int InitPutRequest(OCClientResponse * clientResponse)
     getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) <<
     "/a/room" << queryInterface[TEST].text;
     cbData.cb = putReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
 
@@ -288,7 +287,7 @@ int InitGetRequest(OCClientResponse * clientResponse)
     std::cout << "Get Query: " << getQuery.str() << std::endl;
 
     cbData.cb = getReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS,
             &cbData, NULL, 0);
@@ -310,7 +309,7 @@ int InitDiscovery()
     strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
 
     cbData.cb = discoveryReqCB;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS,
             &cbData, NULL, 0);
@@ -322,24 +321,28 @@ int InitDiscovery()
 }
 
 int main(int argc, char* argv[]) {
-    if(argc >= 2 && strcmp(argv[1], "-t") == 0)
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = USE_RANDOM_PORT;
+    uint8_t ifname[] = "eth0";
+    int opt;
+
+    while ((opt = getopt(argc, argv, "t:")) != -1)
     {
-        TEST = atoi(argv[2]);
-        if(TEST >= MAX_TESTS || TEST < 1)
+        switch(opt)
         {
+        case 't':
+            TEST = atoi(optarg);
+            break;
+        default:
             PrintUsage();
-            return 0;
+            return -1;
         }
     }
-    else
-    {
+    if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){
         PrintUsage();
-        return 0;
+        return -1;
     }
-    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*/
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp
new file mode 100644 (file)
index 0000000..5fc9108
--- /dev/null
@@ -0,0 +1,307 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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 <iostream>
+#include <sstream>
+#include "ocstack.h"
+#include "logger.h"
+#include "occlientslow.h"
+
+static int UNICAST_DISCOVERY = 0;
+static int TEST_CASE = 0;
+static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core";
+static std::string putPayload = "{\"state\":\"off\",\"power\":10}";
+static std::string coapServerIP = "255.255.255.255";
+static std::string coapServerPort = "5683";
+static std::string coapServerResource = "/a/led";
+
+int gQuitFlag = 0;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+static void PrintUsage()
+{
+    OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>");
+    OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
+    OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
+    OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request");
+    OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get Request");
+}
+
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+        OCMethod method, OCQualityOfService qos,
+        OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+
+    cbData.cb = cb;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+
+    ret = OCDoResource(&handle, method, query.str().c_str(), 0,
+            NULL,
+            qos, &cbData, options, numOptions);
+
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
+    }
+
+    return ret;
+}
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+    {
+        OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+    }
+
+    if(clientResponse)
+    {
+        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+        OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+                clientResponse->resJSONPayload);
+    }
+    if(clientResponse->rcvdVendorSpecificHeaderOptions &&
+            clientResponse->numRcvdVendorSpecificHeaderOptions)
+    {
+        OC_LOG (INFO, TAG, "Received vendor specific options");
+        uint8_t i = 0;
+        OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
+        for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
+        {
+            if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
+            {
+                OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
+                        ((OCHeaderOption)rcvdOptions[i]).optionID );
+                OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
+                        ((OCHeaderOption)rcvdOptions[i]).optionLength);
+            }
+        }
+    }
+    return OC_STACK_DELETE_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;
+
+    if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
+    {
+        OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
+    }
+
+    if (clientResponse)
+    {
+        OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+
+        OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
+                remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+        OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
+
+        OC_LOG_V(INFO, TAG,
+                "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
+                clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
+                remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
+
+        parseClientResponse(clientResponse);
+
+        switch(TEST_CASE)
+        {
+            case TEST_NON_CON_OP:
+                InitGetRequest(OC_LOW_QOS);
+                break;
+            case TEST_CON_OP:
+                InitGetRequest(OC_HIGH_QOS);
+                break;
+            default:
+                PrintUsage();
+                break;
+        }
+    }
+
+    return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
+
+}
+
+int InitGetRequest(OCQualityOfService qos)
+{
+    OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+    std::ostringstream query;
+    query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+
+    return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
+            OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+}
+
+int InitDiscovery()
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    OCDoHandle handle;
+    /* Start a discovery query*/
+    char szQueryUri[64] = { 0 };
+    if (UNICAST_DISCOVERY)
+    {
+        strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY);
+    }
+    else
+    {
+        strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
+    }
+    cbData.cb = discoveryReqCB;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
+    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";
+    int opt;
+
+    while ((opt = getopt(argc, argv, "u:t:")) != -1)
+    {
+        switch(opt)
+        {
+            case 'u':
+                UNICAST_DISCOVERY = atoi(optarg);
+                break;
+            case 't':
+                TEST_CASE = atoi(optarg);
+                break;
+            default:
+                PrintUsage();
+                return -1;
+        }
+    }
+
+    if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
+            (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) )
+    {
+        PrintUsage();
+        return -1;
+    }
+
+
+    /*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(2);
+    }
+    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'};
+    // ostringstream not working correctly here, hence snprintf
+    snprintf(ipaddr,  sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d);
+    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(OCClientResponse * clientResponse)
+{
+    return "/a/led";
+}
+
+void parseClientResponse(OCClientResponse * clientResponse)
+{
+    coapServerIP = getIPAddrTBServer(clientResponse);
+    coapServerPort = getPortTBServer(clientResponse);
+    coapServerResource = getQueryStrForGetPut(clientResponse);
+}
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h
new file mode 100644 (file)
index 0000000..60713d7
--- /dev/null
@@ -0,0 +1,95 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OCCLIENT_BASICOPS_H_
+#define OCCLIENT_BASICOPS_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "occlientslow"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#ifndef MAX_LENGTH_IPv4_ADDR
+#define MAX_LENGTH_IPv4_ADDR 16
+#endif
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/**
+ * List of methods that can be inititated from the client
+ */
+typedef enum {
+    TEST_DISCOVER_REQ = 1,
+    TEST_NON_CON_OP,
+    TEST_CON_OP,
+    MAX_TESTS
+} CLIENT_TEST;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+
+/* call getResult in common.cpp to get the result in string format. */
+const char *getResult(OCStackResult result);
+
+/* Get the IP address of the server */
+std::string getIPAddrTBServer(OCClientResponse * clientResponse);
+
+/* Get the port number the server is listening on */
+std::string getPortTBServer(OCClientResponse * clientResponse);
+
+/* Returns the query string for GET and PUT operations */
+std::string getQueryStrForGetPut(OCClientResponse * clientResponse);
+
+/* Following are initialization functions for GET, PUT
+ * POST & Discovery operations
+ */
+int InitGetRequest(OCQualityOfService qos);
+int InitDiscovery();
+
+/* Function to retrieve ip address, port no. of the server
+ *  and query for the operations to be performed.
+ */
+void parseClientResponse(OCClientResponse * clientResponse);
+
+/* This function calls OCDoResource() which in turn makes calls
+ * to the lower layers
+ */
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+        OCMethod method, OCQualityOfService qos,
+        OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Following are callback functions for the  GET and Discovery operations
+ */
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
+
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+        OCClientResponse * clientResponse);
+
+#endif
index a2ca7dc..061bb81 100644 (file)
@@ -101,43 +101,51 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     return jsonResponse;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *getResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+    if (maxPayloadSize > strlen ((char *)getResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, getResp,
-                strlen((char *)getResp));
+        strncpy(payload, getResp, strlen((char *)getResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(getResp);
+
+    return ehResult;
 }
 
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *putResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+    if (maxPayloadSize > strlen ((char *)putResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, putResp,
-                strlen((char *)putResp));
+        strncpy(payload, putResp, strlen((char *)putResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(putResp);
+
+    return ehResult;
 }
 
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
 {
     OCEntityHandlerResult ehResult = OC_EH_OK;
     char *respPLPost_light = NULL;
@@ -174,7 +182,7 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
                 gLightInstance[gCurrLightInstance].power = 0;
                 gCurrLightInstance++;
                 respPLPost_light = cJSON_Print(json);
-                strncpy ((char *)ehRequest->newResourceUri, newLightUri, MAX_URI_LENGTH);
+                strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
                 ehResult = OC_EH_RESOURCE_CREATED;
             }
 
@@ -209,23 +217,22 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         }
     }
 
-    if (respPLPost_light != NULL && ehRequest->resJSONPayloadLen > \
-            strlen((char *)respPLPost_light))
+    if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
     {
-        strncpy((char *)ehRequest->resJSONPayload, respPLPost_light,
-                strlen((char *)respPLPost_light));
+        strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(respPLPost_light);
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
     OCEntityHandlerResult ehResult = OC_EH_OK;
 
@@ -236,7 +243,7 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
      * 1a. pass the delete request to the c stack
      * 1b. internally, the c stack figures out what needs to be done and does it accordingly
      *    (e.g. send observers notification, remove observers...)
-     * 1c. the c stack returns with the result whether the request is fullfilLight.
+     * 1c. the c stack returns with the result whether the request is fullfilled.
      * 2. optionally, app removes observers out of its array 'interestedObservers'
      */
 
@@ -286,20 +293,21 @@ OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
         ehResult = OC_EH_FORBIDDEN;
     }
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)deleteResponse))
+    if (maxPayloadSize > strlen ((char *)deleteResponse))
     {
-        strncpy((char *)ehRequest->resJSONPayload, deleteResponse, strlen((char *)deleteResponse));
+        strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                  ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     return ehResult;
 }
 
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
 
@@ -307,14 +315,14 @@ OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *
     response = responsePayloadResourceDoesNotExist;
 
     if ( (ehRequest != NULL) &&
-         (ehRequest->resJSONPayloadLen > strlen ((char *)response)) )
+         (maxPayloadSize > strlen ((char *)response)) )
     {
-        strncpy((char *)ehRequest->resJSONPayload, response, strlen((char *)response));
+        strncpy((char *)payload, response, strlen((char *)response));
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                  ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
     }
 
     return OC_EH_RESOURCE_DELETED;
@@ -323,12 +331,12 @@ OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *
 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
 {
     OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
-            ehRequest->obsInfo->obsId);
+            ehRequest->obsInfo.obsId);
     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
     {
         if (interestedObservers[i].valid == false)
         {
-            interestedObservers[i].observationId = ehRequest->obsInfo->obsId;
+            interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
             interestedObservers[i].valid = true;
             gLightUnderObservation = 1;
             break;
@@ -341,10 +349,10 @@ void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
     bool clientStillObserving = false;
 
     OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
-            ehRequest->obsInfo->obsId);
+            ehRequest->obsInfo.obsId);
     for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
     {
-        if (interestedObservers[i].observationId == ehRequest->obsInfo->obsId)
+        if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
         {
             interestedObservers[i].valid = false;
         }
@@ -365,6 +373,20 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
     OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
 
     OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    // Initialize certain response fields
+    response.numSendVendorSpecificHeaderOptions = 0;
+    memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+    memset(response.resourceUri, 0, sizeof response.resourceUri);
 
     if (flag & OC_INIT_FLAG)
     {
@@ -373,47 +395,62 @@ OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
     if (flag & OC_REQUEST_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
-        if (entityHandlerRequest)
+        if (entityHandlerRequest->resource == NULL) {
+            OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
+            ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_GET == entityHandlerRequest->method)
         {
-            if (entityHandlerRequest->resource == NULL) {
-                OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
-                ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
-            }
-            else if (OC_REST_GET == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_PUT == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_DELETE == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
-                ehResult = ProcessDeleteRequest (entityHandlerRequest);
-            }
-            else
+            OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+            ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_PUT == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+            ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_DELETE == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
+            ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    entityHandlerRequest->method);
+            ehResult = OC_EH_ERROR;
+        }
+
+        // If the result isn't an error or forbidden, send response
+        if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = entityHandlerRequest->requestHandle;
+            response.resourceHandle = entityHandlerRequest->resource;
+            response.ehResult = ehResult;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
             {
-                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
-                        entityHandlerRequest->method);
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ehResult = OC_EH_ERROR;
             }
         }
     }
     if (flag & OC_OBSERVE_FLAG)
     {
         OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
-        if (entityHandlerRequest)
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
-            if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
-            }
-            else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
-            }
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
+        }
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
+        {
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
         }
     }
 
@@ -428,6 +465,20 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
 
     OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    // Initialize certain response fields
+    response.numSendVendorSpecificHeaderOptions = 0;
+    memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+    memset(response.resourceUri, 0, sizeof response.resourceUri);
 
     if (flag & OC_INIT_FLAG)
     {
@@ -436,80 +487,97 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
     if (flag & OC_REQUEST_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
-        if (entityHandlerRequest)
+        if (OC_REST_GET == entityHandlerRequest->method)
         {
-            if (OC_REST_GET == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_PUT == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_POST == entityHandlerRequest->method)
-            {
-                OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ehResult = ProcessPostRequest (entityHandlerRequest);
-            }
-            else if (OC_REST_DELETE == entityHandlerRequest->method)
+            OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+            ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_PUT == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+            ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_POST == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+            ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
+        }
+        else if (OC_REST_DELETE == entityHandlerRequest->method)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
+            ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    entityHandlerRequest->method);
+        }
+
+        // If the result isn't an error or forbidden, send response
+        if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
+        {
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = entityHandlerRequest->requestHandle;
+            response.resourceHandle = entityHandlerRequest->resource;
+            response.ehResult = ehResult;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Handle vendor specific options
+            if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
+                    entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
             {
-                OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
-                ehResult = ProcessDeleteRequest (entityHandlerRequest);
+                OC_LOG (INFO, TAG, "Received vendor specific options");
+                uint8_t i = 0;
+                OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
+                for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
+                {
+                    if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
+                    {
+                        OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
+                                ((OCHeaderOption)rcvdOptions[i]).optionID );
+                        OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
+                                ((OCHeaderOption)rcvdOptions[i]).optionLength);
+                    }
+                }
+                OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
+                uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
+                uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
+                sendOptions[0].protocolID = OC_COAP_ID;
+                sendOptions[0].optionID = 2248;
+                memcpy(sendOptions[0].optionData, option2, sizeof(option2));
+                sendOptions[0].optionLength = 10;
+                sendOptions[1].protocolID = OC_COAP_ID;
+                sendOptions[1].optionID = 2600;
+                memcpy(sendOptions[1].optionData, option3, sizeof(option3));
+                sendOptions[1].optionLength = 10;
+                response.numSendVendorSpecificHeaderOptions = 2;
             }
-            else
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
             {
-                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
-                        entityHandlerRequest->method);
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ehResult = OC_EH_ERROR;
             }
         }
     }
     if (flag & OC_OBSERVE_FLAG)
     {
         OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
-        if (entityHandlerRequest)
+
+        if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
-            if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
-                ProcessObserveRegister (entityHandlerRequest);
-            }
-            else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
-            {
-                OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
-                ProcessObserveDeregister (entityHandlerRequest);
-            }
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
+            ProcessObserveRegister (entityHandlerRequest);
         }
-    }
-    if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
-            entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
-    {
-        OC_LOG (INFO, TAG, "Received vendor specific options");
-        uint8_t i = 0;
-        OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
-        for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
+        else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
         {
-            if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
-            {
-                OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
-                        ((OCHeaderOption)rcvdOptions[i]).optionID );
-                OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
-                        ((OCHeaderOption)rcvdOptions[i]).optionLength);
-            }
+            OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
+            ProcessObserveDeregister (entityHandlerRequest);
         }
-        OCHeaderOption * sendOptions = entityHandlerRequest->sendVendorSpecificHeaderOptions;
-        uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
-        uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
-        sendOptions[0].protocolID = OC_COAP_ID;
-        sendOptions[0].optionID = 2248;
-        memcpy(sendOptions[0].optionData, option2, sizeof(option2));
-        sendOptions[0].optionLength = 10;
-        sendOptions[1].protocolID = OC_COAP_ID;
-        sendOptions[1].optionID = 2600;
-        memcpy(sendOptions[1].optionData, option3, sizeof(option3));
-        sendOptions[1].optionLength = 10;
-        entityHandlerRequest->numSendVendorSpecificHeaderOptions = 2;
     }
 
     return ehResult;
index c34f130..f5e45e5 100644 (file)
@@ -70,11 +70,24 @@ void *ChangeLightRepresentation (void *param);
 
 /* Following methods process the PUT, GET, POST, Delete,
  * & Observe requests */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                          OCEntityHandlerResponse *response,
+                                          char *payload,
+                                          uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
+                                            char *payload,
+                                            uint16_t maxPayloadSize);
+
+OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest,
+                                                         char *payload,
+                                                         uint16_t maxPayloadSize);
+
 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest);
 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest);
 
index 971056d..e7f092b 100644 (file)
@@ -29,7 +29,7 @@
 #include "cJSON.h"
 #include "ocserverbasicops.h"
 
-int gQuitFlag = 0;
+volatile sig_atomic_t gQuitFlag = 0;
 
 static LEDResource LED;
 // This variable determines instance number of the LED resource.
@@ -81,47 +81,56 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     return jsonResponse;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *getResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+    if (maxPayloadSize > strlen ((char *)getResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, getResp,
-                strlen((char *)getResp));
+        strncpy(payload, getResp, strlen((char *)getResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(getResp);
+
+    return ehResult;
 }
 
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    OCEntityHandlerResult ehResult;
     char *putResp = constructJsonResponse(ehRequest);
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+    if (maxPayloadSize > strlen ((char *)putResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, putResp,
-                strlen((char *)putResp));
+        strncpy(payload, putResp, strlen((char *)putResp));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(putResp);
+
+    return ehResult;
 }
 
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
     char *respPLPost_led = NULL;
     cJSON *json;
     cJSON *format;
+    OCEntityHandlerResult ehResult;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -183,18 +192,21 @@ void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         }
     }
 
-    if (respPLPost_led != NULL && ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+    if ((respPLPost_led != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_led)))
     {
-        strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
-                strlen((char *)respPLPost_led));
+        strncpy(payload, respPLPost_led, strlen((char *)respPLPost_led));
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(respPLPost_led);
+
+    return ehResult;
 }
 
 OCEntityHandlerResult
@@ -202,9 +214,15 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         OCEntityHandlerRequest *entityHandlerRequest)
 {
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
+
     if (flag & OC_INIT_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
+        ehResult = OC_EH_OK;
     }
     if (flag & OC_REQUEST_FLAG)
     {
@@ -214,26 +232,48 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             if (OC_REST_GET == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
+                ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
             }
             else if (OC_REST_PUT == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
+                ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
             }
             else if (OC_REST_POST == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ProcessPostRequest (entityHandlerRequest);
+                ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
             }
             else
             {
                 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
                         entityHandlerRequest->method);
             }
+
+            if (ehResult == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
         }
     }
-    return OC_EH_OK;
+    return ehResult;
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
@@ -251,8 +291,6 @@ int main(int argc, char* argv[])
     uint8_t* paddr = NULL;
     uint16_t port = OC_WELL_KNOWN_PORT;
     uint8_t ifname[] = "eth0";
-    int opt;
-
 
     OC_LOG(DEBUG, TAG, "OCServer is starting...");
     /*Get Ip address on defined interface and initialize coap on it with random port number
index af9f00c..74f862e 100644 (file)
@@ -54,9 +54,15 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
 /* Following methods process the PUT, GET, POST
  * requests
  */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                          char *payload,
+                                          uint16_t maxPayloadSize);
 
 /* call getResult in common.cpp to get the result in string format. */
 const char *getResult(OCStackResult result);
index 7a6d239..364d7a1 100644 (file)
@@ -33,7 +33,7 @@ const char *getResult(OCStackResult result);
 
 #define TAG PCF("ocservercontainer")
 
-int gQuitFlag = 0;
+volatile sig_atomic_t gQuitFlag = 0;
 int gLightUnderObservation = 0;
 void createResources();
 typedef struct LIGHTRESOURCE{
@@ -69,18 +69,40 @@ const char rspPutFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"false
 const char rspPutFanCollection[] = "{\"href\":\"/a/fan\"}";
 const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}";
 
+typedef enum {
+    TEST_INVALID = 0,
+    TEST_DEFAULT_COLL_EH,
+    TEST_APP_COLL_EH,
+    MAX_TESTS
+} SERVER_TEST;
+
+void PrintUsage()
+{
+    OC_LOG(INFO, TAG, "Usage : ocservercoll -t <Test Case>");
+    OC_LOG(INFO, TAG, "Test Case 1 : Create room resource with default collection entity handler.");
+    OC_LOG(INFO, TAG, "Test Case 2 : Create room resource with application collection entity handler.");
+}
+
+unsigned static int TEST = TEST_INVALID;
+
 static OCEntityHandlerResult
-HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char* errStr)
+HandleCallback(OCEntityHandlerRequest * ehRequest,
+               const char* opStr,
+               const char* errStr,
+               char *payload,
+               uint16_t maxPayloadSize)
 {
     OCEntityHandlerResult ret = OC_EH_OK;
 
-    if (strlen(opStr) < ehRequest->resJSONPayloadLen)
+    // Append opStr or errStr, after making sure there is
+    // enough room in the payload
+    if (strlen(opStr) < (maxPayloadSize - strlen(payload)))
     {
-        strncat((char*)ehRequest->resJSONPayload, opStr, ehRequest->resJSONPayloadLen);
+        strncat((char*)payload, opStr, strlen(opStr));
     }
-    else if (strlen(errStr) < ehRequest->resJSONPayloadLen)
+    else if (strlen(errStr) < (maxPayloadSize - strlen(payload)))
     {
-        strncat((char*)ehRequest->resJSONPayload, errStr, ehRequest->resJSONPayloadLen);
+        strncat((char*)payload, errStr, strlen(errStr));
         ret = OC_EH_ERROR;
     }
     else
@@ -92,7 +114,7 @@ HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char
 }
 
 static void
-PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest )
+PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
 {
     const char* typeOfMessage;
 
@@ -115,10 +137,12 @@ PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehReques
              (ehRequest->method == OC_REST_GET) ? "OC_REST_GET" : "OC_REST_PUT" );
 }
 
-OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
-        OCEntityHandlerRequest * ehRequest )
+OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
+                                            OCEntityHandlerRequest * ehRequest)
 {
     OCEntityHandlerResult ret = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG_V(INFO, TAG, "Callback for Room");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -131,90 +155,136 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
         {
             if(query.find("oc.mi.def") != std::string::npos)
             {
-                ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom);
+                ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom, payload, sizeof(payload));
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
                 }
             }
             else if(query.find("oc.mi.ll") != std::string::npos)
             {
-                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom);
+                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
                 }
             }
             else if(query.find("oc.mi.b") != std::string::npos)
             {
-                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom);
+                ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
+                }
+            }
+            if (ret == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = ehRequest->requestHandle;
+                response.resourceHandle = ehRequest->resource;
+                response.ehResult = ret;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof response.resourceUri);
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ret = OC_EH_ERROR;
                 }
             }
         }
-        if(OC_REST_PUT == ehRequest->method)
+        else if(OC_REST_PUT == ehRequest->method)
         {
             if(query.find("oc.mi.def") != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom);
+                    ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom, payload, sizeof(payload));
                 }
             }
             if(query.find("oc.mi.ll") != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom);
+                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan, payload, sizeof(payload));
                 }
             }
             if(query.find("oc.mi.b") != std::string::npos)
             {
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom);
+                    ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
                 }
                 if(ret != OC_EH_ERROR)
                 {
-                    ret = HandleCallback(ehRequest, ",", ",");
-                    ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan);
+                    ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+                    ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
                 }
             }
+            if (ret == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = ehRequest->requestHandle;
+                response.resourceHandle = ehRequest->resource;
+                response.ehResult = ret;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof response.resourceUri);
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ret = OC_EH_ERROR;
+                }
+            }
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    ehRequest->method);
+            ret = OC_EH_ERROR;
         }
     }
     else if (ehRequest && flag == OC_OBSERVE_FLAG)
@@ -224,8 +294,11 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
     return ret;
 }
 
-OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
+{
     OCEntityHandlerResult ret = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG_V(INFO, TAG, "Callback for Light");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -234,11 +307,39 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityH
     {
         if(OC_REST_GET == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight);
+            ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
+        }
+        else if(OC_REST_PUT == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
         }
-        if(OC_REST_PUT == ehRequest->method)
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    ehRequest->method);
+            ret = OC_EH_ERROR;
+        }
+
+        if (ret == OC_EH_OK)
         {
-            ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight);
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = ehRequest->requestHandle;
+            response.resourceHandle = ehRequest->resource;
+            response.ehResult = ret;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            response.numSendVendorSpecificHeaderOptions = 0;
+            memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+            memset(response.resourceUri, 0, sizeof response.resourceUri);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
+            {
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ret = OC_EH_ERROR;
+            }
         }
     }
     else if (ehRequest && flag == OC_OBSERVE_FLAG)
@@ -249,8 +350,11 @@ OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityH
     return ret;
 }
 
-OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
+{
     OCEntityHandlerResult ret = OC_EH_OK;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG_V(INFO, TAG, "Callback for Fan");
     PrintReceivedMsgInfo(flag, ehRequest );
@@ -259,12 +363,41 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHan
     {
         if(OC_REST_GET == ehRequest->method)
         {
-            ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan);
+            ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
+        }
+        else if(OC_REST_PUT == ehRequest->method)
+        {
+            ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    ehRequest->method);
+            ret = OC_EH_ERROR;
         }
-        if(OC_REST_PUT == ehRequest->method)
+
+        if (ret == OC_EH_OK)
         {
-            ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan);
+            // Format the response.  Note this requires some info about the request
+            response.requestHandle = ehRequest->requestHandle;
+            response.resourceHandle = ehRequest->resource;
+            response.ehResult = ret;
+            response.payload = (unsigned char *)payload;
+            response.payloadSize = strlen(payload);
+            response.numSendVendorSpecificHeaderOptions = 0;
+            memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+            memset(response.resourceUri, 0, sizeof response.resourceUri);
+            // Indicate that response is NOT in a persistent buffer
+            response.persistentBufferFlag = 0;
+
+            // Send the response
+            if (OCDoResponse(&response) != OC_STACK_OK)
+            {
+                OC_LOG(ERROR, TAG, "Error sending response");
+                ret = OC_EH_ERROR;
+            }
         }
+
     }
     else if (ehRequest && flag == OC_OBSERVE_FLAG)
     {
@@ -275,8 +408,10 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHan
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
-void handleSigInt(int signum) {
-    if (signum == SIGINT) {
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
         gQuitFlag = 1;
     }
 }
@@ -303,18 +438,36 @@ void *ChangeLightRepresentation (void *param)
     return NULL;
 }
 
-int main() {
-    printf("hello world from main\n");
-    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+int main(int argc, char* argv[])
+{
     uint8_t addr[20] = {0};
     uint8_t* paddr = NULL;
     uint16_t port = 0;
     uint8_t ifname[] = "eth0";
     pthread_t threadId;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "t:")) != -1)
+    {
+        switch(opt)
+        {
+        case 't':
+            TEST = atoi(optarg);
+            break;
+        default:
+            PrintUsage();
+            return -1;
+        }
+    }
+    if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){
+        PrintUsage();
+        return -1;
+    }
 
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
     /*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,
+    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);
@@ -339,8 +492,10 @@ int main() {
     // Break from loop with Ctrl-C
     OC_LOG(INFO, TAG, "Entering ocserver main loop...");
     signal(SIGINT, handleSigInt);
-    while (!gQuitFlag) {
-        if (OCProcess() != OC_STACK_OK) {
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
             OC_LOG(ERROR, TAG, "OCStack process error");
             return 0;
         }
@@ -355,13 +510,15 @@ int main() {
 
     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
 
-    if (OCStop() != OC_STACK_OK) {
+    if (OCStop() != OC_STACK_OK)
+    {
         OC_LOG(ERROR, TAG, "OCStack process error");
     }
 
     return 0;
 }
-void createResources() {
+void createResources()
+{
     light.state = false;
 
     OCResourceHandle fan;
@@ -383,12 +540,26 @@ void createResources() {
     OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
 
     OCResourceHandle room;
-    res = OCCreateResource(&room,
-            "core.room",
-            "oc.mi.b",
-            "/a/room",
-            OCEntityHandlerRoomCb,
-            OC_DISCOVERABLE);
+
+    if(TEST == TEST_APP_COLL_EH)
+    {
+        res = OCCreateResource(&room,
+                "core.room",
+                "oc.mi.b",
+                "/a/room",
+                OCEntityHandlerRoomCb,
+                OC_DISCOVERABLE);
+    }
+    else
+    {
+        res = OCCreateResource(&room,
+                "core.room",
+                "oc.mi.b",
+                "/a/room",
+                NULL,
+                OC_DISCOVERABLE);
+    }
+
     OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
     OCBindResourceInterfaceToResource(room, "oc.mi.ll");
     OCBindResourceInterfaceToResource(room, "oc.mi.def");
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp
new file mode 100644 (file)
index 0000000..e1184e1
--- /dev/null
@@ -0,0 +1,362 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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 <sys/time.h>
+#include <list>
+#include "ocstack.h"
+#include "ocmalloc.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "ocserverslow.h"
+
+volatile sig_atomic_t gQuitFlag = 0;
+
+static std::list<OCEntityHandlerRequest *> gRequestList;
+static constexpr unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static unsigned int gCurrLedInstance = 0;
+static constexpr unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+//char *gResourceUri= const_cast<char *>("/a/led");
+char *gResourceUri= (char *)"/a/led";
+
+static constexpr uint16_t OC_WELL_KNOWN_PORT = 5683;
+
+//This function takes the request as an input and returns the response
+//in JSON format.
+char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+{
+    cJSON *json = cJSON_CreateObject();
+    cJSON *format;
+    char *jsonResponse;
+    LEDResource *currLEDResource = &LED;
+
+    OC_LOG(INFO, TAG, "Entering constructJsonResponse");
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        OC_LOG(INFO, TAG, "handle 0");
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = const_cast<char *>("a/led/0");
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        OC_LOG(INFO, TAG, "handle 1");
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = const_cast<char *>("a/led/1");
+    }
+
+    if(OC_REST_PUT == ehRequest->method)
+    {
+        cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
+        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
+                "on") ? true:false);
+        currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
+        cJSON_Delete(putJson);
+    }
+
+    cJSON_AddStringToObject(json,"href",gResourceUri);
+    cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
+    cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off"));
+    cJSON_AddNumberToObject(format, "power", currLEDResource->power);
+
+    OC_LOG(INFO, TAG, "Before constructJsonResponse print");
+    jsonResponse = cJSON_Print(json);
+    OC_LOG(INFO, TAG, "Before constructJsonResponse delete");
+    cJSON_Delete(json);
+
+    OC_LOG(INFO, TAG, "Before constructJsonResponse return");
+    return jsonResponse;
+}
+
+void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+{
+    OC_LOG(INFO, TAG, "Entering ProcessGetRequest");
+    char *getResp = constructJsonResponse(ehRequest);
+    OC_LOG(INFO, TAG, "After constructJsonResponse");
+    OCEntityHandlerResponse response;
+
+    // Format the response.  Note this requires some info about the request
+    response.requestHandle = ehRequest->requestHandle;
+    response.resourceHandle = ehRequest->resource;
+    response.ehResult = OC_EH_OK;
+    response.payload = (unsigned char *)getResp;
+    response.payloadSize = strlen(getResp) + 1;
+    response.numSendVendorSpecificHeaderOptions = 0;
+    memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+    memset(response.resourceUri, 0, sizeof(response.resourceUri));
+    // Indicate that response is NOT in a persistent buffer
+    response.persistentBufferFlag = 0;
+
+    // Send the response
+    if (OCDoResponse(&response) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "Error sending response");
+    }
+
+    free(getResp);
+}
+
+OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
+{
+    OC_LOG(INFO, TAG, "Copying received request for slow response");
+    OCEntityHandlerRequest *request = (OCEntityHandlerRequest *)OCMalloc(sizeof(OCEntityHandlerRequest));
+    if (request)
+    {
+        // Do shallow copy
+        memcpy(request, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
+        // Do deep copy of query
+        request->query = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->query) + 1);
+        if (request->query)
+        {
+            strcpy((char *)request->query, (const char *)entityHandlerRequest->query);
+
+            // Copy the request payload
+            request->reqJSONPayload = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->reqJSONPayload) + 1);
+            if (request->reqJSONPayload)
+            {
+                strcpy((char *)request->reqJSONPayload, (const char *)entityHandlerRequest->reqJSONPayload);
+
+                // Ignore vendor specific header options for example
+                request->numRcvdVendorSpecificHeaderOptions = 0;
+                request->rcvdVendorSpecificHeaderOptions = NULL;
+            }
+            else
+            {
+                OCFree(request->query);
+                OCFree(request);
+                request = NULL;
+            }
+        }
+        else
+        {
+            OCFree(request);
+            request = NULL;
+        }
+    }
+
+    if (request)
+    {
+        OC_LOG(INFO, TAG, "Copied client request");
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Error copying client request");
+    }
+    return request;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest)
+{
+    OCEntityHandlerResult result = OC_EH_ERROR;
+    OCEntityHandlerRequest *request = NULL;
+
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+    if (flag & OC_INIT_FLAG)
+    {
+        OC_LOG(INFO, TAG, "Flag includes OC_INIT_FLAG");
+        result = OC_EH_OK;
+    }
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            OC_LOG_V (INFO, TAG, "request query %s from client",
+                                        entityHandlerRequest->query);
+            OC_LOG_V (INFO, TAG, "request payload %s from client",
+                                        entityHandlerRequest->reqJSONPayload);
+            // Make deep copy of received request and queue it for slow processing
+            request = CopyRequest(entityHandlerRequest);
+            if (request)
+            {
+
+                OC_LOG(INFO, TAG, "Scheduling slow response for received request");
+                gRequestList.push_back(request);
+                // Indicate to the stack that this is a slow response
+                result = OC_EH_SLOW;
+                // Start the slow response alarm
+                alarm(SLOW_RESPONSE_DELAY_SEC);
+            }
+            else
+            {
+                OC_LOG(ERROR, TAG, "Error queuing request for slow response");
+                // Indicate to the stack that this is a slow response
+                result = OC_EH_ERROR;
+            }
+        }
+        else
+        {
+            OC_LOG(ERROR, TAG, "Invalid request");
+            result = OC_EH_ERROR;
+        }
+    }
+    return result;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+// SIGINT alarm handler:  alarm set by entity handler.  Does
+// slow response when fired
+void AlarmHandler(int sig)
+{
+    if (sig == SIGALRM)
+    {
+        OC_LOG (INFO, TAG, "Server starting slow response");
+        if (gRequestList.empty())
+        {
+            OC_LOG (INFO, TAG, "No requests to service");
+            return;
+        }
+
+        // Get the request from the list
+        OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
+        gRequestList.pop_front();
+        if (entityHandlerRequest->method == OC_REST_GET)
+        {
+            OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+            ProcessGetRequest (entityHandlerRequest);
+        }
+        else
+        {
+            OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                    entityHandlerRequest->method);
+        }
+        // Free the request
+        OCFree(entityHandlerRequest->query);
+        OCFree(entityHandlerRequest->reqJSONPayload);
+        OCFree(entityHandlerRequest);
+
+        // If there are more requests in list, re-arm the alarm signal
+        if (gRequestList.empty())
+        {
+            alarm(SLOW_RESPONSE_DELAY_SEC);
+        }
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    uint8_t addr[20] = {0};
+    uint8_t* paddr = NULL;
+    uint16_t port = OC_WELL_KNOWN_PORT;
+    uint8_t ifname[] = "eth0";
+
+
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+    /*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
+     */
+    createLEDResource(gResourceUri, &LED, false, 0);
+
+    // Initialize slow response alarm
+    signal(SIGALRM, AlarmHandler);
+
+    // 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(2);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    // Free requests
+    if (!gRequestList.empty())
+    {
+        for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
+        {
+            OCFree((*iter)->query);
+            OCFree((*iter)->reqJSONPayload);
+            OCFree(*iter);
+        }
+        gRequestList.clear();
+    }
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            "oc.mi.def",
+            uri,
+            OCEntityHandlerCb,
+            OC_DISCOVERABLE|OC_OBSERVABLE);
+    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h
new file mode 100644 (file)
index 0000000..bf37c34
--- /dev/null
@@ -0,0 +1,71 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OCSERVER_SLOW_H_
+#define OCSERVER_SLOW_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "ocserverslow"
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+//-----------------------------------------------------------------------------
+// Function prototypes
+//-----------------------------------------------------------------------------
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following method process the GET request
+ */
+void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
+
+/* call getResult in common.cpp to get the result in string format. */
+const char *getResult(OCStackResult result);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Entity Handler callback functions */
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest);
+
+#endif
index 8664f2e..5358170 100644 (file)
@@ -59,8 +59,8 @@ const char *getResult(OCStackResult result) {
     case OC_STACK_NO_OBSERVERS:
         return "OC_STACK_NO_OBSERVERS";
     #ifdef WITH_PRESENCE
-    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-        return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+    case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+        return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
     case OC_STACK_PRESENCE_STOPPED:
         return "OC_STACK_PRESENCE_STOPPED";
     #endif
index 7ed8d14..5635802 100644 (file)
@@ -81,47 +81,59 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     return jsonResponse;
 }
 
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                        char *payload, size_t maxPayloadSize)
 {
-    char *getResp = constructJsonResponse(ehRequest);
+    OCEntityHandlerResult ehResult;
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+    char *getResp = constructJsonResponse(ehRequest);
+    if (maxPayloadSize > strlen (getResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, getResp,
-                strlen((char *)getResp));
+        strcpy(payload, getResp);
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(getResp);
+
+    return ehResult;
 }
 
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                        char *payload, size_t maxPayloadSize)
 {
-    char *putResp = constructJsonResponse(ehRequest);
+    OCEntityHandlerResult ehResult;
 
-    if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+    char *putResp = constructJsonResponse(ehRequest);
+    if (maxPayloadSize > strlen (putResp))
     {
-        strncpy((char *)ehRequest->resJSONPayload, putResp,
-                strlen((char *)putResp));
+        strcpy(payload, putResp);
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(putResp);
+
+    return ehResult;
 }
 
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                        char *payload, size_t maxPayloadSize)
 {
     char *respPLPost_led = NULL;
     cJSON *json;
     cJSON *format;
+    OCEntityHandlerResult ehResult;
 
     /*
      * The entity handler determines how to process a POST request.
@@ -183,18 +195,21 @@ void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
         }
     }
 
-    if (respPLPost_led != NULL && ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+    if ((respPLPost_led != NULL) && (maxPayloadSize > strlen (respPLPost_led)))
     {
-        strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
-                strlen((char *)respPLPost_led));
+        strcpy(payload, respPLPost_led);
+        ehResult = OC_EH_OK;
     }
     else
     {
         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
-                ehRequest->resJSONPayloadLen);
+                maxPayloadSize);
+        ehResult = OC_EH_ERROR;
     }
 
     free(respPLPost_led);
+
+    return ehResult;
 }
 
 OCEntityHandlerResult
@@ -202,9 +217,15 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
         OCEntityHandlerRequest *entityHandlerRequest)
 {
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response;
+    char payload[MAX_RESPONSE_LENGTH];
+
     if (flag & OC_INIT_FLAG)
     {
         OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
+        ehResult = OC_EH_OK;
     }
     if (flag & OC_REQUEST_FLAG)
     {
@@ -214,26 +235,48 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             if (OC_REST_GET == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
-                ProcessGetRequest (entityHandlerRequest);
+                ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload));
             }
             else if (OC_REST_PUT == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
-                ProcessPutRequest (entityHandlerRequest);
+                ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload));
             }
             else if (OC_REST_POST == entityHandlerRequest->method)
             {
                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
-                ProcessPostRequest (entityHandlerRequest);
+                ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload));
             }
             else
             {
                 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
                         entityHandlerRequest->method);
             }
+
+            if (ehResult == OC_EH_OK)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (unsigned char *)payload;
+                response.payloadSize = strlen(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
         }
     }
-    return OC_EH_OK;
+    return ehResult;
 }
 
 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
@@ -288,7 +331,6 @@ int main(int argc, char* argv[])
             return 0;
         }
         nanosleep(&timeout, NULL);
-        //sleep(2);
     }
 
     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
index af9f00c..4edbd8e 100644 (file)
@@ -54,9 +54,15 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
 /* Following methods process the PUT, GET, POST
  * requests
  */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         size_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         char *payload,
+                                         size_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                          char *payload,
+                                          size_t maxPayloadSize);
 
 /* call getResult in common.cpp to get the result in string format. */
 const char *getResult(OCStackResult result);
index 2e4b276..a5a4000 100644 (file)
@@ -92,10 +92,10 @@ ValidateQuery (const unsigned char *query, OCResourceHandle resource,
         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)
             {
@@ -123,45 +123,59 @@ ValidateQuery (const unsigned char *query, OCResourceHandle resource,
         return OC_STACK_INVALID_QUERY;
     }
 
-    if (!ifPtr)
-    {
-        // IF not specified in query, use default IF
-        *ifParam = STACK_IF_DEFAULT;
-    }
-    else
+    if (ifPtr)
     {
         if(CheckIFParamSupport((OCResource *)resource, ifPtr) != OC_STACK_OK)
+        {
             return OC_STACK_INVALID_QUERY;
-
+        }
         if (strcmp (ifPtr, OC_RSRVD_INTERFACE_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)
+    else
     {
-        // RT not specified in query. Use the first resource type for the resource as default.
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+        // IF not specified in query, use default IF
+        *ifParam = STACK_IF_DEFAULT;
     }
-    else
+
+    if (rtPtr)
     {
         if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK)
+        {
             *rtParam = rtPtr;
+        }
         else
+        {
             return OC_STACK_INVALID_QUERY;
+        }
+    }
+    else
+    {
+        // RT not specified in query. Use the first resource type for the resource as default.
+        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
     }
     OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam);
 
     return OC_STACK_OK;
 }
-static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandlerRequest *ehRequest)
+
+
+static OCStackResult BuildRootResourceJSON(OCResource *resource,
+        unsigned char * bufferPtr, uint16_t *remaining)
 {
     OCStackResult ret = OC_STACK_ERROR;
     cJSON *resObj;
@@ -170,25 +184,18 @@ static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandler
 
     OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON"));
     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)
+    if (jsonLen < *remaining)
     {
-        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--;
+        strcpy((char*) bufferPtr, jsonStr);
+        *remaining -= jsonLen;
+        bufferPtr += jsonLen;
         ret = OC_STACK_OK;
     }
 
@@ -200,112 +207,170 @@ static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandler
 
 
 static OCStackResult
-BuildCollectionJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest,
+HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
                        uint8_t filterOn, char *filterValue)
 {
     OCStackResult ret = OC_STACK_ERROR;
-    ret = BuildRootResourceJSON(resource, ehRequest);
+    unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+    size_t jsonbufferLength = 0;
+    uint16_t remaining = 0;
+    unsigned char * ptr = NULL;
+    OCResource * collResource = (OCResource *) ehRequest->resource;
+
+    ptr = jsonbuffer;
+    remaining = MAX_RESPONSE_LENGTH;
+
+    ret = BuildRootResourceJSON(collResource, ptr, &remaining);
+    ptr += strlen((char*)ptr);
+
+    if (ret == OC_STACK_OK && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1))
+    {
+        *ptr = OC_JSON_SEPARATOR;
+        ptr++;
+        remaining--;
+    }
+    else
+    {
+        ret = OC_STACK_ERROR;
+    }
+    *(ptr + 1) = '\0';
 
-    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];
+            OCResource* temp = collResource->rsrcResources[i];
             if (temp)
             {
-                ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)buffer, &remaining);
+                ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)ptr, &remaining);
                 if (ret != OC_STACK_OK)
                 {
                     break;
                 }
-
-                buffer += strlen((char*)buffer);
-                if (resource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
+                ptr += strlen((char*)ptr);
+                if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
                 {
-                    *buffer = OC_JSON_SEPARATOR;
-                    buffer++;
+                    *ptr = OC_JSON_SEPARATOR;
+                    ptr++;
                     remaining--;
                 }
+                *(ptr + 1) = '\0';
             }
             else
             {
                 break;
             }
         }
-        ehRequest->resJSONPayload = buffer;
-        ehRequest->resJSONPayloadLen = remaining;
     }
 
+    jsonbufferLength = strlen((const char *)jsonbuffer);
+    if(ret == OC_STACK_OK && jsonbufferLength)
+    {
+        OCEntityHandlerResponse response;
+        memset(&response, 0, sizeof(OCEntityHandlerResponse));
+        response.ehResult = OC_EH_OK;
+        response.payload = jsonbuffer;
+        response.payloadSize = jsonbufferLength + 1;
+        response.persistentBufferFlag = 0;
+        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+        response.resourceHandle = (OCResourceHandle) collResource;
+        ret = OCDoResponse(&response);
+    }
     return ret;
 }
 
-
 static OCStackResult
-BuildCollectionBatchJSONResponse(OCEntityHandlerFlag flag,
-                OCResource *resource, OCEntityHandlerRequest *ehRequest)
+HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 {
     OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+    size_t jsonbufferLength = 0;
+    uint16_t remaining = 0;
+    unsigned char * ptr = NULL;
+    OCResource * collResource = (OCResource *) ehRequest->resource;
+
+    ptr = jsonbuffer;
+    remaining = MAX_RESPONSE_LENGTH;
+
+    stackRet = BuildRootResourceJSON(collResource, ptr, &remaining);
+    ptr += strlen((char*)ptr);
+    *(ptr + 1) = '\0';
+
+    jsonbufferLength = strlen((const char *)jsonbuffer);
+    if(jsonbufferLength)
+    {
+        OCEntityHandlerResponse response;
+        memset(&response, 0, sizeof(OCEntityHandlerResponse));
+        response.ehResult = OC_EH_OK;
+        response.payload = jsonbuffer;
+        response.payloadSize = jsonbufferLength + 1;
+        response.persistentBufferFlag = 0;
+        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+        response.resourceHandle = (OCResourceHandle) collResource;
+        stackRet = OCDoResponse(&response);
+    }
 
-    stackRet = BuildRootResourceJSON(resource, ehRequest);
     if (stackRet == OC_STACK_OK)
     {
-        OCResourceHandle origResourceHandle = ehRequest->resource;
-
         for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
         {
-            OCResource* temp = resource->rsrcResources[i];
+            OCResource* temp = collResource->rsrcResources[i];
             if (temp)
             {
+                // Note that all entity handlers called through a collection
+                // will get the same pointer to ehRequest, the only difference
+                // is ehRequest->resource
                 ehRequest->resource = (OCResourceHandle) temp;
 
-                ehRet = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
-                stackRet = EntityHandlerCodeToOCStackCode(ehRet);
+                ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
 
-                if(ehRet == OC_EH_OK)
+                // The default collection handler is returning as OK
+                if(stackRet != OC_STACK_SLOW_RESOURCE)
                 {
-                    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;
-                    }
+                    stackRet = OC_STACK_OK;
                 }
-                else
+                // if a single resource is slow, then entire response will be treated
+                // as slow response
+                if(ehResult == OC_EH_SLOW)
                 {
-                    break;
+                    OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+                    ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
+                    stackRet = EntityHandlerCodeToOCStackCode(ehResult);
                 }
             }
             else
             {
-               break;
+                break;
             }
         }
-
-        ehRequest->resource = origResourceHandle;
+        ehRequest->resource = (OCResourceHandle) collResource;
     }
     return stackRet;
 }
 
+uint8_t GetNumOfResourcesInCollection (OCResource *resource)
+{
+    uint8_t num = 0;
+    for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+    {
+        if (resource->rsrcResources[i])
+        {
+            num++;
+        }
+    }
+    return num;
+}
+
 
 OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                                               OCEntityHandlerRequest *ehRequest)
 {
-    OCStackResult result;
-    OCStackIfTypes ifQueryParam;
-    char *rtQueryParam;
+    OCStackResult result = OC_STACK_ERROR;
+    OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
+    char *rtQueryParam = NULL;
 
-    OC_LOG(INFO, TAG, PCF("DefaultCollectionEntityHandler"));
+    OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
 
     if (flag != OC_REQUEST_FLAG)
         return OC_STACK_ERROR;
@@ -328,19 +393,19 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                 // 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, PCF("STACK_IF_DEFAULT"));
-                return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
-                             ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+                return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
 
             case STACK_IF_LL:
                 OC_LOG(INFO, TAG, PCF("STACK_IF_LL"));
-                return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
-                             ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+                return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
 
             case STACK_IF_BATCH:
                 OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH"));
-                return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+                ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+                ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+                        GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+                return HandleBatchInterface(ehRequest);
 
             default:
                 return OC_STACK_ERROR;
@@ -357,7 +422,10 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                 return OC_STACK_ERROR;
 
             case STACK_IF_BATCH:
-                return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+                ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+                ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+                        GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+                return HandleBatchInterface(ehRequest);
 
             default:
                 return OC_STACK_ERROR;
index c59089f..eb624ce 100644 (file)
@@ -29,6 +29,7 @@
 #include "debug.h"
 #include "ocrandom.h"
 #include "ocmalloc.h"
+#include "ocserverrequest.h"
 
 // Module Name
 #define MOD_NAME PCF("ocobserve")
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
 
 static struct ResourceObserver * serverObsList = NULL;
-extern uint32_t SERVER_DISCOVERABLE;
 
-OCStackResult OCObserverStatus(OCCoAPToken * token, uint8_t status)
+// send notifications based on the qos of the request
+// The qos passed as a parameter overrides what the client requested
+// If we want the client preference taking high priority make:
+// qos = resourceObserver->qos;
+OCQualityOfService DetermineObserverQoS(OCMethod method, ResourceObserver * resourceObserver,
+        OCQualityOfService appQoS)
 {
-    OCStackResult result = OC_STACK_ERROR;
-    ResourceObserver * observer = NULL;
-    OCEntityHandlerRequest ehRequest;
-    OCObservationInfo observationInfo;
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
-
-    switch(status)
+    OCQualityOfService decidedQoS = appQoS;
+    if(appQoS == OC_NA_QOS)
     {
-    case OC_OBSERVER_NOT_INTERESTED:
-        OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
-        observer = GetObserverUsingToken (token);
-        if(observer)
-        {
-            FormOCEntityHandlerRequest(&ehRequest, OC_REST_CANCEL_OBSERVE, bufRes, 
-                                        NULL, NULL, NULL);
-            ehRequest.obsInfo = &observationInfo;
-            ehRequest.obsInfo->action = OC_OBSERVE_DEREGISTER;
-            ehRequest.obsInfo->obsId = observer->observeId;
-            observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
-        }
-        //observer is dead, or it is not observing anymore
-        result = DeleteObserverUsingToken (token);
-        if(result != OC_STACK_OK)
-        {
-            result = OC_STACK_OBSERVER_NOT_REMOVED;
-        }
-        else
-        {
-            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
-        }
-        break;
-    case OC_OBSERVER_STILL_INTERESTED:
-        //observer is still interested
-        OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
-                notifications, reset the failedCount"));
-        observer = GetObserverUsingToken(token);
-        if(observer)
-        {
-            observer->forceHighQos = 0;
-            observer->failedCommCount = 0;
-            result = OC_STACK_OK;
-        }
-        else
-        {
-            result = OC_STACK_OBSERVER_NOT_FOUND;
-        }
-        break;
-    case OC_OBSERVER_FAILED_COMM:
-        //observer is not reachable
-        OC_LOG(DEBUG, TAG, PCF("observer is not reachable"));
-        observer = GetObserverUsingToken(token);
-        if(observer)
-        {
-            if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
-            {
-                FormOCEntityHandlerRequest(&ehRequest, OC_REST_CANCEL_OBSERVE, bufRes, 
-                                            NULL, NULL, NULL);
-                ehRequest.obsInfo = &observationInfo;
-                ehRequest.obsInfo->action = OC_OBSERVE_DEREGISTER;
-                ehRequest.obsInfo->obsId = observer->observeId;
-                observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
-
-                result = DeleteObserverUsingToken (token);
-                if(result != OC_STACK_OK)
-                {
-                    result = OC_STACK_OBSERVER_NOT_REMOVED;
-                }
-                else
-                {
-                    OC_LOG(DEBUG, TAG, PCF("removing an observer"));
-                }
-            }
-            else
-            {
-                observer->failedCommCount++;
-                result = OC_STACK_OBSERVER_NOT_REMOVED;
-            }
-            observer->forceHighQos = 1;
-            OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
-        }
-        break;
-    default:
-        break;
+        decidedQoS = resourceObserver->qos;
     }
 
-    return result;
-}
-
-OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
-{
-    OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
-    OCEntityHandlerRequest *ehReq = request->entityHandlerRequest;
-    OCObserveReq *obs = request->observe;
-    OCObservationInfo observationInfo;
-    OCObservationId obsId;
-    ResourceObserver *resObs = NULL;
-
-    OC_LOG(INFO, TAG, PCF("Entering ProcessObserveRequest"));
-
-    request->entityHandlerRequest->resource = (OCResourceHandle)resource;
-    request->entityHandlerRequest->obsInfo = &observationInfo;
-
-    if (obs->option == OC_RESOURCE_OBSERVE_REGISTER)
+    if(appQoS != OC_HIGH_QOS)
     {
-        // Request to register new observation
-        observationInfo.action = OC_OBSERVE_REGISTER;
-        // Generate observation Id for the request
-        while (1)
-        {
-            if (OC_STACK_OK != GenerateObserverId (&obsId))
-                return OC_STACK_ERROR;
-
-            // Check if observation Id already exists
-            resObs = GetObserverUsingId (obsId);
-            if (NULL == resObs)
-            {
-                OC_LOG_V(INFO, TAG, "Observation ID is %d", obsId);
-                break;
-            }
-        }
-
-        observationInfo.obsId = obsId;
-        // Register the observation request with entity handler
-        ehRet = resource->entityHandler ((OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG),
-                                         request->entityHandlerRequest);
-        if (ehRet == OC_EH_OK)
-        {
-            // Add subscriber to the server observation list
-            stackRet = AddObserver ((const char*)(request->resourceUrl),
-                                    (const char *)(ehReq->query),
-                                    obsId, obs->token, obs->subAddr,
-                                    resource, request->qos);
-            if(stackRet != OC_STACK_OK)
-            {
-                obs->result = OC_STACK_OBSERVER_NOT_ADDED;
-                stackRet = OC_STACK_OBSERVER_NOT_ADDED;
-                // If the observation was not added in the stack notify the entity handler
-                observationInfo.action = OC_OBSERVE_DEREGISTER;
-                // If the entity handler is unable to deregister, stack cannot do anything,
-                // hence the return value from entity handler is not being checked
-                resource->entityHandler (OC_OBSERVE_FLAG, request->entityHandlerRequest);
-            }
-            else
+        OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
+                resourceObserver->lowQosCount);
+        #ifdef WITH_PRESENCE
+        if((resourceObserver->forceHighQos \
+                || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
+                && method != OC_REST_PRESENCE)
+        #else
+        if(resourceObserver->forceHighQos \
+                || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT)
+        #endif
             {
-                OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+            resourceObserver->lowQosCount = 0;
+            // at some point we have to to send CON to check on the
+            // availability of observer
+            OC_LOG(INFO, TAG, PCF("This time we are sending the  notification as High qos"));
+            decidedQoS = OC_HIGH_QOS;
             }
-        }
-        else
-        {
-            stackRet = OC_STACK_OBSERVER_NOT_ADDED;
-        }
-    }
-    else if (obs->option == OC_RESOURCE_OBSERVE_DEREGISTER)
-    {
-        // Request to deregister observation
-        observationInfo.action = OC_OBSERVE_DEREGISTER;
-
-        // Get observation Id using token
-        resObs = GetObserverUsingToken (obs->token);
-        if (NULL == resObs)
-        {
-            // Stack does not contain this observation request
-            // Either token is incorrect or observation list is corrupted
-            return OC_STACK_ERROR;
-        }
-        observationInfo.action = OC_OBSERVE_DEREGISTER;
-        observationInfo.obsId = resObs->observeId;
-        // Deregister the observation with entity handler. Ignoring return value
-        // from entity handler and deleting the observation from stack
-        resource->entityHandler ((OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG),
-                                 request->entityHandlerRequest);
-        stackRet = DeleteObserverUsingToken (obs->token);
-        if(stackRet != OC_STACK_OK)
-        {
-            obs->result = OC_STACK_OBSERVER_NOT_REMOVED;
-            stackRet = OC_STACK_OBSERVER_NOT_REMOVED;
-        }
         else
         {
-            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+            (resourceObserver->lowQosCount)++;
         }
     }
-    else
-    {
-        // Invalid observe option
-        OC_LOG(ERROR, TAG, PCF("Invalid CoAP observe option"));
-        obs->result = OC_STACK_INVALID_OBSERVE_PARAM;
-    }
-    return stackRet;
+    return decidedQoS;
 }
 
-OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
-                OCResourceType *resourceType, OCQualityOfService qos)
+#ifdef WITH_PRESENCE
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCResourceType *resourceType, OCQualityOfService qos)
+#else
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+        OCQualityOfService qos)
+#endif
 {
+    OC_LOG(INFO, TAG, PCF("Entering SendObserverNotification"));
+    OCStackResult result = OC_STACK_ERROR;
+    ResourceObserver * resourceObserver = serverObsList;
     uint8_t numObs = 0;
-    OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehRet = OC_EH_ERROR;
-    ResourceObserver *resourceObserver = serverObsList;
-    OCEntityHandlerRequest entityHandlerReq;
-    unsigned char* jsonPayload = NULL;
-    unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+    OCServerRequest * request = NULL;
+    OCEntityHandlerRequest ehRequest = {0};
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     // Find clients that are observing this resource
     while (resourceObserver)
@@ -255,103 +106,172 @@ OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uin
             if(method != OC_REST_PRESENCE)
             {
             #endif
-                // Invoke the entity handler for the client to process
-                // the query according to the new representation
-                FormOCEntityHandlerRequest(&entityHandlerReq, OC_REST_GET, bufRes,
-                        NULL, resourceObserver->query, NULL);
-                entityHandlerReq.resource = (OCResourceHandle)resPtr;
-
-                // Even if entity handler for a resource is not successful
-                // we continue calling entity handler for other resources
-                ehRet = BuildObsJSONResponse((OCResource *) resPtr, &entityHandlerReq);
-                jsonPayload = (unsigned char *)(entityHandlerReq.resJSONPayload);
+                qos = DetermineObserverQoS(method, resourceObserver, qos);
+                result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+                        0, resPtr->sequenceNum, qos, resourceObserver->query,
+                        NULL, NULL,
+                        &resourceObserver->token, resourceObserver->addr,
+                        resourceObserver->resUri, 0);
+                request->observeResult = OC_STACK_OK;
+                if(request && result == OC_STACK_OK)
+                {
+                    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+                                request->method, (OCResourceHandle) resPtr, request->query,
+                                request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+                                request->rcvdVendorSpecificHeaderOptions, OC_OBSERVE_NO_OPTION, 0);
+                    if(result == OC_STACK_OK)
+                    {
+                        ehResult = resPtr->entityHandler(OC_REQUEST_FLAG, &ehRequest);
+                        if(ehResult == OC_EH_ERROR)
+                        {
+                            FindAndDeleteServerRequest(request);
+                        }
+                    }
+                }
             #ifdef WITH_PRESENCE
             }
             else
             {
+                OCEntityHandlerResponse ehResponse = {0};
+                unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0};
                 //we know it is the default entity handler
                 OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
-
-                // we create the payload here
-                if(resourceType)
+                result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+                        0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS,
+                        NULL, NULL, NULL, &resourceObserver->token,
+                        resourceObserver->addr, resourceObserver->resUri, 0);
+                if(result == OC_STACK_OK)
                 {
-                    sprintf((char *)bufRes, "%u:%u:%s",
-                            resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
-                }
-                else
-                {
-                    sprintf((char *)bufRes, "%u:%u", resPtr->sequenceNum, maxAge);
+                    // we create the payload here
+                    if(resourceType)
+                    {
+                        sprintf((char *)presenceResBuf, "%u:%u:%s",
+                                resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
+                    }
+                    else
+                    {
+                        sprintf((char *)presenceResBuf, "%u:%u", resPtr->sequenceNum, maxAge);
+                    }
+                    memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+                    ehResponse.ehResult = OC_EH_OK;
+                    ehResponse.payload = presenceResBuf;
+                    ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1;
+                    ehResponse.persistentBufferFlag = 0;
+                    ehResponse.requestHandle = (OCRequestHandle) request;
+                    ehResponse.resourceHandle = (OCResourceHandle) resPtr;
+                    strcpy((char *)ehResponse.resourceUri, (const char *)resourceObserver->resUri);
+                    result = OCDoResponse(&ehResponse);
                 }
-
-                jsonPayload = bufRes;
-                ehRet = OC_EH_OK;
             }
-
             #endif
-            if (OC_EH_OK == ehRet)
+        }
+        resourceObserver = resourceObserver->next;
+    }
+    if (numObs == 0)
+    {
+        OC_LOG(INFO, TAG, PCF("Resource has no observers"));
+        result = OC_STACK_NO_OBSERVERS;
+    }
+    return result;
+}
+
+OCStackResult SendListObserverNotification (OCResource * resource,
+        OCObservationId  *obsIdList, uint8_t numberOfIds,
+        unsigned char *notificationJSONPayload, uint32_t maxAge,
+        OCQualityOfService qos)
+{
+    uint8_t numIds = numberOfIds;
+    ResourceObserver *observation = NULL;
+    uint8_t numSentNotification = 0;
+    OCServerRequest * request = NULL;
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerResponse ehResponse;
+    memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+
+    OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification"));
+    while(numIds)
+    {
+        OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
+        observation = NULL;
+        observation = GetObserverUsingId (*obsIdList);
+        if(observation)
+        {
+            // Found observation - verify if it matches the resource handle
+            if (observation->resource == resource)
             {
-                stackRet = OC_STACK_OK;
-                OC_LOG_V(INFO, TAG, "OCStack payload: %s",
-                        jsonPayload);
-
-                // send notifications based on the qos of the request
-                // The qos passed as a parameter overrides what the client requested
-                // If we want the client preference taking high priority add:
-                // qos = resourceObserver->qos;
-                if(qos == OC_NA_QOS){
-                    qos = resourceObserver->qos;
-                }
-                if(qos != OC_HIGH_QOS)
+                qos = DetermineObserverQoS(OC_REST_GET, observation, qos);
+
+                result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+                        0, resource->sequenceNum, qos, observation->query,
+                        NULL, NULL, &observation->token,
+                        observation->addr, observation->resUri, 0);
+                request->observeResult = OC_STACK_OK;
+                if(request && result == OC_STACK_OK)
                 {
-                    OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
-                            resourceObserver->lowQosCount);
-                    #ifdef WITH_PRESENCE
-                    if((resourceObserver->forceHighQos \
-                            || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
-                            && method != OC_REST_PRESENCE)
-                    #else
-                    if(resourceObserver->forceCON \
-                            || resourceObserver->NONCount >= MAX_OBSERVER_NON_COUNT)
-                    #endif
+                    memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+                    ehResponse.ehResult = OC_EH_OK;
+                    ehResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+                    if(!ehResponse.payload)
                     {
-                        resourceObserver->lowQosCount = 0;
-                        // at some point we have to to send CON to check on the
-                        // availability of observer
-                        OC_LOG(INFO, TAG, PCF("This time we are sending the \
-                                notification as High qos"));
-                        qos = OC_HIGH_QOS;
+                        FindAndDeleteServerRequest(request);
+                        continue;
                     }
-                    else
+                    strcpy((char *)ehResponse.payload, (const char *)notificationJSONPayload);
+                    ehResponse.payloadSize = strlen((const char *)ehResponse.payload) + 1;
+                    ehResponse.persistentBufferFlag = 0;
+                    ehResponse.requestHandle = (OCRequestHandle) request;
+                    ehResponse.resourceHandle = (OCResourceHandle) resource;
+                    result = OCDoResponse(&ehResponse);
+                    if(result == OC_STACK_OK)
                     {
-                        resourceObserver->lowQosCount++;
+                        OCFree(ehResponse.payload);
+                        FindAndDeleteServerRequest(request);
                     }
                 }
-                stackRet = OCSendCoAPNotification(resourceObserver->resUri, resourceObserver->addr,
-                        qos, &(resourceObserver->token), jsonPayload, resPtr, maxAge);
-            }
-            else
-            {
-                stackRet = OC_STACK_ERROR;
+                else
+                {
+                    FindAndDeleteServerRequest(request);
+                }
+
+                numSentNotification++;
             }
         }
-        resourceObserver = resourceObserver->next;
+        obsIdList++;
+        numIds--;
     }
-    if (numObs == 0)
+    if(numSentNotification == numberOfIds)
     {
-        OC_LOG(INFO, TAG, PCF("Resource has no observers"));
-        stackRet = OC_STACK_NO_OBSERVERS;
+        return OC_STACK_OK;
+    }
+    else if(numSentNotification == 0)
+    {
+        return OC_STACK_NO_OBSERVERS;
+    }
+    else
+    {
+        //TODO: we need to signal that not every one in the
+        // list got an update, should we also indicate who did not receive on?
+        return OC_STACK_OK;
     }
-    return stackRet;
 }
 
 OCStackResult GenerateObserverId (OCObservationId *observationId)
 {
-    OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
+    ResourceObserver *resObs = NULL;
 
+    OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
     VERIFY_NON_NULL (observationId);
-    *observationId = OCGetRandomByte();
-    return OC_STACK_OK;
 
+    do
+    {
+        *observationId = OCGetRandomByte();
+        // Check if observation Id already exists
+        resObs = GetObserverUsingId (*observationId);
+    } while (NULL != resObs);
+
+    OC_LOG_V(INFO, TAG, "Observation ID is %u", *observationId);
+
+    return OC_STACK_OK;
 exit:
     return OC_STACK_ERROR;
 }
@@ -385,7 +305,7 @@ OCStackResult AddObserver (const char         *resUri,
         }
 
         obsNode->token.tokenLength = token->tokenLength;
-        memcpy (&(obsNode->token.token), token->token, token->tokenLength);
+        memcpy (obsNode->token.token, token->token, token->tokenLength);
 
         obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr));
         VERIFY_NON_NULL (obsNode->addr);
index c9ed805..3ee30cb 100644 (file)
@@ -32,6 +32,9 @@
 
 /// Module Name
 #define TAG PCF("ocresource")
+#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+            {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
+
 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
              TAG, PCF(#arg " is NULL")); return (retVal); } }
 
@@ -182,6 +185,7 @@ OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filt
         }
     }
     jsonStr = cJSON_PrintUnformatted (resObj);
+
     jsonLen = strlen(jsonStr);
     if (jsonLen < *remaining)
     {
@@ -195,39 +199,10 @@ OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filt
     cJSON_Delete (resObj);
     free (jsonStr);
 
-
     OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
     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)
 {
@@ -277,7 +252,7 @@ OCResource *FindResourceByUri(const char* resourceUri)
 }
 
 
-OCStackResult DetermineResourceHandling (OCRequest *request,
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
                                          ResourceHandling *handling,
                                          OCResource **resource)
 {
@@ -312,11 +287,12 @@ OCStackResult DetermineResourceHandling (OCRequest *request,
 
             // Resource does not exist
             // and default device handler does not exist
+            *handling = OC_RESOURCE_NOT_SPECIFIED;
             return OC_STACK_NO_RESOURCE;
         }
 
         // secure resource will entertain only authorized requests
-        if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secure == 0))
+        if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0))
         {
             OC_LOG(INFO, TAG, PCF("Un-authorized request. Ignore it!"));
             return OC_STACK_RESOURCE_ERROR;
@@ -356,6 +332,9 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
         case OC_EH_OK:
             result = OC_STACK_OK;
             break;
+        case OC_EH_SLOW:
+            result = OC_STACK_SLOW_RESOURCE;
+            break;
         case OC_EH_ERROR:
             result = OC_STACK_ERROR;
             break;
@@ -366,7 +345,7 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
             result = OC_STACK_RESOURCE_CREATED;
             break;
         case OC_EH_RESOURCE_DELETED:
-            result = OC_STACK_NO_RESOURCE;
+            result = OC_STACK_RESOURCE_DELETED;
             break;
         default:
             result = OC_STACK_ERROR;
@@ -376,26 +355,29 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
 }
 
 static OCStackResult
-HandleVirtualResource (OCRequest *request, OCResource* resource)
+HandleVirtualResource (OCServerRequest *request, OCResource* resource)
 {
     OCStackResult result = OC_STACK_ERROR;
     char *filterValue = NULL;
     uint8_t filterOn = 0;
     uint16_t remaining = 0;
-    unsigned char *buffer = NULL;
+    unsigned char * ptr = NULL;
+    uint8_t firstLoopDone = 0;
+    unsigned char discoveryResBuf[MAX_RESPONSE_LENGTH] = {0};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
 
     result = ValidateUrlQuery (request->resourceUrl,
-            request->entityHandlerRequest->query, &filterOn,
+            request->query, &filterOn,
             &filterValue);
 
     if (result == OC_STACK_OK)
     {
         if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
         {
-            remaining = request->entityHandlerRequest->resJSONPayloadLen;
-            buffer = request->entityHandlerRequest->resJSONPayload;
+            ptr = discoveryResBuf;
+            remaining = MAX_RESPONSE_LENGTH;
+
             while(resource)
             {
                 if((resource->resourceProperties & OC_ACTIVE)
@@ -403,205 +385,260 @@ HandleVirtualResource (OCRequest *request, OCResource* resource)
                 {
                     // if there is data on the buffer, we have already added a response,
                     // so we need to add a comma before we do anything
-                    if(buffer != request->entityHandlerRequest->resJSONPayload
-                        && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
+                    if(firstLoopDone
+                            && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
                     {
-                        *buffer = OC_JSON_SEPARATOR;
-                        buffer++;
+                        *ptr = OC_JSON_SEPARATOR;
+                        ptr++;
                         remaining--;
                     }
-
+                    firstLoopDone = 1;
                     result = BuildVirtualResourceResponse(resource, filterOn, filterValue,
-                            (char*)buffer, &remaining);
+                            (char*)ptr, &remaining);
+
                     if (result != OC_STACK_OK)
                     {
                         // if this failed, we need to remove the comma added above.
-                        if(buffer != request->entityHandlerRequest->resJSONPayload)
+                        if(!firstLoopDone)
                         {
-                            buffer--;
-                            *buffer = '\0';
+                            ptr--;
+                            *ptr = '\0';
                             remaining++;
                         }
-
                         break;
                     }
-                    buffer += strlen((char*)buffer);
+                    ptr += strlen((char *)ptr);
+                    *(ptr + 1) = '\0';
                 }
                 resource = resource->next;
             }
+
+            if(strlen((const char *)discoveryResBuf) > 0)
+            {
+                OCEntityHandlerResponse response = {0};
+
+                response.ehResult = OC_EH_OK;
+                response.payload = discoveryResBuf;
+                response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
+                response.persistentBufferFlag = 0;
+                response.requestHandle = (OCRequestHandle) request;
+                response.resourceHandle = (OCResourceHandle) resource;
+
+                result = OCDoResponse(&response);
+            }
         }
         #ifdef WITH_PRESENCE
         else
         {
             if(resource->resourceProperties & OC_ACTIVE){
-                SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+                SendPresenceNotification(resource->rsrcType);
             }
-            result = OC_STACK_PRESENCE_DO_NOT_HANDLE;
         }
         #endif
     }
-
-    if (result == OC_STACK_OK)
-    {
-        request->entityHandlerRequest->resJSONPayloadLen = remaining;
-        request->entityHandlerRequest->resJSONPayload = buffer;
-    }
-
+    result = OC_STACK_VIRTUAL_DO_NOT_HANDLE;
     return result;
 }
 
 static OCStackResult
-HandleDefaultDeviceEntityHandler (OCRequest *request)
+HandleDefaultDeviceEntityHandler (OCServerRequest *request)
 {
     OCStackResult result = OC_STACK_OK;
-    OCEntityHandlerResult ehResult;
-    OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerRequest ehRequest = {0};
+
+    OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
+    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+            request->method, (OCResourceHandle) NULL, request->query,
+            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->rcvdVendorSpecificHeaderOptions, (OCObserveAction)request->observationOption, (OCObservationId)0);
+    VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // At this point we know for sure that defaultDeviceHandler exists
-    ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, ehRequest,
+    ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
                                   (char*) request->resourceUrl);
-
+    if(ehResult == OC_EH_SLOW)
+    {
+        OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+        request->slowFlag = 1;
+    }
+    else if(ehResult == OC_EH_ERROR)
+    {
+        FindAndDeleteServerRequest(request);
+    }
     result = EntityHandlerCodeToOCStackCode(ehResult);
-
-    ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
-                                    strlen((char*)ehRequest->resJSONPayload);
-    ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
-
+exit:
     return result;
 }
 
 static OCStackResult
-HandleResourceWithEntityHandler (OCRequest *request,
+HandleResourceWithEntityHandler (OCServerRequest *request,
                                  OCResource *resource,
                                  uint8_t collectionResource)
 {
-    OCStackResult result = OC_STACK_OK;
-    OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
+    ResourceObserver *resObs = NULL;
 
-    OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+    OCEntityHandlerRequest ehRequest = {0};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
-
-    ehRequest->resource = (OCResourceHandle)resource;
-
-    // status code from entity handler is ignored unless observe call
-    if (request->observe == NULL)
+    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+            request->method, (OCResourceHandle) resource, request->query,
+            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->rcvdVendorSpecificHeaderOptions,
+            (OCObserveAction)request->observationOption, 0);
+    VERIFY_SUCCESS(result, OC_STACK_OK);
+
+    if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
     {
-        ehResult = resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
-        result = EntityHandlerCodeToOCStackCode(ehResult);
+        OC_LOG(INFO, TAG, PCF("No observation requested"));
+        ehFlag = OC_REQUEST_FLAG;
     }
-    else
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
+            !collectionResource)
     {
-        // If an observation register/deregister is included handle separately
-        if (!collectionResource)
+        OC_LOG(INFO, TAG, PCF("Registering observation requested"));
+        result = GenerateObserverId(&ehRequest.obsInfo.obsId);
+        VERIFY_SUCCESS(result, OC_STACK_OK);
+
+        result = AddObserver ((const char*)(request->resourceUrl),
+                (const char *)(request->query),
+                ehRequest.obsInfo.obsId, &request->requestToken,
+                &request->requesterAddr, resource, request->qos);
+        if(result == OC_STACK_OK)
         {
-            result = ProcessObserveRequest (resource, request);
+            OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+            request->observeResult = OC_STACK_OK;
+            ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
         }
         else
         {
-            // Observation on collection resources not currently supported
-            result = OC_STACK_ERROR;
+            result = OC_STACK_OK;
+            request->observeResult = OC_STACK_ERROR;
+            OC_LOG(DEBUG, TAG, PCF("Observer Addition failed"));
+            ehFlag = OC_REQUEST_FLAG;
         }
+
     }
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
+            !collectionResource)
+    {
+        OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
+        resObs = GetObserverUsingToken (&request->requestToken);
+        if (NULL == resObs)
+        {
+            // Stack does not contain this observation request
+            // Either token is incorrect or observation list is corrupted
+            result = OC_STACK_ERROR;
+            goto exit;
+        }
+        ehRequest.obsInfo.obsId = resObs->observeId;
+        ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
 
-    if (result == OC_STACK_OK || OC_STACK_RESOURCE_CREATED)
+        result = DeleteObserverUsingToken (&request->requestToken);
+        if(result == OC_STACK_OK)
+        {
+            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+            request->observeResult = OC_STACK_OK;
+        }
+        else
+        {
+            result = OC_STACK_OK;
+            request->observeResult = OC_STACK_ERROR;
+            OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+        }
+    }
+    else
     {
-        ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
-            strlen((char*)ehRequest->resJSONPayload);
-        ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
+        result = OC_STACK_ERROR;
+        goto exit;
     }
 
+    ehResult = resource->entityHandler(ehFlag, &ehRequest);
+    if(ehResult == OC_EH_SLOW)
+    {
+        OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+        request->slowFlag = 1;
+    }
+    else if(ehResult == OC_EH_ERROR)
+    {
+        FindAndDeleteServerRequest(request);
+    }
+    result = EntityHandlerCodeToOCStackCode(ehResult);
+exit:
     return result;
 }
 
-
 static OCStackResult
-HandleCollectionResourceDefaultEntityHandler (OCRequest *request,
+HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
                                               OCResource *resource)
 {
-    request->entityHandlerRequest->resource = (OCResourceHandle)resource;
-    return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, request->entityHandlerRequest));
-}
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerRequest ehRequest = {0};
+
+    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+            request->method, (OCResourceHandle) resource, request->query,
+            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+            request->rcvdVendorSpecificHeaderOptions,
+            (OCObserveAction)request->observationOption, (OCObservationId) 0);
+    if(result != OC_STACK_OK)
+    {
+        return result;
+    }
 
+    return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
+}
 
 OCStackResult
-BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request)
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *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;
-            }
-
+        {
+            ret = HandleVirtualResource (request, resource);
+            break;
+        }
         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
-            {
-                ret = HandleDefaultDeviceEntityHandler(request);
-                break;
-            }
+        {
+            ret = HandleDefaultDeviceEntityHandler(request);
+            break;
+        }
         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
-            {
-                OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
-                return OC_STACK_ERROR;
-            }
-
+        {
+            OC_LOG(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;
-            }
+        {
+            ret = HandleResourceWithEntityHandler (request, resource, 0);
+            break;
+        }
         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
-            {
-                ret = HandleResourceWithEntityHandler (request, resource, 1);
-                break;
-            }
-
+        {
+            ret = HandleResourceWithEntityHandler (request, resource, 1);
+            break;
+        }
         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
-            {
-                ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
-                break;
-            }
-
+        {
+            ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
+            break;
+        }
+        case OC_RESOURCE_NOT_SPECIFIED:
+        {
+            ret = OC_STACK_NO_RESOURCE;
+            break;
+        }
         default:
-            {
-                OC_LOG(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);
+        {
+            OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
+            return OC_STACK_ERROR;
+        }
     }
-
-    // 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/resource/csdk/stack/src/ocserverrequest.c b/resource/csdk/stack/src/ocserverrequest.c
new file mode 100644 (file)
index 0000000..44d3f6c
--- /dev/null
@@ -0,0 +1,383 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH 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 "ocstack.h"
+#include "ocserverrequest.h"
+#include "ocresource.h"
+
+// Module Name
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
+
+#define TAG  PCF("ocserverrequest")
+
+static struct OCServerRequest * serverRequestList = NULL;
+static struct OCServerResponse * serverResponseList = NULL;
+
+OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token)
+{
+    OCServerRequest * out = NULL;
+    LL_FOREACH (serverRequestList, out)
+    {
+        OC_LOG(INFO, TAG,PCF("comparing tokens"));
+        OC_LOG_BUFFER(INFO, TAG, token.token, token.tokenLength);
+        OC_LOG_BUFFER(INFO, TAG, out->requestToken.token, out->requestToken.tokenLength);
+        if((out->requestToken.tokenLength == token.tokenLength) &&
+                (memcmp(out->requestToken.token, token.token, token.tokenLength) == 0))
+        {
+            return out;
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+    return NULL;
+}
+
+OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle)
+{
+    OCServerRequest * out = NULL;
+    LL_FOREACH (serverRequestList, out)
+    {
+        if(out == handle)
+        {
+            return out;
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+    return NULL;
+}
+
+OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
+{
+    OCServerResponse * out = NULL;
+    LL_FOREACH (serverResponseList, out)
+    {
+        if(out->requestHandle == handle)
+        {
+            return out;
+        }
+    }
+    OC_LOG(INFO, TAG, PCF("Server Response not found!!"));
+    return NULL;
+}
+
+OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
+        uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
+        uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
+        OCQualityOfService qos, unsigned char * query,
+        OCHeaderOption * rcvdVendorSpecificHeaderOptions,
+        unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
+        OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize)
+{
+    OCServerRequest * serverRequest = NULL;
+
+    serverRequest = (OCServerRequest *) OCMalloc(sizeof(OCServerRequest) + reqTotalSize - 1);
+    VERIFY_NON_NULL(serverRequest);
+
+    memset(serverRequest, 0, sizeof(OCServerRequest) + reqTotalSize - 1);
+
+    serverRequest->coapID = coapID;
+    serverRequest->delayedResNeeded = delayedResNeeded;
+    serverRequest->secured = secured;
+    serverRequest->notificationFlag = notificationFlag;
+
+    serverRequest->method = method;
+    serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions;
+    serverRequest->observationOption = observationOption;
+    serverRequest->observeResult = OC_STACK_ERROR;
+    serverRequest->qos = qos;
+    serverRequest->ehResponseHandler = HandleSingleResponse;
+    serverRequest->numResponses = 1;
+    if(query)
+    {
+        memcpy(serverRequest->query, query, strlen((const char *)query) + 1);
+    }
+    if(rcvdVendorSpecificHeaderOptions)
+    {
+        memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
+            MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
+    }
+    if(reqJSONPayload)
+    {
+        memcpy((void *)serverRequest->reqJSONPayload, (void *)reqJSONPayload,
+            strlen((const char *)reqJSONPayload) + 1);
+    }
+    serverRequest->requestComplete = 0;
+    if(requestToken)
+    {
+        memcpy(&serverRequest->requestToken, requestToken, sizeof(OCCoAPToken));
+    }
+    if(requesterAddr)
+    {
+        memcpy(&serverRequest->requesterAddr, requesterAddr, sizeof(OCDevAddr));
+    }
+    if(resourceUrl)
+    {
+        memcpy(serverRequest->resourceUrl, resourceUrl, strlen((const char *)resourceUrl) + 1);
+    }
+    *request = serverRequest;
+    OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
+    LL_APPEND (serverRequestList, serverRequest);
+    return OC_STACK_OK;
+
+exit:
+    if (serverRequest)
+    {
+        OCFree(serverRequest);
+        serverRequest = NULL;
+    }
+    *request = NULL;
+    return OC_STACK_NO_MEMORY;
+}
+
+OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
+{
+    OCServerResponse * serverResponse = NULL;
+
+    serverResponse = (OCServerResponse *) OCMalloc(sizeof(OCServerResponse));
+    VERIFY_NON_NULL(serverResponse);
+    memset(serverResponse, 0, sizeof(OCServerResponse));
+
+    serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+    VERIFY_NON_NULL(serverResponse->payload);
+    memset(serverResponse->payload, 0, sizeof(MAX_RESPONSE_LENGTH));
+
+    serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
+    serverResponse->requestHandle = requestHandle;
+
+    *response = serverResponse;
+    OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
+    LL_APPEND (serverResponseList, serverResponse);
+    return OC_STACK_OK;
+
+exit:
+    if (serverResponse)
+    {
+        OCFree(serverResponse);
+        serverResponse = NULL;
+    }
+    *response = NULL;
+    return OC_STACK_NO_MEMORY;
+}
+
+// Form the OCEntityHandlerRequest struct
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
+        OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
+        uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+        OCObservationId observeID)
+{
+    if (entityHandlerRequest)
+    {
+        memset(entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
+        entityHandlerRequest->requestHandle = request;
+        entityHandlerRequest->method = method;
+        entityHandlerRequest->resource = (OCResourceHandle) resource;
+        entityHandlerRequest->query = queryBuf;
+        entityHandlerRequest->reqJSONPayload = bufReqPayload;
+        entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
+        entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
+
+        entityHandlerRequest->obsInfo.action = observeAction;
+        entityHandlerRequest->obsInfo.obsId = observeID;
+        return OC_STACK_OK;
+    }
+
+    return OC_STACK_INVALID_PARAM;
+}
+
+void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
+{
+    OCServerResponse* tmp;
+    if(serverResponse)
+    {
+        LL_FOREACH(serverResponseList, tmp)
+        {
+            if (serverResponse == tmp)
+            {
+                DeleteServerResponse(tmp);
+                return;
+            }
+        }
+    }
+}
+
+void DeleteServerResponse(OCServerResponse * serverResponse)
+{
+    if(serverResponse) {
+        LL_DELETE(serverResponseList, serverResponse);
+        OCFree(serverResponse->payload);
+        OCFree(serverResponse);
+        OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
+    }
+}
+
+void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
+{
+    OCServerRequest* tmp;
+    if(serverRequest)
+    {
+        LL_FOREACH(serverRequestList, tmp)
+        {
+            if (serverRequest == tmp)
+            {
+                DeleteServerRequest(tmp);
+                return;
+            }
+        }
+    }
+}
+
+void DeleteServerRequest(OCServerRequest * serverRequest)
+{
+    if(serverRequest) {
+        LL_DELETE(serverRequestList, serverRequest);
+        OCFree(serverRequest);
+        serverRequest = NULL;
+        OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+    }
+}
+
+OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCServerProtocolResponse protocolResponse;
+    memset(&protocolResponse, 0, sizeof(OCServerProtocolResponse));
+
+    OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
+
+    OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
+    // Format protocol response structure with data needed for
+    // sending the response
+    protocolResponse.qos = serverRequest->qos;
+
+    if((OCResource *)ehResponse->resourceHandle &&
+            ((OCResource *)ehResponse->resourceHandle)->resourceProperties == (OCResourceProperty) 0)
+    {
+        ehResponse->ehResult = OC_EH_RESOURCE_DELETED;
+    }
+    protocolResponse.result = EntityHandlerCodeToOCStackCode(ehResponse->ehResult);
+    protocolResponse.requesterAddr = &serverRequest->requesterAddr;
+    protocolResponse.requestToken = &serverRequest->requestToken;
+    protocolResponse.numSendVendorSpecificHeaderOptions = ehResponse->numSendVendorSpecificHeaderOptions;
+    protocolResponse.sendVendorSpecificHeaderOptions = ehResponse->sendVendorSpecificHeaderOptions;
+    protocolResponse.resourceUri = ehResponse->resourceUri;
+    protocolResponse.delayedResNeeded = serverRequest->delayedResNeeded;
+    protocolResponse.secured = serverRequest->secured;
+    protocolResponse.slowFlag = serverRequest->slowFlag;
+    protocolResponse.notificationFlag = serverRequest->notificationFlag;
+
+    //should we put the prefix and suffix here?
+    protocolResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+    if(!protocolResponse.payload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+    strcpy((char *)protocolResponse.payload, (const char *)OC_JSON_PREFIX);
+    strcat((char *)protocolResponse.payload, (const char *)ehResponse->payload);
+    strcat((char *)protocolResponse.payload, (const char *)OC_JSON_SUFFIX);
+    protocolResponse.payloadSize = strlen((const char *)protocolResponse.payload) + 1;
+    protocolResponse.resourceUri = ehResponse->resourceUri;
+
+    //revise the following
+    protocolResponse.coapID = serverRequest->coapID;
+    if(serverRequest->observeResult == OC_STACK_OK)
+    {
+        protocolResponse.observationOption = serverRequest->observationOption;
+    }
+    else
+    {
+        protocolResponse.observationOption = OC_OBSERVE_NO_OPTION;
+    }
+    // Make call to OCCoAP layer
+    result = OCDoCoAPResponse(&protocolResponse);
+
+    OCFree(protocolResponse.payload);
+    //Delete the request
+    FindAndDeleteServerRequest(serverRequest);
+    return result;
+}
+
+OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
+{
+    OCStackResult stackRet = OC_STACK_ERROR;
+    OCServerRequest * serverRequest = NULL;
+    OCServerResponse * serverResponse = NULL;
+
+    OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload);
+
+    serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+    serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+
+    if(serverRequest)
+    {
+        if(!serverResponse)
+        {
+            OC_LOG(INFO, TAG, PCF("This is the first response fragment"));
+            stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
+            if (OC_STACK_OK != stackRet)
+            {
+                OC_LOG(ERROR, TAG, PCF("Error adding server response"));
+                return stackRet;
+            }
+            VERIFY_NON_NULL(serverResponse);
+            VERIFY_NON_NULL(serverResponse->payload);
+        }
+
+        if((serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 1 &&
+                serverRequest->numResponses == 1) ||
+                (serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 2 &&
+                        serverRequest->numResponses > 1))
+        {
+            OC_LOG(INFO, TAG, PCF("There is room in response buffer"));
+            // append
+            sprintf((char *)serverResponse->payload, "%s%s", (char *)serverResponse->payload, (char *)ehResponse->payload);
+            OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
+            serverResponse->remainingPayloadSize -= ehResponse->payloadSize;
+            (serverRequest->numResponses)--;
+            if(serverRequest->numResponses == 0)
+            {
+                OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
+                ehResponse->payload = serverResponse->payload;
+                ehResponse->payloadSize = strlen((char *) serverResponse->payload) + 1;
+                stackRet = HandleSingleResponse(ehResponse);
+                //Delete the request and response
+                FindAndDeleteServerRequest(serverRequest);
+                FindAndDeleteServerResponse(serverResponse);
+            }
+            else
+            {
+                OC_LOG(INFO, TAG, PCF("More response fragment to come"));
+                // TODO: we should consider using strcat rather than setting a char by char here!
+                sprintf((char *)serverResponse->payload, "%s%c", (char *)serverResponse->payload,OC_JSON_SEPARATOR);
+                OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
+                (serverResponse->remainingPayloadSize)--;
+                stackRet = OC_STACK_OK;
+            }
+        }
+        else
+        {
+            OC_LOG(INFO, TAG, PCF("No room in response buffer"));
+            //Delete the request and response
+            FindAndDeleteServerRequest(serverRequest);
+            FindAndDeleteServerResponse(serverResponse);
+            stackRet = OC_STACK_NO_MEMORY;
+        }
+    }
+exit:
+    return stackRet;
+}
index 8b08345..67bbb68 100644 (file)
@@ -31,6 +31,7 @@
 #include "debug.h"
 #include "occoap.h"
 #include "ocmalloc.h"
+#include "ocserverrequest.h"
 
 //-----------------------------------------------------------------------------
 // Typedefs
@@ -68,12 +69,112 @@ OCDeviceEntityHandler defaultDeviceHandler;
 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
              TAG, PCF(#arg " is NULL")); return (retVal); } }
 
+//TODO: we should allow the server to define this
+#define MAX_OBSERVE_AGE (0x2FFFFUL)
 //-----------------------------------------------------------------------------
 // Internal API function
 //-----------------------------------------------------------------------------
 
+// This internal function is called to update the stack with the status of
+// observers and communication failures
+OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    ResourceObserver * observer = NULL;
+    OCEntityHandlerRequest ehRequest;
+    memset(&ehRequest, 0, sizeof(OCEntityHandlerRequest));
+
+    switch(status)
+    {
+    case OC_OBSERVER_NOT_INTERESTED:
+        OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
+        observer = GetObserverUsingToken (token);
+        if(observer)
+        {
+            result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
+                    OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+                    NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+            if(result != OC_STACK_OK)
+            {
+                return result;
+            }
+            observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
+        }
+        //observer is not observing anymore
+        result = DeleteObserverUsingToken (token);
+        if(result == OC_STACK_OK)
+        {
+            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+        }
+        else
+        {
+            result = OC_STACK_OK;
+            OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+        }
+        break;
+    case OC_OBSERVER_STILL_INTERESTED:
+        //observer is still interested
+        OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
+                notifications, reset the failedCount"));
+        observer = GetObserverUsingToken(token);
+        if(observer)
+        {
+            observer->forceHighQos = 0;
+            observer->failedCommCount = 0;
+            result = OC_STACK_OK;
+        }
+        else
+        {
+            result = OC_STACK_OBSERVER_NOT_FOUND;
+        }
+        break;
+    case OC_OBSERVER_FAILED_COMM:
+        //observer is not reachable
+        OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
+        observer = GetObserverUsingToken(token);
+        if(observer)
+        {
+            if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
+            {
+                result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
+                        OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+                        NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+                if(result != OC_STACK_OK)
+                {
+                    return OC_STACK_ERROR;
+                }
+                observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
+                //observer is unreachable
+                result = DeleteObserverUsingToken (token);
+                if(result == OC_STACK_OK)
+                {
+                    OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+                }
+                else
+                {
+                    result = OC_STACK_OK;
+                    OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+                }
+            }
+            else
+            {
+                observer->failedCommCount++;
+                result = OC_STACK_CONTINUE;
+            }
+            observer->forceHighQos = 1;
+            OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
+        }
+        break;
+    default:
+        OC_LOG(ERROR, TAG, PCF("Unknown status"));
+        result = OC_STACK_ERROR;
+        break;
+        }
+    return result;
+}
+
 //This function will be called back by occoap layer when a request is received
-OCStackResult HandleStackRequests(OCRequest * request)
+OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
 {
     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
 
@@ -81,16 +182,53 @@ OCStackResult HandleStackRequests(OCRequest * request)
     ResourceHandling resHandling;
     OCResource *resource;
 
-    VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
-    VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
-
-    result = DetermineResourceHandling (request, &resHandling, &resource);
+    OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
+    if(!request)
+    {
+        OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
+        result = AddServerRequest(&request, protocolRequest->coapID,
+                protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
+                protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
+                protocolRequest->observationOption, protocolRequest->qos,
+                protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
+                protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
+                &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
+                protocolRequest->reqTotalSize);
+        if (OC_STACK_OK != result)
+        {
+            OC_LOG(ERROR, TAG, PCF("Error adding server request"));
+            return result;
+        }
+        VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
 
-    if (result == OC_STACK_OK)
+        if(!protocolRequest->reqMorePacket)
+        {
+            request->requestComplete = 1;
+        }
+    }
+    else
     {
-        result = BuildJSONResponse(resHandling, resource, request);
+        OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
     }
 
+    if(request->requestComplete)
+    {
+        OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
+        result = DetermineResourceHandling (request, &resHandling, &resource);
+        if (result == OC_STACK_OK)
+        {
+            result = ProcessRequest(resHandling, resource, request);
+        }
+        else
+        {
+            result = OC_STACK_ERROR;
+        }
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
+        result = OC_STACK_CONTINUE;
+    }
     return result;
 }
 
@@ -206,9 +344,9 @@ static void deleteAllResources();
 static void incrementSequenceNumber(OCResource * resPtr);
 static OCStackResult verifyUriQueryLength(const char * inputUri,
         uint16_t uriLen);
+static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
 
-
 //-----------------------------------------------------------------------------
 // Public APIs
 //-----------------------------------------------------------------------------
@@ -709,7 +847,7 @@ OCStackResult OCStartPresence(const uint32_t ttl)
     // a different random 32-bit integer number is used
     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
 
-    return SendPresenceNotification(NULL, OC_LOW_QOS);
+    return SendPresenceNotification(NULL);
 }
 
 /**
@@ -730,7 +868,7 @@ OCStackResult OCStopPresence()
     result = OCChangeResourceProperty(
             &(((OCResource *) presenceResource.handle)->resourceProperties),
             OC_ACTIVE, 0);
-    result = SendPresenceNotification(NULL, OC_LOW_QOS);
+    result = SendPresenceNotification(NULL);
 
     return result;
 }
@@ -862,7 +1000,7 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(pointer->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(pointer->rsrcType);
     }
     #endif
 exit:
@@ -975,7 +1113,7 @@ OCStackResult OCBindResource(
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
     }
     #endif
 
@@ -1033,7 +1171,7 @@ OCStackResult OCUnBindResource(
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
     }
     #endif
 
@@ -1159,7 +1297,7 @@ OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(resource->rsrcType);
     }
     #endif
 
@@ -1197,7 +1335,7 @@ OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(resource->rsrcType);
     }
     #endif
 
@@ -1495,7 +1633,7 @@ OCStackResult OCBindResourceHandler(OCResourceHandle handle,
     if(presenceResource.handle)
     {
         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+        SendPresenceNotification(resource->rsrcType);
     }
     #endif
 
@@ -1538,6 +1676,7 @@ void incrementSequenceNumber(OCResource * resPtr)
     return;
 }
 
+#ifdef WITH_PRESENCE
 /**
  * Notify Presence subscribers that a resource has been modified
  *
@@ -1546,7 +1685,7 @@ void incrementSequenceNumber(OCResource * resPtr)
  * @param qos          - Quality Of Service
  *
  */
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos)
+OCStackResult SendPresenceNotification(OCResourceType *resourceType)
 {
     OCResource *resPtr = NULL;
     OCStackResult result;
@@ -1566,10 +1705,10 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOf
         maxAge = 0;
     }
 
-    result = SendObserverNotification(method, resPtr, maxAge, resourceType, qos);
-
+    result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
     return result;
 }
+#endif
 
 /**
  * Notify observers that an observed value has changed.
@@ -1582,18 +1721,18 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOf
  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
  */
 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
+
+    OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
+
     OCResource *resPtr = NULL;
     OCStackResult result;
     OCMethod method = OC_REST_NOMETHOD;
     uint32_t maxAge = 0;
 
-    OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
-
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
-
     // Verify that the resource exists
     resPtr = findResource ((OCResource *) handle);
-    if (NULL == resPtr)
+    if (NULL == resPtr || myStackMode == OC_CLIENT)
     {
         return OC_STACK_NO_RESOURCE;
     }
@@ -1602,8 +1741,12 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
         //only increment in the case of regular observing (not presence)
         incrementSequenceNumber(resPtr);
         method = OC_REST_OBSERVE;
-        maxAge = 0x2FFFF;
-        result = SendObserverNotification (method, resPtr, maxAge, NULL, qos);
+        maxAge = MAX_OBSERVE_AGE;
+        #ifdef WITH_PRESENCE
+        result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
+        #else
+        result = SendAllObserverNotification (method, resPtr, maxAge, qos);
+        #endif
         return result;
     }
 }
@@ -1617,27 +1760,14 @@ OCNotifyListOfObservers (OCResourceHandle handle,
 {
     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
 
+    OCResource *resPtr = NULL;
+    //TODO: we should allow the server to define this
+    uint32_t maxAge = MAX_OBSERVE_AGE;
+
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
 
-    uint8_t numIds = numberOfIds;
-    ResourceObserver *observation;
-    OCResource *resPtr = NULL;
-    uint32_t maxAge = 0;
-    unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
-    unsigned char *currPtr;
-    uint8_t numSentNotification = 0;
-
-    // Verify the notification payload length does not exceed the maximim
-    // the stack can handle
-    if ((strlen((char *)notificationJSONPayload) +
-         OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
-    {
-        OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
-        return OC_STACK_ERROR;
-    }
-
     // Verify that the resource exists
     resPtr = findResource ((OCResource *) handle);
     if (NULL == resPtr || myStackMode == OC_CLIENT)
@@ -1647,75 +1777,88 @@ OCNotifyListOfObservers (OCResourceHandle handle,
     else
     {
         incrementSequenceNumber(resPtr);
-        //TODO: we should allow the serve to define thisl
-        maxAge = 0x2FFFF;
     }
+    return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
+            notificationJSONPayload, maxAge, qos));
+}
 
-    while (numIds)
+/**
+ * Send a response to a request.
+ * The response can be a regular, slow, or block (i.e. a response that
+ * is too large to be sent in a single PDU and must span multiple transmissions)
+ *
+ * @param response - pointer to structure that contains response parameters
+ *
+ * @return
+ *     OC_STACK_OK                         - No errors; Success
+ *     OC_STACK_INVALID_PARAM              - Invalid pointer to OCServerResponse
+ *     OC_STACK_INVALID_REQUEST_HANDLE     - Request handle not found
+ *     OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
+ *                                           persistent response buffer is necessary
+ */
+OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCServerRequest *serverRequest = NULL;
+
+    OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
+
+    // Validate input parameters
+    VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
+
+    // TODO: Placeholder for creating a response entry when implementing
+    // block transfer feature
+
+    // If a response payload is present, check if block transfer is required
+    if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
+            (const char *)ehResponse->payload, ehResponse->payloadSize))
     {
-        OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
-        observation = NULL;
-        observation = GetObserverUsingId (*obsIdList);
-        if (observation)
+        OC_LOG(INFO, TAG, PCF("Block transfer required"));
+
+        // Persistent response buffer is needed for block transfer
+        if (!ehResponse->persistentBufferFlag)
         {
-            // Found observation - verify if it matches the resource handle
-            if (observation->resource == resPtr)
-            {
-                strcpy((char*)bufNotify, OC_JSON_PREFIX);
-                currPtr = bufNotify + OC_JSON_PREFIX_LEN;
-                memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
-                currPtr += strlen((char *)notificationJSONPayload);
-                strcpy((char*)currPtr, OC_JSON_SUFFIX);
-
-                // send notifications based on the qos of the request
-                // The qos passed as a parameter overrides what the client requested
-                // If we want the client preference taking high priority add:
-                // QoS = resourceObserver->qos;
-                if(qos == OC_NA_QOS){
-                    qos = observation->qos;
-                }
-                if(qos != OC_HIGH_QOS)
-                {
-                    OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
-                            observation->lowQosCount);
-                    if(observation->forceHighQos \
-                            || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
-                    {
-                        observation->lowQosCount = 0;
-                        // at some point we have to to send CON to check on the
-                        // availability of observer
-                        OC_LOG(INFO, TAG, PCF("This time we are sending the \
-                                notification as High qos"));
-                        qos = OC_HIGH_QOS;
-                    }
-                    else
-                    {
-                        observation->lowQosCount++;
-                    }
-                }
-                OCSendCoAPNotification (observation->resUri, observation->addr,
-                                        qos, &(observation->token),
-                                        bufNotify, resPtr, maxAge);
-                numSentNotification++;
-            }
+            OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
+            return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
         }
-        obsIdList++;
-        numIds--;
-    }
-    if(numSentNotification == numberOfIds)
-    {
-        return OC_STACK_OK;
-    }
-    else if(numSentNotification == 0)
-    {
-        return OC_STACK_NO_OBSERVERS;
+        // TODO: Placeholder for block transfer handling
+        // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
+            // when implementing the block transfer feature
     }
     else
     {
-        //TODO: we need to signal that not every one in the
-        // list got an update, should we also indicate who did not receive on?
-        return OC_STACK_OK;
+        // Normal response
+
+        // Get pointer to request info
+        serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+        if(serverRequest)
+        {
+            result = serverRequest->ehResponseHandler(ehResponse);
+        }
     }
+    return result;
+}
+
+/**
+ * Cancel a response.  Applies to a block response
+ *
+ * @param responseHandle - response handle set by stack in OCServerResponse after
+ *                         OCDoResponse is called
+ *
+ * @return
+ *     OC_STACK_OK               - No errors; Success
+ *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
+ */
+OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
+{
+    OCStackResult result = OC_STACK_NOTIMPL;
+
+    OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
+
+    // TODO: validate response handle
+
+    return result;
 }
 
 //-----------------------------------------------------------------------------
@@ -1728,7 +1871,7 @@ static OCDoHandle GenerateInvocationHandle()
 {
     OCDoHandle handle = NULL;
     // Generate token here, it will be deleted when the transaction is deleted
-    handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+    handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
     if (handle)
     {
         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
@@ -1859,7 +2002,7 @@ int deleteResource(OCResource *resource) {
             if(presenceResource.handle)
             {
                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-                SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+                SendPresenceNotification(resource->rsrcType);
             }
             #endif
 
@@ -2059,6 +2202,45 @@ OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
 }
 
 /**
+ * Determine if a request/response must be sent in a block transfer because it is too large to be
+ * sent in a single PDU.  This function can be used for either a request or a response
+ *
+ * @param request  - NULL or pointer to request
+ * @param response - NULL or pointer to response
+ * @param size     - 0 or size of the request/response.  If 0, strlen is used for determining
+ *                   the length of the request/response
+ *
+ * @return
+ *    0 - packet transfer NOT required (i.e. normal request/response)
+ *    1 - packet transfer required (i.e. block transfer needed)
+ */
+uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
+{
+    uint8_t result = 0;
+
+    // Determine if we are checking a request or a response
+    if (request)
+    {
+        // If size is greater than 0, use it for the request size value, otherwise
+        // assume request is null terminated and use strlen for size value
+        if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
+        {
+            result = 1;
+        }
+    }
+    else if (response)
+    {
+        // If size is greater than 0, use it for the response size value, otherwise
+        // assume response is null terminated and use strlen for size value
+        if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
+        {
+            result = 1;
+        }
+    }
+    return result;
+}
+
+/**
  * Retrieves a resource type based upon a uri string if the uri string contains only just one
  * resource attribute (and that has to be of type "rt").
  *
@@ -2118,5 +2300,3 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
     exit:
         return OC_STACK_NO_MEMORY;
 }
-
-
index a69b10d..f753da8 100644 (file)
@@ -72,7 +72,7 @@ CORE_COBJ = WInterrupts.o wiring.o wiring_digital.o
 CORE_CPPOBJ = main.o Stream.o WMath.o WString.o HardwareSerial.o Print.o SPI.o IPAddress.o wiring_analog.o
 ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o
 ETH_UTIL_CPPOBJ = socket.o w5100.o
-OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocstack.o occoaphelper.o occoap.o occlientcb.o
+OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocserverrequest.o ocstack.o occoaphelper.o occoap.o occlientcb.o
 OCDEPENDENT_CPPOBJ = wiring_analog.o
 CJSON_COBJ = cJSON.o
 
index 4f9d70d..ac76a47 100644 (file)
@@ -44,33 +44,36 @@ OBJ_DIR       := $(OUT_DIR)/obj
 
 OUT_DIR          := $(PWD)
 
-OCLOGGER_DIR   = $(ROOT_DIR)/logger
+LOGGER_DIR     = $(ROOT_DIR)/logger
+OC_LOG_DIR      = $(ROOT_DIR)/../oc_logger
 OCRANDOM_DIR   = $(ROOT_DIR)/ocrandom
 OCSOCKET_DIR   = $(ROOT_DIR)/ocsocket
-LCOAP_DIR              = $(ROOT_DIR)/libcoap-4.1.1
-OCCOAP_DIR             = $(ROOT_DIR)/occoap
+LCOAP_DIR      = $(ROOT_DIR)/libcoap-4.1.1
+OCCOAP_DIR     = $(ROOT_DIR)/occoap
 OCTBSTACK_DIR  = $(ROOT_DIR)/stack
 
-OCLOGGER_INC   = $(OCLOGGER_DIR)/include
+LOGGER_INC     = $(LOGGER_DIR)/include
+OC_LOG_INC     = $(OC_LOG_DIR)/include
 OCRANDOM_INC   = $(OCRANDOM_DIR)/include
 OCSOCKET_INC   = $(OCSOCKET_DIR)/include
-LCOAP_INC              = $(LCOAP_DIR)
-OCCOAP_INC             = $(OCCOAP_DIR)/include
+LCOAP_INC      = $(LCOAP_DIR)
+OCCOAP_INC     = $(OCCOAP_DIR)/include
 OCTBSTACK_INC  = $(OCTBSTACK_DIR)/include
 
-INC_DIRS       := -I$(OCLOGGER_INC)
+INC_DIRS       := -I$(LOGGER_INC)
+INC_DIRS       += -I$(OC_LOG_INC)
 INC_DIRS       += -I$(OCRANDOM_INC)
 INC_DIRS       += -I$(OCSOCKET_INC)
 INC_DIRS       += -I$(LCOAP_INC)
 INC_DIRS       += -I$(OCCOAP_INC)
 INC_DIRS       += -I$(OCTBSTACK_INC)
 INC_DIRS       += -I$(OCTBSTACK_INC)/internal
-INC_DIRS  += -I$(GTEST_DIR)/include
+INC_DIRS       += -I$(GTEST_DIR)/include
 
 CC_FLAGS.debug      := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
-                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
 CC_FLAGS.release    := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
-                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) 
+                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) 
                                        
 LDLIBS         += -loctbstack -lpthread -lgtest -lgtest_main
 CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
index bf47613..31c8dff 100644 (file)
@@ -43,7 +43,7 @@ extern "C" {
 #include <stdint.h>
 using namespace std;
 
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
 //-----------------------------------------------------------------------------
 // Private variables
 //-----------------------------------------------------------------------------
@@ -57,7 +57,7 @@ extern "C"  OCStackApplicationResult asyncDoResourcesCallback(void* ctx, OCDoHan
 
     EXPECT_EQ(OC_STACK_OK, clientResponse->result);
 
-    if(ctx == (void*)CTX_VAL) {
+    if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
     }
     OC_LOG_V(INFO, TAG, "result = %d", clientResponse->result);
@@ -128,9 +128,10 @@ TEST(StackTest, DoResourceDeviceDiscovery) {
     char szQueryUri[64] = { 0 };
     strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     cbData.cb = asyncDoResourcesCallback;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
+
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
     //EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
@@ -158,9 +159,9 @@ TEST(StackTest, UpdateResourceNullURI) {
     char szQueryUri[64] = { 0 };
     strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
     cbData.cb = asyncDoResourcesCallback;
-    cbData.context = (void*)CTX_VAL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
     //EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
index f27f8a5..ae6eb32 100644 (file)
@@ -50,8 +50,7 @@ class Resource
     protected:
     OCResourceHandle m_resourceHandle;
     OCRepresentation m_rep;
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)=0;
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)=0;
 };
 
 class DeviceResource : public Resource
@@ -63,10 +62,10 @@ class DeviceResource : public Resource
         std::string resourceURI = "/device";
         std::string resourceTypeName = "intel.fridge";
         std::string resourceInterface = DEFAULT_INTERFACE;
-        EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1);
 
-        EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler, this,
-                                                                         PH::_1, PH::_2);
+        EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler
+                                            ,this, PH::_1);
 
         std::cout << "Setting device default entity handler\n";
         OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
@@ -92,7 +91,7 @@ class DeviceResource : public Resource
         return m_rep;
     }
 
-    void deleteDeviceResource()
+    OCStackResult deleteDeviceResource()
     {
         OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
         if(OC_STACK_OK != result)
@@ -100,13 +99,14 @@ class DeviceResource : public Resource
             throw std::runtime_error(
                std::string("Device Resource failed to unregister/delete") + std::to_string(result));
         }
+        return result;
     }
 
     std::string m_modelName;
     protected:
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
         if(request)
         {
             // Get the header options from the request
@@ -152,30 +152,45 @@ class DeviceResource : public Resource
 
                 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
                 {
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
+                    pResponse->setHeaderOptions(serverHeaderOptions);
+
                     if(request->getRequestType() == "GET")
                     {
-                        if(response)
+                        std::cout<<"DeviceResource Get Request"<<std::endl;
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get(), "");
+                        if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            std::cout<<"DeviceResource Get Request"<<std::endl;
-                            response->setErrorCode(200);
-                            response->setHeaderOptions(serverHeaderOptions);
-                            response->setResourceRepresentation(get(), "");
+                            ehResult = OC_EH_OK;
                         }
                     }
-                    if(request->getRequestType() == "DELETE")
+                    else if(request->getRequestType() == "DELETE")
                     {
-                        if(response)
+                        std::cout<<"DeviceResource Delete Request"<<std::endl;
+                        if(deleteDeviceResource() == OC_STACK_OK)
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
+                            ehResult = OC_EH_OK;
+                        }
+                        else
                         {
-                            std::cout<<"DeviceResource Delete Request"<<std::endl;
-                            deleteDeviceResource();
-                            response->setErrorCode(200);
-                            response->setHeaderOptions(serverHeaderOptions);
+                            pResponse->setResponseResult(OC_EH_ERROR);
+                            ehResult = OC_EH_ERROR;
                         }
+                        OCPlatform::sendResponse(pResponse);
                     }
                     else
                     {
                         std::cout <<"DeviceResource unsupported request type "
                         << request->getRequestType() << std::endl;
+                        pResponse->setResponseResult(OC_EH_ERROR);
+                        OCPlatform::sendResponse(pResponse);
+                        ehResult = OC_EH_ERROR;
                     }
                 }
                 else
@@ -189,12 +204,12 @@ class DeviceResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 
-    virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
     {
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
         if(request)
         {
             std::cout << "In Default Entity Handler, uri received: "
@@ -202,19 +217,27 @@ class DeviceResource : public Resource
 
             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
             {
+                auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                pResponse->setRequestHandle(request->getRequestHandle());
+                pResponse->setResourceHandle(request->getResourceHandle());
+
                 if(request->getRequestType() == "GET")
                 {
-                    if(response)
+                    std::cout<<"Default Entity Handler: Get Request"<<std::endl;
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout<<"Default Entity Handler: Get Request"<<std::endl;
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
                     std::cout <<"Default Entity Handler: unsupported request type "
                     << request->getRequestType() << std::endl;
+                    pResponse->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(pResponse);
+                    ehResult = OC_EH_ERROR;
                 }
             }
             else
@@ -223,7 +246,7 @@ class DeviceResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
    }
 
 };
@@ -236,7 +259,7 @@ class LightResource : public Resource
         std::string resourceURI = "/light";
         std::string resourceTypeName = "intel.fridge.light";
         std::string resourceInterface = DEFAULT_INTERFACE;
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
         uint8_t resourceProperty = 0;
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
             resourceURI,
@@ -265,9 +288,9 @@ class LightResource : public Resource
 
     bool m_isOn;
     protected:
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
         if(request)
         {
             std::cout << "In entity handler for Light, URI is : "
@@ -275,30 +298,38 @@ class LightResource : public Resource
 
             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
             {
+                auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                pResponse->setRequestHandle(request->getRequestHandle());
+                pResponse->setResourceHandle(request->getResourceHandle());
+
                 if(request->getRequestType() == "GET")
                 {
-                    if(response)
+                    std::cout<<"Light Get Request"<<std::endl;
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout<<"Light Get Request"<<std::endl;
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if(request->getRequestType() == "PUT")
                 {
-                    if(response)
+                    std::cout <<"Light Put Request"<<std::endl;
+                    put(request->getResourceRepresentation());
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout <<"Light Put Request"<<std::endl;
-                        put(request->getResourceRepresentation());
-
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(),"");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
                     std::cout << "Light unsupported request type"
                     << request->getRequestType() << std::endl;
+                    pResponse->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(pResponse);
+                    ehResult = OC_EH_ERROR;
                 }
             }
             else
@@ -307,7 +338,7 @@ class LightResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 };
 
@@ -320,7 +351,7 @@ class DoorResource : public Resource
         std::string resourceURI = "/door/"+ side;
         std::string resourceTypeName = "intel.fridge.door";
         std::string resourceInterface = DEFAULT_INTERFACE;
-        EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1);
 
         uint8_t resourceProperty = 0;
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
@@ -353,10 +384,11 @@ class DoorResource : public Resource
     bool m_isOpen;
     std::string m_side;
     protected:
-    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-            std::shared_ptr<OCResourceResponse> response)
+    virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
         std::cout << "EH of door invoked " << std::endl;
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
         if(request)
         {
             std::cout << "In entity handler for Door, URI is : "
@@ -364,31 +396,40 @@ class DoorResource : public Resource
 
             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
             {
+                auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                pResponse->setRequestHandle(request->getRequestHandle());
+                pResponse->setResourceHandle(request->getResourceHandle());
+
                 if(request->getRequestType() == "GET")
                 {
-                    if(response)
+                    // note that we know the side because std::bind gives us the
+                    // appropriate object
+                    std::cout<< m_side << " Door Get Request"<<std::endl;
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(), "");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        // note that we know the side because std::bind gives us the
-                        // appropriate object
-                        std::cout<<m_side << " Door Get Request"<<std::endl;
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if(request->getRequestType() == "PUT")
                 {
-                    if(response)
+                    std::cout << m_side <<" Door Put Request"<<std::endl;
+                    put(request->getResourceRepresentation());
+                    pResponse->setErrorCode(200);
+                    pResponse->setResourceRepresentation(get(),"");
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                     {
-                        std::cout <<m_side <<" Door Put Request"<<std::endl;
-                        put(request->getResourceRepresentation());
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(),"");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
                     std::cout <<m_side<<" Door unsupported request type "
                     << request->getRequestType() << std::endl;
+                    pResponse->setResponseResult(OC_EH_ERROR);
+                    OCPlatform::sendResponse(pResponse);
+                    ehResult = OC_EH_ERROR;
                 }
             }
             else
@@ -397,7 +438,7 @@ class DoorResource : public Resource
             }
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 
 };
index 069b362..d9e4959 100644 (file)
@@ -33,8 +33,7 @@ using namespace OC;
 using namespace std;
 
 // Forward declaring the entityHandler
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
 /// This class represents a single resource named 'lightResource'. This resource has
 
@@ -173,10 +172,22 @@ public:
 // Create the instance of the resource class (in this case instance of class 'GarageResource').
 GarageResource myGarage;
 
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response)
+OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(myGarage.get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     if(request)
     {
@@ -198,34 +209,21 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(myGarage.get());
+                    ehResult = OC_EH_OK;
                 }
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
-
                 OCRepresentation rep = request->getResourceRepresentation();
-
                 // Do related operations related to PUT request
-
-                // Update the lightResource
                 myGarage.put(rep);
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(myGarage.get());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "POST")
             {
@@ -246,7 +244,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return ehResult;
 }
 
 int main(int argc, char* argv[1])
index 6b3dd42..6586ac6 100644 (file)
@@ -50,7 +50,7 @@ void LightResource::createResource(const unsigned int resource_number)
  OCStackResult result = OC::OCPlatform::registerResource(
                                             m_resourceHandle, resourceURI, resourceTypeName,
                                             DEFAULT_INTERFACE,
-                                            std::bind(&LightResource::entityHandler, this, std::placeholders::_1, std::placeholders::_2),
+                                            std::bind(&LightResource::entityHandler, this, std::placeholders::_1),
                                             OC_DISCOVERABLE | OC_OBSERVABLE);
   if (OC_STACK_OK != result)
    std::cout << "Resource creation failed.\n";
@@ -99,7 +99,7 @@ void LightResource::unregisterResource()
 
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     if(!request)
      {
@@ -107,12 +107,6 @@ OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceReq
         return OC_EH_ERROR;
      }
 
-    if(!response)
-     {
-        cerr << "entityHandler(): Received invalid response object.\n";
-        return OC_EH_ERROR;
-     }
-
     switch(request->getRequestHandlerFlag())
     {
         default:
@@ -124,37 +118,37 @@ OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceReq
                 break;
 
         case RequestHandlerFlag::RequestFlag:
-                dispatch_request(request->getRequestType(), request, response);
+                dispatch_request(request->getRequestType(), request);
                 break;
 
         case RequestHandlerFlag::ObserverFlag:
-                handle_observe_event(request, response);
+                handle_observe_event(request);
                 break;
     }
 
     return OC_EH_OK;
 }
 
-void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request)
 {
  std::cout << "dispatch_request(): " << request_type << '\n';
 
  if("GET" == request_type)
-  return handle_get_request(request, response);
+  return handle_get_request(request);
 
  if("PUT" == request_type)
-  return handle_put_request(request, response);
+  return handle_put_request(request);
 
  if("POST" == request_type)
-  return handle_post_request(request, response);
+  return handle_post_request(request);
 
  if("DELETE" == request_type)
-  return handle_delete_request(request, response);
+  return handle_delete_request(request);
 
  cerr << "entityHandler(): Invalid request type \"" << request_type << "\".\n";
 }
 
-void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request)
 {
  cout << "handle_get_request():\n";
 
@@ -163,11 +157,16 @@ void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> reques
  // ...do any processing of the query here...
 
  // Get a representation of the resource and send it back as a response:
- response->setErrorCode(200);
- response->setResourceRepresentation(getRepresentation());
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(getRepresentation());
+ OCPlatform::sendResponse(pResponse);
 }
 
-void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request)
 {
  // Here's how you would get any query parameters:
  const auto query_params_map = request->getQueryParameters();
@@ -177,25 +176,27 @@ void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> reques
 
  setRepresentation(rep);
 
- if(!response)
-  return;
-
- response->setErrorCode(200);
- response->setResourceRepresentation(getRepresentation());
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(getRepresentation());
+ OCPlatform::sendResponse(pResponse);
 }
 
-void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request)
 {
  // ...demo-code...
 }
 
-void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request)
 {
  // ...demo-code...
 }
 
 // Set up observation in a separate thread:
-void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request)
 {
  if(observe_thread.joinable())
   return;
index c569302..494b366 100644 (file)
@@ -75,20 +75,19 @@ class LightResource
     void addInterface(const std::string& interface) const;
 
     private:
-    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                        std::shared_ptr<OCResourceResponse> response);
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
     private:
     void observe_function();
 
     // Request handlers:
     private:
-    void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
-     void handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+    void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request);
+    void handle_get_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_put_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_post_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_delete_request(std::shared_ptr<OCResourceRequest> request);
+    void handle_observe_event(std::shared_ptr<OCResourceRequest> request);
 };
 
 }} // namespace Intel::OCDemo
index 6d5e70d..6fd7df3 100644 (file)
@@ -70,8 +70,8 @@ void presenceHandler(OCStackResult result, const unsigned int nonce)
         case OC_STACK_PRESENCE_TIMEOUT:
             std::cout << "Presence Timeout\n";
             break;
-        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-            std::cout << "Presence do not handle\n";
+        case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+            std::cout << "Virtual do not handle\n";
             break;
         default:
             std::cout << "Error\n";
index 305537b..ab75567 100644 (file)
@@ -34,8 +34,7 @@ using namespace OC;
 using namespace std;
 
 // Forward declaring the entityHandler
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
 
 /// This class represents a single resource named 'lightResource'. This resource has
 /// two simple properties named 'state' and 'power'
@@ -151,7 +150,7 @@ public:
 // Create the instance of the resource class (in this case instance of class 'LightResource').
 LightResource myLightResource;
 
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     cout << "\tIn Server CPP entity handler:\n";
     return OC_EH_OK;
index 029ab3f..8494d31 100644 (file)
@@ -24,8 +24,6 @@
 
 #include <functional>
 
-#include <pthread.h>
-
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -34,12 +32,12 @@ using namespace std;
 
 
 // Forward declaring the entityHandler (room)
-OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request,
-                                        std::shared_ptr<OCResourceResponse> response);
-OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request,
-                                         std::shared_ptr<OCResourceResponse> response);
-OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request,
-                                       std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request);
+OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request);
+OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request);
+
+/// Specifies whether default collection entity handler is used or not
+bool useDefaultCollectionEH = false;
 
 class RoomResource
 {
@@ -110,13 +108,26 @@ public:
     /// This function internally calls registerResource API.
     void createResources()
     {
+        // This function internally creates and registers the resource.
         using namespace OC::OCPlatform;
-        // This will internally create and register the resource.
-        OCStackResult result = registerResource(
+        OCStackResult result = OC_STACK_ERROR;
+
+        // Based on the case, we will use default collection EH (by passing NULL in entity handler
+        // parameter) or use application entity handler.
+        if(useDefaultCollectionEH)
+        {
+            result = registerResource(
+                                    m_roomHandle, m_roomUri, m_roomTypes[0],
+                                    m_roomInterfaces[0], NULL,
+                                    OC_DISCOVERABLE | OC_OBSERVABLE);
+        }
+        else
+        {
+            result = registerResource(
                                     m_roomHandle, m_roomUri, m_roomTypes[0],
                                     m_roomInterfaces[0], entityHandlerRoom,
-                                    OC_DISCOVERABLE | OC_OBSERVABLE
-                                  );
+                                    OC_DISCOVERABLE | OC_OBSERVABLE);
+        }
 
         if (OC_STACK_OK != result)
         {
@@ -135,22 +146,18 @@ public:
             cout << "Binding TypeName to Resource was unsuccessful\n";
         }
 
-        result = registerResource(
-                                    m_lightHandle, m_lightUri, m_lightTypes[0],
-                                    m_lightInterfaces[0], entityHandlerLight,
-                                    OC_DISCOVERABLE | OC_OBSERVABLE
-                                   );
+        result = registerResource(m_lightHandle, m_lightUri, m_lightTypes[0],
+                                  m_lightInterfaces[0], entityHandlerLight,
+                                  OC_DISCOVERABLE | OC_OBSERVABLE);
 
         if (OC_STACK_OK != result)
         {
             cout << "Resource creation (light) was unsuccessful\n";
         }
 
-        result = registerResource(
-                                    m_fanHandle, m_fanUri, m_fanTypes[0],
-                                    m_fanInterfaces[0], entityHandlerFan,
-                                    OC_DISCOVERABLE | OC_OBSERVABLE
-                                   );
+        result = registerResource(m_fanHandle, m_fanUri, m_fanTypes[0],
+                                  m_fanInterfaces[0], entityHandlerFan,
+                                  OC_DISCOVERABLE | OC_OBSERVABLE);
 
         if (OC_STACK_OK != result)
         {
@@ -233,11 +240,46 @@ public:
 // Create the instance of the resource class (in this case instance of class 'RoomResource').
 RoomResource myRoomResource;
 
-OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request,
-                       std::shared_ptr<OCResourceResponse> response)
+OCStackResult sendRoomResponse(std::shared_ptr<OCResourceRequest> pRequest)
 {
-    cout << "\tIn Server CPP entity handler:\n";
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+
+    // Check for query params (if any)
+    QueryParamsMap queryParamsMap = pRequest->getQueryParameters();
+
+    cout << "\t\t\tquery params: \n";
+    for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
+    {
+        cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
+    }
+
+    OCRepresentation rep;
+    rep = myRoomResource.getRoomRepresentation();
 
+    auto findRes = queryParamsMap.find("if");
+
+    if(findRes != queryParamsMap.end())
+    {
+        pResponse->setResourceRepresentation(rep, findRes->second);
+    }
+    else
+    {
+        pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
+    }
+
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+// This function prepares a response for any incoming request to Light resource.
+bool prepareLightResponse(std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "\tIn Server CPP (Light) prepareLightResponse:\n";
+    bool result = false;
     if(request)
     {
         // Get the request type and request flag
@@ -258,64 +300,18 @@ OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> reque
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
-                cout << "\t\t\tquery params: \n";
-                for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
-                {
-                    cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
-                }
-
-                OCRepresentation rep;
-                rep = myRoomResource.getRoomRepresentation();
-
-                if(response)
-                {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    auto findRes = queryParamsMap.find("if");
-
-                    if(findRes != queryParamsMap.end())
-                    {
-                        response->setResourceRepresentation(rep, findRes->second);
-                    }
-                    else
-                    {
-                        response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
-                    }
-                }
-
+                // GET operations are directly handled while sending the response
+                // in the sendLightResponse function
+                result = true;
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
+                OCRepresentation rep = request->getResourceRepresentation();
 
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
-                entityHandlerLight(request, response);
-                entityHandlerFan(request, response);
-
-                OCRepresentation rep;
-                rep = myRoomResource.getRoomRepresentation();
-
-                if(response)
-                {
-                    response->setErrorCode(200);
-
-                    auto findRes = queryParamsMap.find("if");
-
-                    if(findRes != queryParamsMap.end())
-                    {
-                        response->setResourceRepresentation(rep, findRes->second);
-                    }
-                    else
-                    {
-                        response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
-                    }
-                }
+                // Do related operations related to PUT request
+                myRoomResource.setLightRepresentation(rep);
+                result= true;
             }
             else if(requestType == "POST")
             {
@@ -336,13 +332,14 @@ OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> reque
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return result;
 }
 
-OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request,
-                                         std::shared_ptr<OCResourceResponse> response)
+// This function prepares a response for any incoming request to Fan resource.
+bool prepareFanResponse(std::shared_ptr<OCResourceRequest> request)
 {
-    cout << "\tIn Server CPP (Light) entity handler:\n";
+    cout << "\tIn Server CPP (Fan) prepareFanResponse:\n";
+    bool result = false;
 
     if(request)
     {
@@ -364,14 +361,9 @@ OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> requ
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
-                {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-                    response->setResourceRepresentation(myRoomResource.getLightRepresentation());
-                }
-
+                // GET operations are directly handled while sending the response
+                // in the sendLightResponse function
+                result = true;
             }
             else if(requestType == "PUT")
             {
@@ -380,15 +372,8 @@ OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> requ
                 OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to PUT request
-                myRoomResource.setLightRepresentation(rep);
-
-                if(response)
-                {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-                    response->setResourceRepresentation(myRoomResource.getLightRepresentation());
-                }
-
+                myRoomResource.setFanRepresentation(rep);
+                result = true;
             }
             else if(requestType == "POST")
             {
@@ -409,13 +394,13 @@ OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> requ
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return result;
 }
 
-OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request,
-                                       std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request)
 {
-    cout << "\tIn Server CPP (Fan) entity handler:\n";
+    cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     if(request)
     {
@@ -437,30 +422,21 @@ OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> reques
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(OC_STACK_OK == sendRoomResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(myRoomResource.getFanRepresentation());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
-
-                OCRepresentation rep = request->getResourceRepresentation();
-
-                // Do related operations related to PUT request
-                myRoomResource.setFanRepresentation(rep);
-
-                if(response)
+                // Call these functions to prepare the response for child resources and
+                // then send the final response using sendRoomResponse function
+                prepareLightResponse(request);
+                prepareFanResponse(request);
+                if(OC_STACK_OK == sendRoomResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-                    response->setResourceRepresentation(myRoomResource.getFanRepresentation());
+                    ehResult = OC_EH_OK;
                 }
             }
             else if(requestType == "POST")
@@ -482,11 +458,112 @@ OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> reques
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return ehResult;
+}
+
+OCStackResult sendLightResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(myRoomResource.getLightRepresentation());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+
+
+OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "\tIn Server CPP (Light) entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    if(prepareLightResponse(request))
+    {
+        if(OC_STACK_OK == sendLightResponse(request))
+        {
+            ehResult = OC_EH_OK;
+        }
+        else
+        {
+            std::cout << "sendLightResponse failed." << std::endl;
+        }
+    }
+    else
+    {
+        std::cout << "PrepareLightResponse failed." << std::endl;
+    }
+    return ehResult;
+}
+
+OCStackResult sendFanResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(myRoomResource.getFanRepresentation());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+
+OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "\tIn Server CPP (Fan) entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    if(prepareFanResponse(request))
+    {
+        if(OC_STACK_OK == sendFanResponse(request))
+        {
+            ehResult = OC_EH_OK;
+        }
+        else
+        {
+            std::cout << "sendFanResponse failed." << std::endl;
+        }
+    }
+    else
+    {
+        std::cout << "PrepareFanResponse failed." << std::endl;
+    }
+
+    return ehResult;
 }
 
-int main()
+void printUsage()
 {
+    std::cout << std::endl;
+    std::cout << "Usage : roomserver <value>\n";
+    std::cout << "1 : Create room resource with default collection entity handler.\n";
+    std::cout << "2 : Create room resource with application collection entity handler.\n";
+}
+
+int main(int argc, char* argv[1])
+{
+    printUsage();
+
+    if(argc == 2)
+    {
+        int value = atoi(argv[1]);
+        switch (value)
+        {
+            case 1:
+                useDefaultCollectionEH = true;
+                break;
+            case 2:
+            default:
+                break;
+       }
+    }
+    else
+    {
+        return -1;
+    }
+
     // Create PlatformConfig object
     PlatformConfig cfg {
         OC::ServiceType::InProc,
index c2d4a48..732cd4d 100644 (file)
@@ -118,7 +118,7 @@ void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, co
     }
     else
     {
-        std::cout << "onPost Response error: " << eCode << std::endl;
+        std::cout << "onPost2 Response error: " << eCode << std::endl;
         std::exit(-1);
     }
 }
index 204de3e..f3363c5 100644 (file)
@@ -131,7 +131,7 @@ void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, co
     }
     else
     {
-        std::cout << "onPost Response error: " << eCode << std::endl;
+        std::cout << "onPost2 Response error: " << eCode << std::endl;
         std::exit(-1);
     }
 }
index 444c4dc..3aafe17 100644 (file)
@@ -186,7 +186,7 @@ struct FooResource
         uint8_t resourceProperty = OC_DISCOVERABLE;
 
         EntityHandler eh(std::bind(&FooResource::entityHandler,
-                    this, std::placeholders::_1, std::placeholders::_2));
+                    this, std::placeholders::_1));
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
                 resourceURI, resourceTypeName,
                                     resourceInterface,
@@ -214,14 +214,27 @@ struct FooResource
         rep.getValue("barCount", m_barCount);
     }
 
-    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                        std::shared_ptr<OCResourceResponse> response)
+    OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+    {
+        auto pResponse = std::make_shared<OC::OCResourceResponse>();
+        pResponse->setRequestHandle(pRequest->getRequestHandle());
+        pResponse->setResourceHandle(pRequest->getResourceHandle());
+        pResponse->setResourceRepresentation(get(), "");
+        pResponse->setErrorCode(200);
+        pResponse->setResponseResult(OC_EH_OK);
+
+        return OCPlatform::sendResponse(pResponse);
+    }
+
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
         std::cout<<"\tConsumer Entity Handler:"<<std::endl;
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
         if(request)
         {
-            // Note: Most of the handlers are not here, since this is for demoing client/server co-process existence.
+            // Note: Most of the handlers are not here, since this is for
+            // demoing client/server co-process existence.
             // See simpleserver for a more complete example.
             if(request->getRequestHandlerFlag()  == RequestHandlerFlag::RequestFlag)
             {
@@ -230,11 +243,9 @@ struct FooResource
                 if(request->getRequestType() == "GET")
                 {
                     std::cout<<"\t\t\trequestType : GET"<<std::endl;
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if (request->getRequestType() == "PUT")
@@ -243,16 +254,15 @@ struct FooResource
 
                     OCRepresentation rep = request->getResourceRepresentation();
                     put(rep);
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
                 {
-                    std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<request->getRequestType()<<std::endl;
+                    std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<
+                            request->getRequestType()<<std::endl;
                 }
             }
             else
@@ -274,10 +284,11 @@ struct FooResource
             std::cout << "Request Invalid!"<<std::endl;
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
 
 };
+
 int main()
 {
     PlatformConfig cfg {
index 186ffd4..780429a 100644 (file)
@@ -36,6 +36,7 @@ namespace PH = std::placeholders;
 
 int gObservation = 0;
 void * ChangeLightRepresentation (void *param);
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 
 // Specifies where to notify all observers or list of observers
 // false: notifies all observers
@@ -47,6 +48,9 @@ bool isListOfObservers = false;
 // true: secure resource
 bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
+
 // Forward declaring the entityHandler
 
 /// This class represents a single resource named 'lightResource'. This resource has
@@ -83,8 +87,8 @@ public:
     /// This function internally calls registerResource API.
     void createResource()
     {
-        std::string resourceURI = m_lightUri; // URI of the resource
-        std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
+        std::string resourceURI = m_lightUri; //URI of the resource
+        std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light
         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
 
         // OCResourceProperty is defined ocstack.h
@@ -97,7 +101,7 @@ public:
         {
             resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
         }
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         // This will internally create and register the resource.
         OCStackResult result = OCPlatform::registerResource(
@@ -126,7 +130,7 @@ public:
         {
             resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
         }
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         OCResourceHandle resHandle;
 
@@ -239,13 +243,10 @@ public:
 private:
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                    std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
-    OCEntityHandlerResult result = OC_EH_OK;
-
     cout << "\tIn Server CPP entity handler:\n";
-
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
     if(request)
     {
         // Get the request type and request flag
@@ -261,39 +262,51 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         if(requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
+            auto pResponse = std::make_shared<OC::OCResourceResponse>();
+            pResponse->setRequestHandle(request->getRequestHandle());
+            pResponse->setResourceHandle(request->getResourceHandle());
 
             // If the request type is GET
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(isSlowResponse) // Slow response case
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    static int startedThread = 0;
+                    if(!startedThread)
+                    {
+                        std::thread t(handleSlowResponse, (void *)this, request);
+                        startedThread = 1;
+                        t.detach();
+                    }
+                    ehResult = OC_EH_SLOW;
+                }
+                else // normal response case.
+                {
+                    pResponse->setErrorCode(200);
+                    pResponse->setResponseResult(OC_EH_OK);
+                    pResponse->setResourceRepresentation(get());
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                    {
+                        ehResult = OC_EH_OK;
+                    }
                 }
             }
             else if(requestType == "PUT")
             {
                 cout << "\t\t\trequestType : PUT\n";
-
                 OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to PUT request
-
                 // Update the lightResource
                 put(rep);
-
-                if(response)
+                pResponse->setErrorCode(200);
+                pResponse->setResponseResult(OC_EH_OK);
+                pResponse->setResourceRepresentation(get());
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "POST")
             {
@@ -302,26 +315,19 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 OCRepresentation rep = request->getResourceRepresentation();
 
                 // Do related operations related to POST request
-
                 OCRepresentation rep_post = post(rep);
-
-                if(response)
+                pResponse->setResourceRepresentation(rep_post);
+                pResponse->setErrorCode(200);
+                if(rep_post.hasAttribute("createduri"))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(rep_post);
-
-                    if(rep_post.hasAttribute("createduri"))
-                    {
-                        result = OC_EH_RESOURCE_CREATED;
-
-                        response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                    }
-
+                    pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                    pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                 }
 
-                // POST request operations
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                {
+                    ehResult = OC_EH_OK;
+                }
             }
             else if(requestType == "DELETE")
             {
@@ -358,6 +364,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                 startedThread = 1;
             }
+            ehResult = OC_EH_OK;
         }
     }
     else
@@ -365,7 +372,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         std::cout << "Request invalid" << std::endl;
     }
 
-    return result;
+    return ehResult;
 }
 
 };
@@ -422,14 +429,36 @@ void * ChangeLightRepresentation (void *param)
     return NULL;
 }
 
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    LightResource* lightPtr = (LightResource*) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(lightPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
+
 void PrintUsage()
 {
     std::cout << std::endl;
-    std::cout << "Usage : simpleserver < secure resource and observer >\n";
+    std::cout << "Usage : simpleserver <value>\n";
     std::cout << "    Default - Non-secure resource and notify all observers\n";
     std::cout << "    1 - Non-secure resource and notify list of observers\n\n";
     std::cout << "    2 - Secure resource and notify all observers\n";
     std::cout << "    3 - Secure resource and notify list of observers\n\n";
+    std::cout << "    4 - Non-secure resource, GET slow response, notify all observers\n";
 }
 
 
@@ -459,6 +488,8 @@ int main(int argc, char* argv[1])
                 isListOfObservers = true;
                 isSecure = true;
                 break;
+            case 4:
+                isSlowResponse = true;
             default:
                 break;
        }
@@ -480,7 +511,8 @@ int main(int argc, char* argv[1])
     OCPlatform::Configure(cfg);
     try
     {
-        // Create the instance of the resource class (in this case instance of class 'LightResource').
+        // Create the instance of the resource class
+        // (in this case instance of class 'LightResource').
         LightResource myLight;
 
         // Invoke createResource function of class light.
index 1b20294..70a5dfc 100644 (file)
@@ -42,8 +42,6 @@ void * ChangeLightRepresentation (void *param);
 // 1 - notifies list of observers
 int isListOfObservers = 0;
 
-// Forward declaring the entityHandler
-
 /// This class represents a single resource named 'lightResource'. This resource has
 /// two simple properties named 'state' and 'power'
 
@@ -85,7 +83,7 @@ public:
         // OCResourceProperty is defined ocstack.h
         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         // This will internally create and register the resource.
         OCStackResult result = OCPlatform::registerResource(
@@ -107,7 +105,7 @@ public:
         // OCResourceProperty is defined ocstack.h
         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+        EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
 
         OCResourceHandle resHandle;
 
@@ -180,7 +178,6 @@ public:
             if(OC_STACK_OK == createResource1())
             {
                 std::cout << "Created a new resource\n";
-
                 OCRepresentation rep1;
                 rep1.setValue("createduri", std::string("/a/light1"));
 
@@ -224,11 +221,41 @@ public:
     }
 
 private:
+
+OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
+OCStackResult sendPostResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+
+    OCRepresentation rep = pRequest->getResourceRepresentation();
+    OCRepresentation rep_post = post(rep);
+
+    pResponse->setResourceRepresentation(rep_post);
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    return OCPlatform::sendResponse(pResponse);
+}
+
 // This is just a sample implementation of entity handler.
 // Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
 {
     cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
     if(request)
     {
@@ -239,7 +266,6 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         if(requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
-
             // entity handler to perform resource initialization operations
         }
         if(requestFlag & RequestHandlerFlag::RequestFlag)
@@ -250,13 +276,9 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
             if(requestType == "GET")
             {
                 cout << "\t\t\trequestType : GET\n";
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    ehResult = OC_EH_OK;
                 }
             }
             else if(requestType == "PUT")
@@ -264,40 +286,21 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 cout << "\t\t\trequestType : PUT\n";
 
                 OCRepresentation rep = request->getResourceRepresentation();
-
                 // Do related operations related to PUT request
-
                 // Update the lightResource
                 put(rep);
-
-                if(response)
+                if(OC_STACK_OK == sendResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(get());
+                    ehResult = OC_EH_OK;
                 }
-
             }
             else if(requestType == "POST")
             {
                 cout << "\t\t\trequestType : POST\n";
-
-                OCRepresentation rep = request->getResourceRepresentation();
-
-                // Do related operations related to POST request
-
-                OCRepresentation rep_post = post(rep);
-
-                if(response)
+                if(OC_STACK_OK == sendPostResponse(request))
                 {
-                    // TODO Error Code
-                    response->setErrorCode(200);
-
-                    response->setResourceRepresentation(rep_post);
+                    ehResult = OC_EH_OK;
                 }
-
-                // POST request operations
             }
             else if(requestType == "DELETE")
             {
@@ -334,6 +337,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
                 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                 startedThread = 1;
             }
+            ehResult = OC_EH_OK;
         }
     }
     else
@@ -341,7 +345,7 @@ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
         std::cout << "Request invalid" << std::endl;
     }
 
-    return OC_EH_OK;
+    return ehResult;
 }
 
 };
index c2f9ec0..71d09b3 100644 (file)
@@ -59,7 +59,7 @@ struct FooResource
         uint8_t resourceProperty = OC_DISCOVERABLE;
 
         EntityHandler eh(std::bind(&FooResource::entityHandler, this,
-                                    std::placeholders::_1, std::placeholders::_2));
+                                    std::placeholders::_1));
         OCStackResult result = OCPlatform::registerResource(m_resourceHandle, m_uri,
                                     m_resourceType, resourceInterface, eh, resourceProperty);
         if(OC_STACK_OK != result)
@@ -85,10 +85,22 @@ struct FooResource
         rep.getValue("barCount", m_barCount);
     }
 
-    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                        std::shared_ptr<OCResourceResponse> response)
+    OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+    {
+        auto pResponse = std::make_shared<OC::OCResourceResponse>();
+        pResponse->setRequestHandle(pRequest->getRequestHandle());
+        pResponse->setResourceHandle(pRequest->getResourceHandle());
+        pResponse->setResourceRepresentation(get(), "");
+        pResponse->setErrorCode(200);
+        pResponse->setResponseResult(OC_EH_OK);
+
+        return OCPlatform::sendResponse(pResponse);
+    }
+
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
     {
         std::cout<<"\tConsumer Entity Handler:"<<std::endl;
+        OCEntityHandlerResult ehResult = OC_EH_ERROR;
 
         if(request)
         {
@@ -101,11 +113,9 @@ struct FooResource
                 if(request->getRequestType() == "GET")
                 {
                     std::cout<<"\t\t\trequestType : GET"<<std::endl;
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else if (request->getRequestType() == "PUT")
@@ -114,11 +124,9 @@ struct FooResource
 
                     OCRepresentation rep = request->getResourceRepresentation();
                     put(rep);
-
-                    if(response)
+                    if(OC_STACK_OK == sendResponse(request))
                     {
-                        response->setErrorCode(200);
-                        response->setResourceRepresentation(get(), "");
+                        ehResult = OC_EH_OK;
                     }
                 }
                 else
@@ -146,9 +154,8 @@ struct FooResource
             std::cout << "Request Invalid!"<<std::endl;
         }
 
-        return OC_EH_OK;
+        return ehResult;
     }
-
 };
 
 void putResourceInfo(const HeaderOptions& headerOptions,
index a6a2d10..10e0515 100644 (file)
@@ -75,6 +75,8 @@ namespace OC
         virtual OCStackResult stopPresence() = 0;
 
         virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) = 0;
+
+        virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse) = 0;
     };
 }
 
index dfed790..aab856b 100644 (file)
@@ -32,7 +32,8 @@ namespace OC
     class InProcServerWrapper : public IServerWrapper
     {
     public:
-        InProcServerWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
+        InProcServerWrapper(
+            std::weak_ptr<std::recursive_mutex> csdkLock,
             PlatformConfig cfg);
         virtual ~InProcServerWrapper();
 
@@ -69,6 +70,8 @@ namespace OC
         virtual OCStackResult stopPresence();
 
         virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler);
+
+        virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
     private:
         void processFunc();
         std::thread m_processThread;
index 94f997f..95f27d0 100644 (file)
@@ -196,8 +196,8 @@ namespace OC
 
     typedef std::function<void(std::shared_ptr<OCResource>)> FindCallback;
 
-    typedef std::function<OCEntityHandlerResult (const std::shared_ptr<OCResourceRequest>,
-                                const std::shared_ptr<OCResourceResponse>)> EntityHandler;
+    typedef std::function<OCEntityHandlerResult(
+                            const std::shared_ptr<OCResourceRequest>)> EntityHandler;
 
     typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
 
index 39d1792..61a0f48 100644 (file)
@@ -400,8 +400,14 @@ namespace OC
                         bool isObservable, const std::vector<std::string>& resourceTypes,
                         const std::vector<std::string>& interfaces);
 
-
-
+        /**
+        * Allows application entity handler to send response to an incoming request.
+        *
+        * @param pResponse - OCResourceResponse pointer that will permit to set values related
+        * to resource response. <br>
+        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        */
+        OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
     }
 }
 
index 47598d2..896ce3a 100644 (file)
@@ -423,6 +423,15 @@ namespace OC
                         bool isObservable, const std::vector<std::string>& resourceTypes,
                         const std::vector<std::string>& interfaces);
 
+        /**
+        * Allows application entity handler to send response to an incoming request.
+        *
+        * @param pResponse - OCResourceResponse pointer that will permit to set values related
+        * to resource response. <br>
+        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        */
+        OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
+
     private:
         PlatformConfig m_cfg;
 
@@ -442,14 +451,14 @@ namespace OC
         OCPlatform_impl(const PlatformConfig& config);
 
         /**
-        *  Private function to initalize the platfrom
+        * Private function to initalize the platfrom
         */
         void init(const PlatformConfig& config);
 
         /**
-         * Private constructor/operators to prevent copying
-         * of this object
-         */
+        * Private constructor/operators to prevent copying
+        * of this object
+        */
         OCPlatform_impl(const OCPlatform_impl& other)= delete;
         OCPlatform_impl& operator=(const OCPlatform_impl&) = delete;
         OCPlatform_impl& operator=(const OCPlatform_impl&&) = delete;
index 5b7e206..a435b47 100644 (file)
@@ -79,7 +79,8 @@ namespace OC
 
         /**
         *  Provides the entire resource attribute representation
-        *  @return OCRepresentation reference containing the name value pairs representing the resource's attributes
+        *  @return OCRepresentation reference containing the name value pairs
+        *   representing the resource's attributes
         */
         const OCRepresentation& getResourceRepresentation() const {return m_representation;}
 
@@ -106,10 +107,35 @@ namespace OC
             return m_resourceUri;
         }
 
-        /** This API retrieves headerOptions which was sent from a client
+        /**
+        * This API retrieves headerOptions which was sent from a client
+        *
         * @return std::map HeaderOptions with the header options
         */
-        const HeaderOptions& getHeaderOptions() const {return m_headerOptions;}
+        const HeaderOptions& getHeaderOptions() const
+        {
+            return m_headerOptions;
+        }
+
+        /**
+        * This API retrieves the request handle
+        *
+        * @return OCRequestHandle
+        */
+        const OCRequestHandle& getRequestHandle() const
+        {
+            return m_requestHandle;
+        }
+
+        /**
+        * This API retrieves the resource handle
+        *
+        * return OCResourceHandle
+        */
+        const OCResourceHandle& getResourceHandle() const
+        {
+            return m_resourceHandle;
+        }
 
     private:
         std::string m_requestType;
@@ -119,6 +145,9 @@ namespace OC
         OCRepresentation m_representation;
         ObservationInfo m_observationInfo;
         HeaderOptions m_headerOptions;
+        OCRequestHandle m_requestHandle;
+        OCResourceHandle m_resourceHandle;
+
 
     private:
         friend void (::formResourceRequest)(OCEntityHandlerFlag, OCEntityHandlerRequest*,
@@ -171,6 +200,27 @@ namespace OC
         {
             m_headerOptions = headerOptions;
         }
+
+        /**
+        * This API allows to set request handle
+        * @param requestHandle - OCRequestHandle type used to set the
+        * request handle
+        */
+        void setRequestHandle(const OCRequestHandle& requestHandle)
+        {
+            m_requestHandle = requestHandle;
+        }
+
+        /**
+        * This API allows to set the resource handle
+        * @param resourceHandle - OCResourceHandle type used to set the
+        * resource handle
+        */
+        void setResourceHandle(const OCResourceHandle& resourceHandle)
+        {
+            m_resourceHandle = resourceHandle;
+        }
+
     };
  }// namespace OC
 
index ee660e3..1c8e3fa 100644 (file)
 
 using namespace std;
 
-
-void (processResourceResponse)(OCEntityHandlerFlag,
-                                 OCEntityHandlerRequest*,
-                                 std::shared_ptr<OC::OCResourceResponse> pResponse);
-
-
 namespace OC
 {
+    class InProcServerWrapper;
+
     /**
     *   @brief  OCResourceResponse provides APIs to set the response details
     */
@@ -88,6 +84,36 @@ namespace OC
         }
 
         /**
+        * This API allows to set request handle
+        *
+        * @param requestHandle - OCRequestHandle type used to set the request handle
+        */
+        void setRequestHandle(const OCRequestHandle& requestHandle)
+        {
+            m_requestHandle = requestHandle;
+        }
+
+        /**
+        * This API allows to set the resource handle
+        *
+        * @param resourceHandle - OCResourceHandle type used to set the resource handle
+        */
+        void setResourceHandle(const OCResourceHandle& resourceHandle)
+        {
+            m_resourceHandle = resourceHandle;
+        }
+
+        /**
+        * This API allows to set the EntityHandler response result
+        *
+        * @param responseResult - OCEntityHandlerResult type to set the result value
+        */
+        void setResponseResult(const OCEntityHandlerResult& responseResult)
+        {
+            m_responseResult = responseResult;
+        }
+
+        /**
         *  API to set the entire resource attribute representation
         *  @param attributeMap reference containing the name value pairs representing
         *         the resource's attributes
@@ -134,10 +160,13 @@ namespace OC
         HeaderOptions m_headerOptions;
         std::string m_interface;
         OCRepresentation m_representation;
+        OCRequestHandle m_requestHandle;
+        OCResourceHandle m_resourceHandle;
+        OCEntityHandlerResult m_responseResult;
+
     private:
-        friend void (::processResourceResponse)(OCEntityHandlerFlag,
-                            OCEntityHandlerRequest*,
-                            std::shared_ptr<OC::OCResourceResponse> pResponse);
+        friend class InProcServerWrapper;
+
         std::string getPayload() const
         {
             MessageContainer inf;
@@ -202,6 +231,36 @@ namespace OC
         {
             return m_headerOptions;
         }
+
+        /**
+        * This API retrieves the request handle
+        *
+        * @return OCRequestHandle value
+        */
+        const OCRequestHandle& getRequestHandle() const
+        {
+            return m_requestHandle;
+        }
+
+        /**
+        * This API retrieves the resource handle
+        *
+        * @return OCResourceHandle value
+        */
+        const OCResourceHandle& getResourceHandle() const
+        {
+            return m_resourceHandle;
+        }
+
+        /**
+        * This API retrieves the entity handle response result
+        *
+        * @return OCEntityHandler result value
+        */
+        const OCEntityHandlerResult getResponseResult() const
+        {
+            return m_responseResult;
+        }
     };
 
 } // namespace OC
index a38e83c..be51f3d 100644 (file)
@@ -91,12 +91,17 @@ namespace OC
             return OC_STACK_NOTIMPL;
         }
 
-
         virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler)
         {
             //Not implemented yet
             return OC_STACK_NOTIMPL;
         }
+
+        virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+        {
+           //Not implemented yet
+           return OC_STACK_NOTIMPL;
+        }
     };
 }
 
index b169726..b29fb0c 100644 (file)
@@ -91,6 +91,10 @@ namespace OC
         static const std::string INVALID_OPTION             = "Invalid option";
         static const std::string GENERAL_FAULT              = "General Fault";
         static const std::string MALFORMED_STACK_RESPONSE   = "Response from OC_STACK is malformed";
+        static const std::string VIRTUAL_DO_NOT_HANDLE      = "Virtual Do Not Handle";
+        static const std::string PERSISTENT_BUFFER_REQUIRED = "Persistent response buffer required";
+        static const std::string STACK_CONTINUE             = "Stack continue";
+        static const std::string INVALID_REQUEST_HANDLE     = "Invalid request handle";
         static const std::string UNKNOWN_ERROR              = "Unknown Error";
         static const std::string INVALID_REPRESENTATION     = "Invalid Payload JSON";
         static const std::string INVALID_JSON_TYPE          = "Unrecognized JSON Type ";
index 751dc87..27741f9 100644 (file)
@@ -47,6 +47,9 @@ void formResourceRequest(OCEntityHandlerFlag flag,
                          OCEntityHandlerRequest * entityHandlerRequest,
                          std::shared_ptr<OCResourceRequest> pRequest)
 {
+    pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
+    pRequest->setResourceHandle(entityHandlerRequest->resource);
+
     if(flag & OC_INIT_FLAG)
     {
         pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
@@ -116,64 +119,12 @@ void formResourceRequest(OCEntityHandlerFlag flag,
     {
         pRequest->setRequestHandlerFlag(
                    OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
-        if(entityHandlerRequest->obsInfo)
-        {
-            OC::ObservationInfo observationInfo;
-            observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo->action;
-            observationInfo.obsId = entityHandlerRequest->obsInfo->obsId;
-            pRequest->setObservationInfo(observationInfo);
-        }
-    }
-}
-
-void processResourceResponse(OCEntityHandlerFlag flag,
-                             OCEntityHandlerRequest * entityHandlerRequest,
-                             std::shared_ptr<OCResourceResponse> pResponse)
-{
-    if(flag & OC_REQUEST_FLAG)
-    {
-        // TODO we could use const reference
-        std::string payLoad;
-        HeaderOptions serverHeaderOptions;
-
-        if(pResponse)
-        {
-            payLoad = pResponse->getPayload();
-            serverHeaderOptions = pResponse->getHeaderOptions();
-        }
-        else
-        {
-            throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
-        }
 
-        if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen)
-        {
-            int i = 0;
-            entityHandlerRequest->numSendVendorSpecificHeaderOptions =
-                        serverHeaderOptions.size();
-            for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
-            {
-                entityHandlerRequest->sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
-                entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionID =
-                        static_cast<uint16_t>(it->getOptionID());
-                entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionLength =
-                        (it->getOptionData()).length() + 1;
-                memcpy(entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionData,
-                        (it->getOptionData()).c_str(),
-                        (it->getOptionData()).length() + 1);
-                i++;
-            }
-
-            strncpy((char*)entityHandlerRequest->resJSONPayload,
-                        payLoad.c_str(),
-                        entityHandlerRequest->resJSONPayloadLen);
-        }
-        else
-        {
-            throw OCException(OC::Exception::STR_PAYLOAD_OVERFLOW, OC_STACK_MALFORMED_RESPONSE);
-        }
+        OC::ObservationInfo observationInfo;
+        observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
+        observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
+        pRequest->setObservationInfo(observationInfo);
     }
-
 }
 
 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
@@ -191,7 +142,6 @@ OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
     }
 
     auto pRequest = std::make_shared<OC::OCResourceRequest>();
-    auto pResponse = std::make_shared<OC::OCResourceResponse>();
 
     formResourceRequest(flag, entityHandlerRequest, pRequest);
 
@@ -199,7 +149,7 @@ OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
 
     if(defaultDeviceEntityHandler)
     {
-        result = defaultDeviceEntityHandler(pRequest, pResponse);
+        result = defaultDeviceEntityHandler(pRequest);
     }
     else
     {
@@ -207,8 +157,6 @@ OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
         return OC_EH_ERROR;
     }
 
-    processResourceResponse(flag, entityHandlerRequest, pResponse);
-
     return result;
 }
 
@@ -227,7 +175,6 @@ OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
     }
 
     auto pRequest = std::make_shared<OC::OCResourceRequest>();
-    auto pResponse = std::make_shared<OC::OCResourceResponse>();
 
     formResourceRequest(flag, entityHandlerRequest, pRequest);
 
@@ -251,15 +198,7 @@ OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
         // Call CPP Application Entity Handler
         if(entityHandlerEntry->second)
         {
-            result = entityHandlerEntry->second(pRequest, pResponse);
-
-            if(OC_EH_RESOURCE_CREATED == result)
-            {
-                std::string createdUri = pResponse->getNewResourceUri();
-                strncpy(reinterpret_cast<char*>(entityHandlerRequest->newResourceUri),
-                        createdUri.c_str(),
-                        createdUri.length() + 1);
-            }
+            result = entityHandlerEntry->second(pRequest);
         }
         else
         {
@@ -273,8 +212,6 @@ OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
         return OC_EH_ERROR;
     }
 
-    processResourceResponse(flag, entityHandlerRequest, pResponse);
-
     return result;
 }
 
@@ -445,6 +382,7 @@ namespace OC
 
         return result;
     }
+
     OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
                                         (EntityHandler entityHandler)
     {
@@ -572,6 +510,74 @@ namespace OC
         return result;
     }
 
+    OCStackResult InProcServerWrapper::sendResponse(
+        const std::shared_ptr<OCResourceResponse> pResponse)
+    {
+        auto cLock = m_csdkLock.lock();
+        OCStackResult result = OC_STACK_ERROR;
+
+        if(!pResponse)
+        {
+            result = OC_STACK_MALFORMED_RESPONSE;
+            throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
+        }
+        else
+        {
+            OCEntityHandlerResponse response;
+            std::string payLoad;
+            HeaderOptions serverHeaderOptions;
+
+            payLoad = pResponse->getPayload();
+            serverHeaderOptions = pResponse->getHeaderOptions();
+
+            response.requestHandle = pResponse->getRequestHandle();
+            response.resourceHandle = pResponse->getResourceHandle();
+            response.ehResult = pResponse->getResponseResult();
+            response.payload = (unsigned char*) payLoad.c_str();
+            response.payloadSize = payLoad.length() + 1;
+            response.persistentBufferFlag = 0;
+
+            response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
+            int i = 0;
+            for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
+            {
+                response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
+                response.sendVendorSpecificHeaderOptions[i].optionID =
+                    static_cast<uint16_t>(it->getOptionID());
+                response.sendVendorSpecificHeaderOptions[i].optionLength =
+                    (it->getOptionData()).length() + 1;
+                memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
+                    (it->getOptionData()).c_str(),
+                    (it->getOptionData()).length() + 1);
+                i++;
+            }
+
+            if(OC_EH_RESOURCE_CREATED == response.ehResult)
+            {
+                std::string createdUri = pResponse->getNewResourceUri();
+                strncpy(reinterpret_cast<char*>(response.resourceUri),
+                        createdUri.c_str(),
+                        createdUri.length() + 1);
+            }
+
+            if(cLock)
+            {
+                std::lock_guard<std::recursive_mutex> lock(*cLock);
+                result = OCDoResponse(&response);
+            }
+            else
+            {
+                result = OC_STACK_ERROR;
+            }
+
+            if(result != OC_STACK_OK)
+            {
+                oclog() << "Error sending response\n";
+            }
+            return result;
+        }
+    }
+
     InProcServerWrapper::~InProcServerWrapper()
     {
         if(m_processThread.joinable())
index 612dc1d..97381e5 100644 (file)
@@ -63,20 +63,22 @@ std::string OC::OCException::reason(const OCStackResult sr)
             return OC::Exception::NO_OBSERVERS;
         case OC_STACK_OBSERVER_NOT_FOUND:
             return OC::Exception::OBSV_NO_FOUND;
-        case OC_STACK_OBSERVER_NOT_ADDED:
-            return OC::Exception::OBSV_NOT_ADDED;
-        case OC_STACK_OBSERVER_NOT_REMOVED:
-            return OC::Exception::OBSV_NOT_REMOVED;
 #ifdef WITH_PRESENCE
         case OC_STACK_PRESENCE_STOPPED:
             return OC::Exception::PRESENCE_STOPPED;
-        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
-            return OC::Exception::PRESENCE_NOT_HANDLED;
 #endif
+        case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+            return OC::Exception::VIRTUAL_DO_NOT_HANDLE;
         case OC_STACK_INVALID_OPTION:
             return OC::Exception::INVALID_OPTION;
         case OC_STACK_MALFORMED_RESPONSE:
             return OC::Exception::MALFORMED_STACK_RESPONSE;
+        case OC_STACK_PERSISTENT_BUFFER_REQUIRED:
+            return OC::Exception::PERSISTENT_BUFFER_REQUIRED;
+        case OC_STACK_CONTINUE:
+            return OC::Exception::STACK_CONTINUE;
+        case OC_STACK_INVALID_REQUEST_HANDLE:
+            return OC::Exception::INVALID_REQUEST_HANDLE;
         case OC_STACK_ERROR:
             return OC::Exception::GENERAL_FAULT;
     }
index 4390a4f..f26ffc7 100644 (file)
@@ -189,5 +189,10 @@ namespace OC
         {
             return OCPlatform_impl::Instance().unsubscribePresence(presenceHandle);
         }
+
+        OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+        {
+            return OCPlatform_impl::Instance().sendResponse(pResponse);
+        }
     } // namespace OCPlatform
 } //namespace OC
index fee95c9..e99cea7 100644 (file)
@@ -113,16 +113,16 @@ namespace OC
     }
 
     OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle,
-                                                ObservationIds& observationIds,
-                                                const std::shared_ptr<OCResourceResponse> pResponse)
+                                       ObservationIds& observationIds,
+                                       const std::shared_ptr<OCResourceResponse> pResponse)
     {
         return notifyListOfObservers(resourceHandle, observationIds, pResponse, m_cfg.QoS);
     }
 
     OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle,
-                                                ObservationIds& observationIds,
-                                                const std::shared_ptr<OCResourceResponse> pResponse,
-                                                QualityOfService QoS)
+                                       ObservationIds& observationIds,
+                                       const std::shared_ptr<OCResourceResponse> pResponse,
+                                       QualityOfService QoS)
     {
         if(!pResponse)
         {
@@ -293,4 +293,9 @@ namespace OC
                              ref(presenceHandle));
     }
 
+    OCStackResult OCPlatform_impl::sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+    {
+        return checked_guard(m_server, &IServerWrapper::sendResponse,
+                             pResponse);
+    }
 } //namespace OC
index 002d7fe..c55d8f9 100644 (file)
@@ -201,11 +201,8 @@ OCStackResult result_guard(const OCStackResult r)
     case OC_STACK_SLOW_RESOURCE:
     case OC_STACK_NO_OBSERVERS:
     case OC_STACK_OBSERVER_NOT_FOUND:
-    case OC_STACK_OBSERVER_NOT_ADDED:
-    case OC_STACK_OBSERVER_NOT_REMOVED:
 #ifdef WITH_PRESENCE
     case OC_STACK_PRESENCE_STOPPED:
-    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
 #endif
 
     break;
index 1b9c601..e299b43 100644 (file)
@@ -35,8 +35,7 @@ using namespace OC;
 using namespace std;
 
 // Entity handler used for register and find test
-OCEntityHandlerResult entityHandler_rf(std::shared_ptr<OCResourceRequest> request,
-                    std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler_rf(std::shared_ptr<OCResourceRequest> request)
 {
     return OC_EH_OK;
 }