******************************************************************/
#include "oickeepalive.h"
+#include "oickeepaliveinternal.h"
#include <stdio.h>
#include <string.h>
#include "oic_string.h"
#include "oic_time.h"
#include "ocrandom.h"
+#include "octhread.h"
#include "uarraylist.h"
#include "ocstackinternal.h"
#include "ocpayloadcbor.h"
#include "ocpayload.h"
#include "ocresourcehandler.h"
#include "logger.h"
+#include "cautilinterface.h"
+#include <coap/utlist.h>
/**
* Logging tag for module name.
#define KEEPALIVE_RESPONSE_TIMEOUT_SEC 60
/**
- * The Min time interval value. (2 minutes)
- * start from 2 minutes and increases in multiples of 2 up to a maximum of 64minutes.
- */
-#define KEEPALIVE_MIN_INTERVAL 2
-
-/**
- * The Max time interval value. (64 minutes)
- */
-#define KEEPALIVE_MAX_INTERVAL 64
-
-/**
- * Default counts of interval value.
- */
-#define DEFAULT_INTERVAL_COUNT 6
-
-/**
* KeepAlive key to parser Payload Table.
*/
static const char INTERVAL[] = "in";
static const char INTERVAL_ARRAY[] = "inarray";
/**
- * To check if KeepAlive is initialized.
- */
-static bool g_isKeepAliveInitialized = false;
-
-/**
* Pointer to handle of the newly created KeepAlive resource.
*/
static OCResourceHandle g_keepAliveHandle = NULL;
/**
* KeepAlive table which holds connection interval.
*/
-static u_arraylist_t *g_keepAliveConnectionTable = NULL;
+static struct KeepAliveEntry_t *g_keepAliveConnectionTable = NULL;
+
+/**
+ * Mutex to synchronize device object list.
+ */
+static oc_mutex g_mutexObjectList = NULL;
/**
* KeepAlive table entries.
*/
-typedef struct
+typedef struct KeepAliveEntry_t
{
OCMode mode; /**< host Mode of Operation. */
CAEndpoint_t remoteAddr; /**< destination Address. */
- uint32_t interval; /**< time interval for KeepAlive. in seconds.*/
+ int64_t interval; /**< time interval for KeepAlive. in seconds.*/
int32_t currIndex; /**< current interval value index. */
- size_t intervalSize; /**< total interval counts. */
- int64_t *intervalInfo; /**< interval values for KeepAlive. */
bool sentPingMsg; /**< if oic client already sent ping message. */
uint64_t timeStamp; /**< last sent or received ping message. in microseconds. */
+ OCDoHandle handle; /**< Invocation handle tied to original call to OCDoResource().*/
+ struct KeepAliveEntry_t *next; /**< Linked list; for multiple keepalive info list.*/
} KeepAliveEntry_t;
/**
* Send disconnect message to remove connection.
*/
-static OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry);
-
-/**
- * Send ping message to remote endpoint.
- */
-static OCStackResult SendPingMessage(KeepAliveEntry_t *entry);
-
-/**
- * Increase interval value to send next ping message.
- */
-static void IncreaseInterval(KeepAliveEntry_t *entry);
-
-/**
- * Ping Message callback registered with RI for KeepAlive Request.
- */
-static OCStackApplicationResult PingRequestCallback(void* ctx, OCDoHandle handle,
- OCClientResponse * clientResponse);
+static OCStackResult OCSendDisconnectMessage(const KeepAliveEntry_t *entry);
/**
* This function creates KeepAlive resource.
* @return ::OC_STACK_OK or Appropriate error code.
*/
-static OCStackResult CreateKeepAliveResource();
+static OCStackResult OCCreateKeepAliveResource();
/**
* This function deletes KeepAlive resource.
* @return ::OC_STACK_OK or Appropriate error code.
*/
-static OCStackResult DeleteKeepAliveResource();
+static OCStackResult OCDeleteKeepAliveResource();
/**
* API to handle the GET request received for a KeepAlive resource.
- * @param[in] endPoint RemoteEndpoint which sent the packet.
- * @param[in] requestInfo Received coap packet.
+ * @param[in] request Request Received.
+ * @param[in] resource Resource handle used for sending the response.
* @return ::OC_STACK_OK or Appropriate error code.
*/
-static OCStackResult HandleKeepAliveGETRequest(const CAEndpoint_t* endPoint,
- const CARequestInfo_t* requestInfo);
+static OCEntityHandlerResult OCHandleKeepAliveGETRequest(OCServerRequest *request,
+ const OCResource *resource);
/**
* API to handle the PUT request received for a KeepAlive resource.
- * @param[in] endPoint RemoteEndpoint which sent the packet.
- * @param[in] requestInfo Received coap packet.
+ * @param[in] request Request Received.
+ * @param[in] resource Resource handle used for sending the response.
* @return ::OC_STACK_OK or Appropriate error code.
*/
-static OCStackResult HandleKeepAlivePUTRequest(const CAEndpoint_t* endPoint,
- const CARequestInfo_t* requestInfo);
+static OCEntityHandlerResult OCHandleKeepAlivePOSTRequest(OCServerRequest *request,
+ const OCResource *resource);
/**
- * API to handle the Response payload.
- * @param[in] endpoint RemoteEndpoint which sent the packet.
- * @param[in] responseCode Received reseponse code.
- * @param[in] respPayload Response payload.
- * @return ::OC_STACK_OK or Appropriate error code.
- */
-OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
- OCStackResult responseCode,
- const OCRepPayload *respPayload);
-/**
* Gets keepalive entry.
* @param[in] endpoint Remote Endpoint information (like ipaddress,
* port, reference uri and transport type) to
* which the ping message has to be sent.
- * @param[out] index index of array list.
* @return KeepAlive entry to send ping message.
*/
-static KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *index);
+static KeepAliveEntry_t *OCGetEntryFromEndpoint(const CAEndpoint_t *endpoint);
/**
* Add keepalive entry.
* @param[in] endpoint Remote Endpoint information (like ipaddress,
* port, reference uri and transport type).
* @param[in] mode Whether it is OIC Server or OIC Client.
- * @param[in] intervalArray Received interval values from cloud server.
+ * @param[in] interval Sent interval value to remote device.
* @return The KeepAlive entry added in KeepAlive Table.
*/
-KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
- int64_t *intervalArray);
+KeepAliveEntry_t *OCAddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
+ int64_t interval);
/**
* Remove keepalive entry.
* port, reference uri and transport type).
* @return The KeepAlive entry removed in KeepAlive Table.
*/
-static OCStackResult RemoveKeepAliveEntry(const CAEndpoint_t *endpoint);
+static OCStackResult OCRemoveKeepAliveEntry(const CAEndpoint_t *endpoint);
+
+/**
+ * Create KeepAlive paylaod to send message.
+ * @param[in] interval The interval value to be sent.
+ * @return Created representation payload.
+ */
+static OCRepPayload *OCCreateKeepAlivePayload(int64_t interval);
+
+/**
+ * Send response to remote device.
+ * @param[in] request Request Received.
+ * @param[in] result Result to be sent.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+static OCStackResult OCSendKeepAliveResponse(OCServerRequest *request,
+ OCEntityHandlerResult result);
+
+/**
+ * Add resource type name to payload for GET request.
+ * @param[in] payload Pointer to the payload to which byte string needs to be added.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+static OCStackResult OCAddResourceTypeNameToPayload(OCRepPayload *payload);
+
+/**
+ * Add resource interface name to payload for GET request.
+ * @param[in] payload Pointer to the payload to which byte string needs to be added.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+static OCStackResult OCAddResourceInterfaceNameToPayload(OCRepPayload *payload);
-OCStackResult InitializeKeepAlive(OCMode mode)
+OCStackResult OCInitializeKeepAlive(OCMode mode)
{
- OIC_LOG(DEBUG, TAG, "InitializeKeepAlive IN");
- if (g_isKeepAliveInitialized)
+ OIC_LOG(DEBUG, TAG, "OCInitializeKeepAlive IN");
+
+ if (!g_mutexObjectList)
{
- OIC_LOG(DEBUG, TAG, "KeepAlive already initialized");
- return OC_STACK_OK;
+ g_mutexObjectList = oc_mutex_new();
+ if (!g_mutexObjectList)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create mutex!");
+ return OC_STACK_ERROR;
+ }
}
if (OC_CLIENT != mode)
{
// Create the KeepAlive Resource[/oic/ping].
- OCStackResult result = CreateKeepAliveResource();
+ OCStackResult result = OCCreateKeepAliveResource();
if (OC_STACK_OK != result)
{
- OIC_LOG_V(ERROR, TAG, "CreateKeepAliveResource failed[%d]", result);
+ OIC_LOG_V(ERROR, TAG, "OCCreateKeepAliveResource failed[%d]", result);
return result;
}
}
- if (!g_keepAliveConnectionTable)
+ OIC_LOG(DEBUG, TAG, "OCInitializeKeepAlive OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult OCTerminateKeepAlive(OCMode mode)
+{
+ OIC_LOG(DEBUG, TAG, "OCTerminateKeepAlive IN");
+
+ if (g_mutexObjectList)
{
- g_keepAliveConnectionTable = u_arraylist_create();
- if (NULL == g_keepAliveConnectionTable)
+ oc_mutex_free(g_mutexObjectList);
+ g_mutexObjectList = NULL;
+ }
+
+ if (OC_CLIENT != mode)
+ {
+ // Delete the KeepAlive Resource[/oic/ping].
+ OCStackResult result = OCDeleteKeepAliveResource();
+ if (OC_STACK_OK != result)
{
- OIC_LOG(ERROR, TAG, "Creating KeepAlive Table failed");
- TerminateKeepAlive(mode);
- return OC_STACK_ERROR;
+ OIC_LOG_V(ERROR, TAG, "OCDeleteKeepAliveResource failed[%d]", result);
+ return result;
}
}
- g_isKeepAliveInitialized = true;
-
- OIC_LOG(DEBUG, TAG, "InitializeKeepAlive OUT");
+ OIC_LOG(DEBUG, TAG, "OCTerminateKeepAlive OUT");
return OC_STACK_OK;
}
-OCStackResult TerminateKeepAlive(OCMode mode)
+OCStackResult OCFindKeepAliveResource(OCDoHandle *handle, const char *remoteAddr,
+ OCCallbackData *cbData)
{
- OIC_LOG(DEBUG, TAG, "TerminateKeepAlive IN");
- if (!g_isKeepAliveInitialized)
+ // Validate input parameters
+ VERIFY_NON_NULL(remoteAddr, FATAL, OC_STACK_INVALID_CALLBACK);
+ VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
+ VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
+
+ // Send discover message to find ping resource
+ char requestUri[MAX_QUERY_LENGTH] = { 0 };
+ snprintf(requestUri, MAX_QUERY_LENGTH, "%s%s", remoteAddr, KEEPALIVE_RESOURCE_URI);
+ OCStackResult result = OCDoResource(handle, OC_REST_DISCOVER, requestUri,
+ NULL, NULL, CT_ADAPTER_TCP, OC_HIGH_QOS,
+ cbData, NULL, 0);
+ if (OC_STACK_OK != result)
{
- OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
+ OIC_LOG(ERROR, TAG, "OCDoResource has failed");
+ }
+ return result;
+}
+
+OCStackResult OCSendKeepAliveRequest(OCDoHandle *handle, const char *remoteAddr,
+ OCPayload *payload, OCCallbackData *cbData)
+{
+ VERIFY_NON_NULL(remoteAddr, FATAL, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
+ VERIFY_NON_NULL(payload, FATAL, OC_STACK_INVALID_CALLBACK);
+
+ OIC_LOG(DEBUG, TAG, "SendKeepAliveRequest IN");
+
+ // Parse the remote device address to send ping message.
+ OCDevAddr *devAddr = NULL;
+ char requestUri[MAX_QUERY_LENGTH] = { 0 };
+ snprintf(requestUri, MAX_QUERY_LENGTH, "%s%s", remoteAddr, KEEPALIVE_RESOURCE_URI);
+ OCStackResult result = ParseRequestUri(requestUri, OC_DEFAULT_ADAPTER, OC_DEFAULT_FLAGS,
+ &devAddr, NULL, NULL);
+ if (result != OC_STACK_OK)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", remoteAddr);
return OC_STACK_ERROR;
}
- if (OC_CLIENT != mode)
+ VERIFY_NON_NULL(devAddr, FATAL, OC_STACK_INVALID_PARAM);
+
+ if (!(devAddr->adapter & OC_ADAPTER_TCP))
{
- // Delete the KeepAlive Resource[/oic/ping].
- OCStackResult result = DeleteKeepAliveResource();
- if (OC_STACK_OK != result)
+ OIC_LOG_V(DEBUG, TAG, "Not supported connectivity type");
+ OICFree(devAddr);
+ return OC_STACK_ERROR;
+ }
+
+ // Get entry from KeepAlive table.
+ CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
+ CopyDevAddrToEndpoint(devAddr, &endpoint);
+
+ oc_mutex_lock(g_mutexObjectList);
+ KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(&endpoint);
+ if (!entry)
+ {
+ OIC_LOG(DEBUG, TAG, "There is no connection info in KeepAlive table");
+
+ entry = OCAddKeepAliveEntry(&endpoint, OC_CLIENT, 0);
+ if (!entry)
{
- OIC_LOG_V(ERROR, TAG, "DeleteKeepAliveResource failed[%d]", result);
- return result;
+ oc_mutex_unlock(g_mutexObjectList);
+ OIC_LOG(ERROR, TAG, "Failed to add new KeepAlive entry");
+ OICFree(devAddr);
+ return OC_STACK_ERROR;
}
}
- if (NULL != g_keepAliveConnectionTable)
+ // Get "in" value from payload.
+ int64_t interval = 0;
+ bool findValue = OCRepPayloadGetPropInt((OCRepPayload *) payload, INTERVAL, &interval);
+ if (findValue && interval)
{
- u_arraylist_destroy(g_keepAliveConnectionTable);
- g_keepAliveConnectionTable = NULL;
+ if (entry->sentPingMsg)
+ {
+ oc_mutex_unlock(g_mutexObjectList);
+ OIC_LOG(ERROR, TAG, "Already sent a ping request to remote device");
+ OICFree(devAddr);
+ return OC_STACK_ERROR;
+ }
+ entry->interval = interval;
+ OIC_LOG_V(DEBUG, TAG, "Send ping message with interval [%" PRId64 "]", entry->interval);
}
- g_isKeepAliveInitialized = false;
+ // Get "inarray" value from payload.
+ int64_t *inArray = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ OCRepPayloadGetIntArray((OCRepPayload *) payload, INTERVAL_ARRAY, &inArray, dimensions);
+ if (inArray)
+ {
+ uint8_t len = 0;
+ char newArray[MAX_URI_LENGTH] = { 0 };
+ size_t inArraySize = calcDimTotal(dimensions);
+ for (size_t i = 0; i < inArraySize; i++)
+ {
+ len += snprintf(newArray + len, MAX_URI_LENGTH, "% " PRId64, inArray[i]);
+ }
+ OICFree(inArray);
+ OIC_LOG_V(DEBUG, TAG, "Send update interval message with inarray [ %s]", newArray);
+ }
+
+ // Send keepalive message.
+ result = OCDoResource(&entry->handle, OC_REST_POST, KEEPALIVE_RESOURCE_URI,
+ devAddr, (OCPayload *) payload, CT_ADAPTER_TCP,
+ OC_HIGH_QOS, cbData, NULL, 0);
+ if (OC_STACK_OK != result)
+ {
+ oc_mutex_unlock(g_mutexObjectList);
+ OIC_LOG(ERROR, TAG, "OCDoResource has failed");
+ OICFree(devAddr);
+ return result;
+ }
+
+ // Update timeStamp with time sent ping message for next ping message.
+ entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
+ entry->sentPingMsg = true;
+ if (handle)
+ {
+ *handle = entry->handle;
+ }
+
+ oc_mutex_unlock(g_mutexObjectList);
+ OIC_LOG(DEBUG, TAG, "SendKeepAliveRequest OUT");
+ OICFree(devAddr);
+ return result;
+}
- OIC_LOG(DEBUG, TAG, "TerminateKeepAlive OUT");
+OCStackResult OCHandleKeepAliveResponse(const CAEndpoint_t *endPoint, const OCPayload *payload)
+{
+ (void) payload;
+ VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
+
+ // Receive response message about post /oic/ping request.
+ OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveResponse IN");
+
+ // Get entry from KeepAlive table.
+ oc_mutex_lock(g_mutexObjectList);
+ KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(endPoint);
+ if (entry)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Received response about interval [%" PRId64 "]", entry->interval);
+
+ // Set sentPingMsg values with false.
+ entry->sentPingMsg = false;
+ entry->handle = NULL;
+ }
+
+ oc_mutex_unlock(g_mutexObjectList);
+ OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveResponse OUT");
return OC_STACK_OK;
}
-OCStackResult CreateKeepAliveResource()
+OCStackResult OCCreateKeepAliveResource()
{
- OIC_LOG(DEBUG, TAG, "InitKeepAliveResource IN");
+ OIC_LOG(DEBUG, TAG, "OCCreateKeepAliveResource IN");
// Create a KeepAlive resource
OCStackResult result = OCCreateResource(&g_keepAliveHandle,
KEEPALIVE_RESOURCE_TYPE_NAME,
- KEEPALIVE_RESOURCE_INTF_NAME,
+ OC_RSRVD_INTERFACE_DEFAULT,
KEEPALIVE_RESOURCE_URI,
NULL,
NULL,
- OC_DISCOVERABLE);
+ OC_RES_PROP_NONE);
+ if (OC_STACK_OK == result)
+ {
+ result = BindResourceInterfaceToResource((OCResource *) g_keepAliveHandle,
+ KEEPALIVE_RESOURCE_INTF_NAME);
+ }
if (OC_STACK_OK != result)
{
OIC_LOG_V(ERROR, TAG, "Create resource for KeepAlive failed[%d]", result);
}
- OIC_LOG(DEBUG, TAG, "InitKeepAliveResource OUT");
+ OIC_LOG(DEBUG, TAG, "OCCreateKeepAliveResource OUT");
return result;
}
-OCStackResult DeleteKeepAliveResource()
+OCStackResult OCDeleteKeepAliveResource()
{
- OIC_LOG(DEBUG, TAG, "DeleteKeepAliveResource IN");
+ OIC_LOG(DEBUG, TAG, "OCDeleteKeepAliveResource IN");
// Create a KeepAlive resource
OCStackResult result = OCDeleteResource(g_keepAliveHandle);
OIC_LOG_V(ERROR, TAG, "Delete resource for KeepAlive failed[%d]", result);
}
- OIC_LOG(DEBUG, TAG, "DeleteKeepAliveResource OUT");
+ OIC_LOG(DEBUG, TAG, "OCDeleteKeepAliveResource OUT");
return result;
}
-OCStackResult HandleKeepAliveRequest(const CAEndpoint_t* endPoint,
- const CARequestInfo_t* requestInfo)
+OCStackResult OCHandleKeepAliveRequest(OCServerRequest *request,
+ const OCResource *resource)
{
- VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
- VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
- OIC_LOG(DEBUG, TAG, "HandleKeepAliveRequest IN");
+ OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveRequest IN");
- OCStackResult result = OC_STACK_OK;
- if (CA_PUT == requestInfo->method)
+ OCEntityHandlerResult result = OC_EH_ERROR;
+ if (OC_REST_GET == request->method)
+ {
+ switch ((OCObserveAction)request->observationOption)
+ {
+ case OC_OBSERVE_NO_OPTION:
+ case OC_OBSERVE_REGISTER:
+ case OC_OBSERVE_DEREGISTER:
+ OIC_LOG(DEBUG, TAG, "Received GET request");
+ result = OCHandleKeepAliveGETRequest(request, resource);
+ break;
+ default:
+ OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
+ result = OC_EH_UNAUTHORIZED_REQ;
+ }
+ }
+ else if (OC_REST_PUT == request->method || OC_REST_POST == request->method)
{
- result = HandleKeepAlivePUTRequest(endPoint, requestInfo);
+ OIC_LOG(DEBUG, TAG, "Received PUT/POST request");
+ result = OCHandleKeepAlivePOSTRequest(request, resource);
}
- else if (CA_GET == requestInfo->method)
+ else
{
- result = HandleKeepAliveGETRequest(endPoint, requestInfo);
+ OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
+ result = OC_EH_UNAUTHORIZED_REQ;
}
- OIC_LOG(DEBUG, TAG, "HandleKeepAliveRequest OUT");
- return result;
+ OCStackResult ret = OCSendKeepAliveResponse(request, result);
+ if (OC_STACK_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "SendKeepAliveResponse failed with result %u", ret);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveRequest OUT");
+ return ret;
}
-OCStackResult HandleKeepAliveGETRequest(const CAEndpoint_t* endPoint,
- const CARequestInfo_t* requestInfo)
+OCStackResult OCSendKeepAliveResponse(OCServerRequest *request,
+ OCEntityHandlerResult result)
{
- VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
- VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
-
- OIC_LOG_V(DEBUG, TAG, "Find Ping resource [%s]", requestInfo->info.resourceUri);
+ VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
- CAResponseResult_t result = CA_CONTENT;
- OCResource *resourcePtr = FindResourceByUri(requestInfo->info.resourceUri);
- if (!resourcePtr)
- {
- // Resource URL not specified
- OIC_LOG_V(DEBUG, TAG, "There is no Ping resource [%s]", requestInfo->info.resourceUri);
- result = CA_NOT_FOUND;
- }
+ OIC_LOG_V(DEBUG, TAG, "Send KeepAlive response with entity result[%d]", result);
- SendDirectStackResponse(endPoint, requestInfo->info.messageId, result, requestInfo->info.type,
- requestInfo->info.numOptions, requestInfo->info.options,
- requestInfo->info.token, requestInfo->info.tokenLength,
- requestInfo->info.resourceUri);
+ // Convert OCDevAddr to CAEndpoint_t.
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
+ CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
- return OC_STACK_OK;
-}
+ oc_mutex_lock(g_mutexObjectList);
+ KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(&endpoint);
+ int64_t interval = (entry) ? entry->interval : 0;
+ oc_mutex_unlock(g_mutexObjectList);
-OCStackResult HandleKeepAlivePUTRequest(const CAEndpoint_t* endPoint,
- const CARequestInfo_t* requestInfo)
-{
- VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
- VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
+ // Create KeepAlive payload to send response message.
+ OCRepPayload *payload = OCCreateKeepAlivePayload(interval);
- // Get entry from KeepAlive table.
- uint32_t index = 0;
- KeepAliveEntry_t *entry = GetEntryFromEndpoint(endPoint, &index);
- if (!entry)
+ // Add resource type/interface name to payload for GET request.
+ if (OC_REST_GET == request->method && OC_EH_OK == result)
{
- OIC_LOG(ERROR, TAG, "Received the first keepalive message from client");
- entry = AddKeepAliveEntry(endPoint, OC_SERVER, NULL);
- if (!entry)
- {
- OIC_LOG(ERROR, TAG, "Failed to add new keepalive entry");
- return OC_STACK_ERROR;
- }
+ OCAddResourceTypeNameToPayload(payload);
+ OCAddResourceInterfaceNameToPayload(payload);
}
- OCPayload *ocPayload = NULL;
- OCParsePayload(&ocPayload, PAYLOAD_TYPE_REPRESENTATION,
- requestInfo->info.payload, requestInfo->info.payloadSize);
- OCRepPayload *repPayload = (OCRepPayload *)ocPayload;
-
- int64_t interval = 0;
- OCRepPayloadGetPropInt(repPayload, INTERVAL, &interval);
- entry->interval = interval;
- OIC_LOG_V(DEBUG, TAG, "Received interval is [%d]", entry->interval);
- entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
+ OCEntityHandlerResponse ehResponse = { .ehResult = result,
+ .payload = (OCPayload*) payload,
+ .requestHandle = request->requestId,
+ .resourceHandle = g_keepAliveHandle };
+ OICStrcpy(ehResponse.resourceUri, sizeof(ehResponse.resourceUri), KEEPALIVE_RESOURCE_URI);
// Send response message.
- SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_CHANGED, requestInfo->info.type,
- requestInfo->info.numOptions, requestInfo->info.options,
- requestInfo->info.token, requestInfo->info.tokenLength,
- requestInfo->info.resourceUri);
-
- return OC_STACK_OK;
+ return OCDoResponse(&ehResponse);
}
-OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
- OCStackResult responseCode,
- const OCRepPayload *respPayload)
+OCEntityHandlerResult OCHandleKeepAliveGETRequest(OCServerRequest *request,
+ const OCResource *resource)
{
- VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
-
- OIC_LOG(DEBUG, TAG, "HandleKeepAliveResponse IN");
+ VERIFY_NON_NULL(request, FATAL, OC_EH_ERROR);
+ VERIFY_NON_NULL(resource, FATAL, OC_EH_ERROR);
- // Get entry from KeepAlive table.
- uint32_t index = 0;
- KeepAliveEntry_t *entry = GetEntryFromEndpoint(endPoint, &index);
- if (!entry)
- {
- // Receive response message about find /oic/ping request.
- OIC_LOG(ERROR, TAG, "There is no connection info in KeepAlive table");
-
- if (OC_STACK_NO_RESOURCE == responseCode)
- {
- OIC_LOG(ERROR, TAG, "Server doesn't have a ping resource");
- return OC_STACK_ERROR;
- }
- else if (OC_STACK_OK == responseCode)
- {
- int64_t *recvInterval = NULL;
- size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
- OCRepPayloadGetIntArray(respPayload, INTERVAL_ARRAY, &recvInterval, dimensions);
- size_t serverIntervalSize = calcDimTotal(dimensions);
+ OIC_LOG_V(DEBUG, TAG, "Find Ping resource [%s]", request->resourceUrl);
- entry = AddKeepAliveEntry(endPoint, OC_CLIENT, recvInterval);
- if (!entry)
- {
- OIC_LOG(ERROR, TAG, "Failed to add new KeepAlive entry");
- return OC_STACK_ERROR;
- }
-
- if (serverIntervalSize)
- {
- // update interval size with received size of server.
- entry->intervalSize = serverIntervalSize;
- }
-
- // Send first ping message
- return SendPingMessage(entry);
- }
- }
- else
+ OCResource *resourcePtr = FindResourceByUri(request->resourceUrl);
+ if (!resourcePtr)
{
- // Set sentPingMsg values with false.
- entry->sentPingMsg = false;
+ // Resource URL not specified
+ OIC_LOG_V(DEBUG, TAG, "There is no Ping resource [%s]", request->resourceUrl);
+ return OC_EH_RESOURCE_NOT_FOUND;
}
- OIC_LOG(DEBUG, TAG, "HandleKeepAliveResponse OUT");
- return OC_STACK_OK;
+ return OC_EH_OK;
}
-void ProcessKeepAlive()
+OCEntityHandlerResult OCHandleKeepAlivePOSTRequest(OCServerRequest *request,
+ const OCResource *resource)
{
- if (!g_isKeepAliveInitialized)
+ VERIFY_NON_NULL(request, FATAL, OC_EH_ERROR);
+ VERIFY_NON_NULL(resource, FATAL, OC_EH_ERROR);
+
+ int64_t interval = 0;
+ OCPayload *ocPayload = NULL;
+ OCStackResult result = OCParsePayload(&ocPayload, PAYLOAD_TYPE_REPRESENTATION,
+ request->payload, request->payloadSize);
+ if (OC_STACK_OK != result)
{
- OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
- return;
+ OIC_LOG(ERROR, TAG, "Representation parse failed");
+ return OC_EH_ERROR;
+ }
+ bool findValue = OCRepPayloadGetPropInt((OCRepPayload *) ocPayload, INTERVAL, &interval);
+ if (!findValue)
+ {
+ OIC_LOG(ERROR, TAG, "Can't find the time interval property");
+ OCPayloadDestroy(ocPayload);
+ return OC_EH_BAD_REQ;
}
- uint32_t len = u_arraylist_length(g_keepAliveConnectionTable);
+ // Get entry from KeepAlive table.
+ CAEndpoint_t endpoint = { .adapter = OC_ADAPTER_TCP };
+ CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
- for (uint32_t i = 0; i < len; i++)
+ oc_mutex_lock(g_mutexObjectList);
+ KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(&endpoint);
+ if (!entry)
{
- KeepAliveEntry_t *entry = u_arraylist_get(g_keepAliveConnectionTable, i);
- if (NULL == entry)
+ OIC_LOG(ERROR, TAG, "Received the first keepalive message from client");
+ entry = OCAddKeepAliveEntry(&endpoint, OC_SERVER, 0);
+ if (!entry)
{
- continue;
+ oc_mutex_unlock(g_mutexObjectList);
+ OIC_LOG(ERROR, TAG, "Failed to add new keepalive entry");
+ OCPayloadDestroy(ocPayload);
+ return OC_EH_INTERNAL_SERVER_ERROR;
}
+ }
+
+ entry->interval = interval;
+ OIC_LOG_V(DEBUG, TAG, "Received interval is [%" PRId64 "]", entry->interval);
+ entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
+ oc_mutex_unlock(g_mutexObjectList);
+
+ OCPayloadDestroy(ocPayload);
+ return OC_EH_OK;
+}
- uint64_t currentTime = OICGetCurrentTime(TIME_IN_US);
- if (OC_CLIENT == entry->mode)
+void OCProcessKeepAlive()
+{
+ oc_mutex_lock(g_mutexObjectList);
+ KeepAliveEntry_t *entry = NULL;
+ KeepAliveEntry_t *tmp = NULL;
+ LL_FOREACH_SAFE(g_keepAliveConnectionTable, entry, tmp)
+ {
+ if (entry)
{
- if (entry->sentPingMsg)
+ uint64_t currentTime = OICGetCurrentTime(TIME_IN_US);
+ if (OC_CLIENT == entry->mode)
{
- /*
- * If an OIC Client does not receive the response within 1 minutes,
- * terminate the connection.
- * In this case the timeStamp means last time sent ping message.
- */
- if ((KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp)
+ if (entry->sentPingMsg)
{
- OIC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes.");
+ /*
+ * If an OIC Client does not receive the response within 1 minutes,
+ * terminate the connection.
+ * In this case the timeStamp means last time sent ping message.
+ */
+ if ((KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp)
+ {
+ OIC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes.");
- // Send message to disconnect session.
- SendDisconnectMessage(entry);
+ // Send message to disconnect session.
+ OCSendDisconnectMessage(entry);
+ }
}
}
- else
+ else if (OC_SERVER == entry->mode)
{
+ /*
+ * If an OIC Server does not receive a PUT/POST request to ping resource
+ * within the specified interval time, terminate the connection.
+ * In this case the timeStamp means last time received ping message.
+ */
if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC)
<= currentTime - entry->timeStamp)
{
- // Increase interval value.
- IncreaseInterval(entry);
-
- OCStackResult result = SendPingMessage(entry);
- if (OC_STACK_OK != result)
- {
- OIC_LOG(ERROR, TAG, "Failed to send ping request");
- continue;
- }
+ OIC_LOG(DEBUG, TAG, "Server does not receive a PUT/POST request.");
+ OCSendDisconnectMessage(entry);
}
}
}
- else if (OC_SERVER == entry->mode)
- {
- /*
- * If an OIC Server does not receive a PUT request to ping resource
- * within the specified interval time, terminate the connection.
- * In this case the timeStamp means last time received ping message.
- */
- if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC)
- <= currentTime - entry->timeStamp)
- {
- OIC_LOG(DEBUG, TAG, "Server does not receive a PUT request.");
- SendDisconnectMessage(entry);
- }
- }
}
+ oc_mutex_unlock(g_mutexObjectList);
}
-void IncreaseInterval(KeepAliveEntry_t *entry)
+OCStackResult OCSendDisconnectMessage(const KeepAliveEntry_t *entry)
{
- VERIFY_NON_NULL_NR(entry, FATAL);
+ VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
- OIC_LOG_V(DEBUG, TAG, "Total interval counts: %d", entry->intervalSize);
- if (entry->intervalSize > entry->currIndex + 1)
+ // notify application that a client does not receive a response.
+ ClientCB *cbNode = GetClientCB(NULL, 0, entry->handle, NULL);
+ if (cbNode)
{
- entry->currIndex++;
- entry->interval = entry->intervalInfo[entry->currIndex];
- OIC_LOG_V(DEBUG, TAG, "increase interval value [%d]", entry->interval);
+ OCClientResponse response = { .devAddr = { .adapter = OC_DEFAULT_ADAPTER } };
+ CopyEndpointToDevAddr(&entry->remoteAddr, &response.devAddr);
+ FixUpClientResponse(&response);
+ response.resourceUri = cbNode->requestUri;
+ response.result = OC_STACK_TIMEOUT;
+
+ cbNode->callBack(cbNode->context, cbNode->handle, &response);
+ FindAndDeleteClientCB(cbNode);
}
-}
-OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry)
-{
- VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
+ CAEndpoint_t endpoint = entry->remoteAddr;
+ if (OC_STACK_OK != OCRemoveKeepAliveEntry(&endpoint))
+ {
+ OIC_LOG(ERROR, TAG, "OCRemoveKeepAliveEntry is failed");
+ return OC_STACK_ERROR;
+ }
/*
* Send empty message to disconnect a connection.
* If CA get the empty message from RI, CA will disconnect a connection.
*/
- CARequestInfo_t requestInfo = { .method = CA_PUT };
- return CASendRequest(&entry->remoteAddr, &requestInfo);
-}
-
-OCStackResult SendPingMessage(KeepAliveEntry_t *entry)
-{
- VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
-
- // Send ping message.
- OCCallbackData pingData = { .cb = PingRequestCallback };
- OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
- CopyEndpointToDevAddr(&(entry->remoteAddr), &devAddr);
-
- OCRepPayload *payload = OCRepPayloadCreate();
- if (!payload)
- {
- OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
- return OC_STACK_ERROR;
- }
- payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
- OCRepPayloadSetPropInt(payload, INTERVAL, entry->interval);
-
- OCDoResource(NULL, OC_REST_PUT, KEEPALIVE_RESOURCE_URI, &devAddr,
- (OCPayload *) payload, CT_ADAPTER_TCP, OC_LOW_QOS, &pingData, NULL, 0);
-
- // Update timeStamp with time sent ping message for next ping message.
- entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
- entry->sentPingMsg = true;
-
- OIC_LOG_V(DEBUG, TAG, "Client sent ping message, interval [%d]", entry->interval);
-
- return OC_STACK_OK;
-}
-
-OCStackApplicationResult PingRequestCallback(void* ctx, OCDoHandle handle,
- OCClientResponse *clientResponse)
-{
- OIC_LOG(DEBUG, TAG, "PingRequestCallback IN");
- (void) ctx;
- (void) handle;
- if (NULL == clientResponse)
+ CAResult_t result = CAUtilTCPDisconnectSession(endpoint.addr, endpoint.port, endpoint.flags);
+ if (OC_STACK_OK != CAResultToOCResult(result))
{
- OIC_LOG(ERROR, TAG, "clientResponse is NULL");
- return OC_STACK_KEEP_TRANSACTION;
+ OIC_LOG(ERROR, TAG, "Failed to disconnect session");
}
- CAEndpoint_t endpoint = { .adapter = CA_ADAPTER_TCP };
- CopyDevAddrToEndpoint(&(clientResponse->devAddr), &endpoint);
-
- HandleKeepAliveResponse(&endpoint, clientResponse->result,
- (OCRepPayload *)clientResponse->payload);
-
- OIC_LOG(DEBUG, TAG, "PingRequestCallback OUT");
- return OC_STACK_KEEP_TRANSACTION;
+ return CAResultToOCResult(result);
}
-KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *index)
+KeepAliveEntry_t *OCGetEntryFromEndpoint(const CAEndpoint_t *endpoint)
{
- if (!g_keepAliveConnectionTable)
- {
- OIC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
- return NULL;
- }
-
- uint32_t len = u_arraylist_length(g_keepAliveConnectionTable);
-
- for (uint32_t i = 0; i < len; i++)
+ KeepAliveEntry_t *entry = NULL;
+ LL_FOREACH(g_keepAliveConnectionTable, entry)
{
- KeepAliveEntry_t *entry = u_arraylist_get(g_keepAliveConnectionTable, i);
- if (NULL == entry)
- {
- continue;
- }
-
- if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
- && (entry->remoteAddr.port == endpoint->port))
+ if (entry)
{
- OIC_LOG(DEBUG, TAG, "Connection Info found in KeepAlive table");
- *index = i;
- return entry;
+ if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
+ && (entry->remoteAddr.port == endpoint->port))
+ {
+ OIC_LOG(DEBUG, TAG, "Connection Info found in KeepAlive table");
+ return entry;
+ }
}
}
return NULL;
}
-KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
- int64_t *intervalInfo)
+KeepAliveEntry_t *OCAddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
+ int64_t interval)
{
if (!endpoint)
{
return NULL;
}
- if (!g_keepAliveConnectionTable)
- {
- OIC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
- return NULL;
- }
-
KeepAliveEntry_t *entry = (KeepAliveEntry_t *) OICCalloc(1, sizeof(KeepAliveEntry_t));
if (NULL == entry)
{
entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
entry->remoteAddr.adapter = endpoint->adapter;
entry->remoteAddr.flags = endpoint->flags;
- entry->remoteAddr.interface = endpoint->interface;
+ entry->remoteAddr.ifindex = endpoint->ifindex;
entry->remoteAddr.port = endpoint->port;
strncpy(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr));
+ entry->interval = interval;
- entry->intervalSize = DEFAULT_INTERVAL_COUNT;
- entry->intervalInfo = intervalInfo;
- if (!entry->intervalInfo)
- {
- entry->intervalInfo = (int64_t*) OICMalloc(entry->intervalSize * sizeof(int64_t));
- for (size_t i = 0; i < entry->intervalSize; i++)
- {
- entry->intervalInfo[i] = KEEPALIVE_MIN_INTERVAL << i;
- }
- }
- entry->interval = entry->intervalInfo[0];
-
- bool result = u_arraylist_add(g_keepAliveConnectionTable, (void *)entry);
- if (!result)
- {
- OIC_LOG(ERROR, TAG, "Adding node to head failed");
- OICFree(entry->intervalInfo);
- OICFree(entry);
- return NULL;
- }
-
+ LL_APPEND(g_keepAliveConnectionTable, entry);
return entry;
}
-OCStackResult RemoveKeepAliveEntry(const CAEndpoint_t *endpoint)
+OCStackResult OCRemoveKeepAliveEntry(const CAEndpoint_t *endpoint)
{
+ OIC_LOG(DEBUG, TAG, "OCRemoveKeepAliveEntry IN");
+
VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
- uint32_t index = 0;
- KeepAliveEntry_t *entry = GetEntryFromEndpoint(endpoint, &index);
- if (!entry)
+ KeepAliveEntry_t *entry = NULL;
+ KeepAliveEntry_t *tmp = NULL;
+ LL_FOREACH_SAFE(g_keepAliveConnectionTable, entry, tmp)
{
- OIC_LOG(ERROR, TAG, "There is no entry in keepalive table.");
- return OC_STACK_ERROR;
- }
+ if (entry)
+ {
+ if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
+ && (entry->remoteAddr.port == endpoint->port))
+ {
+ OIC_LOG_V(DEBUG, TAG, "Remove Connection Info from KeepAlive table, "
+ "remote addr=%s port:%d", entry->remoteAddr.addr,
+ entry->remoteAddr.port);
- KeepAliveEntry_t *removedEntry = u_arraylist_remove(g_keepAliveConnectionTable, index);
- if (NULL == removedEntry)
- {
- OIC_LOG(ERROR, TAG, "Removed Entry is NULL");
- return OC_STACK_ERROR;
+ LL_DELETE(g_keepAliveConnectionTable, entry);
+ OICFree(entry);
+ }
+ }
}
- OIC_LOG_V(DEBUG, TAG, "Remove Connection Info from KeepAlive table, "
- "remote addr=%s port:%d", removedEntry->remoteAddr.addr,
- removedEntry->remoteAddr.port);
-
- OICFree(entry->intervalInfo);
- OICFree(removedEntry);
-
+ OIC_LOG(DEBUG, TAG, "OCRemoveKeepAliveEntry OUT");
return OC_STACK_OK;
}
-void HandleKeepAliveConnCB(const CAEndpoint_t *endpoint, bool isConnected)
+void OCHandleKeepAliveConnCB(const CAEndpoint_t *endpoint, bool isConnected, bool isClient)
{
+ (void) isClient;
VERIFY_NON_NULL_NR(endpoint, FATAL);
if (isConnected)
{
OIC_LOG(DEBUG, TAG, "Received the connected device information from CA");
-
- // Send discover message to find ping resource
- OCCallbackData pingData = { .cb = PingRequestCallback };
- OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
- CopyEndpointToDevAddr(endpoint, &devAddr);
-
- OCDoResource(NULL, OC_REST_DISCOVER, KEEPALIVE_RESOURCE_URI, &devAddr, NULL,
- OC_ADAPTER_TCP, OC_HIGH_QOS, &pingData, NULL, 0);
}
else
{
OIC_LOG(DEBUG, TAG, "Received the disconnected device information from CA");
- OCStackResult result = RemoveKeepAliveEntry(endpoint);
- if(result != OC_STACK_OK)
+ // Do nothing because callback will be removed after one min.
+ /*
+ // notify application that the session is disconnected.
+ oc_mutex_lock(g_mutexObjectList);
+ KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(endpoint);
+ if (entry)
{
- OIC_LOG(ERROR, TAG, "Failed to remove entry");
- return;
+ ClientCB *cbNode = GetClientCB(NULL, 0, entry->handle, NULL);
+ if (cbNode)
+ {
+ OCClientResponse response = { .devAddr = { .adapter = OC_ADAPTER_TCP } };
+ CopyEndpointToDevAddr(&entry->remoteAddr, &response.devAddr);
+ FixUpClientResponse(&response);
+ response.resourceUri = cbNode->requestUri;
+ response.result = OC_STACK_COMM_ERROR;
+
+ cbNode->callBack(cbNode->context, cbNode->handle, &response);
+ FindAndDeleteClientCB(cbNode);
+ }
+ OCRemoveKeepAliveEntry(endpoint);
}
+ oc_mutex_unlock(g_mutexObjectList);
+ */
}
}
+
+OCRepPayload *OCCreateKeepAlivePayload(int64_t interval)
+{
+ OIC_LOG_V(DEBUG, TAG, "Create KeepAlive Payload, interval is [%" PRId64 "]", interval);
+
+ OCRepPayload *payload = OCRepPayloadCreate();
+ if (!payload)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+ payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
+ OCRepPayloadSetPropInt(payload, INTERVAL, interval);
+
+ return payload;
+}
+
+OCStackResult OCAddResourceTypeNameToPayload(OCRepPayload *payload)
+{
+ uint8_t numElement = 0;
+ OCStackResult res = OCGetNumberOfResourceTypes(g_keepAliveHandle, &numElement);
+ if (OC_STACK_OK == res)
+ {
+ size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
+ char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
+ if (!rt)
+ {
+ OIC_LOG(ERROR, TAG, "Could not allocate memory for rf");
+ return OC_STACK_NO_MEMORY;
+ }
+ for (uint8_t i = 0; i < numElement; ++i)
+ {
+ const char *value = OCGetResourceTypeName(g_keepAliveHandle, i);
+ OIC_LOG_V(DEBUG, TAG, "value: %s", value);
+ rt[i] = OICStrdup(value);
+ if (NULL == rt[i])
+ {
+ OIC_LOG_V(ERROR, TAG, "Creating duplicate string for rt failed!");
+ for (uint8_t j = 0; j < i; ++j)
+ {
+ OICFree(rt[j]);
+ }
+ OICFree(rt);
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE, (const char **) rt, rtDim);
+ for (uint8_t i = 0; i < numElement; ++i)
+ {
+ OICFree(rt[i]);
+ }
+ OICFree(rt);
+ }
+
+ return res;
+}
+
+OCStackResult OCAddResourceInterfaceNameToPayload(OCRepPayload *payload)
+{
+ uint8_t numElement = 0;
+ OCStackResult res = OCGetNumberOfResourceInterfaces(g_keepAliveHandle, &numElement);
+ if (OC_STACK_OK == res)
+ {
+ size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
+ char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
+ if (!itf)
+ {
+ OIC_LOG(ERROR, TAG, "Could not allocate memory for itf");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ for (uint8_t i = 0; i < numElement; ++i)
+ {
+ const char *value = OCGetResourceInterfaceName(g_keepAliveHandle, i);
+ OIC_LOG_V(DEBUG, TAG, "value: %s", value);
+ itf[i] = OICStrdup(value);
+ if (NULL == itf[i])
+ {
+ OIC_LOG_V(ERROR, TAG, "Creating duplicate string for itf failed!");
+ for (uint8_t j = 0; j < i; ++j)
+ {
+ OICFree(itf[j]);
+ }
+ OICFree(itf);
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE, (const char **) itf, ifDim);
+ for (uint8_t i = 0; i < numElement; ++i)
+ {
+ OICFree(itf[i]);
+ }
+ OICFree(itf);
+ }
+
+ return res;
+}