X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fstack%2Fsrc%2Focstack.c;h=f5575b1e18e642cc9676933332002c0fb41bb84d;hb=1e743d337b66bda0e44a5ca500d4d7178bb599b5;hp=963c6aad0b26c8169139a2c37c50ccd82a86a5bb;hpb=f03c8766f8326defb4c65dcc57d61ba004c0db4e;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index 963c6aa..f5575b1 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 @@ -49,14 +50,18 @@ #include "oic_malloc.h" #include "oic_string.h" #include "logger.h" +#include "trace.h" #include "ocserverrequest.h" #include "secureresourcemanager.h" +#include "psinterface.h" +#include "psiutils.h" #include "doxmresource.h" #include "cacommon.h" #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" @@ -66,7 +71,7 @@ #endif #ifdef TCP_ADAPTER -#include "oickeepalive.h" +#include "oickeepaliveinternal.h" #endif //#ifdef DIRECT_PAIRING @@ -79,9 +84,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 @@ -109,6 +112,14 @@ typedef enum } OCPresenceState; #endif +#if defined(__WITH_DTLS__) || defined (__WITH_TLS__) +typedef struct +{ + OCOtmEventHandler cb; + void *ctx; +} OCOtmEventHandler_t; +#endif + //----------------------------------------------------------------------------- // Private variables //----------------------------------------------------------------------------- @@ -118,6 +129,10 @@ OCResource *headResource = NULL; static OCResource *tailResource = NULL; static OCResourceHandle platformResource = {0}; static OCResourceHandle deviceResource = {0}; +#ifdef MQ_BROKER +static OCResourceHandle brokerResource = {0}; +#endif + #ifdef WITH_PRESENCE static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED; static PresenceResource presenceResource = {0}; @@ -132,9 +147,17 @@ 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; + +#if defined(__WITH_DTLS__) || defined (__WITH_TLS__) +static OCOtmEventHandler_t g_otmEventHandler = {NULL, NULL}; +#endif + //----------------------------------------------------------------------------- // Macros //----------------------------------------------------------------------------- @@ -249,6 +272,13 @@ static void deleteResourceType(OCResourceType *resourceType); static void deleteResourceInterface(OCResourceInterface *resourceInterface); /** + * Unbind all child resources. + * + * @param resourceChild Specified binded resource head is deleted from parent. + */ +static void unbindChildResources(OCChildResource *resourceChild); + +/** * Delete all of the dynamically allocated elements that were created for the resource. * * @param resource Specified resource. @@ -282,27 +312,10 @@ static void incrementSequenceNumber(OCResource * resPtr); * * Note: At least one interface must succeed to initialize. If all calls to @ref CASelectNetwork * return something other than @ref CA_STATUS_OK, then this function fails. - * + * @param transportType OCTransportAdapter value to select. * @return ::CA_STATUS_OK on success, some other value upon failure. */ -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); +static CAResult_t OCSelectNetwork(OCTransportAdapter transportType); /** * Convert CAResponseResult_t to OCStackResult. @@ -313,15 +326,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. @@ -387,6 +391,7 @@ static OCStackResult getQueryFromUri(const char * uri, char** resourceType, char static OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName); +#ifdef WITH_PRESENCE /** * Reset presence TTL for a ClientCB struct. ttlLevel will be set to 0. * TTL will be set to maxAge. @@ -397,6 +402,7 @@ static OCResourceType *findResourceType(OCResourceType * resourceTypeList, * @return ::OC_STACK_OK on success, some other value upon failure. */ static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds); +#endif /** * Ensure the accept header option is set appropriatly before sending the requests and routing @@ -409,20 +415,55 @@ 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); + //----------------------------------------------------------------------------- // 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 { @@ -441,7 +482,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 } @@ -453,8 +498,13 @@ void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out) out->adapter = (CATransportAdapter_t)in->adapter; out->flags = OCToCATransportFlags(in->flags); OICStrcpy(out->addr, sizeof(out->addr), in->addr); + OICStrcpy(out->remoteId, sizeof(out->remoteId), in->remoteId); #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; @@ -473,12 +523,14 @@ static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t * { VERIFY_NON_NULL(object, FATAL, OC_STACK_INVALID_PARAM); VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM); + OIC_TRACE_BEGIN(%s:OCSendRequest, TAG); #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) OCStackResult rmResult = RMAddInfo(object->routeData, requestInfo, true, NULL); if (OC_STACK_OK != rmResult) { OIC_LOG(ERROR, TAG, "Add destination option failed"); + OIC_TRACE_END(); return rmResult; } #endif @@ -489,8 +541,11 @@ static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t * if(CA_STATUS_OK != result) { OIC_LOG_V(ERROR, TAG, "CASendRequest failed with CA error %u", result); + OIC_TRACE_END(); return CAResultToOCResult(result); } + + OIC_TRACE_END(); return OC_STACK_OK; } //----------------------------------------------------------------------------- @@ -509,11 +564,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, @@ -522,16 +577,23 @@ 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) { + FreeObserver(observer); 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); + } + + FreeObserver(observer); } - 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"); } @@ -544,12 +606,13 @@ 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; result = OC_STACK_OK; + FreeObserver(observer); } else { @@ -560,12 +623,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, @@ -574,15 +637,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) { + FreeObserver(observer); 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"); } @@ -595,10 +663,13 @@ 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); + + FreeObserver(observer); } break; default: @@ -609,32 +680,9 @@ 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; - switch(caCode) { case CA_CREATED: @@ -662,12 +710,36 @@ OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode) case CA_NOT_FOUND: ret = OC_STACK_NO_RESOURCE; break; - case CA_RETRANSMIT_TIMEOUT: - ret = OC_STACK_COMM_ERROR; - break; case CA_REQUEST_ENTITY_TOO_LARGE: ret = OC_STACK_TOO_LARGE_REQ; break; + case CA_METHOD_NOT_ALLOWED: + ret = OC_STACK_METHOD_NOT_ALLOWED; + break; + case CA_NOT_ACCEPTABLE: + ret = OC_STACK_NOT_ACCEPTABLE; + break; + case CA_FORBIDDEN_REQ: + ret = OC_STACK_FORBIDDEN_REQ; + break; + case CA_INTERNAL_SERVER_ERROR: + ret = OC_STACK_INTERNAL_SERVER_ERROR; + break; + case CA_NOT_IMPLEMENTED: + ret = OC_STACK_NOT_IMPLEMENTED; + break; + case CA_BAD_GATEWAY: + ret = OC_STACK_BAD_GATEWAY; + break; + case CA_SERVICE_UNAVAILABLE: + ret = OC_STACK_SERVICE_UNAVAILABLE; + break; + case CA_RETRANSMIT_TIMEOUT: + ret = OC_STACK_GATEWAY_TIMEOUT; + break; + case CA_PROXY_NOT_SUPPORTED: + ret = OC_STACK_PROXY_NOT_SUPPORTED; + break; default: break; } @@ -698,7 +770,8 @@ CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method) // This should not happen but, // give it a value just in case but output an error ret = CA_CONTENT; - OIC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [%d].", method); + OIC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [%d].", + method); } break; case OC_STACK_RESOURCE_CREATED: @@ -707,6 +780,9 @@ CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method) case OC_STACK_RESOURCE_DELETED: ret = CA_DELETED; break; + case OC_STACK_RESOURCE_CHANGED: + ret = CA_CHANGED; + break; case OC_STACK_INVALID_QUERY: ret = CA_BAD_REQ; break; @@ -719,9 +795,36 @@ CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method) case OC_STACK_COMM_ERROR: ret = CA_RETRANSMIT_TIMEOUT; break; + case OC_STACK_METHOD_NOT_ALLOWED: + ret = CA_METHOD_NOT_ALLOWED; + break; + case OC_STACK_NOT_ACCEPTABLE: + ret = CA_NOT_ACCEPTABLE; + break; 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; + case OC_STACK_NOT_IMPLEMENTED: + ret = CA_NOT_IMPLEMENTED; + break; + case OC_STACK_BAD_GATEWAY: + ret = CA_BAD_GATEWAY; + break; + case OC_STACK_SERVICE_UNAVAILABLE: + ret = CA_SERVICE_UNAVAILABLE; + break; + case OC_STACK_GATEWAY_TIMEOUT: + ret = CA_RETRANSMIT_TIMEOUT; + break; + case OC_STACK_PROXY_NOT_SUPPORTED: + ret = CA_PROXY_NOT_SUPPORTED; + break; default: break; } @@ -749,6 +852,7 @@ OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caFlags) return (OCTransportFlags)caFlags; } +#ifdef WITH_PRESENCE static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds) { uint32_t lowerBound = 0; @@ -838,37 +942,16 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) return OC_PRESENCE_TRIGGER_DELETE; } } +#endif // WITH_PRESENCE -/** - * 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; @@ -876,8 +959,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; @@ -904,46 +987,86 @@ 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); + OICStrcat(outputAddress, outputSize, "%25"); + OICStrcat(outputAddress, outputSize, scopeIdPart); + + 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; } +#ifdef WITH_PRESENCE /** * 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)) @@ -956,9 +1079,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) { @@ -1011,39 +1134,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; @@ -1073,6 +1163,37 @@ 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(INFO, TAG, "check for unicast presence"); + cbNode = GetClientCB(NULL, 0, NULL, presenceUri); + if (cbNode) + { + presenceSubscribe = 1; + } + else + { + // check for multicast presence + OIC_LOG(INFO, TAG, "check for multicast presence"); + cbNode = GetClientCB(NULL, 0, NULL, OC_RSRVD_PRESENCE_URI); + if (cbNode) + { + multicastPresenceSubscribe = 1; + } + } + + if (!presenceSubscribe && !multicastPresenceSubscribe) + { + OIC_LOG(INFO, TAG, "Received a presence notification, " + "but need to register presence callback, ignoring"); + goto exit; + } + if (presenceSubscribe) { if(cbNode->sequenceNumber == response.sequenceNumber) @@ -1123,71 +1244,32 @@ 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, "Before calling into application address space for presence"); cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response); + OIC_LOG(INFO, TAG, "After calling into application address space for presence"); if (cbResult == OC_STACK_DELETE_TRANSACTION) { @@ -1198,27 +1280,80 @@ exit: OCPayloadDestroy(response.payload); return result; } +#endif // WITH_PRESENCE + +OCStackResult HandleBatchResponse(char *requestUri, OCRepPayload **payload) +{ + if (requestUri && *payload) + { + char *interfaceName = NULL; + char *rtTypeName = NULL; + char *uriQuery = NULL; + char *uriWithoutQuery = NULL; + if (OC_STACK_OK == getQueryFromUri(requestUri, &uriQuery, &uriWithoutQuery)) + { + if (OC_STACK_OK == ExtractFiltersFromQuery(uriQuery, &interfaceName, &rtTypeName)) + { + if (interfaceName && (0 == strcmp(OC_RSRVD_INTERFACE_BATCH, interfaceName))) + { + char *uri = (*payload)->uri; + if (uri && 0 != strcmp(uriWithoutQuery, uri)) + { + OCRepPayload *newPayload = OCRepPayloadCreate(); + if (newPayload) + { + OCRepPayloadSetUri(newPayload, uri); + newPayload->next = *payload; + *payload = newPayload; + } + } + } + } + } + + OICFree(interfaceName); + OICFree(rtTypeName); + OICFree(uriQuery); + OICFree(uriWithoutQuery); + return OC_STACK_OK; + } + return OC_STACK_INVALID_PARAM; +} void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo) { + OIC_TRACE_MARK(%s:OCHandleResponse:%s, TAG, responseInfo->info.resourceUri); OIC_LOG(DEBUG, TAG, "Enter OCHandleResponse"); +#ifdef WITH_PRESENCE if(responseInfo->info.resourceUri && strcmp(responseInfo->info.resourceUri, OC_RSRVD_PRESENCE_URI) == 0) { HandlePresenceResponse(endPoint, responseInfo); return; } +#endif ClientCB *cbNode = GetClientCB(responseInfo->info.token, responseInfo->info.tokenLength, NULL, NULL); - ResourceObserver * observer = GetObserverUsingToken (responseInfo->info.token, - responseInfo->info.tokenLength); - if(cbNode) { OIC_LOG(INFO, TAG, "There is a cbNode associated with the response token"); +#ifdef __TIZENRT__ + // check obs header option + bool obsHeaderOpt = false; + CAHeaderOption_t *options = responseInfo->info.options; + for (uint8_t i = 0; i< responseInfo->info.numOptions; i++) + { + if (options && options[i].protocolID == CA_COAP_ID && + options[i].optionID == COAP_OPTION_OBSERVE) + { + obsHeaderOpt = true; + break; + } + } +#endif if(responseInfo->result == CA_EMPTY) { OIC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token"); @@ -1234,38 +1369,65 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT) { OIC_LOG(INFO, TAG, "Receiving A Timeout for this token"); - OIC_LOG(INFO, TAG, "Calling into application address space"); OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}}; CopyEndpointToDevAddr(endPoint, &response.devAddr); FixUpClientResponse(&response); - response.resourceUri = responseInfo->info.resourceUri; + response.resourceUri = OICStrdup(responseInfo->info.resourceUri); memcpy(response.identity.id, responseInfo->info.identity.id, sizeof (response.identity.id)); response.identity.id_length = responseInfo->info.identity.id_length; response.result = CAResponseToOCStackResult(responseInfo->result); + OIC_LOG(INFO, TAG, "Before calling into application address space for reTrans timeout"); cbNode->callBack(cbNode->context, cbNode->handle, &response); + OIC_LOG(INFO, TAG, "After calling into application address space for reTrans timeout"); FindAndDeleteClientCB(cbNode); + OICFree((void *)response.resourceUri); } - else +#ifdef __TIZENRT__ + else if ((cbNode->method == OC_REST_OBSERVE || cbNode->method == OC_REST_OBSERVE_ALL) + && (responseInfo->result == CA_CONTENT) && !obsHeaderOpt) { - OIC_LOG(INFO, TAG, "This is a regular response, A client call back is found"); - OIC_LOG(INFO, TAG, "Calling into application address space"); - OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}}; - response.sequenceNumber = -1; CopyEndpointToDevAddr(endPoint, &response.devAddr); FixUpClientResponse(&response); - response.resourceUri = responseInfo->info.resourceUri; + response.resourceUri = OICStrdup(responseInfo->info.resourceUri); memcpy(response.identity.id, responseInfo->info.identity.id, - sizeof (response.identity.id)); + sizeof (response.identity.id)); response.identity.id_length = responseInfo->info.identity.id_length; + response.result = OC_STACK_UNAUTHORIZED_REQ; - response.result = CAResponseToOCStackResult(responseInfo->result); + OIC_LOG(INFO, TAG, "Before calling into application address space for observe resp"); + cbNode->callBack(cbNode->context, + cbNode->handle, + &response); + OIC_LOG(INFO, TAG, "After calling into application address space for observe resp"); + + FindAndDeleteClientCB(cbNode); + OICFree(response.resourceUri); + } +#endif + else + { + OIC_LOG(INFO, TAG, "This is a regular response, A client call back is found"); + + OCClientResponse response; + memset(&response, 0, sizeof(OCClientResponse)); + response.devAddr.adapter = OC_DEFAULT_ADAPTER; + + response.sequenceNumber = MAX_SEQUENCE_NUMBER + 1; + CopyEndpointToDevAddr(endPoint, &response.devAddr); + FixUpClientResponse(&response); + response.resourceUri = OICStrdup(responseInfo->info.resourceUri); + memcpy(response.identity.id, responseInfo->info.identity.id, + sizeof (response.identity.id)); + response.identity.id_length = responseInfo->info.identity.id_length; + + response.result = CAResponseToOCStackResult(responseInfo->result); if(responseInfo->info.payload && responseInfo->info.payloadSize) @@ -1283,14 +1445,21 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { type = PAYLOAD_TYPE_DISCOVERY; } +#ifdef WITH_MQ + else if (strcmp(cbNode->requestUri, OC_RSRVD_WELL_KNOWN_MQ_URI) == 0) + { + type = PAYLOAD_TYPE_DISCOVERY; + } +#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) { @@ -1299,10 +1468,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; } @@ -1311,6 +1480,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { OIC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s", cbNode->method, cbNode->requestUri); + OICFree((void *)response.resourceUri); return; } } @@ -1321,25 +1491,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) + if (cbNode->requestUri) { - type = PAYLOAD_TYPE_RD; + 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; + } } - else if (strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri) == 0) - { - type = PAYLOAD_TYPE_PLATFORM; - } - else if (strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri) == 0) - { - type = PAYLOAD_TYPE_DEVICE; - } - 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; } } @@ -1347,17 +1518,28 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { OIC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s", cbNode->method, cbNode->requestUri); + OICFree((void *)response.resourceUri); return; } - if(OC_STACK_OK != OCParsePayload(&response.payload, + // In case of error, still want application to receive the error message. + if (OCResultToSuccess(response.result) || PAYLOAD_TYPE_REPRESENTATION == type) + { + if(OC_STACK_OK != OCParsePayload(&response.payload, type, responseInfo->info.payload, responseInfo->info.payloadSize)) + { + OIC_LOG(ERROR, TAG, "Error converting payload"); + OCPayloadDestroy(response.payload); + OICFree((void *)response.resourceUri); + return; + } + } + else { - OIC_LOG(ERROR, TAG, "Error converting payload"); - OCPayloadDestroy(response.payload); - return; + OICFree((void *)response.resourceUri); + response.resourceUri = OICStrdup(cbNode->requestUri); } } @@ -1366,7 +1548,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; @@ -1379,7 +1562,6 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp (observationOption << 8) | optionData[i]; } response.sequenceNumber = observationOption; - response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1; start = 1; } @@ -1392,18 +1574,30 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { OIC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS"); OCPayloadDestroy(response.payload); + OICFree((void *)response.resourceUri); return; } - for (uint8_t i = start; i < responseInfo->info.numOptions; i++) + if (response.numRcvdVendorSpecificHeaderOptions > 0) { - memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]), - &(responseInfo->info.options[i]), sizeof(OCHeaderOption)); + response.rcvdVendorSpecificHeaderOptions = + (OCHeaderOption *) OICCalloc(response.numRcvdVendorSpecificHeaderOptions, sizeof(OCHeaderOption)); + if (NULL == response.rcvdVendorSpecificHeaderOptions) + { + OIC_LOG(ERROR, TAG, "Failed to allocate memory for vendor header options"); + OCPayloadDestroy(response.payload); + OICFree((void *)response.resourceUri); + return; + } + + memcpy(response.rcvdVendorSpecificHeaderOptions, responseInfo->info.options + start, + response.numRcvdVendorSpecificHeaderOptions*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", @@ -1411,9 +1605,59 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp } else { +#ifdef RD_CLIENT + if (cbNode->requestUri) + { + // 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 + // set remoteID(device ID) into OCClientResponse callback parameter + if (OC_REST_DISCOVER == cbNode->method) + { + OIC_LOG(INFO, TAG, "cbNode method is OC_REST_DISCOVER"); + OCDiscoveryPayload *payload = (OCDiscoveryPayload*) response.payload; + // Payload can be empty in case of error message. + if (payload && payload->sid) + { + OICStrcpy(response.devAddr.remoteId, sizeof(response.devAddr.remoteId), + payload->sid); + OIC_LOG_V(INFO_PRIVATE, TAG, "Device ID of response : %s", + response.devAddr.remoteId); + } + + if(NULL == response.resourceUri) + { + response.resourceUri = OICStrdup(cbNode->requestUri); + } + } +#ifdef TCP_ADAPTER + if (cbNode->requestUri) + { + OIC_LOG_V(INFO, TAG, "cbNode requestUri is %s", cbNode->requestUri); + if (cbNode->method == OC_REST_POST && + strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0) + { + OCHandleKeepAliveResponse(endPoint, response.payload); + } + } +#endif + if (response.payload && response.payload->type == PAYLOAD_TYPE_REPRESENTATION) + { + OIC_LOG(INFO, TAG, "Handle batch response"); + HandleBatchResponse(cbNode->requestUri, (OCRepPayload **)&response.payload); + } + + OIC_LOG(INFO, TAG, "Before calling into application address space for handleResponse"); OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context, cbNode->handle, &response); + OIC_LOG(INFO, TAG, "After calling into application address space for handleResponse"); + cbNode->sequenceNumber = response.sequenceNumber; if (appFeedback == OC_STACK_DELETE_TRANSACTION) @@ -1431,15 +1675,24 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp //Need to send ACK when the response is CON if(responseInfo->info.type == CA_MSG_CONFIRM) { - SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY, - CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL); + if (!(endPoint->adapter & CA_ADAPTER_TCP)) + { + OIC_LOG(INFO, TAG, "Received a confirmable message. Sending EMPTY"); + SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY, + CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES); + } } + OICFree((void *)response.resourceUri); OCPayloadDestroy(response.payload); + OICFree(response.rcvdVendorSpecificHeaderOptions); } return; } + ResourceObserver * observer = GetObserverUsingToken (responseInfo->info.token, + responseInfo->info.tokenLength); + if(observer) { OIC_LOG(INFO, TAG, "There is an observer associated with the response token"); @@ -1465,6 +1718,8 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength, OC_OBSERVER_FAILED_COMM); } + + FreeObserver(observer); return; } @@ -1480,9 +1735,13 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp } else { - 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); + if (!(endPoint->adapter & CA_ADAPTER_TCP)) + { + 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_RESPONSE_FOR_RES); + } } } @@ -1504,8 +1763,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) @@ -1514,6 +1771,7 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res VERIFY_NON_NULL_NR(responseInfo, FATAL); OIC_LOG(INFO, TAG, "Enter HandleCAResponses"); + OIC_TRACE_BEGIN(%s:HandleCAResponses, TAG); #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) #ifdef ROUTING_GATEWAY @@ -1529,6 +1787,7 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res if(ret != OC_STACK_OK || !needRIHandling) { OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret); + OIC_TRACE_END(); return; } #endif @@ -1544,7 +1803,7 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res #endif OCHandleResponse(endPoint, responseInfo); - + OIC_TRACE_END(); OIC_LOG(INFO, TAG, "Exit HandleCAResponses"); } @@ -1554,19 +1813,11 @@ 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"); + OIC_TRACE_BEGIN(%s:HandleCAErrorResponse, TAG); ClientCB *cbNode = GetClientCB(errorInfo->info.token, errorInfo->info.tokenLength, NULL, NULL); @@ -1579,13 +1830,28 @@ 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); + OIC_LOG(INFO, TAG, "Before calling into application address space for error response"); cbNode->callBack(cbNode->context, cbNode->handle, &response); - FindAndDeleteClientCB(cbNode); + OIC_LOG(INFO, TAG, "After calling into application address space for error response"); + } + + 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"); + OIC_TRACE_END(); } /* @@ -1596,12 +1862,18 @@ 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 = { - .result = responseResult - }; + + if (endPoint->flags & CA_MULTICAST) + { + OIC_LOG(ERROR, TAG, "It is unnecessary to respond to a multicast request"); + return OC_STACK_OK; + } + + CAResponseInfo_t respInfo = { .result = responseResult }; respInfo.info.messageId = coapID; respInfo.info.numOptions = numOptions; @@ -1620,6 +1892,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. @@ -1628,6 +1901,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) @@ -1652,6 +1927,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, @@ -1755,17 +2033,9 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest) void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo) { + OIC_TRACE_MARK(%s:OCHandleRequests:%s, TAG, requestInfo->info.resourceUri); 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) @@ -1855,7 +2125,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; } @@ -1874,7 +2145,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; } @@ -1925,15 +2197,26 @@ 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, + serverRequest.rcvdVendorSpecificHeaderOptions = (OCHeaderOption*) OICCalloc(tempNum, sizeof(OCHeaderOption)); + if (NULL == serverRequest.rcvdVendorSpecificHeaderOptions) + { + OIC_LOG(ERROR, TAG, "Failed to allocated memory to vnd header options!"); + OICFree(serverRequest.payload); + OICFree(serverRequest.requestToken); + return; + } + + memcpy (serverRequest.rcvdVendorSpecificHeaderOptions, requestInfo->info.options, sizeof(CAHeaderOption_t)*tempNum); } @@ -1945,25 +2228,53 @@ 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); + } + } +#ifndef __TIZENRT__ + 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 (serverRequest.observationOption == OC_OBSERVE_REGISTER) + { + if (requestResult == OC_STACK_RESOURCE_ERROR) + { + OIC_LOG_V(ERROR, TAG, "Observe Registration failed due to resource error"); + } + else if (!OCResultToSuccess(requestResult)) + { + DeleteObserverUsingToken(requestInfo->info.token, requestInfo->info.tokenLength); } } +#endif else if(!OCResultToSuccess(requestResult)) { OIC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult); + // Delete observer node if it is OBSERVE failure from app + if (serverRequest.observationOption == OC_OBSERVE_REGISTER) + { + DeleteObserverUsingToken(requestInfo->info.token, requestInfo->info.tokenLength); + } + CAResponseResult_t stackResponse = OCToCAStackResult(requestResult, serverRequest.method); 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. OICFree(serverRequest.payload); OICFree(serverRequest.requestToken); + OICFree(serverRequest.rcvdVendorSpecificHeaderOptions); OIC_LOG(INFO, TAG, "Exit OCHandleRequests"); } @@ -1971,15 +2282,18 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo) { OIC_LOG(INFO, TAG, "Enter HandleCARequests"); + OIC_TRACE_BEGIN(%s:HandleCARequests, TAG); if(!endPoint) { OIC_LOG(ERROR, TAG, "endPoint is NULL"); + OIC_TRACE_END(); return; } if(!requestInfo) { OIC_LOG(ERROR, TAG, "requestInfo is NULL"); + OIC_TRACE_END(); return; } @@ -1999,6 +2313,7 @@ void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque if(OC_STACK_OK != ret || !needRIHandling) { OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret); + OIC_TRACE_END(); return; } #endif @@ -2034,42 +2349,7 @@ void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque OCHandleRequests(endPoint, requestInfo); } 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; + OIC_TRACE_END(); } //----------------------------------------------------------------------------- @@ -2102,6 +2382,16 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags) { + OC_UNUSED(serverFlags); + OC_UNUSED(clientFlags); + + OIC_LOG(DEBUG, TAG, "call OCInit1"); + return OCInit2(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS, OC_DEFAULT_ADAPTER); +} + +OCStackResult OCInit2(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags, + OCTransportAdapter transportType) +{ if(stackState == OC_STACK_INITIALIZED) { OIC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \ @@ -2160,10 +2450,17 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag defaultDeviceHandler = NULL; defaultDeviceHandlerCallbackParameter = NULL; - result = CAResultToOCResult(CAInitialize()); + result = InitializeScheduleResourceList(); + VERIFY_SUCCESS(result, OC_STACK_OK); + + result = CAResultToOCResult(CAInitialize((CATransportAdapter_t)transportType)); + VERIFY_SUCCESS(result, OC_STACK_OK); + + result = CAResultToOCResult(OCSelectNetwork(transportType)); VERIFY_SUCCESS(result, OC_STACK_OK); - result = CAResultToOCResult(OCSelectNetwork()); + result = CAResultToOCResult(CARegisterNetworkMonitorHandler( + OCDefaultAdapterStateChangedHandler, OCDefaultConnectionStateChangedHandler)); VERIFY_SUCCESS(result, OC_STACK_OK); switch (myStackMode) @@ -2191,7 +2488,7 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag VERIFY_SUCCESS(result, OC_STACK_OK); #ifdef TCP_ADAPTER - CARegisterKeepAliveHandler(HandleKeepAliveConnCB); + CARegisterKeepAliveHandler(OCHandleKeepAliveConnCB); #endif #ifdef WITH_PRESENCE @@ -2226,14 +2523,17 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag #ifdef TCP_ADAPTER if (result == OC_STACK_OK) { - result = InitializeKeepAlive(myStackMode); + result = OCInitializeKeepAlive(myStackMode); } #endif + InitializeObserverList(); + exit: if(result != OC_STACK_OK) { OIC_LOG(ERROR, TAG, "Stack initialization error"); + TerminateScheduleResourceList(); deleteAllResources(); CATerminate(); stackState = OC_STACK_UNINITIALIZED; @@ -2252,16 +2552,24 @@ OCStackResult OCStop() } else if (stackState != OC_STACK_INITIALIZED) { - OIC_LOG(ERROR, TAG, "Stack not initialized"); + OIC_LOG(INFO, TAG, "Stack not initialized"); return OC_STACK_ERROR; } + // unset cautil config + CAUtilConfig_t configs = {(CATransportBTFlags_t)CA_DEFAULT_BT_FLAGS}; + CAUtilSetBTConfigure(configs); + 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. presenceResource.presenceTTL = 0; + presenceState = OC_PRESENCE_UNINITIALIZED; #endif // WITH_PRESENCE #ifdef ROUTING_GATEWAY @@ -2272,23 +2580,25 @@ OCStackResult OCStop() #endif #ifdef TCP_ADAPTER - TerminateKeepAlive(myStackMode); + OCTerminateKeepAlive(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(); + // Destroy Observer List Mutex + TerminateObserverList(); stackState = OC_STACK_UNINITIALIZED; return OC_STACK_OK; @@ -2335,26 +2645,12 @@ CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos) } } -/** - * A request uri consists of the following components in order: - * example - * optionally one of - * CoAP over UDP prefix "coap://" - * CoAP over TCP prefix "coap+tcp://" - * optionally one of - * IPv6 address "[1234::5678]" - * IPv4 address "192.168.1.1" - * optional port ":5683" - * resource uri "/oc/core..." - * - * for PRESENCE requests, extract resource type. - */ -static OCStackResult ParseRequestUri(const char *fullUri, - OCTransportAdapter adapter, - OCTransportFlags flags, - OCDevAddr **devAddr, - char **resourceUri, - char **resourceType) +OCStackResult ParseRequestUri(const char *fullUri, + OCTransportAdapter adapter, + OCTransportFlags flags, + OCDevAddr **devAddr, + char **resourceUri, + char **resourceType) { VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK); @@ -2395,7 +2691,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; } @@ -2486,11 +2783,19 @@ static OCStackResult ParseRequestUri(const char *fullUri, { return OC_STACK_NO_MEMORY; } - OICStrcpyPartial(da->addr, sizeof(da->addr), start, len); + + // Decode address per RFC 6874. + result = OCDecodeAddressForRFC6874(da->addr, sizeof(da->addr), start, end); + if (result != OC_STACK_OK) + { + OICFree(*devAddr); + return result; + } + 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); } @@ -2520,7 +2825,7 @@ static OCStackResult ParseRequestUri(const char *fullUri, result = OC_STACK_NO_MEMORY; goto error; } - strcpy(*resourceUri, slash); + OICStrcpy(*resourceUri, (ulen + 1), slash); } // resource type if (type && resourceType) @@ -2555,12 +2860,14 @@ error: return result; } +#ifdef WITH_PRESENCE 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) @@ -2570,6 +2877,7 @@ static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint, return OC_STACK_OK; } +#endif // WITH_PRESENCE /** * Discover or Perform requests on a specified resource @@ -2585,12 +2893,34 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCHeaderOption *options, uint8_t numOptions) { + OCStackResult ret = OCDoRequest(handle, method, requestUri,destination, payload, + connectivityType, qos, cbData, options, numOptions); + + // This is the owner of the payload object, so we free it + OCPayloadDestroy(payload); + return ret; +} + +/** + * Discover or Perform requests on a specified resource + */ +OCStackResult OCDoRequest(OCDoHandle *handle, + OCMethod method, + const char *requestUri, + const OCDevAddr *destination, + OCPayload* payload, + OCConnectivityType connectivityType, + OCQualityOfService qos, + OCCallbackData *cbData, + OCHeaderOption *options, + uint8_t numOptions) +{ OIC_LOG(INFO, TAG, "Entering OCDoResource"); + OIC_TRACE_BEGIN(%s:OCDoRequest, TAG); // 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; @@ -2616,11 +2946,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; } @@ -2629,7 +2966,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: @@ -2642,7 +2978,9 @@ OCStackResult OCDoResource(OCDoHandle *handle, requestInfo.method = CA_DELETE; break; case OC_REST_DISCOVER: - qos = OC_LOW_QOS; +#ifdef WITH_PRESENCE + case OC_REST_PRESENCE: +#endif if (destination || devAddr) { requestInfo.isMulticast = false; @@ -2653,17 +2991,13 @@ OCStackResult OCDoResource(OCDoHandle *handle, tmpDevAddr.flags = flags; destination = &tmpDevAddr; requestInfo.isMulticast = true; + qos = OC_LOW_QOS; } - // 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; @@ -2685,9 +3019,20 @@ OCStackResult OCDoResource(OCDoHandle *handle, result = OC_STACK_NO_MEMORY; goto exit; } + OIC_LOG(DEBUG, TAG, "devAddr is set as destination"); *devAddr = *destination; } + if (devAddr) + { + OIC_LOG_V(INFO_PRIVATE, TAG, "remoteId of devAddr : %s", devAddr->remoteId); + if (!requestInfo.isMulticast) + { + OIC_LOG_V(DEBUG, TAG, "remoteAddr of devAddr : [%s]:[%d]", + devAddr->addr, devAddr->port); + } + } + resHandle = GenerateInvocationHandle(); if (!resHandle) { @@ -2707,7 +3052,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)) { @@ -2753,7 +3097,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; @@ -2762,10 +3107,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); @@ -2774,10 +3126,25 @@ OCStackResult OCDoResource(OCDoHandle *handle, goto exit; } + token = NULL; // Client CB list entry now owns it devAddr = NULL; // Client CB list entry now owns it 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) @@ -2803,13 +3170,12 @@ exit: OICFree(resHandle); } - // This is the owner of the payload object, so we free it - OCPayloadDestroy(payload); OICFree(requestInfo.info.payload); OICFree(devAddr); OICFree(resourceUri); OICFree(resourceType); OICFree(requestInfo.info.options); + OIC_TRACE_END(); return result; } @@ -2903,6 +3269,14 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption FindAndDeleteClientCB(clientCB); break; #endif + case OC_REST_GET: + case OC_REST_PUT: + case OC_REST_POST: + case OC_REST_DELETE: + OIC_LOG_V(INFO, TAG, "Cancelling request callback for resource %s", + clientCB->requestUri); + FindAndDeleteClientCB(clientCB); + break; default: ret = OC_STACK_INVALID_METHOD; @@ -2993,7 +3367,10 @@ OCStackResult OCProcessPresence() OIC_LOG_V(DEBUG, TAG, "moving to TTL level %d", cbNode->presence->TTLlevel); + OIC_LOG(INFO, TAG, "Before calling into application address space for presence timeout"); cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse); + OIC_LOG(INFO, TAG, "After calling into application address space for presence timeout"); + if (cbResult == OC_STACK_DELETE_TRANSACTION) { FindAndDeleteClientCB(cbNode); @@ -3041,6 +3418,11 @@ exit: OCStackResult OCProcess() { + if (stackState == OC_STACK_UNINITIALIZED) + { + OIC_LOG(ERROR, TAG, "OCProcess has failed. ocstack is not initialized"); + return OC_STACK_ERROR; + } #ifdef WITH_PRESENCE OCProcessPresence(); #endif @@ -3051,7 +3433,7 @@ OCStackResult OCProcess() #endif #ifdef TCP_ADAPTER - ProcessKeepAlive(); + OCProcessKeepAlive(); #endif return OC_STACK_OK; } @@ -3059,6 +3441,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), @@ -3078,7 +3461,9 @@ OCStackResult OCStartPresence(const uint32_t ttl) { presenceResource.presenceTTL = ttl; } +#ifndef __TIZENRT__ OIC_LOG_V(DEBUG, TAG, "Presence TTL is %" PRIu32 " seconds", presenceResource.presenceTTL); +#endif if (OC_PRESENCE_UNINITIALIZED == presenceState) { @@ -3110,6 +3495,7 @@ OCStackResult OCStartPresence(const uint32_t ttl) OCStackResult OCStopPresence() { + OIC_LOG(INFO, TAG, "Entering OCStopPresence"); OCStackResult result = OC_STACK_ERROR; if(presenceResource.handle) @@ -3142,61 +3528,12 @@ 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, - const char *uri, OCEntityHandler entityHandler, - void* callbackParam, - uint8_t resourceProperties) +OCStackResult OCCreateResource(OCResourceHandle *handle, + const char *resourceTypeName, + const char *resourceInterfaceName, + const char *uri, OCEntityHandler entityHandler, + void* callbackParam, + uint8_t resourceProperties) { OCResource *pointer = NULL; @@ -3221,15 +3558,25 @@ OCStackResult OCCreateResource(OCResourceHandle *handle, return OC_STACK_INVALID_PARAM; } - if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) + if (!resourceInterfaceName || strlen(resourceInterfaceName) == 0) { resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT; } +#ifdef MQ_PUBLISHER + resourceProperties = resourceProperties | OC_MQ_PUBLISHER; +#endif // Make sure resourceProperties bitmask has allowed properties specified if (resourceProperties > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE | - OC_EXPLICIT_DISCOVERABLE)) + OC_EXPLICIT_DISCOVERABLE +#ifdef MQ_PUBLISHER + | OC_MQ_PUBLISHER +#endif +#ifdef MQ_BROKER + | OC_MQ_BROKER +#endif + )) { OIC_LOG(ERROR, TAG, "Invalid property"); return OC_STACK_INVALID_PARAM; @@ -3452,8 +3799,11 @@ OCStackResult OCUnBindResource( { OCChildResource *temp = tempChildResource->next; OICFree(tempChildResource); - tempLastChildResource->next = temp; - temp = NULL; + if (tempLastChildResource) + { + tempLastChildResource->next = temp; + temp = NULL; + } } OIC_LOG(INFO, TAG, "resource unbound"); @@ -3908,6 +4258,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; @@ -3931,6 +4282,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; @@ -4018,6 +4370,7 @@ OCNotifyListOfObservers (OCResourceHandle handle, OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse) { + OIC_TRACE_BEGIN(%s:OCDoResponse, TAG); OCStackResult result = OC_STACK_ERROR; OCServerRequest *serverRequest = NULL; @@ -4029,13 +4382,14 @@ 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. result = serverRequest->ehResponseHandler(ehResponse); } + OIC_TRACE_END(); return result; } @@ -4150,6 +4504,7 @@ OCStackResult initResources() if(result == OC_STACK_OK) { + CreateResetProfile(); result = OCCreateResource(&deviceResource, OC_RSRVD_RESOURCE_TYPE_DEVICE, OC_RSRVD_INTERFACE_DEFAULT, @@ -4233,6 +4588,9 @@ void deleteAllResources() } memset(&platformResource, 0, sizeof(platformResource)); memset(&deviceResource, 0, sizeof(deviceResource)); +#ifdef MQ_BROKER + memset(&brokerResource, 0, sizeof(brokerResource)); +#endif SRMDeInitSecureResources(); @@ -4289,12 +4647,12 @@ OCStackResult deleteResource(OCResource *resource) headResource = temp->next; } // Deleting tail. - else if (temp == tailResource) + else if (temp == tailResource && prev) { tailResource = prev; tailResource->next = NULL; } - else + else if (prev) { prev->next = temp->next; } @@ -4320,36 +4678,97 @@ void deleteResourceElements(OCResource *resource) return; } - OICFree(resource->uri); - deleteResourceType(resource->rsrcType); - deleteResourceInterface(resource->rsrcInterface); + if (resource->uri) + { + OICFree(resource->uri); + resource->uri = NULL; + } + if (resource->rsrcType) + { + deleteResourceType(resource->rsrcType); + resource->rsrcType = NULL; + } + if (resource->rsrcInterface) + { + deleteResourceInterface(resource->rsrcInterface); + resource->rsrcInterface = NULL; + } + if (resource->rsrcChildResourcesHead) + { + unbindChildResources(resource->rsrcChildResourcesHead); + resource->rsrcChildResourcesHead = NULL; + } + if (resource->rsrcAttributes) + { + OCDeleteResourceAttributes(resource->rsrcAttributes); + resource->rsrcAttributes = NULL; + } + resource = NULL; } void deleteResourceType(OCResourceType *resourceType) { - OCResourceType *pointer = resourceType; OCResourceType *next = NULL; - while (pointer) + for (OCResourceType *pointer = resourceType; pointer; pointer = next) { - next = pointer->next; - OICFree(pointer->resourcetypename); + next = pointer->next ? pointer->next : NULL; + if (pointer->resourcetypename) + { + OICFree(pointer->resourcetypename); + pointer->resourcetypename = NULL; + } OICFree(pointer); - pointer = next; } } void deleteResourceInterface(OCResourceInterface *resourceInterface) { - OCResourceInterface *pointer = resourceInterface; OCResourceInterface *next = NULL; + for (OCResourceInterface *pointer = resourceInterface; pointer; pointer = next) + { + next = pointer->next ? pointer->next : NULL; + if (pointer->name) + { + OICFree(pointer->name); + pointer->name = NULL; + } + OICFree(pointer); + } +} - while (pointer) +void unbindChildResources(OCChildResource *head) +{ + OCChildResource *next = NULL; + for (OCChildResource *current = head; current; current = next) { - next = pointer->next; - OICFree(pointer->name); + next = current->next; + OICFree(current); + } +} + +void OCDeleteResourceAttributes(OCAttribute *rsrcAttributes) +{ + OCAttribute *next = NULL; + for (OCAttribute *pointer = rsrcAttributes; pointer; pointer = next) + { + next = pointer->next ? pointer->next : NULL; + if (pointer->attrName && 0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, pointer->attrName)) + { + OCFreeOCStringLL((OCStringLL *)pointer->attrValue); + pointer->attrValue = NULL; + } + else if (pointer->attrValue) + { + OICFree(pointer->attrValue); + pointer->attrValue = NULL; + } + if (pointer->attrName) + { + OICFree(pointer->attrName); + pointer->attrName = NULL; + } OICFree(pointer); - pointer = next; } } @@ -4427,6 +4846,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) @@ -4463,7 +4883,8 @@ void insertResourceInterface(OCResource *resource, OCResourceInterface *newInter } else { - OCStackResult result = BindResourceInterfaceToResource(resource, OC_RSRVD_INTERFACE_DEFAULT); + OCStackResult result = BindResourceInterfaceToResource(resource, + OC_RSRVD_INTERFACE_DEFAULT); if (result != OC_STACK_OK) { OICFree(newInterface->name); @@ -4606,47 +5027,28 @@ OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithout return OC_STACK_NO_MEMORY; } -static const OicUuid_t* OCGetServerInstanceID(void) -{ - static bool generated = false; - static OicUuid_t sid; - if (generated) - { - return &sid; - } - - if (OC_STACK_OK != GetDoxmDeviceID(&sid)) - { - OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!"); - return NULL; - } - generated = true; - return &sid; -} - const char* OCGetServerInstanceIDString(void) { - static bool generated = false; static char sidStr[UUID_STRING_SIZE]; - - if(generated) + OicUuid_t sid; + if (OC_STACK_OK != GetDoxmDeviceID(&sid)) { - return sidStr; + OIC_LOG(FATAL, TAG, "GetDoxmDeviceID failed!"); + return NULL; } - const OicUuid_t *sid = OCGetServerInstanceID(); - if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK) + if (OCConvertUuidToString(sid.id, sidStr) != RAND_UUID_OK) { OIC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!"); return NULL; } - generated = true; return sidStr; } -CAResult_t OCSelectNetwork() +CAResult_t OCSelectNetwork(OCTransportAdapter transportType) { + OIC_LOG_V(DEBUG, TAG, "OCSelectNetwork [%d]", transportType); CAResult_t retResult = CA_STATUS_FAILED; CAResult_t caResult = CA_STATUS_OK; @@ -4665,20 +5067,28 @@ 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); + } + + OICFree(uri); + uri = NULL; + } + } + + // Free links + size_t count = calcDimTotal(dimensions); + for (size_t k = 0; k < count; k++) + { + OCRepPayloadDestroy(links[k]); + } + OICFree(links); + } + } + } + } + } + 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) + { + int64_t queryIns = atoi(query + 4); + for (uint8_t i = 0; i < numResources; i++) + { + OCResourceHandle resHandle = OCGetResourceHandle(i); + if (resHandle) + { + int64_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, int64_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, + const 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); + } +} + +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; +} + +OCStackResult OCGetDeviceOwnedState(bool *isOwned) +{ + bool isDeviceOwned = true; + OCStackResult ret = OC_STACK_ERROR; + + ret = GetDoxmIsOwned(&isDeviceOwned); + if (OC_STACK_OK == ret) + { + *isOwned = isDeviceOwned; + } + else + { + OIC_LOG(ERROR, TAG, "Device Owned State Get error"); + } + return ret; +} + +void OCClearCallBackList() +{ + DeleteClientCBList(); +} + +void OCClearObserverlist() +{ + DeleteObserverList(); +} + +int OCEncrypt(const unsigned char *pt, size_t pt_len, + unsigned char **ct, size_t *ct_len) +{ +#ifndef __SECURE_PSI__ + OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__); + return 0; +#else + OIC_LOG_V(DEBUG, TAG, "%s", __func__); + + return psiEncrypt(pt, pt_len, ct, ct_len); +#endif // __SECURE_PSI__ +} + +int OCDecrypt(const unsigned char *ct, size_t ct_len, + unsigned char **pt, size_t *pt_len) +{ +#ifndef __SECURE_PSI__ + OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__); + return 0; +#else + OIC_LOG_V(DEBUG, TAG, "%s", __func__); + + return psiDecrypt(ct, ct_len, pt, pt_len); +#endif // __SECURE_PSI__ +} + +OCStackResult OCSetKey(const unsigned char* key) +{ +#ifndef __SECURE_PSI__ + OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__); + return OC_STACK_OK; +#else + OIC_LOG_V(DEBUG, TAG, "%s", __func__); + + return psiSetKey(key); +#endif // __SECURE_PSI__ +} + +OCStackResult OCGetKey(unsigned char* key) +{ +#ifndef __SECURE_PSI__ + OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__); + return OC_STACK_OK; +#else + OIC_LOG_V(DEBUG, TAG, "%s", __func__); + + return psiGetKey(key); +#endif // __SECURE_PSI__ +} + +OCStackResult OCSetSecurePSI(const unsigned char *key, const OCPersistentStorage *psPlain, + const OCPersistentStorage *psEnc, const OCPersistentStorage *psRescue) +{ +#ifndef __SECURE_PSI__ + OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__); + return OC_STACK_OK; +#else + OIC_LOG_V(DEBUG, TAG, "%s", __func__); + + return setSecurePSI(key, psPlain, psEnc, psRescue); +#endif // __SECURE_PSI__ +} + +#if defined(__WITH_DTLS__) || defined (__WITH_TLS__) +static void OtmEventHandler(const char *addr, uint16_t port, const char *uuid, int event) +{ + if (g_otmEventHandler.cb) + { + g_otmEventHandler.cb(g_otmEventHandler.ctx, addr, port, uuid, event); + } +} + +/* TODO Work-around + * It is already declared in srmutility.h. + * We can't include the header file, because of "redefined VERIFY_NON_NULL" + */ +typedef void (*OicSecOtmEventHandler_t)(const char* addr, uint16_t port, + const char* uuid, int event); +void SetOtmEventHandler(OicSecOtmEventHandler_t otmEventHandler); +#endif + +OCStackResult OCSetOtmEventHandler(void *ctx, OCOtmEventHandler cb) +{ +#if defined(__WITH_DTLS__) || defined (__WITH_TLS__) + OIC_LOG_V(DEBUG, TAG, "%s", __func__); + + g_otmEventHandler.cb = cb; + g_otmEventHandler.ctx = ctx; + + if (g_otmEventHandler.cb) + { + OIC_LOG(DEBUG, TAG, "SET OCOtmEventHandler"); + SetOtmEventHandler(OtmEventHandler); + } + else + { + OIC_LOG(DEBUG, TAG, "UNSET OCOtmEventHandler"); + SetOtmEventHandler(NULL); + } +#else + OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__); + OC_UNUSED(ctx); + OC_UNUSED(cb); +#endif + return OC_STACK_OK; +}