X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fstack%2Fsrc%2Focstack.c;h=66ac3bfaafd7ba54988afc7bbea7380cd56ca4aa;hb=refs%2Ftags%2Faccepted%2Ftizen%2F3.0%2Fwearable%2F20161216.083338;hp=d3e892240e9264bf7e364264050b0807877a646c;hpb=6a34b94f142cfa1fc352ffab0e2541d9dc9e9a79;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index d3e8922..66ac3bf 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -36,6 +36,7 @@ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif +#include "iotivity_config.h" #include #include #include @@ -57,7 +58,8 @@ #include "cainterface.h" #include "ocpayload.h" #include "ocpayloadcbor.h" -#include "platform_features.h" +#include "cautilinterface.h" +#include "oicgroup.h" #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) #include "routingutility.h" @@ -80,9 +82,7 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#include "coap_time.h" -#include "utlist.h" -#include "pdu.h" +#include #ifdef HAVE_ARPA_INET_H #include @@ -137,9 +137,13 @@ static bool gRASetInfo = false; #endif OCDeviceEntityHandler defaultDeviceHandler; void* defaultDeviceHandlerCallbackParameter = NULL; -static const char COAP_TCP[] = "coap+tcp:"; +static const char COAP_TCP_SCHEME[] = "coap+tcp:"; +static const char COAPS_TCP_SCHEME[] = "coaps+tcp:"; static const char CORESPEC[] = "core"; +CAAdapterStateChangedCB g_adapterHandler = NULL; +CAConnectionStateChangedCB g_connectionHandler = NULL; + //----------------------------------------------------------------------------- // Macros //----------------------------------------------------------------------------- @@ -293,23 +297,6 @@ static void incrementSequenceNumber(OCResource * resPtr); static CAResult_t OCSelectNetwork(); /** - * Get the CoAP ticks after the specified number of milli-seconds. - * - * @param afterMilliSeconds Milli-seconds. - * @return - * CoAP ticks - */ -static uint32_t GetTicks(uint32_t afterMilliSeconds); - -/** - * Convert CAResult_t to OCStackResult. - * - * @param caResult CAResult_t code. - * @return ::OC_STACK_OK on success, some other value upon failure. - */ -static OCStackResult CAResultToOCStackResult(CAResult_t caResult); - -/** * Convert CAResponseResult_t to OCStackResult. * * @param caCode CAResponseResult_t code. @@ -318,15 +305,6 @@ static OCStackResult CAResultToOCStackResult(CAResult_t caResult); static OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode); /** - * Convert OCStackResult to CAResponseResult_t. - * - * @param caCode OCStackResult code. - * @param method OCMethod method the return code replies to. - * @return ::CA_CONTENT on OK, some other value upon failure. - */ -static CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method); - -/** * Convert OCTransportFlags_t to CATransportModifiers_t. * * @param ocConType OCTransportFlags_t input. @@ -414,20 +392,64 @@ static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds); */ static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo); +/** + * default adapter state change callback method + * + * @param adapter CA network adapter type. + * @param enabled current adapter state. + */ +static void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled); + +/** + * default connection state change callback method + * + * @param info CAEndpoint which has address, port and etc. + * @param isConnected current connection state. + */ +static void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected); + +/** + * Register network monitoring callback. + * Network status changes are delivered these callback. + * @param adapterHandler Adapter state monitoring callback. + * @param connectionHandler Connection state monitoring callback. + */ +static void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler, + CAConnectionStateChangedCB connectionHandler); + //----------------------------------------------------------------------------- // Internal functions //----------------------------------------------------------------------------- -uint32_t GetTicks(uint32_t afterMilliSeconds) +bool checkProxyUri(OCHeaderOption *options, uint8_t numOptions) +{ + if (!options || 0 == numOptions) + { + OIC_LOG (INFO, TAG, "No options present"); + return false; + } + + for (uint8_t i = 0; i < numOptions; i++) + { + if (options[i].protocolID == OC_COAP_ID && options[i].optionID == OC_RSRVD_PROXY_OPTION_ID) + { + OIC_LOG(DEBUG, TAG, "Proxy URI is present"); + return true; + } + } + return false; +} + +uint32_t GetTicks(uint32_t milliSeconds) { coap_tick_t now; coap_ticks(&now); // Guard against overflow of uint32_t - if (afterMilliSeconds <= ((UINT32_MAX - (uint32_t)now) * MILLISECONDS_PER_SECOND) / + if (milliSeconds <= ((UINT32_MAX - (uint32_t)now) * MILLISECONDS_PER_SECOND) / COAP_TICKS_PER_SECOND) { - return now + (afterMilliSeconds * COAP_TICKS_PER_SECOND)/MILLISECONDS_PER_SECOND; + return now + (milliSeconds * COAP_TICKS_PER_SECOND)/MILLISECONDS_PER_SECOND; } else { @@ -446,7 +468,11 @@ void CopyEndpointToDevAddr(const CAEndpoint_t *in, OCDevAddr *out) out->port = in->port; out->ifindex = in->ifindex; #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) - memcpy(out->routeData, in->routeData, sizeof(out->routeData)); + /* This assert is to prevent accidental mismatch between address size macros defined in + * RI and CA and cause crash here. */ + OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE, + "Address size mismatch between RI and CA"); + memcpy(out->routeData, in->routeData, sizeof(in->routeData)); #endif } @@ -459,7 +485,11 @@ void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out) out->flags = OCToCATransportFlags(in->flags); OICStrcpy(out->addr, sizeof(out->addr), in->addr); #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) - memcpy(out->routeData, in->routeData, sizeof(out->routeData)); + /* This assert is to prevent accidental mismatch between address size macros defined in + * RI and CA and cause crash here. */ + OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE, + "Address size mismatch between RI and CA"); + memcpy(out->routeData, in->routeData, sizeof(in->routeData)); #endif out->port = in->port; out->ifindex = in->ifindex; @@ -514,11 +544,11 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat { case OC_OBSERVER_NOT_INTERESTED: OIC_LOG(DEBUG, TAG, "observer not interested in our notifications"); - observer = GetObserverUsingToken (token, tokenLength); - if(observer) + observer = GetObserverUsingToken(token, tokenLength); + if (observer) { result = FormOCEntityHandlerRequest(&ehRequest, - (OCRequestHandle)NULL, + 0, OC_REST_NOMETHOD, &observer->devAddr, (OCResourceHandle)NULL, @@ -527,16 +557,20 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat OC_OBSERVE_DEREGISTER, observer->observeId, 0); - if(result != OC_STACK_OK) + if (result != OC_STACK_OK) { return result; } - observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest, - observer->resource->entityHandlerCallbackParam); + + if (observer->resource && observer->resource->entityHandler) + { + observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest, + observer->resource->entityHandlerCallbackParam); + } } - result = DeleteObserverUsingToken (token, tokenLength); - if(result == OC_STACK_OK) + result = DeleteObserverUsingToken(token, tokenLength); + if (result == OC_STACK_OK) { OIC_LOG(DEBUG, TAG, "Removed observer successfully"); } @@ -549,8 +583,8 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat case OC_OBSERVER_STILL_INTERESTED: OIC_LOG(DEBUG, TAG, "observer still interested, reset the failedCount"); - observer = GetObserverUsingToken (token, tokenLength); - if(observer) + observer = GetObserverUsingToken(token, tokenLength); + if (observer) { observer->forceHighQos = 0; observer->failedCommCount = 0; @@ -565,12 +599,12 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat case OC_OBSERVER_FAILED_COMM: OIC_LOG(DEBUG, TAG, "observer is unreachable"); observer = GetObserverUsingToken (token, tokenLength); - if(observer) + if (observer) { - if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM) + if (observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM) { result = FormOCEntityHandlerRequest(&ehRequest, - (OCRequestHandle)NULL, + 0, OC_REST_NOMETHOD, &observer->devAddr, (OCResourceHandle)NULL, @@ -579,15 +613,19 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat OC_OBSERVE_DEREGISTER, observer->observeId, 0); - if(result != OC_STACK_OK) + if (result != OC_STACK_OK) { return OC_STACK_ERROR; } - observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest, - observer->resource->entityHandlerCallbackParam); - result = DeleteObserverUsingToken (token, tokenLength); - if(result == OC_STACK_OK) + if (observer->resource && observer->resource->entityHandler) + { + observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest, + observer->resource->entityHandlerCallbackParam); + } + + result = DeleteObserverUsingToken(token, tokenLength); + if (result == OC_STACK_OK) { OIC_LOG(DEBUG, TAG, "Removed observer successfully"); } @@ -600,10 +638,11 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat else { observer->failedCommCount++; + observer->forceHighQos = 1; + OIC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d", + observer->failedCommCount); result = OC_STACK_CONTINUE; } - observer->forceHighQos = 1; - OIC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount); } break; default: @@ -614,28 +653,6 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat return result; } -static OCStackResult CAResultToOCStackResult(CAResult_t caResult) -{ - OCStackResult ret = OC_STACK_ERROR; - - switch(caResult) - { - case CA_ADAPTER_NOT_ENABLED: - case CA_SERVER_NOT_STARTED: - ret = OC_STACK_ADAPTER_NOT_ENABLED; - break; - case CA_MEMORY_ALLOC_FAILED: - ret = OC_STACK_NO_MEMORY; - break; - case CA_STATUS_INVALID_PARAM: - ret = OC_STACK_INVALID_PARAM; - break; - default: - break; - } - return ret; -} - OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode) { OCStackResult ret = OC_STACK_ERROR; @@ -672,6 +689,12 @@ OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode) case CA_REQUEST_ENTITY_TOO_LARGE: ret = OC_STACK_TOO_LARGE_REQ; break; + case CA_FORBIDDEN_REQ: + ret = OC_STACK_FORBIDDEN_REQ; + break; + case CA_INTERNAL_SERVER_ERROR: + ret = OC_STACK_INTERNAL_SERVER_ERROR; + break; default: break; } @@ -730,6 +753,12 @@ CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method) case OC_STACK_UNAUTHORIZED_REQ: ret = CA_UNAUTHORIZED_REQ; break; + case OC_STACK_FORBIDDEN_REQ: + ret = CA_FORBIDDEN_REQ; + break; + case OC_STACK_INTERNAL_SERVER_ERROR: + ret = CA_INTERNAL_SERVER_ERROR; + break; default: break; } @@ -847,37 +876,14 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) } } -/** - * Encode an address string to match RFC6874. - * - * @param outputAddress a char array to be written with the encoded string. - * - * @param outputSize size of outputAddress buffer. - * - * @param inputAddress a char array of size <= CA_MAX_URI_LENGTH - * containing a valid IPv6 address string. - * - * @return OC_STACK_OK if encoding succeeded. - * Else an error occured. - */ - OCStackResult encodeAddressForRFC6874(char *outputAddress, - size_t outputSize, - const char *inputAddress) +OCStackResult OCEncodeAddressForRFC6874(char *outputAddress, + size_t outputSize, + const char *inputAddress) { VERIFY_NON_NULL(inputAddress, FATAL, OC_STACK_INVALID_PARAM); VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM); - /** @todo Use a max IPv6 string length instead of CA_MAX_URI_LENGTH. */ -#define ENCODE_MAX_INPUT_LENGTH CA_MAX_URI_LENGTH - - size_t inputLength = strnlen(inputAddress, ENCODE_MAX_INPUT_LENGTH); - - if (inputLength >= ENCODE_MAX_INPUT_LENGTH) - { - OIC_LOG(ERROR, TAG, - "encodeAddressForRFC6874 failed: Invalid input string: too long/unterminated!"); - return OC_STACK_INVALID_PARAM; - } + size_t inputLength = strnlen(inputAddress, outputSize); // inputSize includes the null terminator size_t inputSize = inputLength + 1; @@ -885,8 +891,8 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) if (inputSize > outputSize) { OIC_LOG_V(ERROR, TAG, - "encodeAddressForRFC6874 failed: " - "outputSize (%d) < inputSize (%d)", + "OCEncodeAddressForRFC6874 failed: " + "outputSize (%zu) < inputSize (%zu)", outputSize, inputSize); return OC_STACK_ERROR; @@ -913,25 +919,25 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) // If no string follows the first '%', then the input was invalid. if (scopeIdPart[0] == '\0') { - OIC_LOG(ERROR, TAG, "encodeAddressForRFC6874 failed: Invalid input string: no scope ID!"); + OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: Invalid input string: no scope ID!"); return OC_STACK_ERROR; } // Check to see if the string is already encoded if ((scopeIdPart[0] == '2') && (scopeIdPart[1] == '5')) { - OIC_LOG(ERROR, TAG, "encodeAddressForRFC6874 failed: Input string is already encoded"); + OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: Input string is already encoded"); return OC_STACK_ERROR; } // Fail if we don't have room for encoded string's two additional chars if (outputSize < (inputSize + 2)) { - OIC_LOG(ERROR, TAG, "encodeAddressForRFC6874 failed: Input string is already encoded"); + OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: encoded output will not fit!"); return OC_STACK_ERROR; } - // Restore the null terminator with an escaped '%' character, per RFC6874 + // Restore the null terminator with an escaped '%' character, per RFC 6874 OICStrcpy(outputAddress, scopeIdPart - addressPart, addressPart); strcat(outputAddress, "%25"); strcat(outputAddress, scopeIdPart); @@ -939,20 +945,59 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) return OC_STACK_OK; } +OCStackResult OCDecodeAddressForRFC6874(char *outputAddress, + size_t outputSize, + const char *inputAddress, + const char *end) +{ + VERIFY_NON_NULL(inputAddress, FATAL, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM); + + if (NULL == end) + { + end = inputAddress + strlen(inputAddress); + } + size_t inputLength = end - inputAddress; + + const char *percent = strchr(inputAddress, '%'); + if (!percent || (percent > end)) + { + OICStrcpyPartial(outputAddress, outputSize, inputAddress, inputLength); + } + else + { + if (percent[1] != '2' || percent[2] != '5') + { + return OC_STACK_INVALID_URI; + } + + int addrlen = percent - inputAddress + 1; + OICStrcpyPartial(outputAddress, outputSize, inputAddress, addrlen); + OICStrcpyPartial(outputAddress + addrlen, outputSize - addrlen, + percent + 3, end - percent - 3); + } + + return OC_STACK_OK; +} + /** * The cononical presence allows constructed URIs to be string compared. * * requestUri must be a char array of size CA_MAX_URI_LENGTH */ -static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resourceUri, - char *presenceUri) +static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, + char *presenceUri, bool isMulticast) { VERIFY_NON_NULL(endpoint , FATAL, OC_STACK_INVALID_PARAM); - VERIFY_NON_NULL(resourceUri, FATAL, OC_STACK_INVALID_PARAM); VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM); - CAEndpoint_t *ep = (CAEndpoint_t *)endpoint; + if (isMulticast) + { + OIC_LOG(DEBUG, TAG, "Make Multicast Presence URI"); + return snprintf(presenceUri, CA_MAX_URI_LENGTH, "%s", OC_RSRVD_PRESENCE_URI); + } + CAEndpoint_t *ep = (CAEndpoint_t *)endpoint; if (ep->adapter == CA_ADAPTER_IP) { if ((ep->flags & CA_IPV6) && !(ep->flags & CA_IPV4)) @@ -965,9 +1010,9 @@ static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resource { char addressEncoded[CA_MAX_URI_LENGTH] = {0}; - OCStackResult result = encodeAddressForRFC6874(addressEncoded, - sizeof(addressEncoded), - ep->addr); + OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded, + sizeof(addressEncoded), + ep->addr); if (OC_STACK_OK != result) { @@ -1020,39 +1065,6 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, return OC_STACK_ERROR; } - // check for unicast presence - uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri); - if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri)) - { - return OC_STACK_INVALID_URI; - } - - cbNode = GetClientCB(NULL, 0, NULL, presenceUri); - if (cbNode) - { - presenceSubscribe = 1; - } - else - { - // check for multiicast presence - CAEndpoint_t ep = { .adapter = endpoint->adapter, - .flags = endpoint->flags }; - - uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri); - - cbNode = GetClientCB(NULL, 0, NULL, presenceUri); - if (cbNode) - { - multicastPresenceSubscribe = 1; - } - } - - if (!presenceSubscribe && !multicastPresenceSubscribe) - { - OIC_LOG(ERROR, TAG, "Received a presence notification, but no callback, ignoring"); - goto exit; - } - response.payload = NULL; response.result = OC_STACK_OK; @@ -1082,6 +1094,36 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, maxAge = ((OCPresencePayload*)response.payload)->maxAge; } + // check for unicast presence + uriLen = FormCanonicalPresenceUri(endpoint, presenceUri, + responseInfo->isMulticast); + if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri)) + { + return OC_STACK_INVALID_URI; + } + OIC_LOG(ERROR, TAG, "check for unicast presence"); + cbNode = GetClientCB(NULL, 0, NULL, presenceUri); + if (cbNode) + { + presenceSubscribe = 1; + } + else + { + // check for multicast presence + OIC_LOG(ERROR, TAG, "check for multicast presence"); + cbNode = GetClientCB(NULL, 0, NULL, OC_RSRVD_PRESENCE_URI); + if (cbNode) + { + multicastPresenceSubscribe = 1; + } + } + + if (!presenceSubscribe && !multicastPresenceSubscribe) + { + OIC_LOG(ERROR, TAG, "Received a presence notification, but no callback, ignoring"); + goto exit; + } + if (presenceSubscribe) { if(cbNode->sequenceNumber == response.sequenceNumber) @@ -1132,70 +1174,31 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, ResetPresenceTTL(cbNode, maxAge); cbNode->sequenceNumber = response.sequenceNumber; - - // Ensure that a filter is actually applied. - if( resourceTypeName && cbNode->filterResourceType) - { - if(!findResourceType(cbNode->filterResourceType, resourceTypeName)) - { - goto exit; - } - } } } else { // This is the multicast case - OCMulticastNode* mcNode = NULL; - mcNode = GetMCPresenceNode(presenceUri); - - if(mcNode != NULL) - { - if(mcNode->nonce == response.sequenceNumber) - { - OIC_LOG(INFO, TAG, "No presence change (Multicast)"); - goto exit; - } - mcNode->nonce = response.sequenceNumber; - - if(maxAge == 0) - { - OIC_LOG(INFO, TAG, "Stopping presence"); - response.result = OC_STACK_PRESENCE_STOPPED; - } - } - else + OIC_LOG(INFO, TAG, "this is the multicast presence"); + if (0 == maxAge) { - char* uri = OICStrdup(presenceUri); - if (!uri) - { - OIC_LOG(INFO, TAG, - "No Memory for URI to store in the presence node"); - result = OC_STACK_NO_MEMORY; - goto exit; - } - - result = AddMCPresenceNode(&mcNode, uri, response.sequenceNumber); - if(result == OC_STACK_NO_MEMORY) - { - OIC_LOG(INFO, TAG, - "No Memory for Multicast Presence Node"); - OICFree(uri); - goto exit; - } - // presence node now owns uri + OIC_LOG(INFO, TAG, "Stopping presence"); + response.result = OC_STACK_PRESENCE_STOPPED; } + } - // Ensure that a filter is actually applied. - if(resourceTypeName && cbNode->filterResourceType) + // Ensure that a filter is actually applied. + if (resourceTypeName && cbNode->filterResourceType) + { + OIC_LOG_V(INFO, TAG, "find resource type : %s", resourceTypeName); + if(!findResourceType(cbNode->filterResourceType, resourceTypeName)) { - if(!findResourceType(cbNode->filterResourceType, resourceTypeName)) - { - goto exit; - } + goto exit; } } + OIC_LOG(INFO, TAG, "Callback for presence"); + cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response); if (cbResult == OC_STACK_DELETE_TRANSACTION) @@ -1266,7 +1269,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}}; - response.sequenceNumber = -1; + response.sequenceNumber = MAX_SEQUENCE_NUMBER + 1; CopyEndpointToDevAddr(endPoint, &response.devAddr); FixUpClientResponse(&response); response.resourceUri = responseInfo->info.resourceUri; @@ -1300,12 +1303,13 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp #endif else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0) { - type = PAYLOAD_TYPE_DEVICE; + type = PAYLOAD_TYPE_REPRESENTATION; } else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0) { - type = PAYLOAD_TYPE_PLATFORM; + type = PAYLOAD_TYPE_REPRESENTATION; } + #ifdef ROUTING_GATEWAY else if (strcmp(cbNode->requestUri, OC_RSRVD_GATEWAY_URI) == 0) { @@ -1314,10 +1318,10 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp #endif else if (strcmp(cbNode->requestUri, OC_RSRVD_RD_URI) == 0) { - type = PAYLOAD_TYPE_RD; + type = PAYLOAD_TYPE_REPRESENTATION; } #ifdef TCP_ADAPTER - else if (strcmp(cbNode->requestUri, KEEPALIVE_RESOURCE_URI) == 0) + else if (strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0) { type = PAYLOAD_TYPE_REPRESENTATION; } @@ -1336,25 +1340,26 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp cbNode->method == OC_REST_OBSERVE_ALL || cbNode->method == OC_REST_DELETE) { - char targetUri[MAX_URI_LENGTH]; - snprintf(targetUri, MAX_URI_LENGTH, "%s?rt=%s", OC_RSRVD_RD_URI, - OC_RSRVD_RESOURCE_TYPE_RDPUBLISH); - if (strcmp(targetUri, cbNode->requestUri) == 0) - { - type = PAYLOAD_TYPE_RD; - } - else if (strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri) == 0) - { - type = PAYLOAD_TYPE_PLATFORM; - } - else if (strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri) == 0) + if (cbNode->requestUri) { - type = PAYLOAD_TYPE_DEVICE; + if (0 == strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri)) + { + type = PAYLOAD_TYPE_REPRESENTATION; + } + else if (0 == strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri)) + { + type = PAYLOAD_TYPE_REPRESENTATION; + } + if (type == PAYLOAD_TYPE_INVALID) + { + OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s", + cbNode->method, cbNode->requestUri); + type = PAYLOAD_TYPE_REPRESENTATION; + } } - if (type == PAYLOAD_TYPE_INVALID) + else { - OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s", - cbNode->method, cbNode->requestUri); + OIC_LOG(INFO, TAG, "No Request URI, PROXY URI"); type = PAYLOAD_TYPE_REPRESENTATION; } } @@ -1381,7 +1386,8 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { int start = 0; //First option always with option ID is COAP_OPTION_OBSERVE if it is available. - if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE) + if(responseInfo->info.options + && responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE) { size_t i; uint32_t observationOption; @@ -1411,13 +1417,17 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp for (uint8_t i = start; i < responseInfo->info.numOptions; i++) { - memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]), - &(responseInfo->info.options[i]), sizeof(OCHeaderOption)); + if(&(responseInfo->info.options[i])) + { + memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]), + &(responseInfo->info.options[i]), sizeof(OCHeaderOption)); + } } } if (cbNode->method == OC_REST_OBSERVE && response.sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER && + cbNode->sequenceNumber <= MAX_SEQUENCE_NUMBER && response.sequenceNumber <= cbNode->sequenceNumber) { OIC_LOG_V(INFO, TAG, "Received stale notification. Number :%d", @@ -1425,6 +1435,14 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp } else { +#ifdef RD_CLIENT + // if request uri is '/oic/rd', update ins value of resource. + char *targetUri = strstr(cbNode->requestUri, OC_RSRVD_RD_URI); + if (targetUri) + { + OCUpdateResourceInsWithResponse(cbNode->requestUri, &response); + } +#endif OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context, cbNode->handle, &response); @@ -1446,7 +1464,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp if(responseInfo->info.type == CA_MSG_CONFIRM) { SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY, - CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL); + CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES); } OCPayloadDestroy(response.payload); @@ -1496,7 +1514,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { OIC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET"); SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY, - CA_MSG_RESET, 0, NULL, NULL, 0, NULL); + CA_MSG_RESET, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES); } } @@ -1518,8 +1536,6 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp return; } - - OIC_LOG(INFO, TAG, "Exit OCHandleResponse"); } void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo) @@ -1568,19 +1584,10 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res */ void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo) { - OIC_LOG(INFO, TAG, "Enter HandleCAErrorResponse"); - - if (NULL == endPoint) - { - OIC_LOG(ERROR, TAG, "endPoint is NULL"); - return; - } + VERIFY_NON_NULL_NR(endPoint, FATAL); + VERIFY_NON_NULL_NR(errorInfo, FATAL); - if (NULL == errorInfo) - { - OIC_LOG(ERROR, TAG, "errorInfo is NULL"); - return; - } + OIC_LOG(INFO, TAG, "Enter HandleCAErrorResponse"); ClientCB *cbNode = GetClientCB(errorInfo->info.token, errorInfo->info.tokenLength, NULL, NULL); @@ -1593,10 +1600,22 @@ void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *er memcpy(response.identity.id, errorInfo->info.identity.id, sizeof (response.identity.id)); response.identity.id_length = errorInfo->info.identity.id_length; - response.result = CAResultToOCStackResult(errorInfo->result); + response.result = CAResultToOCResult(errorInfo->result); cbNode->callBack(cbNode->context, cbNode->handle, &response); - FindAndDeleteClientCB(cbNode); + } + + ResourceObserver *observer = GetObserverUsingToken(errorInfo->info.token, + errorInfo->info.tokenLength); + if (observer) + { + OIC_LOG(INFO, TAG, "Receiving communication error for an observer"); + OCStackResult result = CAResultToOCResult(errorInfo->result); + if (OC_STACK_COMM_ERROR == result) + { + OCStackFeedBack(errorInfo->info.token, errorInfo->info.tokenLength, + OC_OBSERVER_FAILED_COMM); + } } OIC_LOG(INFO, TAG, "Exit HandleCAErrorResponse"); @@ -1610,7 +1629,8 @@ void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *er OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID, const CAResponseResult_t responseResult, const CAMessageType_t type, const uint8_t numOptions, const CAHeaderOption_t *options, - CAToken_t token, uint8_t tokenLength, const char *resourceUri) + CAToken_t token, uint8_t tokenLength, const char *resourceUri, + CADataType_t dataType) { OIC_LOG(DEBUG, TAG, "Entering SendDirectStackResponse"); CAResponseInfo_t respInfo = { @@ -1634,6 +1654,7 @@ OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16 respInfo.info.type = type; respInfo.info.resourceUri = OICStrdup (resourceUri); respInfo.info.acceptFormat = CA_FORMAT_UNDEFINED; + respInfo.info.dataType = dataType; #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) // Add the destination to route option from the endpoint->routeData. @@ -1642,6 +1663,8 @@ OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16 if(OC_STACK_OK != result) { OIC_LOG_V(ERROR, TAG, "Add routing option failed [%d]", result); + OICFree (respInfo.info.resourceUri); + OICFree (respInfo.info.options); return result; } if (doPost) @@ -1666,6 +1689,9 @@ OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16 if (NULL == reqInfo.info.options) { OIC_LOG(ERROR, TAG, "Calloc failed"); + OICFree (reqInfo.info.resourceUri); + OICFree (respInfo.info.resourceUri); + OICFree (respInfo.info.options); return OC_STACK_NO_MEMORY; } memcpy (reqInfo.info.options, respInfo.info.options, @@ -1771,15 +1797,6 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque { OIC_LOG(DEBUG, TAG, "Enter OCHandleRequests"); -#ifdef TCP_ADAPTER - if (requestInfo->info.resourceUri && - strcmp(requestInfo->info.resourceUri, KEEPALIVE_RESOURCE_URI) == 0) - { - HandleKeepAliveRequest(endPoint, requestInfo); - return; - } -#endif - OCStackResult requestResult = OC_STACK_ERROR; if(myStackMode == OC_CLIENT) @@ -1869,7 +1886,8 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ, requestInfo->info.type, requestInfo->info.numOptions, requestInfo->info.options, requestInfo->info.token, - requestInfo->info.tokenLength, requestInfo->info.resourceUri); + requestInfo->info.tokenLength, requestInfo->info.resourceUri, + CA_RESPONSE_DATA); OICFree(serverRequest.payload); return; } @@ -1888,7 +1906,8 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR, requestInfo->info.type, requestInfo->info.numOptions, requestInfo->info.options, requestInfo->info.token, - requestInfo->info.tokenLength, requestInfo->info.resourceUri); + requestInfo->info.tokenLength, requestInfo->info.resourceUri, + CA_RESPONSE_DATA); OICFree(serverRequest.payload); return; } @@ -1939,13 +1958,14 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT, requestInfo->info.type, requestInfo->info.numOptions, requestInfo->info.options, requestInfo->info.token, - requestInfo->info.tokenLength, requestInfo->info.resourceUri); + requestInfo->info.tokenLength, requestInfo->info.resourceUri, + CA_RESPONSE_DATA); OICFree(serverRequest.payload); OICFree(serverRequest.requestToken); return; } serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum; - if (serverRequest.numRcvdVendorSpecificHeaderOptions) + if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options) { memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options, sizeof(CAHeaderOption_t)*tempNum); @@ -1959,9 +1979,15 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque if (requestInfo->info.type == CA_MSG_CONFIRM) { SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY, - CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL); + CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL, + CA_RESPONSE_DATA); } } + if (requestResult == OC_STACK_RESOURCE_ERROR + && serverRequest.observationOption == OC_OBSERVE_REGISTER) + { + OIC_LOG_V(ERROR, TAG, "Observe Registration failed due to resource error"); + } else if(!OCResultToSuccess(requestResult)) { OIC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult); @@ -1972,7 +1998,8 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse, requestInfo->info.type, requestInfo->info.numOptions, requestInfo->info.options, requestInfo->info.token, - requestInfo->info.tokenLength, requestInfo->info.resourceUri); + requestInfo->info.tokenLength, requestInfo->info.resourceUri, + CA_RESPONSE_DATA); } // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest. // The token is copied in there, and is thus still owned by this function. @@ -2050,42 +2077,6 @@ void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque OIC_LOG(INFO, TAG, "Exit HandleCARequests"); } -bool validatePlatformInfo(OCPlatformInfo info) -{ - - if (!info.platformID) - { - OIC_LOG(ERROR, TAG, "No platform ID found."); - return false; - } - - if (info.manufacturerName) - { - size_t lenManufacturerName = strlen(info.manufacturerName); - - if(lenManufacturerName == 0 || lenManufacturerName > MAX_MANUFACTURER_NAME_LENGTH) - { - OIC_LOG(ERROR, TAG, "Manufacturer name fails length requirements."); - return false; - } - } - else - { - OIC_LOG(ERROR, TAG, "No manufacturer name present"); - return false; - } - - if (info.manufacturerUrl) - { - if(strlen(info.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH) - { - OIC_LOG(ERROR, TAG, "Manufacturer url fails length requirements."); - return false; - } - } - return true; -} - //----------------------------------------------------------------------------- // Public APIs //----------------------------------------------------------------------------- @@ -2174,12 +2165,19 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag defaultDeviceHandler = NULL; defaultDeviceHandlerCallbackParameter = NULL; + result = InitializeScheduleResourceList(); + VERIFY_SUCCESS(result, OC_STACK_OK); + result = CAResultToOCResult(CAInitialize()); VERIFY_SUCCESS(result, OC_STACK_OK); result = CAResultToOCResult(OCSelectNetwork()); VERIFY_SUCCESS(result, OC_STACK_OK); + result = CAResultToOCResult(CARegisterNetworkMonitorHandler( + OCDefaultAdapterStateChangedHandler, OCDefaultConnectionStateChangedHandler)); + VERIFY_SUCCESS(result, OC_STACK_OK); + switch (myStackMode) { case OC_CLIENT: @@ -2248,6 +2246,7 @@ exit: if(result != OC_STACK_OK) { OIC_LOG(ERROR, TAG, "Stack initialization error"); + TerminateScheduleResourceList(); deleteAllResources(); CATerminate(); stackState = OC_STACK_UNINITIALIZED; @@ -2272,6 +2271,9 @@ OCStackResult OCStop() stackState = OC_STACK_UNINIT_IN_PROGRESS; + CAUnregisterNetworkMonitorHandler(OCDefaultAdapterStateChangedHandler, + OCDefaultConnectionStateChangedHandler); + #ifdef WITH_PRESENCE // Ensure that the TTL associated with ANY and ALL presence notifications originating from // here send with the code "OC_STACK_PRESENCE_STOPPED" result. @@ -2289,21 +2291,20 @@ OCStackResult OCStop() TerminateKeepAlive(myStackMode); #endif - // Free memory dynamically allocated for resources - deleteAllResources(); - DeleteDeviceInfo(); - DeletePlatformInfo(); - CATerminate(); + TerminateScheduleResourceList(); // Remove all observers DeleteObserverList(); + // Free memory dynamically allocated for resources + deleteAllResources(); // Remove all the client callbacks DeleteClientCBList(); + // Terminate connectivity-abstraction layer. + CATerminate(); // De-init the SRM Policy Engine // TODO after BeachHead delivery: consolidate into single SRMDeInit() SRMDeInitPolicyEngine(); - stackState = OC_STACK_UNINITIALIZED; return OC_STACK_OK; } @@ -2355,6 +2356,8 @@ CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos) * optionally one of * CoAP over UDP prefix "coap://" * CoAP over TCP prefix "coap+tcp://" + * CoAP over DTLS prefix "coaps://" + * CoAP over TLS prefix "coaps+tcp://" * optionally one of * IPv6 address "[1234::5678]" * IPv4 address "192.168.1.1" @@ -2409,7 +2412,8 @@ static OCStackResult ParseRequestUri(const char *fullUri, bool istcp = false; if (prefixLen) { - if ((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen))) + if (((prefixLen == sizeof(COAP_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAP_TCP_SCHEME, prefixLen))) + || ((prefixLen == sizeof(COAPS_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAPS_TCP_SCHEME, prefixLen)))) { istcp = true; } @@ -2498,13 +2502,21 @@ static OCStackResult ParseRequestUri(const char *fullUri, da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1); if (!da) { - return OC_STACK_NO_MEMORY; + return OC_STACK_NO_MEMORY; + } + + // Decode address per RFC 6874. + result = OCDecodeAddressForRFC6874(da->addr, sizeof(da->addr), start, end); + if (result != OC_STACK_OK) + { + OICFree(*devAddr); + return result; } - OICStrcpyPartial(da->addr, sizeof(da->addr), start, len); + da->port = port; da->adapter = adapter; da->flags = flags; - if (!strncmp(fullUri, "coaps:", 6)) + if (!strncmp(fullUri, "coaps", 5)) { da->flags = (OCTransportFlags)(da->flags|CA_SECURE); } @@ -2570,11 +2582,12 @@ error: } static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint, - char *resourceUri, char **requestUri) + char **requestUri, + bool isMulticast) { char uri[CA_MAX_URI_LENGTH]; - FormCanonicalPresenceUri(endpoint, resourceUri, uri); + FormCanonicalPresenceUri(endpoint, uri, isMulticast); *requestUri = OICStrdup(uri); if (!*requestUri) @@ -2604,7 +2617,6 @@ OCStackResult OCDoResource(OCDoHandle *handle, // Validate input parameters VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK); VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK); - VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI); OCStackResult result = OC_STACK_ERROR; CAResult_t caResult; @@ -2630,11 +2642,18 @@ OCStackResult OCDoResource(OCDoHandle *handle, adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT); flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS); - result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType); - - if (result != OC_STACK_OK) + if (requestUri) + { + result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType); + if (result != OC_STACK_OK) + { + OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri); + goto exit; + } + } + else if (!checkProxyUri(options, numOptions)) { - OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri); + OIC_LOG(ERROR, TAG, "Request doesn't contain RequestURI/Proxy URI"); goto exit; } @@ -2643,7 +2662,6 @@ OCStackResult OCDoResource(OCDoHandle *handle, case OC_REST_GET: case OC_REST_OBSERVE: case OC_REST_OBSERVE_ALL: - case OC_REST_CANCEL_OBSERVE: requestInfo.method = CA_GET; break; case OC_REST_PUT: @@ -2657,6 +2675,9 @@ OCStackResult OCDoResource(OCDoHandle *handle, break; case OC_REST_DISCOVER: qos = OC_LOW_QOS; +#ifdef WITH_PRESENCE + case OC_REST_PRESENCE: +#endif if (destination || devAddr) { requestInfo.isMulticast = false; @@ -2668,16 +2689,11 @@ OCStackResult OCDoResource(OCDoHandle *handle, destination = &tmpDevAddr; requestInfo.isMulticast = true; } - // CA_DISCOVER will become GET and isMulticast - requestInfo.method = CA_GET; - break; -#ifdef WITH_PRESENCE - case OC_REST_PRESENCE: - // Replacing method type with GET because "presence" - // is a stack layer only implementation. + // OC_REST_DISCOVER: CA_DISCOVER will become GET and isMulticast. + // OC_REST_PRESENCE: Since "presence" is a stack layer only implementation. + // replacing method type with GET. requestInfo.method = CA_GET; break; -#endif default: result = OC_STACK_INVALID_METHOD; goto exit; @@ -2721,7 +2737,6 @@ OCStackResult OCDoResource(OCDoHandle *handle, requestInfo.info.type = qualityOfServiceToMessageType(qos); requestInfo.info.token = token; requestInfo.info.tokenLength = tokenLength; - requestInfo.info.resourceUri = resourceUri; if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL)) { @@ -2767,7 +2782,8 @@ OCStackResult OCDoResource(OCDoHandle *handle, if (method == OC_REST_PRESENCE) { char *presenceUri = NULL; - result = OCPreparePresence(&endpoint, resourceUri, &presenceUri); + result = OCPreparePresence(&endpoint, &presenceUri, + requestInfo.isMulticast); if (OC_STACK_OK != result) { goto exit; @@ -2776,10 +2792,17 @@ OCStackResult OCDoResource(OCDoHandle *handle, // Assign full presence uri as coap://ip:port/oic/ad to add to callback list. // Presence notification will form a canonical uri to // look for callbacks into the application. + if (resourceUri) + { + OICFree(resourceUri); + } resourceUri = presenceUri; } #endif + // update resourceUri onto requestInfo after check presence uri + requestInfo.info.resourceUri = resourceUri; + ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND); result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle, method, devAddr, resourceUri, resourceType, ttl); @@ -2792,6 +2815,20 @@ OCStackResult OCDoResource(OCDoHandle *handle, resourceUri = NULL; // Client CB list entry now owns it resourceType = NULL; // Client CB list entry now owns it +#ifdef WITH_PRESENCE + if (method == OC_REST_PRESENCE) + { + OIC_LOG(ERROR, TAG, "AddClientCB for presence done."); + + if (handle) + { + *handle = resHandle; + } + + goto exit; + } +#endif + // send request result = OCSendRequest(&endpoint, &requestInfo); if (OC_STACK_OK != result) @@ -3073,6 +3110,7 @@ OCStackResult OCProcess() #ifdef WITH_PRESENCE OCStackResult OCStartPresence(const uint32_t ttl) { + OIC_LOG(INFO, TAG, "Entering OCStartPresence"); uint8_t tokenLength = CA_MAX_TOKEN_LEN; OCChangeResourceProperty( &(((OCResource *)presenceResource.handle)->resourceProperties), @@ -3124,6 +3162,7 @@ OCStackResult OCStartPresence(const uint32_t ttl) OCStackResult OCStopPresence() { + OIC_LOG(INFO, TAG, "Entering OCStopPresence"); OCStackResult result = OC_STACK_ERROR; if(presenceResource.handle) @@ -3156,55 +3195,6 @@ OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandle return OC_STACK_OK; } -OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo) -{ - OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo"); - - if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER || myStackMode == OC_GATEWAY) - { - if (validatePlatformInfo(platformInfo)) - { - return SavePlatformInfo(platformInfo); - } - else - { - return OC_STACK_INVALID_PARAM; - } - } - else - { - return OC_STACK_ERROR; - } -} - -OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo) -{ - OIC_LOG(INFO, TAG, "Entering OCSetDeviceInfo"); - - if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0') - { - OIC_LOG(ERROR, TAG, "Null or empty device name."); - return OC_STACK_INVALID_PARAM; - } - - if (deviceInfo.types) - { - OCStringLL *type = deviceInfo.types; - OCResource *resource = findResource((OCResource *) deviceResource); - if (!resource) - { - return OC_STACK_INVALID_PARAM; - } - - while (type) - { - OCBindResourceTypeToResource(deviceResource, type->value); - type = type->next; - } - } - return SaveDeviceInfo(deviceInfo); -} - OCStackResult OCCreateResource(OCResourceHandle *handle, const char *resourceTypeName, const char *resourceInterfaceName, @@ -3932,6 +3922,7 @@ void incrementSequenceNumber(OCResource * resPtr) OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCPresenceTrigger trigger) { + OIC_LOG(INFO, TAG, "SendPresenceNotification"); OCResource *resPtr = NULL; OCStackResult result = OC_STACK_ERROR; OCMethod method = OC_REST_PRESENCE; @@ -3955,6 +3946,7 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCStackResult SendStopNotification() { + OIC_LOG(INFO, TAG, "SendStopNotification"); OCResource *resPtr = NULL; OCStackResult result = OC_STACK_ERROR; OCMethod method = OC_REST_PRESENCE; @@ -4053,7 +4045,7 @@ OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse) // Normal response // Get pointer to request info - serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle); + serverRequest = GetServerRequestUsingHandle(ehResponse->requestHandle); if(serverRequest) { // response handler in ocserverrequest.c. Usually HandleSingleResponse. @@ -4351,6 +4343,7 @@ void deleteResourceElements(OCResource *resource) OICFree(resource->uri); deleteResourceType(resource->rsrcType); deleteResourceInterface(resource->rsrcInterface); + OCDeleteResourceAttributes(resource->rsrcAttributes); } void deleteResourceType(OCResourceType *resourceType) @@ -4381,6 +4374,25 @@ void deleteResourceInterface(OCResourceInterface *resourceInterface) } } +void OCDeleteResourceAttributes(OCAttribute *rsrcAttributes) +{ + OCAttribute *next = NULL; + for (OCAttribute *pointer = rsrcAttributes; pointer; pointer = next) + { + next = pointer->next; + if (pointer->attrName && 0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, pointer->attrName)) + { + OCFreeOCStringLL((OCStringLL *)pointer->attrValue); + } + else + { + OICFree(pointer->attrValue); + } + OICFree(pointer->attrName); + OICFree(pointer); + } +} + void insertResourceType(OCResource *resource, OCResourceType *resourceType) { OCResourceType *pointer = NULL; @@ -4455,6 +4467,7 @@ OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * OCResourceType * rtPointer = resourceTypeList; while(resourceTypeName && rtPointer) { + OIC_LOG_V(DEBUG, TAG, "current resourceType : %s", rtPointer->resourcetypename); if(rtPointer->resourcetypename && strcmp(resourceTypeName, (const char *) (rtPointer->resourcetypename)) == 0) @@ -4658,13 +4671,13 @@ const char* OCGetServerInstanceIDString(void) static bool generated = false; static char sidStr[UUID_STRING_SIZE]; - if(generated) + if (generated) { return sidStr; } const OicUuid_t *sid = OCGetServerInstanceID(); - if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK) + if (sid && OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK) { OIC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!"); return NULL; @@ -4694,20 +4707,20 @@ CAResult_t OCSelectNetwork() }; int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]); - for(int i = 0; iins = ins; + + return OC_STACK_OK; +} + + +OCStackResult OCUpdateResourceInsWithResponse(const char *requestUri, + const OCClientResponse *response) +{ + // Validate input parameters + VERIFY_NON_NULL(requestUri, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(response, ERROR, OC_STACK_INVALID_PARAM); + + char *targetUri = (char *) OICMalloc(strlen(requestUri) + 1); + if (!targetUri) + { + return OC_STACK_NO_MEMORY; + } + strncpy(targetUri, requestUri, strlen(requestUri) + 1); + + if (response->result == OC_STACK_RESOURCE_CHANGED) // publish message + { + OIC_LOG(DEBUG, TAG, "update the ins of published resource"); + + char rdPubUri[MAX_URI_LENGTH] = { 0 }; + snprintf(rdPubUri, MAX_URI_LENGTH, "%s?rt=%s", OC_RSRVD_RD_URI, + OC_RSRVD_RESOURCE_TYPE_RDPUBLISH); + + if (strcmp(rdPubUri, targetUri) == 0) + { + // Update resource unique id in stack. + if (response) + { + if (response->payload) + { + OCRepPayload *rdPayload = (OCRepPayload *) response->payload; + OCRepPayload **links = NULL; + size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 }; + if (OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, + &links, dimensions)) + { + size_t i = 0; + for (; i < dimensions[0]; i++) + { + char *uri = NULL; + if (OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri)) + { + OCResourceHandle handle = OCGetResourceHandleAtUri(uri); + int64_t ins = 0; + if (OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins)) + { + OCBindResourceInsToResource(handle, ins); + } + } + } + } + } + } + } + } + else if (response->result == OC_STACK_RESOURCE_DELETED) // delete message + { + OIC_LOG(DEBUG, TAG, "update the ins of deleted resource with 0"); + + uint8_t numResources = 0; + OCGetNumberOfResources(&numResources); + + char *ins = strstr(targetUri, OC_RSRVD_INS); + if (!ins) + { + for (uint8_t i = 0; i < numResources; i++) + { + OCResourceHandle resHandle = OCGetResourceHandle(i); + if (resHandle) + { + OCBindResourceInsToResource(resHandle, 0); + } + } + } + else + { + const char *token = "&"; + char *iterTokenPtr = NULL; + char *start = strtok_r(targetUri, token, &iterTokenPtr); + + while (start != NULL) + { + char *query = start; + query = strstr(query, OC_RSRVD_INS); + if (query) + { + uint8_t queryIns = atoi(query + 4); + for (uint8_t i = 0; i < numResources; i++) + { + OCResourceHandle resHandle = OCGetResourceHandle(i); + if (resHandle) + { + uint8_t resIns = 0; + OCGetResourceIns(resHandle, &resIns); + if (queryIns && queryIns == resIns) + { + OCBindResourceInsToResource(resHandle, 0); + break; + } + } + } + } + start = strtok_r(NULL, token, &iterTokenPtr); + } + } + } + + OICFree(targetUri); + return OC_STACK_OK; +} + +OCResourceHandle OCGetResourceHandleAtUri(const char *uri) +{ + if (!uri) + { + OIC_LOG(ERROR, TAG, "Resource uri is NULL"); + return NULL; + } + + OCResource *pointer = headResource; + + while (pointer) + { + if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0) + { + OIC_LOG_V(DEBUG, TAG, "Found Resource %s", uri); + return pointer; + } + pointer = pointer->next; + } + return NULL; +} + +OCStackResult OCGetResourceIns(OCResourceHandle handle, uint8_t *ins) +{ + OCResource *resource = NULL; + + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(ins, ERROR, OC_STACK_INVALID_PARAM); + + resource = findResource((OCResource *) handle); + if (resource) + { + *ins = resource->ins; + return OC_STACK_OK; + } + return OC_STACK_ERROR; +} +#endif + +OCStackResult OCSetHeaderOption(OCHeaderOption* ocHdrOpt, size_t* numOptions, uint16_t optionID, + void* optionData, size_t optionDataLength) +{ + if (!ocHdrOpt) + { + OIC_LOG (INFO, TAG, "Header options are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!optionData) + { + OIC_LOG (INFO, TAG, "optionData are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!numOptions) + { + OIC_LOG (INFO, TAG, "numOptions is NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (*numOptions >= MAX_HEADER_OPTIONS) + { + OIC_LOG (INFO, TAG, "Exceeding MAX_HEADER_OPTIONS"); + return OC_STACK_NO_MEMORY; + } + + ocHdrOpt += *numOptions; + ocHdrOpt->protocolID = OC_COAP_ID; + ocHdrOpt->optionID = optionID; + ocHdrOpt->optionLength = + optionDataLength < MAX_HEADER_OPTION_DATA_LENGTH ? + optionDataLength : MAX_HEADER_OPTION_DATA_LENGTH; + memcpy(ocHdrOpt->optionData, (const void*) optionData, ocHdrOpt->optionLength); + *numOptions += 1; + + return OC_STACK_OK; +} + +OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, uint16_t optionID, + void* optionData, size_t optionDataLength, uint16_t* receivedDataLength) +{ + if (!ocHdrOpt || !numOptions) + { + OIC_LOG (INFO, TAG, "No options present"); + return OC_STACK_OK; + } + + if (!optionData) + { + OIC_LOG (INFO, TAG, "optionData are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!receivedDataLength) + { + OIC_LOG (INFO, TAG, "receivedDataLength is NULL"); + return OC_STACK_INVALID_PARAM; + } + + for (uint8_t i = 0; i < numOptions; i++) + { + if (ocHdrOpt[i].optionID == optionID) + { + if (optionDataLength >= ocHdrOpt->optionLength) + { + memcpy(optionData, ocHdrOpt->optionData, ocHdrOpt->optionLength); + *receivedDataLength = ocHdrOpt->optionLength; + return OC_STACK_OK; + } + else + { + OIC_LOG (ERROR, TAG, "optionDataLength is less than the length of received data"); + return OC_STACK_ERROR; + } + } + } + return OC_STACK_OK; +} + +void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled) +{ + OIC_LOG(DEBUG, TAG, "OCDefaultAdapterStateChangedHandler"); + if (g_adapterHandler) + { + g_adapterHandler(adapter, enabled); + } +} + +void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected) +{ + OIC_LOG(DEBUG, TAG, "OCDefaultConnectionStateChangedHandler"); + if (g_connectionHandler) + { + g_connectionHandler(info, isConnected); + } + + /* + * If the client observes one or more resources over a reliable connection, + * then the CoAP server (or intermediary in the role of the CoAP server) + * MUST remove all entries associated with the client endpoint from the lists + * of observers when the connection is either closed or times out. + */ + if (!isConnected) + { + OCDevAddr devAddr = { OC_DEFAULT_ADAPTER }; + CopyEndpointToDevAddr(info, &devAddr); + + // remove observer list with remote device address. + DeleteObserverUsingDevAddr(&devAddr); + } +} + +void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler, + CAConnectionStateChangedCB connectionHandler) +{ + OIC_LOG(DEBUG, TAG, "OCSetNetworkMonitorHandler"); + g_adapterHandler = adapterHandler; + g_connectionHandler = connectionHandler; +} + +OCStackResult OCGetDeviceId(OCUUIdentity *deviceId) +{ + OicUuid_t oicUuid; + OCStackResult ret = OC_STACK_ERROR; + + ret = GetDoxmDeviceID(&oicUuid); + if (OC_STACK_OK == ret) + { + memcpy(deviceId, &oicUuid, UUID_IDENTITY_SIZE); + } + else + { + OIC_LOG(ERROR, TAG, "Device ID Get error"); + } + return ret; +} + +OCStackResult OCSetDeviceId(const OCUUIdentity *deviceId) +{ + OicUuid_t oicUuid; + OCStackResult ret = OC_STACK_ERROR; + + memcpy(&oicUuid, deviceId, UUID_LENGTH); + for (int i = 0; i < UUID_LENGTH; i++) + { + OIC_LOG_V(INFO, TAG, "Set Device Id %x", oicUuid.id[i]); + } + ret = SetDoxmDeviceID(&oicUuid); + return ret; +}