This commit to support exposing vendor specific options to application:
authorYamin S Al-mousa <yamin.s.al-mousa@intel.com>
Wed, 1 Oct 2014 00:48:32 +0000 (17:48 -0700)
committerYamin S Al-mousa <yamin.s.al-mousa@intel.com>
Wed, 1 Oct 2014 00:48:32 +0000 (17:48 -0700)
1) Define a structure defining the vendor specific options
2) Pass an array of vendor specific options needed with the call to OCDoResource
3) Vendor specific header options are checked against the range of acceptable vendor specific header options
4) Vendor specific header options are added to the pdu being sent
5) Vendor specific header options are parsed and added to OCEntityHandlerRequest and OCClientResponse structs
6) Rebased on to master
7) Adding a test case to occlient for sending vendor specific option
8) Adding The number of options to be sent and the ones received, also adding this infor to OCEntityHandlerRequest and OCClientResponse structs
9) Rebased on to master

Change-Id: I5d4c56028bf510fba57ad4fc440565fd4b87ca31

18 files changed:
csdk/libcoap-4.1.1/bits.h
csdk/libcoap-4.1.1/option.h
csdk/libcoap-4.1.1/pdu.h
csdk/occoap/include/occoap.h
csdk/occoap/include/occoaphelper.h
csdk/occoap/src/occoap.c
csdk/occoap/src/occoaphelper.c
csdk/stack/include/ocstack.h
csdk/stack/include/ocstackconfig.h
csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp
csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp
csdk/stack/src/ocstack.c
csdk/stack/test/android/stacktests.cpp
csdk/stack/test/arduino/ArduinoStackTest.cpp
csdk/stack/test/linux/occlient.c
csdk/stack/test/stacktests.cpp
src/InProcClientWrapper.cpp

index 22c0b62..6569c75 100644 (file)
@@ -36,7 +36,7 @@ extern "C" {
  * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
  */
 inline static int
-bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
+bits_setb(uint8_t *vec, size_t size, uint16_t bit) {
   if (size <= (size_t)(bit >> 3))
     return -1;
 
@@ -56,7 +56,7 @@ bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
  * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
  */
 inline static int
-bits_clrb(uint8_t *vec, size_t size, uint8_t bit) {
+bits_clrb(uint8_t *vec, size_t size, uint16_t bit) {
   if (size <= (size_t)(bit >> 3))
     return -1;
 
@@ -75,7 +75,7 @@ bits_clrb(uint8_t *vec, size_t size, uint8_t bit) {
  * @return @c 1 if the bit is set, @c 0 otherwise.
  */
 inline static int
-bits_getb(const uint8_t *vec, size_t size, uint8_t bit) {
+bits_getb(const uint8_t *vec, size_t size, uint16_t bit) {
   if (size <= (size_t)(bit >> 3))
     return -1;
 
index 1644d1c..34cb31f 100644 (file)
@@ -124,6 +124,21 @@ coap_option_setb(coap_opt_filter_t filter, unsigned short type) {
   return bits_setb((uint8_t *)filter, sizeof(coap_opt_filter_t), type);
 }
 
+/**
+* Sets the entire range of vendor specific options in the filter
+*/
+inline static int
+coap_option_setbVendor(coap_opt_filter_t filter)
+{
+    if ((COAP_VENDOR_OPT_START >> 3) > sizeof(coap_opt_filter_t))
+    {
+        return -1;
+    }
+    memset((uint8_t *)filter + (COAP_VENDOR_OPT_START >> 3), 0xFF,
+            sizeof(coap_opt_filter_t) - (COAP_VENDOR_OPT_START >> 3));
+    return 1;
+}
+
 /** 
  * Clears the corresponding bit for @p type in @p filter. This function
  * returns @c 1 if bit was cleared or @c -1 on error (i.e. when the given
index 6e9b282..b89654f 100644 (file)
@@ -92,7 +92,15 @@ extern "C" {
 #define COAP_OPTION_BLOCK2       23 /* C, uint, 0--3 B, (none) */
 #define COAP_OPTION_BLOCK1       27 /* C, uint, 0--3 B, (none) */
 
-#define COAP_MAX_OPT             63 /**< the highest option number we know */
+#define COAP_VENDOR_OPT_START    (2048)
+/**< the highest option number we know
+ * COAP_MAX_OPT has to be larger than COAP_VENDOR_OPT_START
+ * however, we should keep in mind that COAP_MAX_OPT
+ * impacts the size of option filter as its size is about
+ * ceil(COAP_MAX_OPT>>3)
+ * Default is 3000 (just a nice round number)
+ */
+#define COAP_MAX_OPT             (3000)
 
 /* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */
 
index 7ac126b..e0059f1 100644 (file)
@@ -60,13 +60,15 @@ OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode);
  * @param token           - pointer to the token data structure
  * @param Uri             - URI of the resource to interact with
  * @param payload         - CoAP PDU payload
- *
+ * @param options         - The address of an array containing the vendor specific
+ *                          header options to be sent with the request
+ * @param numOptions      - The number of header options to be included
  * @return
  *   0   - success
  *   TBD - TBD error
  */
 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
-                     const char *Uri, const char *payload);
+        const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions);
 
 
 /**
index 279c40d..3e3874c 100644 (file)
@@ -37,6 +37,9 @@
 
 #define BUF_SIZE (64)
 
+// checks if optionID is within vendor specific range
+OCStackResult isVendorSpecific(uint16_t optionID);
+
 // Convert OCStack code to CoAP code
 uint8_t OCToCoAPResponseCode(OCStackResult result);
 
@@ -69,13 +72,15 @@ OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
 
 // Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
 OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
-        OCMethod method, unsigned char * resBuf, unsigned char * reqBuf,
+        OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
         unsigned char * queryBuf);
 
 // 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);
+        uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
+        OCHeaderOption * rcvVendorSpecificHeaderOptions,
+        uint8_t * numRcvVendorSpecificHeaderOptions);
 
 // Internal function to retrieve a Token from received coap pdu
 void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken);
@@ -89,7 +94,7 @@ OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
         uint8_t TTL, OCClientResponse * clientResponse);
 
 // Internal function to create OCClientResponse struct at the client from a received coap pdu
-OCStackResult FormOCClientResponse(OCClientResponse * * clientResponseLoc,
+OCStackResult FormOCClientResponse(OCClientResponse * clientResponse,
         OCStackResult result, OCDevAddr * remote, uint32_t seqNum,
         const unsigned char * resJSONPayload);
 
@@ -100,7 +105,8 @@ void HandleSendQueue(coap_context_t * gCoAPCtx);
 OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
         uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
         uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
-        uint8_t queryLength, unsigned char * query);
+        uint8_t queryLength, unsigned char * query, OCHeaderOption * vendorSpecificHeaderOptions,
+        uint8_t numVendorSpecificHeaderOptions);
 
 // Internal function to retransmit a queue
 OCStackResult ReTXCoAPQueue(coap_context_t * ctx, coap_queue_t * queue);
index 9e3cd5a..6c8379e 100644 (file)
@@ -78,7 +78,7 @@ static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType,
     coap_pdu_t * sentPdu = sentQueue->pdu;
 
     // fill the buffers of Uri and Query
-    result = ParseCoAPPdu(sentPdu, NULL, NULL, &observeOption, NULL, NULL);
+    result = ParseCoAPPdu(sentPdu, NULL, NULL, &observeOption, NULL, NULL, NULL, NULL);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // fill OCCoAPToken structure
@@ -142,11 +142,14 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
     uint8_t * rcvObserveOption = NULL;
     unsigned char * bufReqPayload = NULL;
     uint32_t observeOption = OC_RESOURCE_NO_OBSERVE;
+    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);
+    result = ParseCoAPPdu(recvPdu, rcvdUri, rcvdQuery, &rcvObserveOption, NULL, &bufReqPayload,
+            entityHandlerRequest.rcvdVendorSpecificHeaderOptions,
+            &(entityHandlerRequest.numRcvdVendorSpecificHeaderOptions));
     VERIFY_SUCCESS(result, OC_STACK_OK);
     if(rcvObserveOption){
         observeOption = (uint32_t)(*rcvObserveOption);
@@ -199,21 +202,27 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
             observeOption = rcvdObsReq->option;
             result = FormOptionList(&optList, &mediaType, &maxAge,
                     sizeof(observeOption), &observeOption,
-                    NULL, 0, NULL, 0, NULL);
+                    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);
+                    0, NULL, 0, NULL,
+                    request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
+                    request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
             break;
         }
     }
     else
     {
         result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
-                0, NULL, 0, NULL);
+                0, NULL, 0, NULL,
+                request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
+                request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
     }
 
     VERIFY_SUCCESS(result, OC_STACK_OK);
@@ -251,7 +260,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         const coap_queue_t * rcvdResponse) {
     OCResponse * response = NULL;
     OCCoAPToken rcvdToken;
-    OCClientResponse * clientResponse = NULL;
+    OCClientResponse clientResponse;
     ClientCB * cbNode = NULL;
     unsigned char * bufRes = NULL;
     uint8_t * rcvObserveOption = NULL;
@@ -272,12 +281,15 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     uint32_t higherBound;
     char * tok = NULL;
     #endif
+    memset(&clientResponse, 0, sizeof(OCClientResponse));
 
     VERIFY_NON_NULL(ctx);
     VERIFY_NON_NULL(rcvdResponse);
     recvPdu = rcvdResponse->pdu;
 
-    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &rcvObserveOption, &rcvMaxAgeOption, &bufRes);
+    result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &rcvObserveOption, &rcvMaxAgeOption, &bufRes,
+            clientResponse.rcvdVendorSpecificHeaderOptions,
+            &(clientResponse.numRcvdVendorSpecificHeaderOptions));
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     if(rcvObserveOption){
@@ -337,7 +349,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     }
 
     // fill OCResponse structure
-    result = FormOCResponse(&response, cbNode, maxAge, clientResponse);
+    result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     if(cbNode)
@@ -355,17 +367,17 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
             }
             //TODO: check the standard for methods to detect wrap around condition
             if(cbNode->method == OC_REST_OBSERVE &&
-                    (clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
-                            (clientResponse->sequenceNumber > cbNode->sequenceNumber &&
-                                    clientResponse->sequenceNumber == MAX_SEQUENCE_NUMBER)))
+                    (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
+                            (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
+                                    clientResponse.sequenceNumber == MAX_SEQUENCE_NUMBER)))
             {
                 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
                         Ignoring Incoming:%d  Against Current:%d.",
-                        clientResponse->sequenceNumber, cbNode->sequenceNumber);
+                        clientResponse.sequenceNumber, cbNode->sequenceNumber);
                 goto exit;
             }
-            if(clientResponse->sequenceNumber > cbNode->sequenceNumber){
-                cbNode->sequenceNumber = clientResponse->sequenceNumber;
+            if(clientResponse.sequenceNumber > cbNode->sequenceNumber){
+                cbNode->sequenceNumber = clientResponse.sequenceNumber;
             }
         }
         else
@@ -408,13 +420,13 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     }
                     cbNode->presence->TTLlevel = 0;
                     OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
-                    if(cbNode->sequenceNumber == clientResponse->sequenceNumber)
+                    if(cbNode->sequenceNumber == clientResponse.sequenceNumber)
                     {
                         OC_LOG(INFO, TAG, "===============No presence change");
                         goto exit;
                     }
                     OC_LOG(INFO, TAG, "===============Presence changed, calling up the stack");
-                    cbNode->sequenceNumber = clientResponse->sequenceNumber;;
+                    cbNode->sequenceNumber = clientResponse.sequenceNumber;;
                 }
             }
             #endif
@@ -451,7 +463,6 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     exit:
         OCFree(rcvObserveOption);
         OCFree(rcvMaxAgeOption);
-        OCFree(clientResponse);
         OCFree(response);
 }
 
@@ -537,12 +548,14 @@ exit:
  * @param Uri             - URI of the resource to interact with
  * @param payload         - the request payload to be added to the request before sending
  *                          by the stack when discovery or resource interaction is complete
+ * @param options         - The address of an array containing the vendor specific
+ *                          header options to be sent with the request
  * @return
  *   0   - success
  *   TBD - TBD error
  */
 OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
-                     const char *Uri, const char *payload)
+                     const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions)
 {
 
     OCStackResult ret = OC_STACK_ERROR;
@@ -572,7 +585,7 @@ OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPTo
 
         VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, 0, NULL,
                 (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
-                uri.query.s), OC_STACK_OK);
+                uri.query.s, options, numOptions), OC_STACK_OK);
 
         OC_LOG_V(DEBUG, TAG, "uri.host.s %s", uri.host.s);
         OC_LOG_V(DEBUG, TAG, "uri.path.s %s", uri.path.s);
@@ -649,13 +662,13 @@ OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr, O
     if(!strcmp((const char *)uri, OC_PRESENCE_URI))
     {
         result = FormOptionList(&optList, &mediaType, NULL, 0, NULL,
-                NULL, strlen((char *)uri), uri, 0, NULL);
+                NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
     }
     else
     {
     #endif
         result = FormOptionList(&optList, &mediaType, &maxAge, sizeof(seqNum),
-                &seqNum, NULL, strlen((char *)uri), uri, 0, NULL);
+                &seqNum, NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
     #ifdef WITH_PRESENCE
     }
     #endif
index fe3c81b..b35b1a8 100644 (file)
 // Helper Functions
 //=============================================================================
 
+OCStackResult isVendorSpecific(uint16_t optionID)
+{
+    if(optionID >= COAP_VENDOR_OPT_START && optionID <= COAP_MAX_OPT)
+    {
+        return OC_STACK_OK;
+    }
+    return OC_STACK_INVALID_OPTION;
+}
+
 // Convert OCStack code to CoAP code
 uint8_t OCToCoAPResponseCode(OCStackResult result)
 {
@@ -107,7 +116,9 @@ 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)
+        uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
+        OCHeaderOption * rcvVendorSpecificHeaderOptions,
+        uint8_t * numRcvVendorSpecificHeaderOptions)
 {
     coap_opt_filter_t filter;
     coap_opt_iterator_t opt_iter;
@@ -229,6 +240,32 @@ OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
         }
     }
 
+    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)
+            {
+                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++;
+            *numRcvVendorSpecificHeaderOptions = i;
+        }
+    }
+
     // get the payload
     if(payloadLoc)
     {
@@ -353,30 +390,24 @@ OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
     return OC_STACK_OK;
 }
 
-OCStackResult FormOCClientResponse(OCClientResponse * * clientResponseLoc,
+OCStackResult FormOCClientResponse(OCClientResponse * clientResponse,
         OCStackResult result, OCDevAddr * remote, uint32_t seqNum,
         const unsigned char * resJSONPayload)
 {
-
-    OCClientResponse * clientResponse = (OCClientResponse *) OCMalloc(
-            sizeof(OCClientResponse));
-    if (!clientResponse)
-    {
-        return OC_STACK_NO_MEMORY;
-    }
     clientResponse->sequenceNumber = seqNum;
     clientResponse->result = result;
     clientResponse->addr = remote;
     clientResponse->resJSONPayload = resJSONPayload;
 
-    *clientResponseLoc = clientResponse;
     return OC_STACK_OK;
 }
 
 OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
         uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
         uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
-        uint8_t queryLength, unsigned char * query)
+        uint8_t queryLength, unsigned char * query,
+        OCHeaderOption * vendorSpecificHeaderOptions,
+        uint8_t numVendorSpecificHeaderOptions)
 {
     coap_list_t * optNode = NULL;
     int res;
@@ -412,6 +443,7 @@ OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
     {
         optNode = CreateNewOptionNode(COAP_OPTION_URI_PORT,
                 sizeof(*addPortNumber), (uint8_t *)addPortNumber);
+        VERIFY_NON_NULL(optNode);
         coap_insert(optListLoc, optNode, OrderOptions);
     }
 
@@ -443,6 +475,38 @@ OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
         }
     }
 
+    // make sure that options are valid
+    if(vendorSpecificHeaderOptions && numVendorSpecificHeaderOptions)
+    {
+        uint8_t i = 0;
+        for( i = 0; i < numVendorSpecificHeaderOptions; i++)
+        {
+            if(vendorSpecificHeaderOptions[i].protocolID == OC_COAP_ID)
+            {
+                if(isVendorSpecific(vendorSpecificHeaderOptions[i].optionID)
+                        == OC_STACK_OK &&
+                        vendorSpecificHeaderOptions[i].optionLength <=
+                        MAX_HEADER_OPTION_DATA_LENGTH)
+                {
+                    OC_LOG_V(INFO, TAG, " Adding option %d with",
+                            vendorSpecificHeaderOptions[i].optionID);
+                    OC_LOG_BUFFER(INFO, TAG, vendorSpecificHeaderOptions[i].optionData,
+                            vendorSpecificHeaderOptions[i].optionLength);
+                    optNode = CreateNewOptionNode(vendorSpecificHeaderOptions[i].optionID,
+                            vendorSpecificHeaderOptions[i].optionLength,
+                            vendorSpecificHeaderOptions[i].optionData);
+                    VERIFY_NON_NULL(optNode);
+                    coap_insert(optListLoc, optNode, OrderOptions);
+                }
+                else
+                {
+                    coap_delete_list(*optListLoc);
+                    return OC_STACK_INVALID_OPTION;
+                }
+            }
+        }
+    }
+
     return OC_STACK_OK;
     exit:
         coap_delete_list(*optListLoc);
@@ -618,7 +682,7 @@ OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * que
     OCResponse * response = NULL;
     ClientCB * cbNode = NULL;
     ResourceObserver * observer = NULL;
-    OCClientResponse * clientResponse = NULL;
+    OCClientResponse clientResponse;
     OCCoAPToken token;
     OCStackResult result = OC_STACK_OK;
 
@@ -635,7 +699,7 @@ OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * que
     {
         goto observation;
     }
-    result = FormOCResponse(&response, cbNode, 0, clientResponse);
+    result = FormOCResponse(&response, cbNode, 0, &clientResponse);
     if(result != OC_STACK_OK)
     {
         goto observation;
@@ -656,7 +720,7 @@ observation:
     }
 
     exit:
-        OCFree(clientResponse);
+
         OCFree(response);
     return result;
 }
index 80a5d4d..2b87e0b 100644 (file)
@@ -22,6 +22,7 @@
 #define OCSTACK_H_
 
 #include "ocsocket.h"
+#include "ocstackconfig.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -111,6 +112,14 @@ typedef enum {
 } OCResourceProperty;
 
 /**
+ * Transport Protocol IDs
+ */
+typedef enum {
+    OC_INVALID_ID   = (1 << 0),
+    OC_COAP_ID      = (1 << 1),
+} OCTransportProtocolID;
+
+/**
  * Declares Stack Results & Errors
  */
 typedef enum {
@@ -137,6 +146,7 @@ typedef enum {
     OC_STACK_PRESENCE_STOPPED,
     OC_STACK_PRESENCE_DO_NOT_HANDLE,
     #endif
+    OC_STACK_INVALID_OPTION,
     OC_STACK_ERROR
 } OCStackResult;
 
@@ -174,6 +184,20 @@ typedef struct {
     OCObservationId obsId;
 } OCObservationInfo;
 
+// following structure will be used to define the vendor specific header options to be included
+// in communication packets
+
+typedef struct OCHeaderOption {
+    // The protocol ID this option applies to
+    OCTransportProtocolID protocolID;
+    // The header option ID which will be added to communication packets
+    uint16_t optionID;
+    // its length   191
+    uint16_t optionLength;
+    // pointer to its data
+    uint8_t optionData[MAX_HEADER_OPTION_DATA_LENGTH];
+} OCHeaderOption;
+
 /**
  * Incoming requests handled by the server. Requests are passed in as a parameter to the @ref OCEntityHandler callback API.
  * @brief The @ref OCEntityHandler callback API must be implemented in the application in order to receive these requests.
@@ -194,6 +218,12 @@ typedef struct {
     // Information associated with observation - valid only when OCEntityHandler
     // flag includes OC_OBSERVE_FLAG
     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];
 }OCEntityHandlerRequest;
 
 /**
@@ -208,6 +238,9 @@ typedef struct {
     uint32_t sequenceNumber;
     // resJSONPayload is retrieved from the payload of the received request PDU
     unsigned  const char * resJSONPayload;
+    // An array of the received vendor specific header options
+    uint8_t numRcvdVendorSpecificHeaderOptions;
+    OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
 }OCClientResponse;
 
 typedef enum {
@@ -317,6 +350,9 @@ OCStackResult OCProcess();
  * @param qos                - quality of service
  * @param clientApplicationCB- asynchronous callback function that is invoked
  *                             by the stack when discovery or resource interaction is complete
+ * @param options            - The address of an array containing the vendor specific
+ *                             header options to be sent with the request
+ * @param numOptions         - Number of header options to be included
  *
  * @return
  *     OC_STACK_OK               - no errors
@@ -325,18 +361,24 @@ OCStackResult OCProcess();
  *     OC_STACK_INVALID_URI      - invalid required or reference URI
  */
 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char  *requiredUri, const char  *referenceUri,
-                const char *request, OCQualityOfService qos, OCCallbackData *cbData);
+                const char *request, OCQualityOfService qos, OCCallbackData *cbData, OCHeaderOption * options,
+                uint8_t numOptions);
 
 /**
  * Cancel a request associated with a specific @ref OCDoResource invocation.
  *
  * @param handle - Used to identify a specific OCDoResource invocation.
- * @param qos    - valid only when handle is for an observe method.
+ * @param qos    - used to specify Quality of Service (read below for more info)
+ * @param options- used to specify vendor specific header options when sending
+ *                 explicit observe cancellation
+ * @param numOptions- Number of header options to be included
+ *
  * @return
  *     OC_STACK_OK               - No errors; Success
  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
  */
-OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos);
+OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
+        uint8_t numOptions);
 
 #ifdef WITH_PRESENCE
 /**
index cd4e831..650949c 100644 (file)
  */
 #define MAX_CONTAINED_RESOURCES  (5)
 
+/**
+ *  Maximum number of vendor specific header options an application can set or receive in pdu
+ */
+#define MAX_HEADER_OPTIONS (2)
+
+/**
+ *  Maximum Length of the vendor specific header option
+ */
+#define MAX_HEADER_OPTION_DATA_LENGTH (16)
+
 #endif //OCSTACK_CONFIG_H_
index 9459ed3..18a84bb 100644 (file)
@@ -54,6 +54,7 @@ typedef enum {
     TEST_OBS_PRESENCE,
     #endif
     TEST_OBS_REQ_NON_CANCEL_IMM,
+    TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS,
     MAX_TESTS
 } CLIENT_TEST;
 
@@ -94,7 +95,7 @@ int InitPresence();
 int InitGetRequestToUnavailableResource();
 int InitObserveRequest(OCQualityOfService qos);
 int InitPutRequest();
-int InitGetRequest(OCQualityOfService qos);
+int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions);
 int InitDiscovery();
 void parseClientResponse(OCClientResponse * clientResponse);
 
@@ -113,11 +114,12 @@ static void PrintUsage()
     OC_LOG(INFO, TAG, "-t 8 : Discover Resources and Initiate Nonconfirmable presence");
     #endif
     OC_LOG(INFO, TAG, "-t 9 : Discover Resources and Initiate Nonconfirmable Observe Requests then cancel immediately");
+    OC_LOG(INFO, TAG, "-t 10: Discover Resources and Initiate Nonconfirmable Get Request and add  vendor specific header options");
 }
 
 OCStackResult InvokeOCDoResource(std::ostringstream &query,
                                  OCMethod method, OCQualityOfService qos,
-                                 OCClientResponseHandler cb )
+                                 OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
 {
     OCStackResult ret;
     OCCallbackData cbData;
@@ -126,9 +128,10 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
     cbData.cb = cb;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
+
     ret = OCDoResource(&handle, method, query.str().c_str(), 0,
                        (method == OC_REST_PUT) ? putPayload.c_str() : NULL,
-                       qos, &cbData);
+                       qos, &cbData, options, numOptions);
 
     if (ret != OC_STACK_OK)
     {
@@ -174,6 +177,23 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
         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;
 }
 
@@ -195,13 +215,14 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse
             printf ("************************** CANCEL OBSERVE with ");
             if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON){
                 printf ("RESET\n");
-                if (OCCancel (gObserveDoHandle, OC_NON_CONFIRMABLE) != OC_STACK_OK){
+                if (OCCancel (gObserveDoHandle, OC_NON_CONFIRMABLE, NULL, 0) != OC_STACK_OK){
                     OC_LOG(ERROR, TAG, "Observe cancel error");
                 }
                 return OC_STACK_DELETE_TRANSACTION;
             }else if(TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM){
                 printf ("Deregister\n");
-                if (OCCancel (gObserveDoHandle, OC_CONFIRMABLE) != OC_STACK_OK){
+
+                if (OCCancel (gObserveDoHandle, OC_CONFIRMABLE, NULL, 0) != OC_STACK_OK){
                     OC_LOG(ERROR, TAG, "Observe cancel error");
                 }
             }
@@ -235,7 +256,7 @@ OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientRespon
         if (gNumPresenceNotifies == 15)
         {
             printf ("************************** CANCEL PRESENCE\n");
-            if (OCCancel (gPresenceHandle, OC_NON_CONFIRMABLE) != OC_STACK_OK){
+            if (OCCancel (gPresenceHandle, OC_NON_CONFIRMABLE, NULL, 0) != OC_STACK_OK){
                 OC_LOG(ERROR, TAG, "Presence cancel error");
             }
             return OC_STACK_DELETE_TRANSACTION;
@@ -273,7 +294,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
 
         switch(TEST_CASE){
         case TEST_GET_REQ_NON:
-            InitGetRequest(OC_NON_CONFIRMABLE);
+            InitGetRequest(OC_NON_CONFIRMABLE, 0);
             break;
         case TEST_PUT_REQ_NON:
             InitPutRequest();
@@ -286,7 +307,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
             InitGetRequestToUnavailableResource();
             break;
         case TEST_GET_REQ_CON:
-            InitGetRequest(OC_CONFIRMABLE);
+            InitGetRequest(OC_CONFIRMABLE, 0);
             break;
         case TEST_OBS_REQ_CON:
             InitObserveRequest(OC_CONFIRMABLE);
@@ -296,6 +317,9 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
             InitPresence();
             break;
         #endif
+        case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS:
+            InitGetRequest(OC_NON_CONFIRMABLE, 1);
+            break;
         default:
             PrintUsage();
             break;
@@ -311,7 +335,7 @@ int InitPresence()
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
     std::ostringstream query;
     query << "coap://" << coapServerIP << ":" << coapServerPort << OC_PRESENCE_URI;
-    return (InvokeOCDoResource(query, OC_REST_PRESENCE, OC_NON_CONFIRMABLE, presenceCB));
+    return (InvokeOCDoResource(query, OC_REST_PRESENCE, OC_NON_CONFIRMABLE, presenceCB, NULL, 0));
 }
 #endif
 int InitGetRequestToUnavailableResource()
@@ -319,7 +343,7 @@ int InitGetRequestToUnavailableResource()
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
     std::ostringstream query;
     query << "coap://" << coapServerIP << ":" << coapServerPort << "/SomeUnknownResource";
-    return (InvokeOCDoResource(query, OC_REST_GET, OC_NON_CONFIRMABLE, getReqCB));
+    return (InvokeOCDoResource(query, OC_REST_GET, OC_NON_CONFIRMABLE, getReqCB, NULL, 0));
 }
 
 
@@ -328,7 +352,7 @@ int InitObserveRequest(OCQualityOfService qos)
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
     std::ostringstream query;
     query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
-    return (InvokeOCDoResource(query, OC_REST_OBSERVE, (qos == OC_CONFIRMABLE)? OC_CONFIRMABLE:OC_NON_CONFIRMABLE, obsReqCB));
+    return (InvokeOCDoResource(query, OC_REST_OBSERVE, (qos == OC_CONFIRMABLE)? OC_CONFIRMABLE:OC_NON_CONFIRMABLE, obsReqCB, NULL, 0));
 }
 
 
@@ -337,16 +361,40 @@ int InitPutRequest()
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
     std::ostringstream query;
     query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
-    return (InvokeOCDoResource(query, OC_REST_PUT, OC_NON_CONFIRMABLE, putReqCB));
+    return (InvokeOCDoResource(query, OC_REST_PUT, OC_NON_CONFIRMABLE, putReqCB, NULL, 0));
 }
 
 
-int InitGetRequest(OCQualityOfService qos)
+int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions)
 {
+    OCHeaderOption options[MAX_HEADER_OPTIONS];
+
     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_CONFIRMABLE)? OC_CONFIRMABLE:OC_NON_CONFIRMABLE, getReqCB));
+
+    if(withVendorSpecificHeaderOptions)
+    {
+        uint8_t option0[] = {1,2,3,4,5,6,7,8,9,10};
+        uint8_t option1[] = {11,12,13,14,15,16,17,18,19,20};
+        memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS);
+        options[0].protocolID = OC_COAP_ID;
+        options[0].optionID = 2048;
+        memcpy(options[0].optionData, option0, sizeof(option0));
+        options[0].optionLength = 10;
+        options[1].protocolID = OC_COAP_ID;
+        options[1].optionID = 3000;
+        memcpy(options[1].optionData, option1, sizeof(option1));
+        options[1].optionLength = 10;
+    }
+    if(withVendorSpecificHeaderOptions)
+    {
+        return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_CONFIRMABLE)? OC_CONFIRMABLE:OC_NON_CONFIRMABLE, getReqCB, options, 2));
+    }
+    else
+    {
+        return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_CONFIRMABLE)? OC_CONFIRMABLE:OC_NON_CONFIRMABLE, getReqCB, NULL, 0));
+    }
 }
 
 int InitDiscovery()
@@ -367,7 +415,7 @@ int InitDiscovery()
     cbData.cb = discoveryReqCB;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
-    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack resource error");
index 4898a8c..4a616ea 100644 (file)
@@ -100,7 +100,7 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse
             gNumObserveNotifies++;
             if (gNumObserveNotifies == 3)
             {
-                if (OCCancel (gObserveDoHandle, OC_NON_CONFIRMABLE) != OC_STACK_OK){
+                if (OCCancel (gObserveDoHandle, OC_NON_CONFIRMABLE, NULL, 0) != OC_STACK_OK){
                     OC_LOG(ERROR, TAG, "Observe cancel error");
                 }
             }
@@ -152,7 +152,9 @@ int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse)
     cbData.cb = getReqCB;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
-    ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
+
+    ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE,
+            &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack resource error");
@@ -172,7 +174,9 @@ int InitObserveRequest(OCClientResponse * clientResponse)
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
     OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
-    ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
+
+    ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_NON_CONFIRMABLE,
+            &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack resource error");
@@ -198,7 +202,9 @@ int InitPutRequest(OCClientResponse * clientResponse)
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
     OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
-    ret = OCDoResource(&handle, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(), OC_NON_CONFIRMABLE, &cbData);
+
+    ret = OCDoResource(&handle, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(),
+            OC_NON_CONFIRMABLE, &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack resource error");
@@ -232,7 +238,8 @@ int InitGetRequest(OCClientResponse * clientResponse)
     cbData.cb = getReqCB;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
-    ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE,
+            &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack resource error");
@@ -255,7 +262,8 @@ int InitDiscovery()
     cbData.cb = discoveryReqCB;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
-    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData);
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE,
+            &cbData, NULL, 0);
     if (ret != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack resource error");
index 27fd71c..addf72a 100644 (file)
@@ -131,7 +131,6 @@ OCEntityHandlerResult
 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
                    OCEntityHandlerRequest *entityHandlerRequest, char* uri)
 {
-    const char* typeOfMessage;
 
     OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
     if (flag & OC_INIT_FLAG)
@@ -184,8 +183,6 @@ OCEntityHandlerResult
 OCEntityHandlerCb (OCEntityHandlerFlag flag,
                    OCEntityHandlerRequest *entityHandlerRequest)
 {
-    const char* typeOfMessage;
-
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
     if (flag & OC_INIT_FLAG)
     {
@@ -230,6 +227,35 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
             }
         }
     }
+    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++)
+        {
+            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 = 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 OC_EH_OK;
 }
index 9bc3a3c..b8ab2c1 100644 (file)
@@ -323,6 +323,9 @@ OCStackResult OCStop()
  * @param qos                - quality of service
  * @param cbData             - struct that contains asynchronous callback function that is invoked
  *                             by the stack when discovery or resource interaction is complete
+ * @param options            - The address of an array containing the vendor specific header
+ *                             header options to be sent with the request
+ * @param numOptions         - Number of vendor specific header options to be included
  *
  * @return
  *     OC_STACK_OK               - no errors
@@ -333,7 +336,8 @@ OCStackResult OCStop()
 
 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
                            const char *referenceUri, const char *request,
-                           OCQualityOfService qos, OCCallbackData *cbData)
+                           OCQualityOfService qos, OCCallbackData *cbData,
+                           OCHeaderOption * options, uint8_t numOptions)
 {
     OCStackResult result = OC_STACK_ERROR;
     OCCoAPToken token;
@@ -403,7 +407,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     }
 
     // Make call to OCCoAP layer
-    result = OCDoCoAPResource(method, qos, &token, requiredUri, request);
+    result = OCDoCoAPResource(method, qos, &token, requiredUri, request, options, numOptions);
 
 exit:
     if (result != OC_STACK_OK)
@@ -418,12 +422,17 @@ exit:
  * Cancel a request associated with a specific @ref OCDoResource invocation.
  *
  * @param handle - Used to identify a specific OCDoResource invocation.
+ * @param qos    - used to specify Quality of Service (read below for more info)
+ * @param options- used to specify vendor specific header options when sending
+ *                 explicit observe cancellation
+ * @param numOptions- Number of header options to be included
  *
  * @return
  *     OC_STACK_OK               - No errors; Success
  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
  */
-OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos) {
+OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
+        uint8_t numOptions) {
     /*
      * This ftn is implemented one of two ways in the case of observation:
      *
@@ -459,7 +468,8 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos) {
                 if(qos == OC_CONFIRMABLE)
                 {
                     ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
-                            &(clientCB->token), (const char *) clientCB->requestUri, NULL);
+                            &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
+                            numOptions);
                 }
                 else
                 {
@@ -487,7 +497,7 @@ OCStackResult OCProcessPresence()
     OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
     ClientCB* cbNode = NULL;
     OCDevAddr dst;
-    OCClientResponse * clientResponse = NULL;
+    OCClientResponse clientResponse;
     OCResponse * response = NULL;
 
     LL_FOREACH(cbList, cbNode) {
@@ -515,7 +525,7 @@ OCStackResult OCProcessPresence()
                         {
                             goto exit;
                         }
-                        result = FormOCResponse(&response, cbNode, 0, clientResponse);
+                        result = FormOCResponse(&response, cbNode, 0, &clientResponse);
                         if(result != OC_STACK_OK)
                         {
                             goto exit;
@@ -533,7 +543,7 @@ OCStackResult OCProcessPresence()
                     OCCoAPToken token;
                     OCGenerateCoAPToken(&token);
                     result = OCDoCoAPResource(OC_REST_GET, OC_NON_CONFIRMABLE,
-                            &token, (const char *)cbNode->requestUri, NULL);
+                            &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
                     cbNode->presence->TTLlevel++;
                     OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
                 }
index 33b5cfe..9260836 100644 (file)
@@ -103,7 +103,7 @@ void test4() {
 
 void test5() {
     EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0);
     EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
@@ -116,7 +116,7 @@ void test6() {
 
 void test7() {
     EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0);
     EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
index f17bed4..a4954d7 100644 (file)
@@ -163,7 +163,7 @@ void test4() {
 void test5() {
     OC_LOG(INFO, TAG, PCF("test5"));
     EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0);
     EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
@@ -178,7 +178,7 @@ void test6() {
 void test7() {
     OC_LOG(INFO, TAG, PCF("test7"));
     EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0);
     EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
index d3758a5..6716992 100644 (file)
@@ -73,7 +73,7 @@ int main() {
     char szQueryUri[64] = { 0 };
     strcpy(szQueryUri, OC_EXPLICIT_DEVICE_DISCOVERY_URI);
     if (OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE,
-            0) != OC_STACK_OK) {
+            0, 0, 0) != OC_STACK_OK) {
         OC_LOG(ERROR, TAG, "OCStack resource error");
         return 0;
     }
index e8a303c..bf47613 100644 (file)
@@ -130,7 +130,7 @@ TEST(StackTest, DoResourceDeviceDiscovery) {
     cbData.cb = asyncDoResourcesCallback;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
     //EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
@@ -160,7 +160,7 @@ TEST(StackTest, UpdateResourceNullURI) {
     cbData.cb = asyncDoResourcesCallback;
     cbData.context = (void*)CTX_VAL;
     cbData.cd = NULL;
-    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
     //EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
index d849843..f2886b4 100644 (file)
@@ -235,7 +235,8 @@ namespace OC
                                   resourceType.c_str(),
                                   nullptr, nullptr,
                                   static_cast<OCQualityOfService>(m_cfg.QoS),
-                                  &cbdata);
+                                  &cbdata,
+                                  NULL, 0);
         }
         else
         {
@@ -403,7 +404,8 @@ namespace OC
             result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(),
                                   nullptr, nullptr,
                                   static_cast<OCQualityOfService>(m_cfg.QoS),
-                                  &cbdata);
+                                  &cbdata,
+                                  NULL, 0);
         }
         else
         {
@@ -497,7 +499,8 @@ namespace OC
                                   os.str().c_str(), nullptr,
                                   assembleSetResourcePayload(rep).c_str(),
                                   static_cast<OCQualityOfService>(m_cfg.QoS),
-                                  &cbdata);
+                                  &cbdata,
+                                  NULL, 0);
         }
         else
         {
@@ -566,7 +569,8 @@ namespace OC
                                   os.str().c_str(), nullptr,
                                   nullptr,
                                   static_cast<OCQualityOfService>(m_cfg.QoS),
-                                  &cbdata);
+                                  &cbdata,
+                                  NULL, 0);
         }
         else
         {
@@ -585,7 +589,7 @@ namespace OC
         if(cLock)
         {
             std::lock_guard<std::mutex> lock(*cLock);
-            result = OCCancel(handle, OC_NON_CONFIRMABLE);
+            result = OCCancel(handle, OC_NON_CONFIRMABLE, NULL, 0);
         }
         else
         {
@@ -630,7 +634,7 @@ namespace OC
             return OC_STACK_ERROR;
 
         return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
-                            OC_NON_CONFIRMABLE, &cbdata);
+                            OC_NON_CONFIRMABLE, &cbdata, NULL, 0);
     }
 
     OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
@@ -641,7 +645,7 @@ namespace OC
         if(cLock)
         {
             std::lock_guard<std::mutex> lock(*cLock);
-            result = OCCancel(handle, OC_NON_CONFIRMABLE);
+            result = OCCancel(handle, OC_NON_CONFIRMABLE, NULL, 0);
         }
         else
         {