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=dcfa88d33161511f63cbbf9a73ff4574c64cda8a;hpb=6f3623eee149241df00780fde557ddf20df4c8b6;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index dcfa88d..66ac3bf 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -297,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. @@ -457,16 +440,16 @@ bool checkProxyUri(OCHeaderOption *options, uint8_t numOptions) return false; } -uint32_t GetTicks(uint32_t afterMilliSeconds) +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 { @@ -561,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, @@ -574,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"); } @@ -596,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; @@ -612,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, @@ -626,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"); } @@ -647,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: @@ -661,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; @@ -906,22 +876,9 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) } } -/** - * Encode an address string to match RFC 6874. - * - * @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); @@ -934,7 +891,7 @@ OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr) if (inputSize > outputSize) { OIC_LOG_V(ERROR, TAG, - "encodeAddressForRFC6874 failed: " + "OCEncodeAddressForRFC6874 failed: " "outputSize (%zu) < inputSize (%zu)", outputSize, inputSize); @@ -962,21 +919,21 @@ 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: encoded output will not fit!"); + OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: encoded output will not fit!"); return OC_STACK_ERROR; } @@ -988,6 +945,41 @@ 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. * @@ -1018,9 +1010,9 @@ static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, { 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) { @@ -1311,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) { @@ -1325,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_REPRESENTATION ; + 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; } @@ -1349,13 +1342,13 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { if (cbNode->requestUri) { - if (strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri) == 0) + if (0 == strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri)) { - type = PAYLOAD_TYPE_PLATFORM; + type = PAYLOAD_TYPE_REPRESENTATION; } - else if (strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri) == 0) + else if (0 == strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri)) { - type = PAYLOAD_TYPE_DEVICE; + type = PAYLOAD_TYPE_REPRESENTATION; } if (type == PAYLOAD_TYPE_INVALID) { @@ -1393,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; @@ -1423,8 +1417,11 @@ 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)); + } } } @@ -1587,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); @@ -1612,11 +1600,24 @@ 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); } + 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"); } @@ -1662,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) @@ -1686,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, @@ -1959,7 +1965,7 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque return; } serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum; - if (serverRequest.numRcvdVendorSpecificHeaderOptions) + if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options) { memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options, sizeof(CAHeaderOption_t)*tempNum); @@ -2071,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 //----------------------------------------------------------------------------- @@ -2276,9 +2246,9 @@ exit: if(result != OC_STACK_OK) { OIC_LOG(ERROR, TAG, "Stack initialization error"); + TerminateScheduleResourceList(); deleteAllResources(); CATerminate(); - TerminateScheduleResourceList(); stackState = OC_STACK_UNINITIALIZED; } return result; @@ -2301,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. @@ -2318,22 +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; } @@ -2533,7 +2504,15 @@ 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; @@ -3216,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, @@ -4115,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. @@ -4413,6 +4343,7 @@ void deleteResourceElements(OCResource *resource) OICFree(resource->uri); deleteResourceType(resource->rsrcType); deleteResourceInterface(resource->rsrcInterface); + OCDeleteResourceAttributes(resource->rsrcAttributes); } void deleteResourceType(OCResourceType *resourceType) @@ -4443,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; @@ -4721,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; @@ -4889,7 +4839,7 @@ OCStackResult OCUpdateResourceInsWithResponse(const char *requestUri, { OCRepPayload *rdPayload = (OCRepPayload *) response->payload; OCRepPayload **links = NULL; - size_t dimensions[MAX_REP_ARRAY_DEPTH]; + size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 }; if (OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, &links, dimensions)) { @@ -5103,6 +5053,21 @@ void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isCon { 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,