* @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;
* @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;
* @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;
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
#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) */
* @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);
/**
#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);
// 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);
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);
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);
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
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);
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);
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;
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){
}
// fill OCResponse structure
- result = FormOCResponse(&response, cbNode, maxAge, clientResponse);
+ result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
VERIFY_SUCCESS(result, OC_STACK_OK);
if(cbNode)
}
//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
}
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
exit:
OCFree(rcvObserveOption);
OCFree(rcvMaxAgeOption);
- OCFree(clientResponse);
OCFree(response);
}
* @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;
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);
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
// 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)
{
// 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;
}
}
+ 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)
{
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;
{
optNode = CreateNewOptionNode(COAP_OPTION_URI_PORT,
sizeof(*addPortNumber), (uint8_t *)addPortNumber);
+ VERIFY_NON_NULL(optNode);
coap_insert(optListLoc, optNode, OrderOptions);
}
}
}
+ // 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);
OCResponse * response = NULL;
ClientCB * cbNode = NULL;
ResourceObserver * observer = NULL;
- OCClientResponse * clientResponse = NULL;
+ OCClientResponse clientResponse;
OCCoAPToken token;
OCStackResult result = OC_STACK_OK;
{
goto observation;
}
- result = FormOCResponse(&response, cbNode, 0, clientResponse);
+ result = FormOCResponse(&response, cbNode, 0, &clientResponse);
if(result != OC_STACK_OK)
{
goto observation;
}
exit:
- OCFree(clientResponse);
+
OCFree(response);
return result;
}
#define OCSTACK_H_
#include "ocsocket.h"
+#include "ocstackconfig.h"
#ifdef __cplusplus
extern "C" {
} OCResourceProperty;
/**
+ * Transport Protocol IDs
+ */
+typedef enum {
+ OC_INVALID_ID = (1 << 0),
+ OC_COAP_ID = (1 << 1),
+} OCTransportProtocolID;
+
+/**
* Declares Stack Results & Errors
*/
typedef enum {
OC_STACK_PRESENCE_STOPPED,
OC_STACK_PRESENCE_DO_NOT_HANDLE,
#endif
+ OC_STACK_INVALID_OPTION,
OC_STACK_ERROR
} OCStackResult;
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.
// 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;
/**
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 {
* @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
* 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
/**
*/
#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_
TEST_OBS_PRESENCE,
#endif
TEST_OBS_REQ_NON_CANCEL_IMM,
+ TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS,
MAX_TESTS
} CLIENT_TEST;
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);
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;
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)
{
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;
}
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");
}
}
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;
switch(TEST_CASE){
case TEST_GET_REQ_NON:
- InitGetRequest(OC_NON_CONFIRMABLE);
+ InitGetRequest(OC_NON_CONFIRMABLE, 0);
break;
case TEST_PUT_REQ_NON:
InitPutRequest();
InitGetRequestToUnavailableResource();
break;
case TEST_GET_REQ_CON:
- InitGetRequest(OC_CONFIRMABLE);
+ InitGetRequest(OC_CONFIRMABLE, 0);
break;
case TEST_OBS_REQ_CON:
InitObserveRequest(OC_CONFIRMABLE);
InitPresence();
break;
#endif
+ case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS:
+ InitGetRequest(OC_NON_CONFIRMABLE, 1);
+ break;
default:
PrintUsage();
break;
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()
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));
}
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));
}
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()
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");
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");
}
}
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");
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");
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");
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");
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");
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)
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)
{
}
}
}
+ 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;
}
* @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
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;
}
// 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)
* 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:
*
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
{
OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
ClientCB* cbNode = NULL;
OCDevAddr dst;
- OCClientResponse * clientResponse = NULL;
+ OCClientResponse clientResponse;
OCResponse * response = NULL;
LL_FOREACH(cbList, cbNode) {
{
goto exit;
}
- result = FormOCResponse(&response, cbNode, 0, clientResponse);
+ result = FormOCResponse(&response, cbNode, 0, &clientResponse);
if(result != OC_STACK_OK)
{
goto exit;
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);
}
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());
}
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());
}
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());
}
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());
}
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;
}
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());
}
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());
}
resourceType.c_str(),
nullptr, nullptr,
static_cast<OCQualityOfService>(m_cfg.QoS),
- &cbdata);
+ &cbdata,
+ NULL, 0);
}
else
{
result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(),
nullptr, nullptr,
static_cast<OCQualityOfService>(m_cfg.QoS),
- &cbdata);
+ &cbdata,
+ NULL, 0);
}
else
{
os.str().c_str(), nullptr,
assembleSetResourcePayload(rep).c_str(),
static_cast<OCQualityOfService>(m_cfg.QoS),
- &cbdata);
+ &cbdata,
+ NULL, 0);
}
else
{
os.str().c_str(), nullptr,
nullptr,
static_cast<OCQualityOfService>(m_cfg.QoS),
- &cbdata);
+ &cbdata,
+ NULL, 0);
}
else
{
if(cLock)
{
std::lock_guard<std::mutex> lock(*cLock);
- result = OCCancel(handle, OC_NON_CONFIRMABLE);
+ result = OCCancel(handle, OC_NON_CONFIRMABLE, NULL, 0);
}
else
{
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)
if(cLock)
{
std::lock_guard<std::mutex> lock(*cLock);
- result = OCCancel(handle, OC_NON_CONFIRMABLE);
+ result = OCCancel(handle, OC_NON_CONFIRMABLE, NULL, 0);
}
else
{