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.
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
{
{
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,
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");
}
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;
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,
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");
}
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:
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;
}
}
-/**
- * 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);
if (inputSize > outputSize)
{
OIC_LOG_V(ERROR, TAG,
- "encodeAddressForRFC6874 failed: "
+ "OCEncodeAddressForRFC6874 failed: "
"outputSize (%zu) < inputSize (%zu)",
outputSize, inputSize);
// 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;
}
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.
*
{
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)
{
#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)
{
#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;
}
{
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)
{
{
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;
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));
+ }
}
}
*/
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);
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");
}
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)
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,
return;
}
serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
- if (serverRequest.numRcvdVendorSpecificHeaderOptions)
+ if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options)
{
memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
sizeof(CAHeaderOption_t)*tempNum);
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
//-----------------------------------------------------------------------------
if(result != OC_STACK_OK)
{
OIC_LOG(ERROR, TAG, "Stack initialization error");
+ TerminateScheduleResourceList();
deleteAllResources();
CATerminate();
- TerminateScheduleResourceList();
stackState = OC_STACK_UNINITIALIZED;
}
return result;
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.
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;
}
{
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 (method == OC_REST_PRESENCE)
{
OIC_LOG(ERROR, TAG, "AddClientCB for presence done.");
+
+ if (handle)
+ {
+ *handle = resHandle;
+ }
+
goto exit;
}
#endif
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,
// 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.
OICFree(resource->uri);
deleteResourceType(resource->rsrcType);
deleteResourceInterface(resource->rsrcInterface);
+ OCDeleteResourceAttributes(resource->rsrcAttributes);
}
void deleteResourceType(OCResourceType *resourceType)
}
}
+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;
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;
{
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))
{
{
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,