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 ******************************************************************/
23 #include "routingmanager.h"
24 #include "routingmanagerinterface.h"
25 #include "routingtablemanager.h"
26 #include "routingmessageparser.h"
27 #include "oic_malloc.h"
28 #include "oic_string.h"
30 #include "ulinklist.h"
31 #include "uarraylist.h"
32 #include "ocstackinternal.h"
33 #include "include/logger.h"
36 * Logging tag for module name.
41 * Tag for printing the logs of forwarding the packet.
43 #define RM_TAG "OIC_RM_RAP"
47 * Unique gateway ID generated before hosting a gateway resource.
49 static uint32_t g_GatewayID = 0;
52 * Used for assigning unique ID.to endpoint's connected to this gateway
54 static uint16_t g_EndpointCount = 0;
57 * Routing table which holds hop entries of Gateways with routeCost.
59 static u_linklist_t *g_routingGatewayTable = NULL;
62 * List which holds hop entries with Endpoint information.
64 static u_linklist_t *g_routingEndpointTable = NULL;
67 * Current time in microseconds.
69 static uint64_t g_aliveTime = 0;
72 * Time to refresh the table entries.
74 static uint64_t g_refreshTableTime = 0;
77 * Sequence number for the notification.
79 static uint32_t g_sequenceNumber = 1;
82 * To check if the routing table is validated on 25th seconds.
84 static bool g_isValidated = false;
87 * Multi cast Sequence number.
89 static uint16_t g_mcastsequenceNumber = 1;
92 * To check if RM is initialized.
94 static bool g_isRMInitialized = false;
97 * API to handle the GET request received for a Gateway Resource.
98 * @param[in] request Request Received.
99 * @param[in] resource Resource handle used for sending the response.
100 * @return ::OC_STACK_OK or Appropriate error code.
102 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource);
105 * API to handle the OBSERVE request received for a Gateway Resource.
106 * @param[in,out] request Request Received.
107 * @param[in] resource Resource handle used for sending the response.
108 * @return ::OC_STACK_OK or Appropriate error code.
110 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource);
113 * API to handle the OBSERVE request received for a Gateway Resource.
114 * @param[in,out] request Request Received.
115 * @param[in] resource Resource handle used for sending the response.
116 * @return ::OC_STACK_OK or Appropriate error code.
118 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource);
121 * Adds a observer after generating observer ID whenever observe
122 * request is received.
123 * @param[in,out] request Request handle of the Observe request.
124 * Sets the value of observeResult as OC_STACK_OK
125 * if observer is added successfully.
126 * @param[out] obsID Observer ID generated for the observer.
127 * @return ::OC_STACK_OK or Appropriate error code.
129 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID);
132 * Send Notification to all the observers.
133 * @param[in] payload Payload to be sent in notification.
134 * @return ::OC_STACK_OK or Appropriate error code.
136 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload);
139 * Send Delete request to all the neighbour nodes.
142 void RMSendDeleteToNeighbourNodes();
144 void RMGenerateGatewayID(uint8_t *id, size_t idLen)
146 OIC_LOG(DEBUG, TAG, "RMGenerateGatewayID IN");
147 OCFillRandomMem(id, idLen);
148 OIC_LOG(DEBUG, TAG, "RMGenerateGatewayID OUT");
150 OCStackResult RMInitialize()
152 OIC_LOG(DEBUG, TAG, "RMInitialize IN");
153 if (g_isRMInitialized)
155 OIC_LOG(DEBUG, TAG, "RM already initialized");
159 // Initialize the GatewayResource[/oic/gateway].
160 OCStackResult result = RMInitGatewayResource();
161 if (OC_STACK_OK != result)
163 OIC_LOG_V(ERROR, TAG, "RMInitGatewayResource failed[%d]", result);
167 // Generates a 4 byte Gateway ID.
168 RMGenerateGatewayID((uint8_t *)&g_GatewayID, sizeof(g_GatewayID));
170 OIC_LOG_V(INFO, RM_TAG, "Gateway ID: %u", g_GatewayID);
172 // Initialize the Routing table manager.
173 result = RTMInitialize(&g_routingGatewayTable, &g_routingEndpointTable);
174 if (OC_STACK_OK != result)
176 OIC_LOG_V(ERROR, TAG, "RTMInitialize failed[%d]", result);
180 g_isRMInitialized = true;
182 // Send a DISCOVER request for the gateway resource.
183 result = RMDiscoverGatewayResource();
184 if (OC_STACK_OK != result)
186 OIC_LOG_V(ERROR, TAG, "RMDiscoverGatewayResource failed[%d]", result);
187 RTMTerminate(&g_routingGatewayTable, &g_routingEndpointTable);
191 // Initialize the timer with the current time.
192 g_aliveTime = RTMGetCurrentTime();
193 g_refreshTableTime = g_aliveTime;
195 OIC_LOG(DEBUG, TAG, "RMInitialize OUT");
199 OCStackResult RMTerminate()
201 OIC_LOG(DEBUG, TAG, "RMTerminate IN");
202 if (!g_isRMInitialized)
204 OIC_LOG(ERROR, TAG, "RM not initialized");
205 return OC_STACK_ERROR;
207 // Send DELETE request to neighbour nodes
208 RMSendDeleteToNeighbourNodes();
210 OCStackResult result = RTMTerminate(&g_routingGatewayTable, &g_routingEndpointTable);
211 if (OC_STACK_OK != result)
213 OIC_LOG_V(ERROR, TAG, "CARegisterRoutingMessageHandler failed[%d]", result);
216 g_isRMInitialized = false;
217 OIC_LOG(DEBUG, TAG, "RMTerminate OUT");
221 OCStackResult RMHandleGatewayRequest(OCServerRequest *request, const OCResource *resource)
223 OIC_LOG(DEBUG, TAG, "RMHandleGatewayRequest IN");
225 if (!g_isRMInitialized)
227 OIC_LOG(ERROR, TAG, "RM not initialized");
228 return OC_STACK_ERROR;
231 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
232 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
234 OIC_LOG_V(DEBUG, TAG, "Received request of method: %d", request->method);
236 if (OC_REST_GET == request->method)
238 switch((OCObserveAction)request->observationOption)
240 case OC_OBSERVE_REGISTER:
241 OIC_LOG(DEBUG, TAG, "Received OBSERVE request");
242 RMHandleOBSERVERequest(request, resource);
244 case OC_OBSERVE_DEREGISTER:
245 //TODO: Handle this case
246 OIC_LOG(DEBUG, TAG, "Received OBSERVE deregister");
248 case OC_OBSERVE_NO_OPTION:
249 OIC_LOG(DEBUG, TAG, "Received GET request");
250 RMHandleGETRequest(request, resource);
253 OIC_LOG(DEBUG, TAG, "Not Supported by Routing Manager");
256 else if (OC_REST_DELETE == request->method)
258 OIC_LOG(DEBUG, TAG, "Received a Delete request");
259 RMHandleDELETERequest(request, resource);
261 OIC_LOG(DEBUG, TAG, "RMHandleGatewayRequest OUT");
265 OCStackResult RMHandleRequestPayload(OCDevAddr devAddr, const uint8_t *reqPayload,
268 OIC_LOG(DEBUG, TAG, "RMHandleRequestPayload IN");
269 RM_NULL_CHECK_WITH_RET(reqPayload, TAG, "reqPayload");
271 uint32_t gatewayId = 0;
273 OCStackResult result = RMPParseRequestPayload(reqPayload, payloadSize, &gatewayId);
274 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
275 OIC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
276 // Check if the entry is its own.
277 if (gatewayId == g_GatewayID)
279 OIC_LOG(INFO, TAG, "Own Request Received!!");
280 return OC_STACK_CONTINUE;
283 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
284 CopyDevAddrToEndpoint(&devAddr, &endpoint);
286 OIC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
287 RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
288 destInterfaces.destIntfAddr = endpoint;
289 result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
291 if (OC_STACK_OK != result)
293 OIC_LOG(DEBUG, TAG, "Gateway was not added to the routing table");
297 OIC_LOG(INFO, TAG, "Gateway was added");
298 // Create a list to add the updated entries and notify the observers
299 u_linklist_t *updatedTableList = u_linklist_create();
300 if(!updatedTableList)
302 OIC_LOG(DEBUG, TAG, "Failure to notify");
303 return OC_STACK_NO_MEMORY;
306 RTMGatewayId_t gwId = {.gatewayId = gatewayId};
307 RTMGatewayEntry_t newNode;
308 newNode.destination = &gwId;
309 newNode.routeCost = 1;
310 u_linklist_add(updatedTableList, (void *)&newNode);
311 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
313 OCRepPayload *updatedPayload = NULL;
316 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
317 updatedTableList, false,
319 if (OC_STACK_OK != result)
321 OIC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
322 RMPFreePayload(updatedPayload);
326 result = RMSendNotificationToAll(updatedPayload);
327 RMPFreePayload(updatedPayload);
328 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
331 u_linklist_free(&updatedTableList);
332 OIC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT");
336 OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload)
338 OIC_LOG(DEBUG, TAG, "RMHandleResponsePayload IN");
339 RM_NULL_CHECK_WITH_RET(respPayload, TAG, "respPayload");
341 // Parse the Payload to get the Gateway ID of neighbouring node.
342 uint32_t gatewayId = 0;
344 u_linklist_t *gatewayTableList = NULL;
345 bool isUpdateSeqNum = false;
347 OCStackResult result = RMPParseResponsePayload(respPayload, &gatewayId, &seqNum,
348 &gatewayTableList, &isUpdateSeqNum);
349 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
350 // Check if the entry is its own.
351 if (gatewayId == g_GatewayID)
353 OIC_LOG(INFO, TAG, "-------------->Own entry, continue!!");
354 RTMFreeGatewayRouteTable(&gatewayTableList);
355 return OC_STACK_ERROR;
357 // Convert OCDevAddr to endpoint address
358 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS};
359 CopyDevAddrToEndpoint(devAddr, &endpoint);
360 RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
361 destInterfaces.destIntfAddr = endpoint;
364 OIC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d",
365 seqNum, isUpdateSeqNum);
366 result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces,
367 &g_routingGatewayTable, isUpdateSeqNum);
368 if (OC_STACK_COMM_ERROR == result)
370 OIC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching");
371 // Send a observe request to the gateway.
372 RMSendObserveRequest(devAddr, NULL);
373 RTMFreeGatewayRouteTable(&gatewayTableList);
376 else if (OC_STACK_DUPLICATE_REQUEST == result)
378 OIC_LOG(ERROR, TAG, "Same sequence number is received");
379 RTMFreeGatewayRouteTable(&gatewayTableList);
384 // Check if the payload is for Removal
385 bool doRemoveEntry = false;
387 if (NULL != gatewayTableList && NULL != gatewayTableList->list)
389 RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list);
390 if (headPtr && 0 == headPtr->routeCost)
392 OIC_LOG(INFO, TAG, "Remove entry is called");
393 doRemoveEntry = true;
397 // Create a list to add the updated entries and notify the observers
398 u_linklist_t *updatedTableList = u_linklist_create();
399 if(!updatedTableList)
401 OIC_LOG(DEBUG, TAG, "Failed to allocate memory");
402 return OC_STACK_NO_MEMORY;
405 u_linklist_t *alternativeRouteList = u_linklist_create();
406 if(!alternativeRouteList)
408 OIC_LOG(DEBUG, TAG, "Failed to allocate memory");
409 return OC_STACK_NO_MEMORY;
412 OCRepPayload *updatedPayload = NULL;
413 if (false == doRemoveEntry)
415 OIC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
416 result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
417 if (OC_STACK_OK == result)
419 OIC_LOG(INFO, TAG, "Node was added");
420 RTMGatewayId_t gwId = {.gatewayId = gatewayId};
421 RTMGatewayEntry_t newNode;
422 newNode.destination = &gwId;
423 newNode.routeCost = 1;
424 u_linklist_add(updatedTableList, (void *)&newNode);
425 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
427 if (NULL == gatewayTableList)
429 OIC_LOG(INFO, TAG, "Received a Discover Payload");
431 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
432 updatedTableList, false,
434 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
435 goto sendNotification;
440 // Iterate the Table and get each entry
441 u_linklist_iterator_t *iterTable = NULL;
442 u_linklist_init_iterator(gatewayTableList, &iterTable);
444 while (NULL != iterTable)
446 RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
447 // Check if the entry is its own.
448 if (!entry || entry->destination->gatewayId == g_GatewayID)
450 OIC_LOG(INFO, TAG, "Ignore entry, continue!!");
451 u_linklist_get_next(&iterTable);
455 OIC_LOG_V(INFO, TAG, "Gateway ID: %u", entry->destination->gatewayId);
456 if (true == doRemoveEntry)
458 // Remove the entry from RTM.
459 RTMGatewayEntry_t *existEntry = NULL;
460 result = RTMRemoveGatewayDestEntry(entry->destination->gatewayId, gatewayId,
461 &destInterfaces, &existEntry,
462 &g_routingGatewayTable);
463 if (OC_STACK_OK != result && NULL != existEntry)
465 u_linklist_add(alternativeRouteList, (void *)existEntry);
470 // Add the entry to RTM.
471 entry->routeCost = entry->routeCost + 1;
472 result = RTMAddGatewayEntry(entry->destination->gatewayId, gatewayId,
473 entry->routeCost, NULL, &g_routingGatewayTable);
476 if (OC_STACK_OK == result)
478 OIC_LOG(INFO, TAG, "Gateway was added/removed");
479 u_linklist_add(updatedTableList, (void *)entry);
480 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
482 u_linklist_get_next(&iterTable);
485 if ( 0 < u_linklist_length(alternativeRouteList))
487 OIC_LOG(DEBUG, TAG, "Alternative routing found");
488 // Send the notification.
489 OCRepPayload *removeTablePayload = NULL;
491 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
492 alternativeRouteList, false,
493 &removeTablePayload);
494 if (OC_STACK_OK != result)
496 OIC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
497 RMPFreePayload(removeTablePayload);
500 result = RMSendNotificationToAll(removeTablePayload);
501 RMPFreePayload(removeTablePayload);
502 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
505 if ( 0 >= u_linklist_length(updatedTableList))
507 OIC_LOG_V(DEBUG, TAG, "No updation is needed, Length is %d",
508 u_linklist_length(updatedTableList));
513 if (true == doRemoveEntry)
515 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, updatedTableList,
516 false, &updatedPayload);
520 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
521 updatedTableList, false,
524 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
527 result = RMSendNotificationToAll(updatedPayload);
528 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
531 RMPFreePayload(updatedPayload);
532 RTMFreeGatewayRouteTable(&gatewayTableList);
533 u_linklist_free(&updatedTableList);
534 u_linklist_free(&alternativeRouteList);
535 OIC_LOG(DEBUG, TAG, "RMHandleResponsePayload OUT");
539 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource)
541 OIC_LOG(DEBUG, TAG, "RMHandleGETRequest IN");
542 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
543 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
545 OCRepPayload *payload = NULL;
546 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
547 if (OC_STACK_OK != result)
549 OIC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload failed[%d]", result);
553 // Send a response for GET request
554 result = RMSendResponse(request, resource, payload);
555 if (OC_STACK_OK != result)
557 OIC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
558 RMPFreePayload(payload);
562 RMPFreePayload(payload);
563 // Send a observe request
564 result = RMSendObserveRequest(&(request->devAddr), NULL);
565 if (OC_STACK_OK != result)
567 OIC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
569 OIC_LOG(DEBUG, TAG, "RMHandleGETRequest OUT");
573 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource)
575 OIC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest IN");
576 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
577 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
579 // Parse payload and add the gateway entry.
580 if (0 < request->payloadSize)
582 RMHandleRequestPayload(request->devAddr, request->payload, request->payloadSize);
585 // Generate and add observer.
586 OCObservationId obsID = 0;
587 OCStackResult result = RMAddObserver(request, &obsID);
588 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
589 OIC_LOG_V(DEBUG, TAG, "Observer ID is %d", obsID);
592 // Get the Routing table from RTM
593 OCRepPayload *payload = NULL;
594 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
595 OIC_LOG(DEBUG, TAG, "Construct Routing table payload");
596 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
597 g_routingGatewayTable, true,
599 if (OC_STACK_OK != result)
601 OIC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
602 RMPFreePayload(payload);
606 result = RMSendResponse(request, resource, payload);
607 RMPFreePayload(payload);
608 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
610 OIC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest OUT");
614 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource)
616 OIC_LOG(DEBUG, TAG, "RMHandleDELETERequest IN");
617 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
618 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
620 uint32_t gatewayId = 0;
621 OCStackResult result = RMPParseRequestPayload(request->payload, request->payloadSize,
623 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
624 OIC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
626 OIC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", gatewayId);
628 u_linklist_t *removedGatewayNodes = NULL;
629 result = RTMRemoveGatewayEntry(gatewayId, &removedGatewayNodes, &g_routingGatewayTable);
630 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
632 if (0 < u_linklist_length(removedGatewayNodes))
634 OCRepPayload *resPayloads = NULL;
636 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedGatewayNodes,
637 false, &resPayloads);
638 if (OC_STACK_OK != result)
640 OIC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
641 RMPFreePayload(resPayloads);
644 result = RMSendNotificationToAll(resPayloads);
645 RMPFreePayload(resPayloads);
646 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
647 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
651 RTMFreeGatewayRouteTable(&removedGatewayNodes);
652 OIC_LOG(DEBUG, TAG, "RMHandleDELETERequest OUT");
656 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID)
658 OIC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
659 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
660 RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
662 // Generate the ObserverID
663 CAEndpoint_t endpoint = {.adapter = 0};
664 CopyDevAddrToEndpoint(&(request->devAddr), &endpoint);
666 // Check if observer is already added.
667 if (true == RTMIsObserverPresent(endpoint, obsID, g_routingGatewayTable))
669 OIC_LOG(DEBUG, TAG, "Observer is present");
670 request->observeResult = OC_STACK_OK;
674 OCStackResult result = RMAddObserverToStack(request, obsID);
675 request->observeResult = result;
676 if (OC_STACK_OK == result)
678 OIC_LOG(DEBUG, TAG, "Added observer successfully");
680 // Add the observer to the list.
681 result = RTMAddObserver(*obsID, endpoint, &g_routingGatewayTable);
682 if (OC_STACK_OK != result)
684 OIC_LOG_V(DEBUG, TAG, "RMAddObserver failed[%d]", result);
687 OIC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
691 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload)
693 OIC_LOG(DEBUG, TAG, "RMSendNotificationToAll IN");
694 RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
696 OCObservationId *obsList = NULL;
698 // Get the complete observer list.
699 RTMGetObserverList(&obsList, &obsLen, g_routingGatewayTable);
700 OCStackResult result = OC_STACK_OK;
701 OIC_LOG_V(DEBUG, TAG, "Number of observers is %d", obsLen);
704 // Send notification to the list of observers.
705 OIC_LOG_V(DEBUG, TAG, "Sending notification with Sequence Number: %d", g_sequenceNumber);
706 result = RMSendNotificationForListofObservers(obsList, obsLen, payload);
707 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
708 g_aliveTime = RTMGetCurrentTime();
713 OIC_LOG(DEBUG, TAG, "RMSendNotificationToAll OUT");
717 #ifdef WITH_PROCESS_EVENT
718 static void compareAndApplyTimeout(uint32_t *nextEventTime,
721 uint32_t timeoutMs = timeoutSec * MS_PER_SEC;
722 if (timeoutMs < *nextEventTime)
724 *nextEventTime = timeoutMs;
728 void RMProcess(uint32_t *nextEventTime)
729 #else // WITH_PROCESS_EVENT
731 #endif // !WITH_PROCESS_EVENT
733 if (!g_isRMInitialized)
738 OCStackResult result = OC_STACK_OK;
739 uint64_t currentTime = RTMGetCurrentTime();
740 if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
742 g_aliveTime = currentTime;
743 // Construct a payload with only the current sequence number.
744 OCRepPayload *payload = NULL;
745 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
747 if (OC_STACK_OK != result)
749 OIC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
750 RMPFreePayload(payload);
753 OIC_LOG(DEBUG, TAG, "Sending the alive notification to all");
754 // Send notification for every 15s to all the neighbours.
755 result = RMSendNotificationToAll(payload);
756 RMPFreePayload(payload);
757 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
758 #ifdef WITH_PROCESS_EVENT
759 compareAndApplyTimeout(nextEventTime, GATEWAY_ALIVE_TIMEOUT);
760 #endif // WITH_PROCESS_EVENT
762 #ifdef WITH_PROCESS_EVENT
765 compareAndApplyTimeout(nextEventTime,
766 GATEWAY_ALIVE_TIMEOUT - (currentTime - g_aliveTime));
768 #endif // WITH_PROCESS_EVENT
770 if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
772 OIC_LOG(DEBUG, TAG, "Validating the routing table");
773 u_linklist_t *removedEntries = NULL;
774 // Remove the invalid gateway entries.
775 RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
776 if (0 < u_linklist_length(removedEntries))
778 OCRepPayload *resPayloads = NULL;
780 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
781 false, &resPayloads);
782 RTMFreeGatewayRouteTable(&removedEntries);
783 if (OC_STACK_OK != result)
785 OIC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
786 RMPFreePayload(resPayloads);
789 result = RMSendNotificationToAll(resPayloads);
790 RMPFreePayload(resPayloads);
791 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
792 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
794 g_refreshTableTime = currentTime;
795 g_isValidated = false;
796 u_linklist_free(&removedEntries);
797 #ifdef WITH_PROCESS_EVENT
798 compareAndApplyTimeout(nextEventTime, ROUTINGTABLE_VALIDATION_TIMEOUT);
799 #endif // WITH_PROCESS_EVENT
802 #ifdef WITH_PROCESS_EVENT
805 compareAndApplyTimeout(nextEventTime,
806 ROUTINGTABLE_VALIDATION_TIMEOUT - (currentTime - g_refreshTableTime));
808 #endif // WITH_PROCESS_EVENT
810 if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
812 OIC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %llu", currentTime);
813 u_linklist_t* invalidInterfaces = NULL;
814 RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
815 if (0 < u_linklist_length(invalidInterfaces))
817 u_linklist_iterator_t *iterTable = NULL;
818 u_linklist_init_iterator(invalidInterfaces, &iterTable);
819 while (NULL != iterTable)
821 RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
824 u_linklist_get_next(&iterTable);
827 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
828 CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
829 RMSendObserveRequest(&devAddr, NULL);
830 u_linklist_get_next(&iterTable);
833 g_isValidated = true;
834 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
835 u_linklist_free(&invalidInterfaces);
836 #ifdef WITH_PROCESS_EVENT
837 compareAndApplyTimeout(nextEventTime, ROUTINGTABLE_REFRESH_TIMEOUT);
838 #endif // WITH_PROCESS_EVENT
840 #ifdef WITH_PROCESS_EVENT
843 compareAndApplyTimeout(nextEventTime,
844 ROUTINGTABLE_REFRESH_TIMEOUT - (currentTime - g_refreshTableTime));
846 #endif // WITH_PROCESS_EVENT
852 OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
854 OIC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
855 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
856 OIC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
857 OIC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
861 void RMSendDeleteToNeighbourNodes()
863 OIC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
864 u_linklist_t *neighbourNodes = NULL;
865 RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
867 if (0 >= u_linklist_length(neighbourNodes))
869 OIC_LOG(DEBUG, TAG, "No neighbour nodes present");
873 u_linklist_iterator_t *iterTable = NULL;
874 u_linklist_init_iterator(neighbourNodes, &iterTable);
875 while (NULL != iterTable)
878 OCRepPayload *payload = NULL;
879 // Created payload is freed in the OCDoResource() api.
880 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
881 if (OC_STACK_OK != result)
883 OIC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
884 RMPFreePayload(payload);
885 u_linklist_free(&neighbourNodes);
889 RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
892 for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
894 RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
897 OIC_LOG(ERROR, RM_TAG, "Failed to get dest address");
900 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
901 CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
902 OIC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
903 dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
904 RMSendDeleteRequest(&devAddr, payload);
908 u_linklist_get_next(&iterTable);
911 u_linklist_free(&neighbourNodes);
912 OIC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
915 uint32_t RMGetGatewayId()
917 if (!g_isRMInitialized)
919 OIC_LOG(ERROR, TAG, "RM not initialized");
925 uint16_t RMGetMcastSeqNumber()
927 if (!g_isRMInitialized)
929 OIC_LOG(DEBUG, TAG, "RM not initialized");
932 return ++g_mcastsequenceNumber;
936 * This function is lifeline of packet forwarding module, hence we are going to do some serious
937 * handling here. Following are the expectations from this function:
938 * 1) If routing option is not available, forward packet to RI only. else:
939 * 2) If source is empty in routing option, packet is from end device, add an end device entry and
940 * add "GatewayId:ClientId" as source.
941 * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
942 * multicast on other interfaces. Also remove routing Option and forward to RI. (Before
943 * forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
945 * 4) If destination is present in routing option, its unicast packet,
946 * a) If self gatewayId is present in destination and no clientId, remove routing option
948 * b) If self gatewayId and a clientId is present in destination, forward to end device.
949 * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
952 OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
953 bool *selfDestination, bool *isEmptyMsg)
955 RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
956 RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
957 RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
959 bool forward = false;
960 bool isEMPTYPacket = false;
961 CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
962 CAInfo_t *info = NULL;
965 CARequestInfo_t *msg = message;
967 RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
971 CAResponseInfo_t *msg = message;
973 RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
976 // 1. If routing option is not available, forward packet to RI only.
977 int8_t routeIndex = -1;
978 RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
979 if (-1 >= routeIndex)
981 OIC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
982 // Let RI handle this packet.
983 *selfDestination = true;
987 // Get existing values in packet route option.
988 RMRouteOption_t routeOption = {.srcGw = 0};
989 OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
990 if (OC_STACK_OK != res)
992 OIC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
993 return OC_STACK_ERROR;
997 * 2) If source is empty in routing option, packet is from end device, add an end device entry
998 * and add "GatewayId:ClientId" as source.
1000 if (g_GatewayID == routeOption.srcGw)
1002 OIC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
1003 if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
1005 g_mcastsequenceNumber = routeOption.mSeqNum;
1008 return OC_STACK_ERROR;
1010 else if (0 == routeOption.srcGw)
1012 OIC_LOG(INFO, RM_TAG, "Source missing in option");
1013 // Packet from end device as Gateway will add source in option.
1014 uint16_t endpointId = g_EndpointCount + 1;
1015 OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
1016 if (OC_STACK_OK == res)
1018 g_EndpointCount = endpointId;
1019 OIC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
1021 else if (OC_STACK_DUPLICATE_REQUEST == res)
1023 OIC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
1027 OIC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
1028 return OC_STACK_ERROR;
1031 // add source option.
1032 routeOption.srcGw = g_GatewayID;
1033 routeOption.srcEp = endpointId;
1034 OIC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
1038 * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
1039 * multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
1040 * caller of this function).
1042 if (0 == routeOption.destGw)
1044 OIC_LOG(INFO, RM_TAG, "Destination missing in option");
1045 // This is a multicast packet.
1046 if (g_GatewayID == routeOption.srcGw)
1048 routeOption.mSeqNum = ++g_mcastsequenceNumber;
1052 OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
1053 &g_routingGatewayTable);
1054 if (OC_STACK_OK != update)
1056 // this shouldnt have been forwarded. ignore.
1057 OIC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
1058 routeOption.mSeqNum);
1059 return OC_STACK_ERROR;
1064 *selfDestination = true;
1067 // Send multicast on every adapter except the one from which packet was received
1068 // TODO::: support to be added for IP hop.
1069 if (sender->adapter != CA_ADAPTER_IP)
1071 nextHop.adapter |= CA_ADAPTER_IP;
1072 nextHop.flags |= CA_IPV4 | CA_IPV6;
1075 if(sender->adapter != CA_ADAPTER_GATT_BTLE)
1077 nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
1080 if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
1082 nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
1085 // Only requests are sent as multicast.
1088 CARequestInfo_t *msg = message;
1089 msg->isMulticast = true;
1091 goto rewriteandexit;
1093 else if (g_GatewayID == routeOption.destGw)
1095 OIC_LOG(INFO, RM_TAG, "GatewayId found in destination");
1097 // Check the MSGType of RouteOption to find if the packet is EMPTY packet.
1098 if (ACK == routeOption.msgType || RST == routeOption.msgType)
1100 isEMPTYPacket = true;
1104 * This unicast packet either belongs to us or any of our connected end devices
1105 * check if packet belongs to end device.
1107 if (0 != routeOption.destEp)
1109 // forward packet to the client.
1110 OIC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1111 CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1112 g_routingEndpointTable);
1115 OIC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1116 return OC_STACK_ERROR;
1119 nextHop = *clientInfo;
1121 *selfDestination = false;
1122 goto rewriteandexit;
1126 // packet is for us.
1127 OIC_LOG(INFO, RM_TAG, "Received packet for self");
1129 *selfDestination = true;
1130 goto rewriteandexit;
1136 * This unicast packet belongs to other gateway.
1137 * we only want to print first 4 bytes of packet as readable GatewayId.
1139 OIC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1140 RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1143 OIC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1144 return OC_STACK_ERROR;
1147 // TODO:: check preferences among multiple interface addresses, for now sending on first one
1148 RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1151 OIC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1152 return OC_STACK_ERROR;
1155 nextHop = address->destIntfAddr;
1157 *selfDestination = false;
1158 goto rewriteandexit;
1165 // Don't forward any packet meant for gateway resource.
1166 if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)) &&
1167 (ACK != routeOption.msgType))
1169 OIC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1171 else if (sender->flags & CA_SECURE)
1173 OIC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1174 return OC_STACK_ERROR;
1176 else if (isEMPTYPacket)
1178 OIC_LOG(DEBUG, TAG, "The message to be Forwarded is a EMPTY message");
1179 CAResponseInfo_t responseMessage = {.result = CA_EMPTY};
1180 if (ACK == routeOption.msgType)
1182 responseMessage.info.type = CA_MSG_ACKNOWLEDGE;
1186 responseMessage.info.type = CA_MSG_RESET;
1189 responseMessage.info.messageId = info->messageId;
1190 responseMessage.info.dataType = CA_RESPONSE_DATA;
1192 CAResult_t caRes = CASendResponse(&nextHop, &responseMessage);
1193 if (CA_STATUS_OK != caRes)
1195 OIC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1196 caRes, nextHop.addr);
1197 // Since a response is always unicast, return error here.
1198 return OC_STACK_ERROR;
1203 // rewrite any changes in routing option.
1204 res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1205 if (OC_STACK_OK != res)
1207 OIC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1211 * When forwarding a packet, do not attempt retransmission as its the responsibility of
1212 * packet originator node.
1214 info->skipRetransmission = true;
1217 CARequestInfo_t *msg = message;
1218 msg->info.dataType = CA_REQUEST_DATA;
1219 CAResult_t caRes = CASendRequest(&nextHop, msg);
1220 if (CA_STATUS_OK != caRes)
1222 OIC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1224 if(0 == routeOption.destGw)
1227 * No point going forward as unicast packet could not be forwarded
1228 * not returning error for multicast as we may still let RI process
1231 return OC_STACK_ERROR;
1237 CAResponseInfo_t *msg = message;
1238 msg->info.dataType = CA_RESPONSE_DATA;
1239 CAResult_t caRes = CASendResponse(&nextHop, msg);
1240 if (CA_STATUS_OK != caRes)
1242 OIC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1243 caRes, nextHop.addr);
1244 // Since a response is always unicast, return error here.
1245 return OC_STACK_ERROR;
1256 OIC_LOG(DEBUG, TAG, "POST message with type ACK in Route Option");
1257 if (NULL != isEmptyMsg)
1264 OIC_LOG(DEBUG, TAG, "Response for EMPTY message is received");
1265 CAResponseInfo_t *msg = message;
1266 if (ACK == (MSGType)routeOption.msgType)
1268 msg->info.type = CA_MSG_ACKNOWLEDGE;
1272 msg->info.type = CA_MSG_RESET;
1274 msg->result = CA_EMPTY;
1275 OICFree(msg->info.token);
1276 msg->info.token = NULL;
1277 msg->info.tokenLength = 0;
1282 OIC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1286 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1287 bool *selfDestination, bool *isEmptyMsg)
1289 if (!g_isRMInitialized)
1291 OIC_LOG(INFO, TAG, "RM not initialized");
1292 *selfDestination = true;
1295 OCStackResult res = RMHandlePacket(true, message, sender, selfDestination, isEmptyMsg);
1299 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1300 bool *selfDestination)
1302 if (!g_isRMInitialized)
1304 OIC_LOG(INFO, TAG, "RM not initialized");
1305 *selfDestination = true;
1308 OCStackResult res = RMHandlePacket(false, message, sender, selfDestination, NULL);