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 ####
-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"
###############################################################################
$(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"
OCTBSTACK_SRC + 'occlientcb.c',
OCTBSTACK_SRC + 'ocresource.c',
OCTBSTACK_SRC + 'ocobserve.c',
+ OCTBSTACK_SRC + 'ocserverrequest.c',
OCTBSTACK_SRC + 'occollection.c',
]
* 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.
*/
* 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.
* 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
* @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.
*
* @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_ */
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) {
coap_address_t src, dst;
coap_queue_t *node;
- unsigned char delayRes = 0;
+ unsigned char delayedResNeeded = 0;
#ifdef WITH_CONTIKI
pbuf = uip_appdata;
// 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
}
//set the delayed response flag
- node->delayedResponse = delayRes;
+ node->delayedResNeeded = delayedResNeeded;
//set the secure flag on the received packet
#if defined(WITH_DTLS)
if (ctx->timer_configured)
{
- printf("clearing\n");
sys_untimeout(coap_retransmittimer_execute, (void*)ctx);
ctx->timer_configured = 0;
}
* */
delay = 0;
}
-
- printf("scheduling for %d ticks\n", delay);
sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx);
ctx->timer_configured = 1;
}
#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;
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;
#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 */
* 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
* 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
if (existing_node) {
node->timeout = existing_node->timeout;
- node->delayedResponse = existing_node->delayedResponse;
+ node->delayedResNeeded = existing_node->delayedResNeeded;
}
// Add the node in cachedqueue list
node->t = (now - ctx->sendqueue_basetime) + node->timeout;
}
- node->delayedResponse = 0;
+ node->delayedResNeeded = 0;
node->next = NULL;
coap_insert_node(&ctx->sendqueue, node);
}
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)
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
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
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);
// 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);
#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
//=============================================================================
// 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);
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
{
// 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)
{
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)
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);
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));
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"));
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.",
{
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
{
}
#endif
}
-
HandleStackResponses(response);
}
else if(!cbNode && isObserveNotification)
VERIFY_SUCCESS(result, OC_STACK_OK);
}
exit:
- OCFree(rcvObserveOption);
- OCFree(rcvMaxAgeOption);
OCFree(response);
}
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);
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;
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
*
#include "occoaphelper.h"
#include "ocstackconfig.h"
#include "logger.h"
-#include "ocobserve.h"
#include "coap_time.h"
#include "ocmalloc.h"
ret = COAP_RESPONSE_405;
break;
+ case OC_STACK_NOTIMPL :
+ ret = COAP_RESPONSE_501;
+ break;
+
default:
ret = COAP_RESPONSE_500;
}
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)
// 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)
{
}
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,
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);
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;
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;
}
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);
#include "ocstack.h"
#include "ocresource.h"
+uint8_t GetNumOfResourcesInCollection (OCResource *resource);
+
OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *entityHandlerRequest);
/* 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
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();
#include "ocstack.h"
#include "ocstackinternal.h"
+#include "ocserverrequest.h"
#define OC_RSRVD_OC "oc"
#define OC_RSRVD_PAYLOAD "payload"
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,
--- /dev/null
+//******************************************************************
+//
+// 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
#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
//-----------------------------------------------------------------------------
typedef enum {
STACK_IF_DEFAULT = 0,
STACK_IF_LL,
- STACK_IF_BATCH
+ STACK_IF_BATCH,
+ STACK_IF_INVALID
} OCStackIfTypes;
typedef struct resourcetype_t {
// 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 {
//-----------------------------------------------------------------------------
// 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);
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,
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;
*/
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
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
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;
/**
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),
} 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.
*/
* @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.
*/
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
}
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"));
}
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:
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
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)
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)
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)
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)/$@
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)/$@
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,
}
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");
}
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");
}
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");
}
}
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");
}
}
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");
}
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");
}
}
#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");
}
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");
}
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)
// 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
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,
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");
}
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");
}
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");
}
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");
}
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)
// 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
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
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"\
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);
}
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)
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)
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,
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());
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());
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);
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);
}
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*/
--- /dev/null
+//******************************************************************
+//
+// 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);
+}
--- /dev/null
+//******************************************************************
+//
+// 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
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;
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;
}
}
}
- 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;
* 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'
*/
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__);
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;
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;
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;
}
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)
{
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");
}
}
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)
{
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;
/* 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);
#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.
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.
}
}
- 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
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)
{
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 */
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
/* 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);
#define TAG PCF("ocservercontainer")
-int gQuitFlag = 0;
+volatile sig_atomic_t gQuitFlag = 0;
int gLightUnderObservation = 0;
void createResources();
typedef struct LIGHTRESOURCE{
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
}
static void
-PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest )
+PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
{
const char* typeOfMessage;
(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 );
{
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)
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 );
{
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)
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 );
{
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)
{
}
/* 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;
}
}
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);
// 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;
}
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;
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");
--- /dev/null
+//******************************************************************
+//
+// 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;
+}
--- /dev/null
+//******************************************************************
+//
+// 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
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
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.
}
}
- 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
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)
{
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 */
return 0;
}
nanosleep(&timeout, NULL);
- //sleep(2);
}
OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
/* 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);
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)
{
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;
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;
}
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;
// 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;
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;
#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)
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;
}
}
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);
/// 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); } }
}
}
jsonStr = cJSON_PrintUnformatted (resObj);
+
jsonLen = strlen(jsonStr);
if (jsonLen < *remaining)
{
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)
{
}
-OCStackResult DetermineResourceHandling (OCRequest *request,
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
ResourceHandling *handling,
OCResource **resource)
{
// 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;
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;
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;
}
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)
{
// 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;
}
--- /dev/null
+//******************************************************************
+//
+// 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;
+}
#include "debug.h"
#include "occoap.h"
#include "ocmalloc.h"
+#include "ocserverrequest.h"
//-----------------------------------------------------------------------------
// Typedefs
#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)"));
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;
}
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
//-----------------------------------------------------------------------------
// a different random 32-bit integer number is used
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- return SendPresenceNotification(NULL, OC_LOW_QOS);
+ return SendPresenceNotification(NULL);
}
/**
result = OCChangeResourceProperty(
&(((OCResource *) presenceResource.handle)->resourceProperties),
OC_ACTIVE, 0);
- result = SendPresenceNotification(NULL, OC_LOW_QOS);
+ result = SendPresenceNotification(NULL);
return result;
}
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(pointer->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(pointer->rsrcType);
}
#endif
exit:
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
return;
}
+#ifdef WITH_PRESENCE
/**
* Notify Presence subscribers that a resource has been modified
*
* @param qos - Quality Of Service
*
*/
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos)
+OCStackResult SendPresenceNotification(OCResourceType *resourceType)
{
OCResource *resPtr = NULL;
OCStackResult result;
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.
* 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;
}
//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;
}
}
{
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)
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;
}
//-----------------------------------------------------------------------------
{
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]));
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
}
/**
+ * 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").
*
exit:
return OC_STACK_NO_MEMORY;
}
-
-
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
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
#include <stdint.h>
using namespace std;
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
//-----------------------------------------------------------------------------
// Private variables
//-----------------------------------------------------------------------------
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);
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());
}
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());
}
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
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);
return m_rep;
}
- void deleteDeviceResource()
+ OCStackResult deleteDeviceResource()
{
OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
if(OC_STACK_OK != result)
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
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
}
}
- 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: "
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
}
}
- return OC_EH_OK;
+ return ehResult;
}
};
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,
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 : "
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
}
}
- return OC_EH_OK;
+ return ehResult;
}
};
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,
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 : "
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
}
}
- return OC_EH_OK;
+ return ehResult;
}
};
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
// 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)
{
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")
{
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
int main(int argc, char* argv[1])
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";
// 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)
{
return OC_EH_ERROR;
}
- if(!response)
- {
- cerr << "entityHandler(): Received invalid response object.\n";
- return OC_EH_ERROR;
- }
-
switch(request->getRequestHandlerFlag())
{
default:
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";
// ...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();
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;
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
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";
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'
// 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;
#include <functional>
-#include <pthread.h>
-
#include "OCPlatform.h"
#include "OCApi.h"
// 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
{
/// 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)
{
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)
{
// 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
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")
{
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)
{
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")
{
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")
{
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)
{
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")
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,
}
else
{
- std::cout << "onPost Response error: " << eCode << std::endl;
+ std::cout << "onPost2 Response error: " << eCode << std::endl;
std::exit(-1);
}
}
}
else
{
- std::cout << "onPost Response error: " << eCode << std::endl;
+ std::cout << "onPost2 Response error: " << eCode << std::endl;
std::exit(-1);
}
}
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,
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)
{
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")
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
std::cout << "Request Invalid!"<<std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
};
+
int main()
{
PlatformConfig cfg {
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
// 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
/// 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
{
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(
{
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;
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
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")
{
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")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
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";
}
isListOfObservers = true;
isSecure = true;
break;
+ case 4:
+ isSlowResponse = true;
default:
break;
}
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.
// 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'
// 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(
// 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;
if(OC_STACK_OK == createResource1())
{
std::cout << "Created a new resource\n";
-
OCRepresentation rep1;
rep1.setValue("createduri", std::string("/a/light1"));
}
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)
{
if(requestFlag & RequestHandlerFlag::InitFlag)
{
cout << "\t\trequestFlag : Init\n";
-
// entity handler to perform resource initialization operations
}
if(requestFlag & RequestHandlerFlag::RequestFlag)
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")
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")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
};
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)
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)
{
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")
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 << "Request Invalid!"<<std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
-
};
void putResourceInfo(const HeaderOptions& headerOptions,
virtual OCStackResult stopPresence() = 0;
virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) = 0;
+
+ virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse) = 0;
};
}
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();
virtual OCStackResult stopPresence();
virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler);
+
+ virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
private:
void processFunc();
std::thread m_processThread;
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;
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);
}
}
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;
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;
/**
* 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;}
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;
OCRepresentation m_representation;
ObservationInfo m_observationInfo;
HeaderOptions m_headerOptions;
+ OCRequestHandle m_requestHandle;
+ OCResourceHandle m_resourceHandle;
+
private:
friend void (::formResourceRequest)(OCEntityHandlerFlag, OCEntityHandlerRequest*,
{
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
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
*/
}
/**
+ * 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
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;
{
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
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;
+ }
};
}
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 ";
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);
{
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,
}
auto pRequest = std::make_shared<OC::OCResourceRequest>();
- auto pResponse = std::make_shared<OC::OCResourceResponse>();
formResourceRequest(flag, entityHandlerRequest, pRequest);
if(defaultDeviceEntityHandler)
{
- result = defaultDeviceEntityHandler(pRequest, pResponse);
+ result = defaultDeviceEntityHandler(pRequest);
}
else
{
return OC_EH_ERROR;
}
- processResourceResponse(flag, entityHandlerRequest, pResponse);
-
return result;
}
}
auto pRequest = std::make_shared<OC::OCResourceRequest>();
- auto pResponse = std::make_shared<OC::OCResourceResponse>();
formResourceRequest(flag, entityHandlerRequest, pRequest);
// 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
{
return OC_EH_ERROR;
}
- processResourceResponse(flag, entityHandlerRequest, pResponse);
-
return result;
}
return result;
}
+
OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
(EntityHandler entityHandler)
{
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())
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;
}
{
return OCPlatform_impl::Instance().unsubscribePresence(presenceHandle);
}
+
+ OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+ {
+ return OCPlatform_impl::Instance().sendResponse(pResponse);
+ }
} // namespace OCPlatform
} //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)
{
ref(presenceHandle));
}
+ OCStackResult OCPlatform_impl::sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+ {
+ return checked_guard(m_server, &IServerWrapper::sendResponse,
+ pResponse);
+ }
} //namespace OC
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;
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;
}