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"
22 #include "oickeepaliveinternal.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
31 #include "uarraylist.h"
32 #include "ocstackinternal.h"
33 #include "ocpayloadcbor.h"
34 #include "ocpayload.h"
35 #include "ocresourcehandler.h"
37 #include "cautilinterface.h"
38 #include <coap/utlist.h>
41 * Logging tag for module name.
43 #define TAG "OIC_RI_KEEPALIVE"
45 static const uint64_t USECS_PER_SEC = 1000000;
47 //-----------------------------------------------------------------------------
49 //-----------------------------------------------------------------------------
50 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
51 {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
53 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
54 TAG, #arg " is NULL"); return (retVal); } }
56 #define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OIC_LOG((logLevel), \
57 TAG, #arg " is NULL"); return; } }
59 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OIC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
63 * The KeepAlive table entries are removed
64 * if it can't receive response message within 60 seconds.
66 #define KEEPALIVE_RESPONSE_TIMEOUT_SEC 60
69 * KeepAlive key to parser Payload Table.
71 static const char INTERVAL[] = "in";
74 * KeepAlive key to get interval values from Payload Table.
76 static const char INTERVAL_ARRAY[] = "inarray";
79 * Pointer to handle of the newly created KeepAlive resource.
81 static OCResourceHandle g_keepAliveHandle = NULL;
84 * KeepAlive table which holds connection interval.
86 static struct KeepAliveEntry_t *g_keepAliveConnectionTable = NULL;
89 * Mutex to synchronize device object list.
91 static oc_mutex g_mutexObjectList = NULL;
94 * KeepAlive table entries.
96 typedef struct KeepAliveEntry_t
98 OCMode mode; /**< host Mode of Operation. */
99 CAEndpoint_t remoteAddr; /**< destination Address. */
100 int64_t interval; /**< time interval for KeepAlive. in seconds.*/
101 int32_t currIndex; /**< current interval value index. */
102 bool sentPingMsg; /**< if oic client already sent ping message. */
103 uint64_t timeStamp; /**< last sent or received ping message. in microseconds. */
104 OCDoHandle handle; /**< Invocation handle tied to original call to OCDoResource().*/
105 struct KeepAliveEntry_t *next; /**< Linked list; for multiple keepalive info list.*/
109 * Send disconnect message to remove connection.
111 static OCStackResult OCSendDisconnectMessage(const KeepAliveEntry_t *entry);
114 * This function creates KeepAlive resource.
115 * @return ::OC_STACK_OK or Appropriate error code.
117 static OCStackResult OCCreateKeepAliveResource();
120 * This function deletes KeepAlive resource.
121 * @return ::OC_STACK_OK or Appropriate error code.
123 static OCStackResult OCDeleteKeepAliveResource();
126 * API to handle the GET request received for a KeepAlive resource.
127 * @param[in] request Request Received.
128 * @param[in] resource Resource handle used for sending the response.
129 * @return ::OC_STACK_OK or Appropriate error code.
131 static OCEntityHandlerResult OCHandleKeepAliveGETRequest(OCServerRequest *request,
132 const OCResource *resource);
135 * API to handle the PUT request received for a KeepAlive resource.
136 * @param[in] request Request Received.
137 * @param[in] resource Resource handle used for sending the response.
138 * @return ::OC_STACK_OK or Appropriate error code.
140 static OCEntityHandlerResult OCHandleKeepAlivePOSTRequest(OCServerRequest *request,
141 const OCResource *resource);
144 * Gets keepalive entry.
145 * @param[in] endpoint Remote Endpoint information (like ipaddress,
146 * port, reference uri and transport type) to
147 * which the ping message has to be sent.
148 * @return KeepAlive entry to send ping message.
150 static KeepAliveEntry_t *OCGetEntryFromEndpoint(const CAEndpoint_t *endpoint);
153 * Add keepalive entry.
154 * @param[in] endpoint Remote Endpoint information (like ipaddress,
155 * port, reference uri and transport type).
156 * @param[in] mode Whether it is OIC Server or OIC Client.
157 * @param[in] interval Sent interval value to remote device.
158 * @return The KeepAlive entry added in KeepAlive Table.
160 KeepAliveEntry_t *OCAddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
164 * Remove keepalive entry.
165 * @param[in] endpoint Remote Endpoint information (like ipaddress,
166 * port, reference uri and transport type).
167 * @return The KeepAlive entry removed in KeepAlive Table.
169 static OCStackResult OCRemoveKeepAliveEntry(const CAEndpoint_t *endpoint);
172 * Create KeepAlive paylaod to send message.
173 * @param[in] interval The interval value to be sent.
174 * @return Created representation payload.
176 static OCRepPayload *OCCreateKeepAlivePayload(int64_t interval);
179 * Send response to remote device.
180 * @param[in] request Request Received.
181 * @param[in] result Result to be sent.
182 * @return ::OC_STACK_OK or Appropriate error code.
184 static OCStackResult OCSendKeepAliveResponse(OCServerRequest *request,
185 OCEntityHandlerResult result);
188 * Add resource type name to payload for GET request.
189 * @param[in] payload Pointer to the payload to which byte string needs to be added.
190 * @return ::OC_STACK_OK or Appropriate error code.
192 static OCStackResult OCAddResourceTypeNameToPayload(OCRepPayload *payload);
195 * Add resource interface name to payload for GET request.
196 * @param[in] payload Pointer to the payload to which byte string needs to be added.
197 * @return ::OC_STACK_OK or Appropriate error code.
199 static OCStackResult OCAddResourceInterfaceNameToPayload(OCRepPayload *payload);
201 OCStackResult OCInitializeKeepAlive(OCMode mode)
203 OIC_LOG(DEBUG, TAG, "OCInitializeKeepAlive IN");
205 if (!g_mutexObjectList)
207 g_mutexObjectList = oc_mutex_new();
208 if (!g_mutexObjectList)
210 OIC_LOG(ERROR, TAG, "Failed to create mutex!");
211 return OC_STACK_ERROR;
215 if (OC_CLIENT != mode)
217 // Create the KeepAlive Resource[/oic/ping].
218 OCStackResult result = OCCreateKeepAliveResource();
219 if (OC_STACK_OK != result)
221 OIC_LOG_V(ERROR, TAG, "OCCreateKeepAliveResource failed[%d]", result);
226 OIC_LOG(DEBUG, TAG, "OCInitializeKeepAlive OUT");
230 OCStackResult OCTerminateKeepAlive(OCMode mode)
232 OIC_LOG(DEBUG, TAG, "OCTerminateKeepAlive IN");
234 if (g_mutexObjectList)
236 oc_mutex_free(g_mutexObjectList);
237 g_mutexObjectList = NULL;
240 if (OC_CLIENT != mode)
242 // Delete the KeepAlive Resource[/oic/ping].
243 OCStackResult result = OCDeleteKeepAliveResource();
244 if (OC_STACK_OK != result)
246 OIC_LOG_V(ERROR, TAG, "OCDeleteKeepAliveResource failed[%d]", result);
251 OIC_LOG(DEBUG, TAG, "OCTerminateKeepAlive OUT");
255 OCStackResult OCFindKeepAliveResource(OCDoHandle *handle, const char *remoteAddr,
256 OCCallbackData *cbData)
258 // Validate input parameters
259 VERIFY_NON_NULL(remoteAddr, FATAL, OC_STACK_INVALID_CALLBACK);
260 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
261 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
263 // Send discover message to find ping resource
264 char requestUri[MAX_QUERY_LENGTH] = { 0 };
265 snprintf(requestUri, MAX_QUERY_LENGTH, "%s%s", remoteAddr, KEEPALIVE_RESOURCE_URI);
266 OCStackResult result = OCDoResource(handle, OC_REST_DISCOVER, requestUri,
267 NULL, NULL, CT_ADAPTER_TCP, OC_HIGH_QOS,
269 if (OC_STACK_OK != result)
271 OIC_LOG(ERROR, TAG, "OCDoResource has failed");
276 OCStackResult OCSendKeepAliveRequest(OCDoHandle *handle, const char *remoteAddr,
277 OCPayload *payload, OCCallbackData *cbData)
279 VERIFY_NON_NULL(remoteAddr, FATAL, OC_STACK_INVALID_PARAM);
280 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_PARAM);
281 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
282 VERIFY_NON_NULL(payload, FATAL, OC_STACK_INVALID_CALLBACK);
284 OIC_LOG(DEBUG, TAG, "SendKeepAliveRequest IN");
286 // Parse the remote device address to send ping message.
287 OCDevAddr *devAddr = NULL;
288 char requestUri[MAX_QUERY_LENGTH] = { 0 };
289 snprintf(requestUri, MAX_QUERY_LENGTH, "%s%s", remoteAddr, KEEPALIVE_RESOURCE_URI);
290 OCStackResult result = ParseRequestUri(requestUri, OC_DEFAULT_ADAPTER, OC_DEFAULT_FLAGS,
291 &devAddr, NULL, NULL);
292 if (result != OC_STACK_OK)
294 OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", remoteAddr);
295 return OC_STACK_ERROR;
298 VERIFY_NON_NULL(devAddr, FATAL, OC_STACK_INVALID_PARAM);
300 if (!(devAddr->adapter & OC_ADAPTER_TCP))
302 OIC_LOG_V(DEBUG, TAG, "Not supported connectivity type");
304 return OC_STACK_ERROR;
307 // Get entry from KeepAlive table.
308 CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
309 CopyDevAddrToEndpoint(devAddr, &endpoint);
311 oc_mutex_lock(g_mutexObjectList);
312 KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(&endpoint);
315 OIC_LOG(DEBUG, TAG, "There is no connection info in KeepAlive table");
317 entry = OCAddKeepAliveEntry(&endpoint, OC_CLIENT, 0);
320 oc_mutex_unlock(g_mutexObjectList);
321 OIC_LOG(ERROR, TAG, "Failed to add new KeepAlive entry");
323 return OC_STACK_ERROR;
327 // Get "in" value from payload.
328 int64_t interval = 0;
329 bool findValue = OCRepPayloadGetPropInt((OCRepPayload *) payload, INTERVAL, &interval);
330 if (findValue && interval)
332 if (entry->sentPingMsg)
334 oc_mutex_unlock(g_mutexObjectList);
335 OIC_LOG(ERROR, TAG, "Already sent a ping request to remote device");
337 return OC_STACK_ERROR;
339 entry->interval = interval;
340 OIC_LOG_V(DEBUG, TAG, "Send ping message with interval [%" PRId64 "]", entry->interval);
343 // Get "inarray" value from payload.
344 int64_t *inArray = NULL;
345 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
346 OCRepPayloadGetIntArray((OCRepPayload *) payload, INTERVAL_ARRAY, &inArray, dimensions);
350 char newArray[MAX_URI_LENGTH] = { 0 };
351 size_t inArraySize = calcDimTotal(dimensions);
352 for (size_t i = 0; i < inArraySize; i++)
354 len += snprintf(newArray + len, MAX_URI_LENGTH, "% " PRId64, inArray[i]);
357 OIC_LOG_V(DEBUG, TAG, "Send update interval message with inarray [ %s]", newArray);
360 // Send keepalive message.
361 result = OCDoResource(&entry->handle, OC_REST_POST, KEEPALIVE_RESOURCE_URI,
362 devAddr, (OCPayload *) payload, CT_ADAPTER_TCP,
363 OC_HIGH_QOS, cbData, NULL, 0);
364 if (OC_STACK_OK != result)
366 oc_mutex_unlock(g_mutexObjectList);
367 OIC_LOG(ERROR, TAG, "OCDoResource has failed");
372 // Update timeStamp with time sent ping message for next ping message.
373 entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
374 entry->sentPingMsg = true;
377 *handle = entry->handle;
380 oc_mutex_unlock(g_mutexObjectList);
381 OIC_LOG(DEBUG, TAG, "SendKeepAliveRequest OUT");
386 OCStackResult OCHandleKeepAliveResponse(const CAEndpoint_t *endPoint, const OCPayload *payload)
389 VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
391 // Receive response message about post /oic/ping request.
392 OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveResponse IN");
394 // Get entry from KeepAlive table.
395 oc_mutex_lock(g_mutexObjectList);
396 KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(endPoint);
399 OIC_LOG_V(DEBUG, TAG, "Received response about interval [%" PRId64 "]", entry->interval);
401 // Set sentPingMsg values with false.
402 entry->sentPingMsg = false;
403 entry->handle = NULL;
406 oc_mutex_unlock(g_mutexObjectList);
407 OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveResponse OUT");
411 OCStackResult OCCreateKeepAliveResource()
413 OIC_LOG(DEBUG, TAG, "OCCreateKeepAliveResource IN");
415 // Create a KeepAlive resource
416 OCStackResult result = OCCreateResource(&g_keepAliveHandle,
417 KEEPALIVE_RESOURCE_TYPE_NAME,
418 OC_RSRVD_INTERFACE_DEFAULT,
419 KEEPALIVE_RESOURCE_URI,
423 if (OC_STACK_OK == result)
425 result = BindResourceInterfaceToResource((OCResource *) g_keepAliveHandle,
426 KEEPALIVE_RESOURCE_INTF_NAME);
429 if (OC_STACK_OK != result)
431 OIC_LOG_V(ERROR, TAG, "Create resource for KeepAlive failed[%d]", result);
434 OIC_LOG(DEBUG, TAG, "OCCreateKeepAliveResource OUT");
438 OCStackResult OCDeleteKeepAliveResource()
440 OIC_LOG(DEBUG, TAG, "OCDeleteKeepAliveResource IN");
442 // Create a KeepAlive resource
443 OCStackResult result = OCDeleteResource(g_keepAliveHandle);
445 if (OC_STACK_OK != result)
447 OIC_LOG_V(ERROR, TAG, "Delete resource for KeepAlive failed[%d]", result);
450 OIC_LOG(DEBUG, TAG, "OCDeleteKeepAliveResource OUT");
454 OCStackResult OCHandleKeepAliveRequest(OCServerRequest *request,
455 const OCResource *resource)
457 VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
458 VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
460 OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveRequest IN");
462 OCEntityHandlerResult result = OC_EH_ERROR;
463 if (OC_REST_GET == request->method)
465 switch ((OCObserveAction)request->observationOption)
467 case OC_OBSERVE_NO_OPTION:
468 case OC_OBSERVE_REGISTER:
469 case OC_OBSERVE_DEREGISTER:
470 OIC_LOG(DEBUG, TAG, "Received GET request");
471 result = OCHandleKeepAliveGETRequest(request, resource);
474 OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
475 result = OC_EH_UNAUTHORIZED_REQ;
478 else if (OC_REST_PUT == request->method || OC_REST_POST == request->method)
480 OIC_LOG(DEBUG, TAG, "Received PUT/POST request");
481 result = OCHandleKeepAlivePOSTRequest(request, resource);
485 OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
486 result = OC_EH_UNAUTHORIZED_REQ;
489 OCStackResult ret = OCSendKeepAliveResponse(request, result);
490 if (OC_STACK_OK != ret)
492 OIC_LOG_V(ERROR, TAG, "SendKeepAliveResponse failed with result %u", ret);
495 OIC_LOG(DEBUG, TAG, "OCHandleKeepAliveRequest OUT");
499 OCStackResult OCSendKeepAliveResponse(OCServerRequest *request,
500 OCEntityHandlerResult result)
502 VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
504 OIC_LOG_V(DEBUG, TAG, "Send KeepAlive response with entity result[%d]", result);
506 // Convert OCDevAddr to CAEndpoint_t.
507 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
508 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
510 oc_mutex_lock(g_mutexObjectList);
511 KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(&endpoint);
512 int64_t interval = (entry) ? entry->interval : 0;
513 oc_mutex_unlock(g_mutexObjectList);
515 // Create KeepAlive payload to send response message.
516 OCRepPayload *payload = OCCreateKeepAlivePayload(interval);
518 // Add resource type/interface name to payload for GET request.
519 if (OC_REST_GET == request->method && OC_EH_OK == result)
521 OCAddResourceTypeNameToPayload(payload);
522 OCAddResourceInterfaceNameToPayload(payload);
525 OCEntityHandlerResponse ehResponse = { .ehResult = result,
526 .payload = (OCPayload*) payload,
527 .requestHandle = request->requestId,
528 .resourceHandle = g_keepAliveHandle };
529 OICStrcpy(ehResponse.resourceUri, sizeof(ehResponse.resourceUri), KEEPALIVE_RESOURCE_URI);
531 // Send response message.
532 return OCDoResponse(&ehResponse);
535 OCEntityHandlerResult OCHandleKeepAliveGETRequest(OCServerRequest *request,
536 const OCResource *resource)
538 VERIFY_NON_NULL(request, FATAL, OC_EH_ERROR);
539 VERIFY_NON_NULL(resource, FATAL, OC_EH_ERROR);
541 OIC_LOG_V(DEBUG, TAG, "Find Ping resource [%s]", request->resourceUrl);
543 OCResource *resourcePtr = FindResourceByUri(request->resourceUrl);
546 // Resource URL not specified
547 OIC_LOG_V(DEBUG, TAG, "There is no Ping resource [%s]", request->resourceUrl);
548 return OC_EH_RESOURCE_NOT_FOUND;
554 OCEntityHandlerResult OCHandleKeepAlivePOSTRequest(OCServerRequest *request,
555 const OCResource *resource)
557 VERIFY_NON_NULL(request, FATAL, OC_EH_ERROR);
558 VERIFY_NON_NULL(resource, FATAL, OC_EH_ERROR);
560 int64_t interval = 0;
561 OCPayload *ocPayload = NULL;
562 OCStackResult result = OCParsePayload(&ocPayload, PAYLOAD_TYPE_REPRESENTATION,
563 request->payload, request->payloadSize);
564 if (OC_STACK_OK != result)
566 OIC_LOG(ERROR, TAG, "Representation parse failed");
569 bool findValue = OCRepPayloadGetPropInt((OCRepPayload *) ocPayload, INTERVAL, &interval);
572 OIC_LOG(ERROR, TAG, "Can't find the time interval property");
573 OCPayloadDestroy(ocPayload);
574 return OC_EH_BAD_REQ;
577 // Get entry from KeepAlive table.
578 CAEndpoint_t endpoint = { .adapter = OC_ADAPTER_TCP };
579 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
581 oc_mutex_lock(g_mutexObjectList);
582 KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(&endpoint);
585 OIC_LOG(ERROR, TAG, "Received the first keepalive message from client");
586 entry = OCAddKeepAliveEntry(&endpoint, OC_SERVER, 0);
589 oc_mutex_unlock(g_mutexObjectList);
590 OIC_LOG(ERROR, TAG, "Failed to add new keepalive entry");
591 OCPayloadDestroy(ocPayload);
592 return OC_EH_INTERNAL_SERVER_ERROR;
596 entry->interval = interval;
597 OIC_LOG_V(DEBUG, TAG, "Received interval is [%" PRId64 "]", entry->interval);
598 entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
599 oc_mutex_unlock(g_mutexObjectList);
601 OCPayloadDestroy(ocPayload);
605 void OCProcessKeepAlive()
607 oc_mutex_lock(g_mutexObjectList);
608 KeepAliveEntry_t *entry = NULL;
609 KeepAliveEntry_t *tmp = NULL;
610 LL_FOREACH_SAFE(g_keepAliveConnectionTable, entry, tmp)
614 uint64_t currentTime = OICGetCurrentTime(TIME_IN_US);
615 if (OC_CLIENT == entry->mode)
617 if (entry->sentPingMsg)
620 * If an OIC Client does not receive the response within 1 minutes,
621 * terminate the connection.
622 * In this case the timeStamp means last time sent ping message.
624 if ((KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp)
626 OIC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes.");
628 // Send message to disconnect session.
629 OCSendDisconnectMessage(entry);
633 else if (OC_SERVER == entry->mode)
636 * If an OIC Server does not receive a PUT/POST request to ping resource
637 * within the specified interval time, terminate the connection.
638 * In this case the timeStamp means last time received ping message.
640 if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC)
641 <= currentTime - entry->timeStamp)
643 OIC_LOG(DEBUG, TAG, "Server does not receive a PUT/POST request.");
644 OCSendDisconnectMessage(entry);
649 oc_mutex_unlock(g_mutexObjectList);
652 OCStackResult OCSendDisconnectMessage(const KeepAliveEntry_t *entry)
654 VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
656 // notify application that a client does not receive a response.
657 ClientCB *cbNode = GetClientCB(NULL, 0, entry->handle, NULL);
660 OCClientResponse response = { .devAddr = { .adapter = OC_DEFAULT_ADAPTER } };
661 CopyEndpointToDevAddr(&entry->remoteAddr, &response.devAddr);
662 FixUpClientResponse(&response);
663 response.resourceUri = cbNode->requestUri;
664 response.result = OC_STACK_TIMEOUT;
666 cbNode->callBack(cbNode->context, cbNode->handle, &response);
667 FindAndDeleteClientCB(cbNode);
670 CAEndpoint_t endpoint = entry->remoteAddr;
671 if (OC_STACK_OK != OCRemoveKeepAliveEntry(&endpoint))
673 OIC_LOG(ERROR, TAG, "OCRemoveKeepAliveEntry is failed");
674 return OC_STACK_ERROR;
678 * Send empty message to disconnect a connection.
679 * If CA get the empty message from RI, CA will disconnect a connection.
681 CAResult_t result = CAUtilTCPDisconnectSession(endpoint.addr, endpoint.port, endpoint.flags);
682 if (OC_STACK_OK != CAResultToOCResult(result))
684 OIC_LOG(ERROR, TAG, "Failed to disconnect session");
687 return CAResultToOCResult(result);
690 KeepAliveEntry_t *OCGetEntryFromEndpoint(const CAEndpoint_t *endpoint)
692 KeepAliveEntry_t *entry = NULL;
693 LL_FOREACH(g_keepAliveConnectionTable, entry)
697 if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
698 && (entry->remoteAddr.port == endpoint->port))
700 OIC_LOG(DEBUG, TAG, "Connection Info found in KeepAlive table");
709 KeepAliveEntry_t *OCAddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
714 OIC_LOG(ERROR, TAG, "endpoint is NULL");
718 KeepAliveEntry_t *entry = (KeepAliveEntry_t *) OICCalloc(1, sizeof(KeepAliveEntry_t));
721 OIC_LOG(ERROR, TAG, "Failed to Calloc KeepAlive Entry");
726 entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
727 entry->remoteAddr.adapter = endpoint->adapter;
728 entry->remoteAddr.flags = endpoint->flags;
729 entry->remoteAddr.ifindex = endpoint->ifindex;
730 entry->remoteAddr.port = endpoint->port;
731 strncpy(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr));
732 entry->interval = interval;
734 LL_APPEND(g_keepAliveConnectionTable, entry);
738 OCStackResult OCRemoveKeepAliveEntry(const CAEndpoint_t *endpoint)
740 OIC_LOG(DEBUG, TAG, "OCRemoveKeepAliveEntry IN");
742 VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
744 KeepAliveEntry_t *entry = NULL;
745 KeepAliveEntry_t *tmp = NULL;
746 LL_FOREACH_SAFE(g_keepAliveConnectionTable, entry, tmp)
750 if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
751 && (entry->remoteAddr.port == endpoint->port))
753 OIC_LOG_V(DEBUG, TAG, "Remove Connection Info from KeepAlive table, "
754 "remote addr=%s port:%d", entry->remoteAddr.addr,
755 entry->remoteAddr.port);
757 LL_DELETE(g_keepAliveConnectionTable, entry);
763 OIC_LOG(DEBUG, TAG, "OCRemoveKeepAliveEntry OUT");
767 void OCHandleKeepAliveConnCB(const CAEndpoint_t *endpoint, bool isConnected, bool isClient)
770 VERIFY_NON_NULL_NR(endpoint, FATAL);
774 OIC_LOG(DEBUG, TAG, "Received the connected device information from CA");
778 OIC_LOG(DEBUG, TAG, "Received the disconnected device information from CA");
780 // Do nothing because callback will be removed after one min.
782 // notify application that the session is disconnected.
783 oc_mutex_lock(g_mutexObjectList);
784 KeepAliveEntry_t *entry = OCGetEntryFromEndpoint(endpoint);
787 ClientCB *cbNode = GetClientCB(NULL, 0, entry->handle, NULL);
790 OCClientResponse response = { .devAddr = { .adapter = OC_ADAPTER_TCP } };
791 CopyEndpointToDevAddr(&entry->remoteAddr, &response.devAddr);
792 FixUpClientResponse(&response);
793 response.resourceUri = cbNode->requestUri;
794 response.result = OC_STACK_COMM_ERROR;
796 cbNode->callBack(cbNode->context, cbNode->handle, &response);
797 FindAndDeleteClientCB(cbNode);
799 OCRemoveKeepAliveEntry(endpoint);
801 oc_mutex_unlock(g_mutexObjectList);
806 OCRepPayload *OCCreateKeepAlivePayload(int64_t interval)
808 OIC_LOG_V(DEBUG, TAG, "Create KeepAlive Payload, interval is [%" PRId64 "]", interval);
810 OCRepPayload *payload = OCRepPayloadCreate();
813 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
816 payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
817 OCRepPayloadSetPropInt(payload, INTERVAL, interval);
822 OCStackResult OCAddResourceTypeNameToPayload(OCRepPayload *payload)
824 uint8_t numElement = 0;
825 OCStackResult res = OCGetNumberOfResourceTypes(g_keepAliveHandle, &numElement);
826 if (OC_STACK_OK == res)
828 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
829 char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
832 OIC_LOG(ERROR, TAG, "Could not allocate memory for rf");
833 return OC_STACK_NO_MEMORY;
835 for (uint8_t i = 0; i < numElement; ++i)
837 const char *value = OCGetResourceTypeName(g_keepAliveHandle, i);
838 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
839 rt[i] = OICStrdup(value);
842 OIC_LOG_V(ERROR, TAG, "Creating duplicate string for rt failed!");
843 for (uint8_t j = 0; j < i; ++j)
848 return OC_STACK_NO_MEMORY;
851 OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE, (const char **) rt, rtDim);
852 for (uint8_t i = 0; i < numElement; ++i)
862 OCStackResult OCAddResourceInterfaceNameToPayload(OCRepPayload *payload)
864 uint8_t numElement = 0;
865 OCStackResult res = OCGetNumberOfResourceInterfaces(g_keepAliveHandle, &numElement);
866 if (OC_STACK_OK == res)
868 size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
869 char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
872 OIC_LOG(ERROR, TAG, "Could not allocate memory for itf");
873 return OC_STACK_NO_MEMORY;
876 for (uint8_t i = 0; i < numElement; ++i)
878 const char *value = OCGetResourceInterfaceName(g_keepAliveHandle, i);
879 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
880 itf[i] = OICStrdup(value);
883 OIC_LOG_V(ERROR, TAG, "Creating duplicate string for itf failed!");
884 for (uint8_t j = 0; j < i; ++j)
889 return OC_STACK_NO_MEMORY;
892 OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE, (const char **) itf, ifDim);
893 for (uint8_t i = 0; i < numElement; ++i)