X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fstack%2Fsrc%2Focstack.c;h=c8c0da583ea58baacde021a3383a9b720bdb0df4;hb=41e04322a0b5684ed05e3b7968f44fc172a664a6;hp=ac14ccd2eac58fb894116e36b81306c103053870;hpb=945944cb3ff5efaccd03e8efa23199e58bd59ded;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index ac14ccd..c8c0da5 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 @@ -51,11 +52,14 @@ #include "logger.h" #include "ocserverrequest.h" #include "secureresourcemanager.h" +#include "psinterface.h" #include "doxmresource.h" #include "cacommon.h" #include "cainterface.h" #include "ocpayload.h" #include "ocpayloadcbor.h" +#include "cautilinterface.h" +#include "oicgroup.h" #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) #include "routingutility.h" @@ -78,9 +82,7 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#include "coap_time.h" -#include "utlist.h" -#include "pdu.h" +#include #ifdef HAVE_ARPA_INET_H #include @@ -117,9 +119,13 @@ 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; +static PresenceResource presenceResource = {0}; static uint8_t PresenceTimeOutSize = 0; static uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100}; #endif @@ -131,9 +137,13 @@ static bool gRASetInfo = false; #endif OCDeviceEntityHandler defaultDeviceHandler; void* defaultDeviceHandlerCallbackParameter = NULL; -static const char COAP_TCP[] = "coap+tcp:"; +static const char COAP_TCP_SCHEME[] = "coap+tcp:"; +static const char COAPS_TCP_SCHEME[] = "coaps+tcp:"; static const char CORESPEC[] = "core"; +CAAdapterStateChangedCB g_adapterHandler = NULL; +CAConnectionStateChangedCB g_connectionHandler = NULL; + //----------------------------------------------------------------------------- // Macros //----------------------------------------------------------------------------- @@ -312,15 +322,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. @@ -408,10 +409,54 @@ static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds); */ static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo); +/** + * default adapter state change callback method + * + * @param adapter CA network adapter type. + * @param enabled current adapter state. + */ +static void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled); + +/** + * default connection state change callback method + * + * @param info CAEndpoint which has address, port and etc. + * @param isConnected current connection state. + */ +static void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected); + +/** + * Register network monitoring callback. + * Network status changes are delivered these callback. + * @param adapterHandler Adapter state monitoring callback. + * @param connectionHandler Connection state monitoring callback. + */ +static void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler, + CAConnectionStateChangedCB connectionHandler); + //----------------------------------------------------------------------------- // Internal functions //----------------------------------------------------------------------------- +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 afterMilliSeconds) { coap_tick_t now; @@ -440,7 +485,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,7 +502,11 @@ void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out) out->flags = OCToCATransportFlags(in->flags); OICStrcpy(out->addr, sizeof(out->addr), in->addr); #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP) - memcpy(out->routeData, in->routeData, sizeof(out->routeData)); + /* This assert is to prevent accidental mismatch between address size macros defined in + * RI and CA and cause crash here. */ + OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE, + "Address size mismatch between RI and CA"); + memcpy(out->routeData, in->routeData, sizeof(in->routeData)); #endif out->port = in->port; out->ifindex = in->ifindex; @@ -633,7 +686,6 @@ static OCStackResult CAResultToOCStackResult(CAResult_t caResult) OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode) { OCStackResult ret = OC_STACK_ERROR; - switch(caCode) { case CA_CREATED: @@ -643,6 +695,8 @@ OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode) ret = OC_STACK_RESOURCE_DELETED; break; case CA_CHANGED: + ret = OC_STACK_RESOURCE_CHANGED; + break; case CA_CONTENT: case CA_VALID: ret = OC_STACK_OK; @@ -695,7 +749,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: @@ -704,6 +759,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; @@ -837,19 +895,105 @@ 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) +{ + VERIFY_NON_NULL(inputAddress, FATAL, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM); + + size_t inputLength = strnlen(inputAddress, outputSize); + + // inputSize includes the null terminator + size_t inputSize = inputLength + 1; + + if (inputSize > outputSize) + { + OIC_LOG_V(ERROR, TAG, + "encodeAddressForRFC6874 failed: " + "outputSize (%zu) < inputSize (%zu)", + outputSize, inputSize); + + return OC_STACK_ERROR; + } + + char* percentChar = strchr(inputAddress, '%'); + + // If there is no '%' character, then no change is required to the string. + if (NULL == percentChar) + { + OICStrcpy(outputAddress, outputSize, inputAddress); + return OC_STACK_OK; + } + + const char* addressPart = &inputAddress[0]; + const char* scopeIdPart = percentChar + 1; + + // Sanity check to make sure this string doesn't have more '%' characters + if (NULL != strchr(scopeIdPart, '%')) + { + return OC_STACK_ERROR; + } + + // 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!"); + 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"); + 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!"); + return OC_STACK_ERROR; + } + + // Restore the null terminator with an escaped '%' character, per RFC 6874 + OICStrcpy(outputAddress, scopeIdPart - addressPart, addressPart); + strcat(outputAddress, "%25"); + strcat(outputAddress, scopeIdPart); + + return OC_STACK_OK; +} + +/** * The cononical presence allows constructed URIs to be string compared. * * requestUri must be a char array of size CA_MAX_URI_LENGTH */ -static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resourceUri, - char *presenceUri) +static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, + char *presenceUri, bool isMulticast) { VERIFY_NON_NULL(endpoint , FATAL, OC_STACK_INVALID_PARAM); - VERIFY_NON_NULL(resourceUri, FATAL, OC_STACK_INVALID_PARAM); VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM); - CAEndpoint_t *ep = (CAEndpoint_t *)endpoint; + if (isMulticast) + { + OIC_LOG(DEBUG, TAG, "Make Multicast Presence URI"); + return snprintf(presenceUri, CA_MAX_URI_LENGTH, "%s", OC_RSRVD_PRESENCE_URI); + } + CAEndpoint_t *ep = (CAEndpoint_t *)endpoint; if (ep->adapter == CA_ADAPTER_IP) { if ((ep->flags & CA_IPV6) && !(ep->flags & CA_IPV4)) @@ -860,8 +1004,19 @@ static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resource } else { + char addressEncoded[CA_MAX_URI_LENGTH] = {0}; + + OCStackResult result = encodeAddressForRFC6874(addressEncoded, + sizeof(addressEncoded), + ep->addr); + + if (OC_STACK_OK != result) + { + return -1; + } + return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://[%s]:%u%s", - ep->addr, ep->port, OC_RSRVD_PRESENCE_URI); + addressEncoded, ep->port, OC_RSRVD_PRESENCE_URI); } } else @@ -906,39 +1061,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; @@ -968,6 +1090,36 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, maxAge = ((OCPresencePayload*)response.payload)->maxAge; } + // check for unicast presence + uriLen = FormCanonicalPresenceUri(endpoint, presenceUri, + responseInfo->isMulticast); + if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri)) + { + return OC_STACK_INVALID_URI; + } + OIC_LOG(ERROR, TAG, "check for unicast presence"); + cbNode = GetClientCB(NULL, 0, NULL, presenceUri); + if (cbNode) + { + presenceSubscribe = 1; + } + else + { + // check for multicast presence + OIC_LOG(ERROR, TAG, "check for multicast presence"); + cbNode = GetClientCB(NULL, 0, NULL, OC_RSRVD_PRESENCE_URI); + if (cbNode) + { + multicastPresenceSubscribe = 1; + } + } + + if (!presenceSubscribe && !multicastPresenceSubscribe) + { + OIC_LOG(ERROR, TAG, "Received a presence notification, but no callback, ignoring"); + goto exit; + } + if (presenceSubscribe) { if(cbNode->sequenceNumber == response.sequenceNumber) @@ -1018,70 +1170,31 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, ResetPresenceTTL(cbNode, maxAge); cbNode->sequenceNumber = response.sequenceNumber; - - // Ensure that a filter is actually applied. - if( resourceTypeName && cbNode->filterResourceType) - { - if(!findResourceType(cbNode->filterResourceType, resourceTypeName)) - { - goto exit; - } - } } } else { // This is the multicast case - OCMulticastNode* mcNode = NULL; - mcNode = GetMCPresenceNode(presenceUri); - - if(mcNode != NULL) - { - if(mcNode->nonce == response.sequenceNumber) - { - OIC_LOG(INFO, TAG, "No presence change (Multicast)"); - goto exit; - } - mcNode->nonce = response.sequenceNumber; - - if(maxAge == 0) - { - OIC_LOG(INFO, TAG, "Stopping presence"); - response.result = OC_STACK_PRESENCE_STOPPED; - } - } - else + OIC_LOG(INFO, TAG, "this is the multicast presence"); + if (0 == maxAge) { - char* uri = OICStrdup(presenceUri); - if (!uri) - { - OIC_LOG(INFO, TAG, - "No Memory for URI to store in the presence node"); - result = OC_STACK_NO_MEMORY; - goto exit; - } - - result = AddMCPresenceNode(&mcNode, uri, response.sequenceNumber); - if(result == OC_STACK_NO_MEMORY) - { - OIC_LOG(INFO, TAG, - "No Memory for Multicast Presence Node"); - OICFree(uri); - goto exit; - } - // presence node now owns uri + OIC_LOG(INFO, TAG, "Stopping presence"); + response.result = OC_STACK_PRESENCE_STOPPED; } + } - // Ensure that a filter is actually applied. - if(resourceTypeName && cbNode->filterResourceType) + // Ensure that a filter is actually applied. + if (resourceTypeName && cbNode->filterResourceType) + { + OIC_LOG_V(INFO, TAG, "find resource type : %s", resourceTypeName); + if(!findResourceType(cbNode->filterResourceType, resourceTypeName)) { - if(!findResourceType(cbNode->filterResourceType, resourceTypeName)) - { - goto exit; - } + goto exit; } } + OIC_LOG(INFO, TAG, "Callback for presence"); + cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response); if (cbResult == OC_STACK_DELETE_TRANSACTION) @@ -1152,7 +1265,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}}; - response.sequenceNumber = -1; + response.sequenceNumber = MAX_SEQUENCE_NUMBER + 1; CopyEndpointToDevAddr(endPoint, &response.devAddr); FixUpClientResponse(&response); response.resourceUri = responseInfo->info.resourceUri; @@ -1178,6 +1291,12 @@ 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; @@ -1194,10 +1313,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_KEEPALIVE_RESOURCE_URI) == 0) { type = PAYLOAD_TYPE_REPRESENTATION; } @@ -1216,25 +1335,26 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp cbNode->method == OC_REST_OBSERVE_ALL || cbNode->method == OC_REST_DELETE) { - char targetUri[MAX_URI_LENGTH]; - snprintf(targetUri, MAX_URI_LENGTH, "%s?rt=%s", OC_RSRVD_RD_URI, - OC_RSRVD_RESOURCE_TYPE_RDPUBLISH); - if (strcmp(targetUri, cbNode->requestUri) == 0) - { - type = PAYLOAD_TYPE_RD; - } - else if (strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri) == 0) - { - type = PAYLOAD_TYPE_PLATFORM; - } - else if (strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri) == 0) + if (cbNode->requestUri) { - type = PAYLOAD_TYPE_DEVICE; + if (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) + { + OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s", + cbNode->method, cbNode->requestUri); + type = PAYLOAD_TYPE_REPRESENTATION; + } } - if (type == PAYLOAD_TYPE_INVALID) + else { - OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s", - cbNode->method, cbNode->requestUri); + OIC_LOG(INFO, TAG, "No Request URI, PROXY URI"); type = PAYLOAD_TYPE_REPRESENTATION; } } @@ -1274,7 +1394,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; } @@ -1299,6 +1418,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp 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", @@ -1327,7 +1447,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp if(responseInfo->info.type == CA_MSG_CONFIRM) { SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY, - CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL); + CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES); } OCPayloadDestroy(response.payload); @@ -1377,7 +1497,7 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp { OIC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET"); SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY, - CA_MSG_RESET, 0, NULL, NULL, 0, NULL); + CA_MSG_RESET, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES); } } @@ -1399,8 +1519,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) @@ -1477,7 +1595,6 @@ void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *er response.result = CAResultToOCStackResult(errorInfo->result); cbNode->callBack(cbNode->context, cbNode->handle, &response); - FindAndDeleteClientCB(cbNode); } OIC_LOG(INFO, TAG, "Exit HandleCAErrorResponse"); @@ -1491,7 +1608,8 @@ void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *er OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID, const CAResponseResult_t responseResult, const CAMessageType_t type, const uint8_t numOptions, const CAHeaderOption_t *options, - CAToken_t token, uint8_t tokenLength, const char *resourceUri) + CAToken_t token, uint8_t tokenLength, const char *resourceUri, + CADataType_t dataType) { OIC_LOG(DEBUG, TAG, "Entering SendDirectStackResponse"); CAResponseInfo_t respInfo = { @@ -1515,6 +1633,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. @@ -1652,15 +1771,6 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque { OIC_LOG(DEBUG, TAG, "Enter OCHandleRequests"); -#ifdef TCP_ADAPTER - if (requestInfo->info.resourceUri && - strcmp(requestInfo->info.resourceUri, KEEPALIVE_RESOURCE_URI) == 0) - { - HandleKeepAliveRequest(endPoint, requestInfo); - return; - } -#endif - OCStackResult requestResult = OC_STACK_ERROR; if(myStackMode == OC_CLIENT) @@ -1750,7 +1860,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; } @@ -1769,7 +1880,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; } @@ -1820,7 +1932,8 @@ 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; @@ -1840,10 +1953,16 @@ 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); } } - else if(requestResult != OC_STACK_OK) + if (requestResult == OC_STACK_RESOURCE_ERROR + && serverRequest.observationOption == OC_OBSERVE_REGISTER) + { + OIC_LOG_V(ERROR, TAG, "Observe Registration failed due to resource error"); + } + else if(!OCResultToSuccess(requestResult)) { OIC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult); @@ -1853,7 +1972,8 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse, requestInfo->info.type, requestInfo->info.numOptions, requestInfo->info.options, requestInfo->info.token, - requestInfo->info.tokenLength, requestInfo->info.resourceUri); + requestInfo->info.tokenLength, requestInfo->info.resourceUri, + CA_RESPONSE_DATA); } // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest. // The token is copied in there, and is thus still owned by this function. @@ -2055,12 +2175,19 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag defaultDeviceHandler = NULL; defaultDeviceHandlerCallbackParameter = NULL; + result = InitializeScheduleResourceList(); + VERIFY_SUCCESS(result, OC_STACK_OK); + result = CAResultToOCResult(CAInitialize()); VERIFY_SUCCESS(result, OC_STACK_OK); result = CAResultToOCResult(OCSelectNetwork()); VERIFY_SUCCESS(result, OC_STACK_OK); + result = CAResultToOCResult(CARegisterNetworkMonitorHandler( + OCDefaultAdapterStateChangedHandler, OCDefaultConnectionStateChangedHandler)); + VERIFY_SUCCESS(result, OC_STACK_OK); + switch (myStackMode) { case OC_CLIENT: @@ -2131,6 +2258,7 @@ exit: OIC_LOG(ERROR, TAG, "Stack initialization error"); deleteAllResources(); CATerminate(); + TerminateScheduleResourceList(); stackState = OC_STACK_UNINITIALIZED; } return result; @@ -2175,6 +2303,7 @@ OCStackResult OCStop() DeleteDeviceInfo(); DeletePlatformInfo(); CATerminate(); + TerminateScheduleResourceList(); // Remove all observers DeleteObserverList(); // Remove all the client callbacks @@ -2236,6 +2365,8 @@ CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos) * optionally one of * CoAP over UDP prefix "coap://" * CoAP over TCP prefix "coap+tcp://" + * CoAP over DTLS prefix "coaps://" + * CoAP over TLS prefix "coaps+tcp://" * optionally one of * IPv6 address "[1234::5678]" * IPv4 address "192.168.1.1" @@ -2290,7 +2421,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; } @@ -2385,7 +2517,7 @@ static OCStackResult ParseRequestUri(const char *fullUri, 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); } @@ -2451,11 +2583,12 @@ error: } static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint, - char *resourceUri, char **requestUri) + char **requestUri, + bool isMulticast) { char uri[CA_MAX_URI_LENGTH]; - FormCanonicalPresenceUri(endpoint, resourceUri, uri); + FormCanonicalPresenceUri(endpoint, uri, isMulticast); *requestUri = OICStrdup(uri); if (!*requestUri) @@ -2485,7 +2618,6 @@ OCStackResult OCDoResource(OCDoHandle *handle, // Validate input parameters VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK); VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK); - VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI); OCStackResult result = OC_STACK_ERROR; CAResult_t caResult; @@ -2511,11 +2643,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) { - OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", 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(ERROR, TAG, "Request doesn't contain RequestURI/Proxy URI"); goto exit; } @@ -2524,7 +2663,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: @@ -2538,6 +2676,9 @@ OCStackResult OCDoResource(OCDoHandle *handle, break; case OC_REST_DISCOVER: qos = OC_LOW_QOS; +#ifdef WITH_PRESENCE + case OC_REST_PRESENCE: +#endif if (destination || devAddr) { requestInfo.isMulticast = false; @@ -2549,16 +2690,11 @@ OCStackResult OCDoResource(OCDoHandle *handle, destination = &tmpDevAddr; requestInfo.isMulticast = true; } - // CA_DISCOVER will become GET and isMulticast + // 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; -#ifdef WITH_PRESENCE - case OC_REST_PRESENCE: - // Replacing method type with GET because "presence" - // is a stack layer only implementation. - requestInfo.method = CA_GET; - break; -#endif default: result = OC_STACK_INVALID_METHOD; goto exit; @@ -2602,7 +2738,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)) { @@ -2648,7 +2783,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; @@ -2657,10 +2793,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); @@ -2673,6 +2816,21 @@ OCStackResult OCDoResource(OCDoHandle *handle, resourceUri = NULL; // Client CB list entry now owns it resourceType = NULL; // Client CB list entry now owns it +#ifdef WITH_PRESENCE + if (method == OC_REST_PRESENCE) + { + if (requestInfo.isMulticast) + { + OIC_LOG(ERROR, TAG, "AddClientCB for presence done."); + goto exit; + } + else + { + OIC_LOG(ERROR, TAG, "this subscribe presence is unicast."); + } + } +#endif + // send request result = OCSendRequest(&endpoint, &requestInfo); if (OC_STACK_OK != result) @@ -2954,6 +3112,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), @@ -3005,6 +3164,7 @@ OCStackResult OCStartPresence(const uint32_t ttl) OCStackResult OCStopPresence() { + OIC_LOG(INFO, TAG, "Entering OCStopPresence"); OCStackResult result = OC_STACK_ERROR; if(presenceResource.handle) @@ -3076,8 +3236,6 @@ OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo) { return OC_STACK_INVALID_PARAM; } - deleteResourceType(resource->rsrcType); - resource->rsrcType = NULL; while (type) { @@ -3118,15 +3276,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; @@ -3805,6 +3973,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; @@ -3828,6 +3997,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; @@ -4047,6 +4217,7 @@ OCStackResult initResources() if(result == OC_STACK_OK) { + CreateResetProfile(); result = OCCreateResource(&deviceResource, OC_RSRVD_RESOURCE_TYPE_DEVICE, OC_RSRVD_INTERFACE_DEFAULT, @@ -4128,6 +4299,11 @@ void deleteAllResources() #endif // WITH_PRESENCE pointer = temp; } + memset(&platformResource, 0, sizeof(platformResource)); + memset(&deviceResource, 0, sizeof(deviceResource)); +#ifdef MQ_BROKER + memset(&brokerResource, 0, sizeof(brokerResource)); +#endif SRMDeInitSecureResources(); @@ -4135,6 +4311,7 @@ void deleteAllResources() // Ensure that the last resource to be deleted is the presence resource. This allows for all // presence notification attributed to their deletion to be processed. deleteResource((OCResource *) presenceResource.handle); + memset(&presenceResource, 0, sizeof(presenceResource)); #endif // WITH_PRESENCE } @@ -4321,6 +4498,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) @@ -4357,7 +4535,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); @@ -4559,20 +4738,20 @@ CAResult_t OCSelectNetwork() }; int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]); - for(int i = 0; iins = ins; + + return OC_STACK_OK; +} + +OCResourceHandle OCGetResourceHandleAtUri(const char *uri) +{ + if (!uri) + { + OIC_LOG(ERROR, TAG, "Resource uri is NULL"); + return NULL; + } + + OCResource *pointer = headResource; + + while (pointer) + { + if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0) + { + OIC_LOG_V(DEBUG, TAG, "Found Resource %s", uri); + return pointer; + } + pointer = pointer->next; + } + return NULL; +} + +OCStackResult OCGetResourceIns(OCResourceHandle handle, uint8_t *ins) +{ + OCResource *resource = NULL; + + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(ins, ERROR, OC_STACK_INVALID_PARAM); + + resource = findResource((OCResource *) handle); + if (resource) + { + *ins = resource->ins; + return OC_STACK_OK; + } + return OC_STACK_ERROR; +} + +OCStackResult OCSetHeaderOption(OCHeaderOption* ocHdrOpt, size_t* numOptions, uint16_t optionID, + void* optionData, size_t optionDataLength) +{ + if (!ocHdrOpt) + { + OIC_LOG (INFO, TAG, "Header options are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!optionData) + { + OIC_LOG (INFO, TAG, "optionData are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!numOptions) + { + OIC_LOG (INFO, TAG, "numOptions is NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (*numOptions >= MAX_HEADER_OPTIONS) + { + OIC_LOG (INFO, TAG, "Exceeding MAX_HEADER_OPTIONS"); + return OC_STACK_NO_MEMORY; + } + + ocHdrOpt += *numOptions; + ocHdrOpt->protocolID = OC_COAP_ID; + ocHdrOpt->optionID = optionID; + ocHdrOpt->optionLength = + optionDataLength < MAX_HEADER_OPTION_DATA_LENGTH ? + optionDataLength : MAX_HEADER_OPTION_DATA_LENGTH; + memcpy(ocHdrOpt->optionData, (const void*) optionData, ocHdrOpt->optionLength); + *numOptions += 1; + + return OC_STACK_OK; +} +OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, uint16_t optionID, + void* optionData, size_t optionDataLength, uint16_t* receivedDataLength) +{ + if (!ocHdrOpt || !numOptions) + { + OIC_LOG (INFO, TAG, "No options present"); + return OC_STACK_OK; + } + + if (!optionData) + { + OIC_LOG (INFO, TAG, "optionData are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!receivedDataLength) + { + OIC_LOG (INFO, TAG, "receivedDataLength is NULL"); + return OC_STACK_INVALID_PARAM; + } + + for (uint8_t i = 0; i < numOptions; i++) + { + if (ocHdrOpt[i].optionID == optionID) + { + if (optionDataLength >= ocHdrOpt->optionLength) + { + memcpy(optionData, ocHdrOpt->optionData, ocHdrOpt->optionLength); + *receivedDataLength = ocHdrOpt->optionLength; + return OC_STACK_OK; + } + else + { + OIC_LOG (ERROR, TAG, "optionDataLength is less than the length of received data"); + return OC_STACK_ERROR; + } + } + } + return OC_STACK_OK; +} +#endif + +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); + } +} + +void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler, + CAConnectionStateChangedCB connectionHandler) +{ + OIC_LOG(DEBUG, TAG, "OCSetNetworkMonitorHandler"); + g_adapterHandler = adapterHandler; + g_connectionHandler = connectionHandler; +} + +OCStackResult OCGetDeviceId(OCUUIdentity *deviceId) +{ + OicUuid_t oicUuid; + OCStackResult ret; + + 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; + OIC_LOG(ERROR, TAG, "Set deviceId DOXM"); + + 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; +}