1 /* ****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
21 #include "oickeepalive.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
29 #include "uarraylist.h"
30 #include "ocstackinternal.h"
31 #include "ocpayloadcbor.h"
32 #include "ocpayload.h"
33 #include "ocresourcehandler.h"
37 * Logging tag for module name.
39 #define TAG "OIC_RI_KEEPALIVE"
41 static const uint64_t USECS_PER_SEC = 1000000;
43 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
46 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
47 {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
49 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
50 TAG, #arg " is NULL"); return (retVal); } }
52 #define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OIC_LOG((logLevel), \
53 TAG, #arg " is NULL"); return; } }
55 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OIC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
59 * The KeepAlive table entries are removed
60 * if it can't receive response message within 60 seconds.
62 #define KEEPALIVE_RESPONSE_TIMEOUT_SEC 60
65 * The Min time interval value. (2 minutes)
66 * start from 2 minutes and increases in multiples of 2 up to a maximum of 64minutes.
68 #define KEEPALIVE_MIN_INTERVAL 2
71 * The Max time interval value. (64 minutes)
73 #define KEEPALIVE_MAX_INTERVAL 64
76 * Default counts of interval value.
78 #define DEFAULT_INTERVAL_COUNT 6
81 * KeepAlive key to parser Payload Table.
83 static const char INTERVAL[] = "in";
86 * KeepAlive key to get interval values from Payload Table.
88 static const char INTERVAL_ARRAY[] = "inarray";
91 * To check if KeepAlive is initialized.
93 static bool g_isKeepAliveInitialized = false;
96 * Pointer to handle of the newly created KeepAlive resource.
98 static OCResourceHandle g_keepAliveHandle = NULL;
101 * KeepAlive table which holds connection interval.
103 static u_arraylist_t *g_keepAliveConnectionTable = NULL;
106 * KeepAlive table entries.
110 OCMode mode; /**< host Mode of Operation. */
111 CAEndpoint_t remoteAddr; /**< destination Address. */
112 int64_t interval; /**< time interval for KeepAlive. in seconds.*/
113 int32_t currIndex; /**< current interval value index. */
114 size_t intervalSize; /**< total interval counts. */
115 int64_t *intervalInfo; /**< interval values for KeepAlive. */
116 bool sentPingMsg; /**< if oic client already sent ping message. */
117 uint64_t timeStamp; /**< last sent or received ping message. in microseconds. */
121 * Send disconnect message to remove connection.
123 static OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry);
126 * Send ping message to remote endpoint.
128 static OCStackResult SendPingMessage(KeepAliveEntry_t *entry);
131 * Increase interval value to send next ping message.
133 static void IncreaseInterval(KeepAliveEntry_t *entry);
136 * Ping Message callback registered with RI for KeepAlive Request.
138 static OCStackApplicationResult PingRequestCallback(void* ctx, OCDoHandle handle,
139 OCClientResponse * clientResponse);
142 * This function creates KeepAlive resource.
143 * @return ::OC_STACK_OK or Appropriate error code.
145 static OCStackResult CreateKeepAliveResource();
148 * This function deletes KeepAlive resource.
149 * @return ::OC_STACK_OK or Appropriate error code.
151 static OCStackResult DeleteKeepAliveResource();
154 * API to handle the GET request received for a KeepAlive resource.
155 * @param[in] request Request Received.
156 * @param[in] resource Resource handle used for sending the response.
157 * @return ::OC_STACK_OK or Appropriate error code.
159 static OCEntityHandlerResult HandleKeepAliveGETRequest(OCServerRequest *request,
160 const OCResource *resource);
163 * API to handle the PUT request received for a KeepAlive resource.
164 * @param[in] request Request Received.
165 * @param[in] resource Resource handle used for sending the response.
166 * @return ::OC_STACK_OK or Appropriate error code.
168 static OCEntityHandlerResult HandleKeepAlivePOSTRequest(OCServerRequest *request,
169 const OCResource *resource);
172 * API to handle the Response payload.
173 * @param[in] endpoint RemoteEndpoint which sent the packet.
174 * @param[in] responseCode Received reseponse code.
175 * @param[in] respPayload Response payload.
176 * @return ::OC_STACK_OK or Appropriate error code.
178 OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
179 OCStackResult responseCode,
180 const OCRepPayload *respPayload);
182 * Gets keepalive entry.
183 * @param[in] endpoint Remote Endpoint information (like ipaddress,
184 * port, reference uri and transport type) to
185 * which the ping message has to be sent.
186 * @param[out] index index of array list.
187 * @return KeepAlive entry to send ping message.
189 static KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *index);
192 * Add keepalive entry.
193 * @param[in] endpoint Remote Endpoint information (like ipaddress,
194 * port, reference uri and transport type).
195 * @param[in] mode Whether it is OIC Server or OIC Client.
196 * @param[in] intervalArray Received interval values from cloud server.
197 * @return The KeepAlive entry added in KeepAlive Table.
199 KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
200 int64_t *intervalArray);
203 * Remove keepalive entry.
204 * @param[in] endpoint Remote Endpoint information (like ipaddress,
205 * port, reference uri and transport type).
206 * @return The KeepAlive entry removed in KeepAlive Table.
208 static OCStackResult RemoveKeepAliveEntry(const CAEndpoint_t *endpoint);
211 * Create KeepAlive paylaod to send message.
212 * @param[in] interval The interval value to be sent.
213 * @return Created representation payload.
215 static OCRepPayload *CreateKeepAlivePayload(int64_t interval);
218 * Send response to remote device.
219 * @param[in] request Request Received.
220 * @param[in] result Result to be sent.
221 * @return ::OC_STACK_OK or Appropriate error code.
223 static OCStackResult SendKeepAliveResponse(OCServerRequest *request,
224 OCEntityHandlerResult result);
227 * Add resource type name to payload for GET request.
228 * @param[in] payload Pointer to the payload to which byte string needs to be added.
229 * @return ::OC_STACK_OK or Appropriate error code.
231 static OCStackResult AddResourceTypeNameToPayload(OCRepPayload *payload);
234 * Add resource interface name to payload for GET request.
235 * @param[in] payload Pointer to the payload to which byte string needs to be added.
236 * @return ::OC_STACK_OK or Appropriate error code.
238 static OCStackResult AddResourceInterfaceNameToPayload(OCRepPayload *payload);
240 OCStackResult InitializeKeepAlive(OCMode mode)
242 OIC_LOG(DEBUG, TAG, "InitializeKeepAlive IN");
243 if (g_isKeepAliveInitialized)
245 OIC_LOG(DEBUG, TAG, "KeepAlive already initialized");
249 if (OC_CLIENT != mode)
251 // Create the KeepAlive Resource[/oic/ping].
252 OCStackResult result = CreateKeepAliveResource();
253 if (OC_STACK_OK != result)
255 OIC_LOG_V(ERROR, TAG, "CreateKeepAliveResource failed[%d]", result);
260 if (!g_keepAliveConnectionTable)
262 g_keepAliveConnectionTable = u_arraylist_create();
263 if (NULL == g_keepAliveConnectionTable)
265 OIC_LOG(ERROR, TAG, "Creating KeepAlive Table failed");
266 TerminateKeepAlive(mode);
267 return OC_STACK_ERROR;
271 g_isKeepAliveInitialized = true;
273 OIC_LOG(DEBUG, TAG, "InitializeKeepAlive OUT");
277 OCStackResult TerminateKeepAlive(OCMode mode)
279 OIC_LOG(DEBUG, TAG, "TerminateKeepAlive IN");
280 if (!g_isKeepAliveInitialized)
282 OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
283 return OC_STACK_ERROR;
286 if (OC_CLIENT != mode)
288 // Delete the KeepAlive Resource[/oic/ping].
289 OCStackResult result = DeleteKeepAliveResource();
290 if (OC_STACK_OK != result)
292 OIC_LOG_V(ERROR, TAG, "DeleteKeepAliveResource failed[%d]", result);
297 if (NULL != g_keepAliveConnectionTable)
299 u_arraylist_destroy(g_keepAliveConnectionTable);
300 g_keepAliveConnectionTable = NULL;
303 g_isKeepAliveInitialized = false;
305 OIC_LOG(DEBUG, TAG, "TerminateKeepAlive OUT");
309 OCStackResult CreateKeepAliveResource()
311 OIC_LOG(DEBUG, TAG, "InitKeepAliveResource IN");
313 // Create a KeepAlive resource
314 OCStackResult result = OCCreateResource(&g_keepAliveHandle,
315 KEEPALIVE_RESOURCE_TYPE_NAME,
316 OC_RSRVD_INTERFACE_DEFAULT,
317 KEEPALIVE_RESOURCE_URI,
321 if (OC_STACK_OK == result)
323 result = BindResourceInterfaceToResource((OCResource *) g_keepAliveHandle,
324 KEEPALIVE_RESOURCE_INTF_NAME);
327 if (OC_STACK_OK != result)
329 OIC_LOG_V(ERROR, TAG, "Create resource for KeepAlive failed[%d]", result);
332 OIC_LOG(DEBUG, TAG, "InitKeepAliveResource OUT");
336 OCStackResult DeleteKeepAliveResource()
338 OIC_LOG(DEBUG, TAG, "DeleteKeepAliveResource IN");
340 // Create a KeepAlive resource
341 OCStackResult result = OCDeleteResource(g_keepAliveHandle);
343 if (OC_STACK_OK != result)
345 OIC_LOG_V(ERROR, TAG, "Delete resource for KeepAlive failed[%d]", result);
348 OIC_LOG(DEBUG, TAG, "DeleteKeepAliveResource OUT");
352 OCStackResult HandleKeepAliveRequest(OCServerRequest *request,
353 const OCResource *resource)
355 VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
356 VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
358 OIC_LOG(DEBUG, TAG, "HandleKeepAliveRequest IN");
360 OCEntityHandlerResult result = OC_EH_ERROR;
361 if (OC_REST_GET == request->method)
363 switch ((OCObserveAction)request->observationOption)
365 case OC_OBSERVE_NO_OPTION:
366 case OC_OBSERVE_REGISTER:
367 case OC_OBSERVE_DEREGISTER:
368 OIC_LOG(DEBUG, TAG, "Received GET request");
369 result = HandleKeepAliveGETRequest(request, resource);
372 OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
373 result = OC_EH_UNAUTHORIZED_REQ;
376 else if (OC_REST_PUT == request->method || OC_REST_POST == request->method)
378 OIC_LOG(DEBUG, TAG, "Received PUT/POST request");
379 result = HandleKeepAlivePOSTRequest(request, resource);
383 OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
384 result = OC_EH_UNAUTHORIZED_REQ;
387 OCStackResult ret = SendKeepAliveResponse(request, result);
388 if (OC_STACK_OK != ret)
390 OIC_LOG_V(ERROR, TAG, "SendKeepAliveResponse failed with result %u", ret);
393 OIC_LOG(DEBUG, TAG, "HandleKeepAliveRequest OUT");
397 OCStackResult SendKeepAliveResponse(OCServerRequest *request,
398 OCEntityHandlerResult result)
400 VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
402 OIC_LOG_V(DEBUG, TAG, "Send KeepAlive response with entity result[%d]", result);
404 // Convert OCDevAddr to CAEndpoint_t.
405 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
406 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
409 KeepAliveEntry_t *entry = GetEntryFromEndpoint(&endpoint, &index);
410 int64_t interval = (entry) ? entry->interval : 0;
412 // Create KeepAlive payload to send response message.
413 OCRepPayload *payload = CreateKeepAlivePayload(interval);
415 // Add resource type/interface name to payload for GET request.
416 if (OC_REST_GET == request->method && OC_EH_OK == result)
418 AddResourceTypeNameToPayload(payload);
419 AddResourceInterfaceNameToPayload(payload);
422 OCEntityHandlerResponse ehResponse = { .ehResult = result,
423 .payload = (OCPayload*) payload,
424 .requestHandle = request->requestId,
425 .resourceHandle = g_keepAliveHandle };
426 OICStrcpy(ehResponse.resourceUri, sizeof(ehResponse.resourceUri), KEEPALIVE_RESOURCE_URI);
428 // Send response message.
429 return OCDoResponse(&ehResponse);
432 OCEntityHandlerResult HandleKeepAliveGETRequest(OCServerRequest *request,
433 const OCResource *resource)
435 VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
436 VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
438 OIC_LOG_V(DEBUG, TAG, "Find Ping resource [%s]", request->resourceUrl);
440 OCResource *resourcePtr = FindResourceByUri(request->resourceUrl);
443 // Resource URL not specified
444 OIC_LOG_V(DEBUG, TAG, "There is no Ping resource [%s]", request->resourceUrl);
445 return OC_EH_RESOURCE_NOT_FOUND;
451 OCEntityHandlerResult HandleKeepAlivePOSTRequest(OCServerRequest *request,
452 const OCResource *resource)
454 VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
455 VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
457 // Get entry from KeepAlive table.
458 CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
459 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
462 KeepAliveEntry_t *entry = GetEntryFromEndpoint(&endpoint, &index);
465 OIC_LOG(ERROR, TAG, "Received the first keepalive message from client");
466 entry = AddKeepAliveEntry(&endpoint, OC_SERVER, NULL);
469 OIC_LOG(ERROR, TAG, "Failed to add new keepalive entry");
470 return OC_EH_INTERNAL_SERVER_ERROR;
474 OCPayload *ocPayload = NULL;
475 OCParsePayload(&ocPayload, PAYLOAD_TYPE_REPRESENTATION,
476 request->payload, request->payloadSize);
477 OCRepPayload *repPayload = (OCRepPayload *)ocPayload;
479 int64_t interval = 0;
480 OCRepPayloadGetPropInt(repPayload, INTERVAL, &interval);
481 entry->interval = interval;
482 OIC_LOG_V(DEBUG, TAG, "Received interval is [%" PRId64 "]", entry->interval);
483 entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
485 OCPayloadDestroy(ocPayload);
490 OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
491 OCStackResult responseCode,
492 const OCRepPayload *respPayload)
494 VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
496 OIC_LOG(DEBUG, TAG, "HandleKeepAliveResponse IN");
498 // Get entry from KeepAlive table.
500 KeepAliveEntry_t *entry = GetEntryFromEndpoint(endPoint, &index);
503 // Receive response message about find /oic/ping request.
504 OIC_LOG(ERROR, TAG, "There is no connection info in KeepAlive table");
506 if (OC_STACK_NO_RESOURCE == responseCode)
508 OIC_LOG(ERROR, TAG, "Server doesn't have a ping resource");
509 return OC_STACK_ERROR;
511 else if (OC_STACK_OK == responseCode)
513 int64_t *recvInterval = NULL;
514 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
515 OCRepPayloadGetIntArray(respPayload, INTERVAL_ARRAY, &recvInterval, dimensions);
516 size_t serverIntervalSize = calcDimTotal(dimensions);
518 entry = AddKeepAliveEntry(endPoint, OC_CLIENT, recvInterval);
521 OIC_LOG(ERROR, TAG, "Failed to add new KeepAlive entry");
522 return OC_STACK_ERROR;
525 if (serverIntervalSize)
527 // update interval size with received size of server.
528 entry->intervalSize = serverIntervalSize;
531 // Send first ping message
532 return SendPingMessage(entry);
537 // Set sentPingMsg values with false.
538 entry->sentPingMsg = false;
540 // Check the received interval value.
541 int64_t interval = 0;
542 OCRepPayloadGetPropInt(respPayload, INTERVAL, &interval);
543 OIC_LOG_V(DEBUG, TAG, "Received interval is [%" PRId64 "]", entry->interval);
546 OIC_LOG(DEBUG, TAG, "HandleKeepAliveResponse OUT");
550 void ProcessKeepAlive()
552 if (!g_isKeepAliveInitialized)
554 OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
558 uint32_t len = u_arraylist_length(g_keepAliveConnectionTable);
560 for (uint32_t i = 0; i < len; i++)
562 KeepAliveEntry_t *entry = (KeepAliveEntry_t *)u_arraylist_get(g_keepAliveConnectionTable,
569 uint64_t currentTime = OICGetCurrentTime(TIME_IN_US);
570 if (OC_CLIENT == entry->mode)
572 if (entry->sentPingMsg)
575 * If an OIC Client does not receive the response within 1 minutes,
576 * terminate the connection.
577 * In this case the timeStamp means last time sent ping message.
579 if ((KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp)
581 OIC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes.");
583 // Send message to disconnect session.
584 SendDisconnectMessage(entry);
589 if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC)
590 <= currentTime - entry->timeStamp)
592 // Increase interval value.
593 IncreaseInterval(entry);
595 OCStackResult result = SendPingMessage(entry);
596 if (OC_STACK_OK != result)
598 OIC_LOG(ERROR, TAG, "Failed to send ping request");
604 else if (OC_SERVER == entry->mode)
607 * If an OIC Server does not receive a PUT request to ping resource
608 * within the specified interval time, terminate the connection.
609 * In this case the timeStamp means last time received ping message.
611 if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC)
612 <= currentTime - entry->timeStamp)
614 OIC_LOG(DEBUG, TAG, "Server does not receive a PUT request.");
615 SendDisconnectMessage(entry);
621 void IncreaseInterval(KeepAliveEntry_t *entry)
623 VERIFY_NON_NULL_NR(entry, FATAL);
625 OIC_LOG_V(DEBUG, TAG, "Total interval counts: %zu", entry->intervalSize);
626 if (entry->intervalSize > (size_t)entry->currIndex + 1)
629 entry->interval = entry->intervalInfo[entry->currIndex];
630 OIC_LOG_V(DEBUG, TAG, "increase interval value [%" PRId64 "]", entry->interval);
634 OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry)
636 VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
639 * Send empty message to disconnect a connection.
640 * If CA get the empty message from RI, CA will disconnect a connection.
643 OCStackResult result = RemoveKeepAliveEntry(&entry->remoteAddr);
644 if (result != OC_STACK_OK)
649 CARequestInfo_t requestInfo = { .method = CA_POST };
650 result = CASendRequest(&entry->remoteAddr, &requestInfo);
651 return CAResultToOCResult(result);
654 OCStackResult SendPingMessage(KeepAliveEntry_t *entry)
656 VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
658 // Send ping message.
659 OCCallbackData pingData = { .context = NULL, .cb = PingRequestCallback };
660 OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
661 CopyEndpointToDevAddr(&(entry->remoteAddr), &devAddr);
663 OCRepPayload *payload = CreateKeepAlivePayload(entry->interval);
664 OCStackResult result = OCDoResource(NULL, OC_REST_POST, KEEPALIVE_RESOURCE_URI, &devAddr,
665 (OCPayload *) payload, CT_ADAPTER_TCP, OC_LOW_QOS,
667 if (OC_STACK_OK != result)
669 OIC_LOG(ERROR, TAG, "OCDoResource has failed");
673 // Update timeStamp with time sent ping message for next ping message.
674 entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
675 entry->sentPingMsg = true;
677 OIC_LOG_V(DEBUG, TAG, "Client sent ping message, interval [%" PRId64 "]", entry->interval);
682 OCStackApplicationResult PingRequestCallback(void* ctx, OCDoHandle handle,
683 OCClientResponse *clientResponse)
687 if (NULL == clientResponse)
689 OIC_LOG(ERROR, TAG, "clientResponse is NULL");
690 return OC_STACK_DELETE_TRANSACTION;
693 CAEndpoint_t endpoint = { .adapter = CA_ADAPTER_TCP };
694 CopyDevAddrToEndpoint(&(clientResponse->devAddr), &endpoint);
696 HandleKeepAliveResponse(&endpoint, clientResponse->result,
697 (OCRepPayload *)clientResponse->payload);
699 return OC_STACK_DELETE_TRANSACTION;
702 KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *index)
704 if (!g_keepAliveConnectionTable)
706 OIC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
710 uint32_t len = u_arraylist_length(g_keepAliveConnectionTable);
712 for (uint32_t i = 0; i < len; i++)
714 KeepAliveEntry_t *entry = (KeepAliveEntry_t *)u_arraylist_get(g_keepAliveConnectionTable,
721 if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
722 && (entry->remoteAddr.port == endpoint->port))
724 OIC_LOG(DEBUG, TAG, "Connection Info found in KeepAlive table");
733 KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
734 int64_t *intervalInfo)
738 OIC_LOG(ERROR, TAG, "endpoint is NULL");
742 if (!g_keepAliveConnectionTable)
744 OIC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
748 KeepAliveEntry_t *entry = (KeepAliveEntry_t *) OICCalloc(1, sizeof(KeepAliveEntry_t));
751 OIC_LOG(ERROR, TAG, "Failed to Calloc KeepAlive Entry");
756 entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
757 entry->remoteAddr.adapter = endpoint->adapter;
758 entry->remoteAddr.flags = endpoint->flags;
759 entry->remoteAddr.ifindex = endpoint->ifindex;
760 entry->remoteAddr.port = endpoint->port;
761 strncpy(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr));
763 entry->intervalSize = DEFAULT_INTERVAL_COUNT;
764 entry->intervalInfo = intervalInfo;
765 if (!entry->intervalInfo)
767 entry->intervalInfo = (int64_t*) OICMalloc(entry->intervalSize * sizeof(int64_t));
768 for (size_t i = 0; i < entry->intervalSize; i++)
770 entry->intervalInfo[i] = KEEPALIVE_MIN_INTERVAL << i;
773 entry->interval = entry->intervalInfo[0];
775 bool result = u_arraylist_add(g_keepAliveConnectionTable, (void *)entry);
778 OIC_LOG(ERROR, TAG, "Adding node to head failed");
779 OICFree(entry->intervalInfo);
787 OCStackResult RemoveKeepAliveEntry(const CAEndpoint_t *endpoint)
789 VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
792 KeepAliveEntry_t *entry = GetEntryFromEndpoint(endpoint, &index);
795 OIC_LOG(ERROR, TAG, "There is no entry in keepalive table.");
796 return OC_STACK_ERROR;
799 KeepAliveEntry_t *removedEntry = (KeepAliveEntry_t *)
800 u_arraylist_remove(g_keepAliveConnectionTable, index);
801 if (NULL == removedEntry)
803 OIC_LOG(ERROR, TAG, "Removed Entry is NULL");
804 return OC_STACK_ERROR;
807 OIC_LOG_V(DEBUG, TAG, "Remove Connection Info from KeepAlive table, "
808 "remote addr=%s port:%d", removedEntry->remoteAddr.addr,
809 removedEntry->remoteAddr.port);
811 OICFree(entry->intervalInfo);
812 OICFree(removedEntry);
817 void HandleKeepAliveConnCB(const CAEndpoint_t *endpoint, bool isConnected)
819 VERIFY_NON_NULL_NR(endpoint, FATAL);
823 OIC_LOG(DEBUG, TAG, "Received the connected device information from CA");
825 // Send discover message to find ping resource
826 OCCallbackData pingData = {.context = NULL, .cb = PingRequestCallback };
827 OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
828 CopyEndpointToDevAddr(endpoint, &devAddr);
830 OCStackResult result = OCDoResource(NULL, OC_REST_DISCOVER, KEEPALIVE_RESOURCE_URI,
831 &devAddr, NULL, CT_ADAPTER_TCP, OC_HIGH_QOS,
833 if (OC_STACK_OK != result)
835 OIC_LOG(ERROR, TAG, "OCDoResource has failed");
841 OIC_LOG(DEBUG, TAG, "Received the disconnected device information from CA");
843 OCStackResult result = RemoveKeepAliveEntry(endpoint);
844 if(result != OC_STACK_OK)
851 OCRepPayload *CreateKeepAlivePayload(int64_t interval)
853 OIC_LOG_V(DEBUG, TAG, "Create KeepAlive Payload, interval is [%" PRId64 "]", interval);
855 OCRepPayload *payload = OCRepPayloadCreate();
858 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
861 payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
862 OCRepPayloadSetPropInt(payload, INTERVAL, interval);
867 OCStackResult AddResourceTypeNameToPayload(OCRepPayload *payload)
869 uint8_t numElement = 0;
870 OCStackResult res = OCGetNumberOfResourceTypes(g_keepAliveHandle, &numElement);
871 if (OC_STACK_OK == res)
873 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
874 char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
875 for (uint8_t i = 0; i < numElement; ++i)
877 const char *value = OCGetResourceTypeName(g_keepAliveHandle, i);
878 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
879 rt[i] = OICStrdup(value);
882 OIC_LOG_V(ERROR, TAG, "Creating duplicate string for rt failed!");
883 for (uint8_t j = 0; j < i; ++j)
888 return OC_STACK_NO_MEMORY;
891 OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE, (const char **) rt, rtDim);
892 for (uint8_t i = 0; i < numElement; ++i)
902 OCStackResult AddResourceInterfaceNameToPayload(OCRepPayload *payload)
904 uint8_t numElement = 0;
905 OCStackResult res = OCGetNumberOfResourceInterfaces(g_keepAliveHandle, &numElement);
906 if (OC_STACK_OK == res)
908 size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
909 char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
910 for (uint8_t i = 0; i < numElement; ++i)
912 const char *value = OCGetResourceInterfaceName(g_keepAliveHandle, i);
913 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
914 itf[i] = OICStrdup(value);
917 OIC_LOG_V(ERROR, TAG, "Creating duplicate string for itf failed!");
918 for (uint8_t j = 0; j < i; ++j)
923 return OC_STACK_NO_MEMORY;
926 OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE, (const char **) itf, ifDim);
927 for (uint8_t i = 0; i < numElement; ++i)