void RetrieveOCCoAPToken(const coap_pdu_t * pdu, 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);
+OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode, uint32_t maxAge,
+ unsigned char * fullUri, unsigned char * rcvdUri, OCCoAPToken * rcvdToken,
+ OCClientResponse * clientResponse, unsigned char * bufRes);
// Internal function to create OCClientResponse struct at the client from a received coap pdu
OCStackResult FormOCClientResponse(OCClientResponse * clientResponse,
//This function is called back by libcoap when a response is received
static void HandleCoAPResponses(struct coap_context_t *ctx,
const coap_queue_t * rcvdResponse) {
+ OCStackResult result = OC_STACK_OK;
+ OCCoAPToken rcvdToken = {{0}};
OCResponse * response = NULL;
- OCCoAPToken rcvdToken;
- OCClientResponse clientResponse = {0};
- ClientCB * cbNode = NULL;
+ OCClientResponse * clientResponse = NULL;
unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
- uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
- uint32_t maxAge = 0;
- OCStackResult result = OC_STACK_ERROR;
coap_pdu_t * sendPdu = NULL;
coap_pdu_t * recvPdu = NULL;
- unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
- uint8_t isObserveNotification = 0;
- #ifdef WITH_PRESENCE
- char * resourceTypeName = NULL;
- uint8_t remoteIpAddr[4];
- uint16_t remotePortNu;
+ uint8_t remoteIpAddr[4] = {0};
+ uint16_t remotePortNu = 0;
+ uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
+ uint32_t maxAge = 0;
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
+ unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
uint16_t rcvdSize2 = 0;
VERIFY_NON_NULL(rcvdResponse);
recvPdu = rcvdResponse->pdu;
+ clientResponse = (OCClientResponse *) OCCalloc(1, sizeof(OCClientResponse));
+
result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
- &clientResponse.numRcvdVendorSpecificHeaderOptions,
- clientResponse.rcvdVendorSpecificHeaderOptions,
+ &(clientResponse->numRcvdVendorSpecificHeaderOptions),
+ clientResponse->rcvdVendorSpecificHeaderOptions,
&rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);
-
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);
- OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
-
- if(sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
- {
- isObserveNotification = 1;
- OC_LOG(INFO, TAG, PCF("Received an observe notification"));
- }
-
- #ifdef WITH_PRESENCE
- if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
- isPresenceNotification = 1;
- OC_LOG(INFO, TAG, PCF("Received a presence notification"));
- tok = strtok((char *)bufRes, "[:]}");
- bufRes[strlen((char *)bufRes)] = ':';
- tok = strtok(NULL, "[:]}");
- bufRes[strlen((char *)bufRes)] = ':';
- VERIFY_NON_NULL(tok);
- sequenceNumber = (uint32_t )atol(tok);
- OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
- 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, "[:]}");
- if(tok) {
- bufRes[strlen((char *)bufRes)] = ':';
- resourceTypeName = (char *)OCMalloc(strlen(tok));
- if(!resourceTypeName)
- {
- goto exit;
- }
- strcpy(resourceTypeName, tok);
- OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
- resourceTypeName);
- }
- bufRes[strlen((char *)bufRes)] = ']';
- }
- #endif
+ // get the address of the remote
+ OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
+ remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+ OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
+ snprintf((char *)fullUri, MAX_URI_LENGTH, "coap://%d.%d.%d.%d:%d%s",
+ remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
+ remotePortNu,rcvdUri);
// fill OCCoAPToken structure
RetrieveOCCoAPToken(recvPdu, &rcvdToken);
OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
// fill OCClientResponse structure
- result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
- (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes);
+ result = FormOCClientResponse(clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code),
+ (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, NULL);
VERIFY_SUCCESS(result, OC_STACK_OK);
- cbNode = GetClientCB(&rcvdToken, NULL, NULL);
-
- #ifdef WITH_PRESENCE
- // Check if the application subscribed for presence
- if(!cbNode)
- {
- // get the address of the remote
- OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr,
- remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
- OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu);
- sprintf((char *)fullUri, "coap://%d.%d.%d.%d:%d%s",
- remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
- remotePortNu,rcvdUri);
- cbNode = GetClientCB(NULL, NULL, fullUri);
- }
-
- // Check if application subscribed for multicast presence
- if(!cbNode)
- {
- sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
- cbNode = GetClientCB(NULL, NULL, fullUri);
- isMulticastPresence = 1;
- isPresenceNotification = 0;
- }
- #endif
-
- // fill OCResponse structure
- result = FormOCResponse(&response, cbNode, maxAge, &clientResponse);
+ result = FormOCResponse(&response, NULL, maxAge, fullUri, rcvdUri,
+ &rcvdToken, clientResponse, bufRes);
VERIFY_SUCCESS(result, OC_STACK_OK);
- 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(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));
- }
- //TODO: check the standard for methods to detect wrap around condition
- if(cbNode->method == OC_REST_OBSERVE &&
- (clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
- (clientResponse.sequenceNumber > cbNode->sequenceNumber &&
- clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER))))
- {
- OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
- Ignoring Incoming:%d Against Current:%d.",
- clientResponse.sequenceNumber, cbNode->sequenceNumber);
- goto exit;
- }
- if(clientResponse.sequenceNumber > cbNode->sequenceNumber){
- cbNode->sequenceNumber = clientResponse.sequenceNumber;
- }
- }
- else
- {
- #ifdef WITH_PRESENCE
- if(isPresenceNotification)
- {
- OC_LOG(INFO, TAG, PCF("Received a presence notification"));
- if(!cbNode->presence)
- {
- cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
- VERIFY_NON_NULL(cbNode->presence);
- cbNode->presence->timeOut = NULL;
- cbNode->presence->timeOut = (uint32_t *)
- OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
- if(!(cbNode->presence->timeOut)){
- OCFree(cbNode->presence);
- goto exit;
- }
- }
- if(maxAge == 0)
- {
- 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
- {
- OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
- cbNode->presence->TTL = maxAge;
- for(int index = 0; index < PresenceTimeOutSize; index++)
- {
- lowerBound = GetTime(((float)(PresenceTimeOut[index])
- /(float)100)*(float)cbNode->presence->TTL);
- higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
- /(float)100)*(float)cbNode->presence->TTL);
- cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
- OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
- OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
- OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d", cbNode->presence->timeOut[index]);
- }
- cbNode->presence->TTLlevel = 0;
- OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
- if(cbNode->sequenceNumber == clientResponse.sequenceNumber)
- {
- OC_LOG(INFO, TAG, PCF("===============No presence change"));
- goto exit;
- }
- OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
- cbNode->sequenceNumber = clientResponse.sequenceNumber;;
- }
-
- // Ensure that a filter is actually applied.
- if(resourceTypeName && response->cbNode->filterResourceType)
- {
- if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
- {
- goto exit;
- }
- }
- }
- else if(isMulticastPresence)
- {
- // Check if the same nonce for a given host
- OCMulticastNode* mcNode = NULL;
- unsigned char senderUri[MAX_URI_LENGTH] = { 0 };
- sprintf((char *)senderUri, "%d.%d.%d.%d:%d",
- remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3],
- remotePortNu);
- mcNode = GetMCPresenceNode(senderUri);
-
- if(maxAge == 0)
- {
- 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 if(mcNode != NULL)
- {
- if(mcNode->nonce == clientResponse.sequenceNumber)
- {
- OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
- goto exit;
- }
- mcNode->nonce = clientResponse.sequenceNumber;
- }
- else
- {
- uint32_t uriLen = strlen((char*)senderUri);
- unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
- if(uri)
- {
- memcpy(uri, senderUri, (uriLen + 1));
- }
- else
- {
- OC_LOG(INFO, TAG,
- PCF("===============No Memory for URI to store in the presence node"));
- goto exit;
- }
- result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
- clientResponse.sequenceNumber);
- if(result == OC_STACK_NO_MEMORY)
- {
- OC_LOG(INFO, TAG,
- PCF("===============No Memory for Multicast Presence Node"));
- goto exit;
- }
- }
-
- // Ensure that a filter is actually applied.
- if(resourceTypeName && response->cbNode->filterResourceType)
- {
- if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
- {
- goto exit;
- }
- }
- }
- #endif
- }
- HandleStackResponses(response);
- }
- else if(!cbNode && isObserveNotification)
+ result = HandleStackResponses(response);
+
+ if(result == OC_STACK_ERROR)
{
- OC_LOG(INFO, TAG, PCF("Received an observe notification, but I do not have callback \
- ------------ sending RESET"));
+ OC_LOG(INFO, TAG, PCF("Received a notification or response that is malformed or incorrect \
+ ------------ sending RESET"));
sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
recvPdu->hdr->id, NULL, NULL, NULL);
VERIFY_NON_NULL(sendPdu);
(coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
VERIFY_SUCCESS(result, OC_STACK_OK);
}
- #ifdef WITH_PRESENCE
- else if(!cbNode && isPresenceNotification)
+ else if(result == OC_STACK_NO_MEMORY)
{
- OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
- ------------ ignoring"));
+ OC_LOG(ERROR, TAG, PCF("Received a notification or response. While processing, local " \
+ "platform or memory pool ran out memory."));
}
- #endif
- else
+
+ if(recvPdu->hdr->type == COAP_MESSAGE_CON)
{
- OC_LOG(INFO, TAG, PCF("Received a response, but I do not have callback. \
- ------------ sending RESET"));
- sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0,
+ 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));
+ result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
+ sendPdu,
+ (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
VERIFY_SUCCESS(result, OC_STACK_OK);
}
+
exit:
- OCFree(resourceTypeName);
OCFree(response);
+ OCFree(clientResponse);
}
//=============================================================================
// Decide method type
switch (method) {
case OC_REST_GET:
- #ifdef WITH_PRESENCE
- case OC_REST_PRESENCE:
- #endif
coapMethod = COAP_REQUEST_GET;
break;
case OC_REST_PUT:
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
*
break;
}
}
+
+OCQualityOfService CoAPToOCQoS(uint8_t qos)
+{
+ switch (qos)
+ {
+ case COAP_MESSAGE_CON:
+ return OC_HIGH_QOS;
+ case COAP_MESSAGE_NON:
+ return OC_LOW_QOS;
+ default:
+ return OC_NA_QOS;
+ }
+}
// Convert CoAP code to OCStack code
OCStackResult CoAPToOCResponseCode(uint8_t coapCode)
{
}
}
-OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
- uint8_t TTL, OCClientResponse * clientResponse)
+OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode, uint32_t maxAge,
+ unsigned char * fullUri, unsigned char * rcvdUri, OCCoAPToken * rcvdToken,
+ OCClientResponse * clientResponse, unsigned char * bufRes)
{
OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
if (!response)
return OC_STACK_NO_MEMORY;
}
response->cbNode = cbNode;
- response->TTL = TTL;
+ response->maxAge = maxAge;
+ response->fullUri = fullUri;
+ response->rcvdUri = rcvdUri;
+ response->rcvdToken = rcvdToken;
response->clientResponse = clientResponse;
+ response->bufRes = bufRes;
*responseLoc = response;
return OC_STACK_OK;
{
goto observation;
}
- result = FormOCResponse(&response, cbNode, 0, &clientResponse);
+ result = FormOCResponse(&response, cbNode, NULL, NULL, NULL, &token, &clientResponse, NULL);
if(result != OC_STACK_OK)
{
goto observation;
* @retval address of the node if found, otherwise NULL
*/
//------------------------------------------------------------------------
-ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
+ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, const unsigned char * requestUri);
/**
* OC_STACK_ERROR with invalid parameters
* OC_STACK_NO_MEMORY when out of memory
*/
+#ifdef WITH_PRESENCE
OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+#endif // WITH_PRESENCE
//-- DeleteClientCBList --------------------------------------------------
/** @ingroup ocstack
* The resulting node from making this call. Null if doesn't exist.
*/
//------------------------------------------------------------------------
-OCMulticastNode* GetMCPresenceNode(unsigned char * uri);
+OCMulticastNode* GetMCPresenceNode(const unsigned char * uri);
/** @ingroup ocstack
*
// handle is retrieved by comparing the token-handle pair in the PDU.
ClientCB * cbNode;
// This is how long this response is valid for (in seconds).
- uint32_t TTL;
+ uint32_t maxAge;
+ // This is the Uri of the resource. (ex. "coap://192.168.1.1/a/led")
+ unsigned char * fullUri;
+ // This is the relative Uri of the resource. (ex. "/a/led")
+ unsigned char * rcvdUri;
+ // This is the received payload.
+ unsigned char * bufRes;
+ // This is the token received OTA.
+ OCCoAPToken * rcvdToken;
// this structure will be passed to client
OCClientResponse * clientResponse;
} OCResponse;
//-----------------------------------------------------------------------------
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);
+OCStackResult HandleStackResponses(OCResponse * response);
#ifdef WITH_PRESENCE
OCStackResult SendPresenceNotification(OCResourceType *resourceType);
-#endif
+#endif // WITH_PRESENCE
+int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
OCStackResult BindResourceInterfaceToResource(OCResource* resource,
const char *resourceInterfaceName);
}
}
-ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri) {
+ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, const unsigned char * requestUri) {
ClientCB* out = NULL;
if(token) {
LL_FOREACH(cbList, out) {
return NULL;
}
+#ifdef WITH_PRESENCE
OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
{
OCResourceType * newResourceType = NULL;
}
return OC_STACK_ERROR;
}
+#endif // WITH_PRESENCE
void DeleteClientCBList() {
ClientCB* out;
return OC_STACK_NO_MEMORY;
}
-OCMulticastNode* GetMCPresenceNode(unsigned char * uri) {
+OCMulticastNode* GetMCPresenceNode(const unsigned char * uri) {
OCMulticastNode* out = NULL;
if(uri) {
// Macros
//-----------------------------------------------------------------------------
#define TAG PCF("OCStack")
+#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); } }
+#define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
+ goto exit;} }
//TODO: we should allow the server to define this
#define MAX_OBSERVE_AGE (0x2FFFFUL)
}
//This function will be called back by occoap layer when a response is received
-void HandleStackResponses(OCResponse * response)
+OCStackResult HandleStackResponses(OCResponse * response)
{
- OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
+ OCStackResult result = OC_STACK_OK;
+ OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
+ uint8_t isObserveNotification = 0;
+ ClientCB * cbNode = NULL;
+ #ifdef WITH_PRESENCE
+ uint8_t isPresenceNotification = 0;
+ uint8_t isMulticastPresence = 0;
+ char * resourceTypeName = NULL;
+ uint32_t lowerBound = 0;
+ uint32_t higherBound = 0;
+ char * tok = NULL;
+ unsigned char * bufRes = response->bufRes;
+ #endif // WITH_PRESENCE
+
+ cbNode = response->cbNode;
+ if(!cbNode)
+ {
+ cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
+ }
+
+ if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
+ {
+ isObserveNotification = 1;
+ OC_LOG(INFO, TAG, PCF("Received an observe notification"));
+ }
+
+ OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
+ response->clientResponse->sequenceNumber);
+ OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
+ OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
+
+#ifdef WITH_PRESENCE
+ if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
+ isPresenceNotification = 1;
+ if(!bufRes)
+ {
+ result = OC_STACK_INVALID_PARAM;
+ goto exit;
+ }
+ tok = strtok((char *)bufRes, "[:]}");
+ bufRes[strlen((char *)bufRes)] = ':';
+ tok = strtok(NULL, "[:]}");
+ bufRes[strlen((char *)bufRes)] = ':';
+ response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
+ OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
+ tok = strtok(NULL, "[:]}");
+ response->maxAge = (uint32_t )atoi(tok);
+ OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
+ tok = strtok(NULL, "[:]}");
+ if(tok)
+ {
+ resourceTypeName = (char *)OCMalloc(strlen(tok));
+ if(!resourceTypeName)
+ {
+ goto exit;
+ }
+ bufRes[strlen((char *)bufRes)] = ':';
+ strcpy(resourceTypeName, tok);
+ OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
+ resourceTypeName);
+ }
+ bufRes[strlen((char *)bufRes)] = ']';
+ }
+
+ // Check if the application subcribed for presence
+ if(!cbNode)
+ {
+ cbNode = GetClientCB(NULL, NULL, response->fullUri);
+ }
+
+ // Check if application subscribed for multicast presence
+ if(!cbNode)
+ {
+ snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
+ OC_MULTICAST_IP, response->rcvdUri);
+ cbNode = GetClientCB(NULL, NULL, response->fullUri);
+ if(cbNode)
+ {
+ isMulticastPresence = 1;
+ isPresenceNotification = 0;
+ }
+ }
+
+ if(cbNode && isPresenceNotification)
+ {
+ OC_LOG(INFO, TAG, PCF("Received a presence notification"));
+ if(!cbNode->presence)
+ {
+ cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
+ VERIFY_NON_NULL_V(cbNode->presence);
+ cbNode->presence->timeOut = NULL;
+ cbNode->presence->timeOut = (uint32_t *)
+ OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
+ if(!(cbNode->presence->timeOut)){
+ OCFree(cbNode->presence);
+ result = OC_STACK_NO_MEMORY;
+ }
+ }
+ if(response->maxAge == 0)
+ {
+ 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
+ {
+ OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
+ cbNode->presence->TTL = response->maxAge;
+ for(int index = 0; index < PresenceTimeOutSize; index++)
+ {
+ lowerBound = GetTime(((float)(PresenceTimeOut[index])
+ /(float)100)*(float)cbNode->presence->TTL);
+ higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
+ /(float)100)*(float)cbNode->presence->TTL);
+ cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
+ OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
+ OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
+ OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
+ cbNode->presence->timeOut[index]);
+ }
+ cbNode->presence->TTLlevel = 0;
+ OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
+ if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
+ {
+ OC_LOG(INFO, TAG, PCF("===============No presence change"));
+ goto exit;
+ }
+ OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
+ cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
+ }
+
+ // Ensure that a filter is actually applied.
+ if(resourceTypeName && cbNode->filterResourceType)
+ {
+ if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+ {
+ goto exit;
+ }
+ }
+ }
+ else if(cbNode && isMulticastPresence)
+ {
+ // Check if the same nonce for a given host
+ OCMulticastNode* mcNode = NULL;
+ mcNode = GetMCPresenceNode(response->fullUri);
+
+ if(response->maxAge == 0)
+ {
+ 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 if(mcNode != NULL)
+ {
+ if(mcNode->nonce == response->clientResponse->sequenceNumber)
+ {
+ OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
+ result = OC_STACK_NO_MEMORY;
+ goto exit;
+ }
+ mcNode->nonce = response->clientResponse->sequenceNumber;
+ }
+ else
+ {
+ uint32_t uriLen = strlen((char*)response->fullUri);
+ unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
+ if(uri)
+ {
+ memcpy(uri, response->fullUri, (uriLen + 1));
+ }
+ else
+ {
+ OC_LOG(INFO, TAG,
+ PCF("===============No Memory for URI to store in the presence node"));
+ result = OC_STACK_NO_MEMORY;
+ goto exit;
+ }
+ result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
+ response->clientResponse->sequenceNumber);
+ if(result == OC_STACK_NO_MEMORY)
+ {
+ OC_LOG(INFO, TAG,
+ PCF("===============No Memory for Multicast Presence Node"));
+ result = OC_STACK_NO_MEMORY;
+ goto exit;
+ }
+ }
+
+ // Ensure that a filter is actually applied.
+ if(resourceTypeName && cbNode->filterResourceType)
+ {
+ if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+ {
+ goto exit;
+ }
+ }
+ }
+
+ else if(!cbNode && isPresenceNotification)
+ {
+ OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
+ ------------ ignoring"));
+ }
+ #endif // WITH_PRESENCE
- if (response->cbNode)
+ if(cbNode)
{
- OC_LOG(INFO, TAG, PCF("Calling into application address space"));
- result = response->cbNode->callBack(response->cbNode->context,
- response->cbNode->handle, response->clientResponse);
- if (result == OC_STACK_DELETE_TRANSACTION ||
+ if(isObserveNotification)
+ {
+ OC_LOG(INFO, TAG, PCF("Received an observe notification"));
+ //TODO: check the standard for methods to detect wrap around condition
+ if(cbNode->method == OC_REST_OBSERVE &&
+ (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
+ (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
+ response->clientResponse->sequenceNumber ==
+ MAX_SEQUENCE_NUMBER)))
+ {
+ OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
+ Ignoring Incoming:%d Against Current:%d.",
+ response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
+ goto exit;
+ }
+ if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
+ cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
+ }
+ }
+
+ response->clientResponse->resJSONPayload = bufRes;
+
+ cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
+
+ if (cbResult == OC_STACK_DELETE_TRANSACTION ||
response->clientResponse->result == OC_STACK_COMM_ERROR ||
- response->clientResponse->result == OC_STACK_RESOURCE_DELETED)
+ (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
+ !isPresenceNotification && !isMulticastPresence))
{
- FindAndDeleteClientCB(response->cbNode);
+ FindAndDeleteClientCB(cbNode);
}
}
+ else
+ {
+ result = OC_STACK_ERROR;
+ }
+
+ exit:
+ #ifdef WITH_PRESENCE
+ OCFree(resourceTypeName);
+ #endif
+ return result;
}
int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
}
else
{
- OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+ OC_LOG(DEBUG, TAG, PCF("Got Resource Type is NULL."));
}
if(result != OC_STACK_OK)
{
goto exit;
}
+#ifdef WITH_PRESENCE
+ if(method == OC_REST_PRESENCE)
+ {
+ // Replacing method type with GET because "presence" is a stack layer only implementation.
+ method = OC_REST_GET;
+ }
+#endif
+
// Make call to OCCoAP layer
result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
{
goto exit;
}
- result = FormOCResponse(&response, cbNode, 0, &clientResponse);
+ result = FormOCResponse(&response, cbNode, NULL, NULL, NULL,
+ &cbNode->token, &clientResponse, NULL);
if(result != OC_STACK_OK)
{
goto exit;
return;
}
-#ifdef WITH_PRESENCE
/**
* Notify Presence subscribers that a resource has been modified
*
* @param qos - Quality Of Service
*
*/
+#ifdef WITH_PRESENCE
OCStackResult SendPresenceNotification(OCResourceType *resourceType)
{
OCResource *resPtr = NULL;
result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
return result;
}
-#endif
-
+#endif // WITH_PRESENCE
/**
* Notify observers that an observed value has changed.
*
static const std::string OBSV_NO_FOUND = "Stack observer not found";
static const std::string OBSV_NOT_ADDED = "Stack observer not added";
static const std::string OBSV_NOT_REMOVED = "Stack observer not removed";
- static const std::string STACK_RESOURCE_DELETED = "The specified resource has been deleted";
+ static const std::string STACK_RESOURCE_DELETED =
+ "The specified resource has been deleted";
static const std::string PRESENCE_STOPPED = "Stack presence stopped";
- static const std::string PRESENCE_NOT_HANDLED = "Stack presence should not be handled";
+ static const std::string PRESENCE_NOT_HANDLED =
+ "Stack presence should not be handled";
+ static const std::string REQUEST_NOT_HANDLED =
+ "Incoming Request should not be handled";
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 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";
case OC_STACK_SLOW_RESOURCE:
case OC_STACK_NO_OBSERVERS:
case OC_STACK_OBSERVER_NOT_FOUND:
+ case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
#ifdef WITH_PRESENCE
case OC_STACK_PRESENCE_STOPPED:
#endif
-
break;
}