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.
47 * Unique gateway ID generated before hosting a gateway resource.
49 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 OC_LOG(DEBUG, TAG, "RMGenerateGatewayID IN");
147 OCFillRandomMem(id, idLen);
148 OC_LOG(DEBUG, TAG, "RMGenerateGatewayID OUT");
150 OCStackResult RMInitialize()
152 OC_LOG(DEBUG, TAG, "RMInitialize IN");
153 if (g_isRMInitialized)
155 OC_LOG(DEBUG, TAG, "RM already initialized");
159 // Initialize the GatewayResource[/oic/gateway].
160 OCStackResult result = RMInitGatewayResource();
161 if (OC_STACK_OK != result)
163 OC_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 OC_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 OC_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 OC_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 OC_LOG(DEBUG, TAG, "RMInitialize OUT");
199 OCStackResult RMTerminate()
201 OC_LOG(DEBUG, TAG, "RMTerminate IN");
202 if (!g_isRMInitialized)
204 OC_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 OC_LOG_V(ERROR, TAG, "CARegisterRoutingMessageHandler failed[%d]", result);
216 g_isRMInitialized = false;
217 OC_LOG(DEBUG, TAG, "RMTerminate OUT");
221 OCStackResult RMHandleGatewayRequest(OCServerRequest *request, const OCResource *resource)
223 OC_LOG(DEBUG, TAG, "RMHandleGatewayRequest IN");
225 if (!g_isRMInitialized)
227 OC_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 OC_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 OC_LOG(DEBUG, TAG, "Received OBSERVE request");
242 RMHandleOBSERVERequest(request, resource);
244 case OC_OBSERVE_DEREGISTER:
245 //TODO: Handle this case
246 OC_LOG(DEBUG, TAG, "Received OBSERVE deregister");
248 case OC_OBSERVE_NO_OPTION:
249 OC_LOG(DEBUG, TAG, "Received GET request");
250 RMHandleGETRequest(request, resource);
253 OC_LOG(DEBUG, TAG, "Not Supported by Routing Manager");
256 else if (OC_REST_DELETE == request->method)
258 OC_LOG(DEBUG, TAG, "Received a Delete request");
259 RMHandleDELETERequest(request, resource);
261 OC_LOG(DEBUG, TAG, "RMHandleGatewayRequest OUT");
265 OCStackResult RMHandleRequestPayload(OCDevAddr devAddr, const uint8_t *reqPayload,
268 OC_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 OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
276 // Check if the entry is its own.
277 if (gatewayId == g_GatewayID)
279 OC_LOG(INFO, TAG, "Own Request Received!!");
280 return OC_STACK_CONTINUE;
283 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
284 CopyDevAddrToEndpoint(&devAddr, &endpoint);
286 OC_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 OC_LOG(DEBUG, TAG, "Gateway was not added to the routing table");
297 OC_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 OC_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 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
321 result = RMSendNotificationToAll(updatedPayload);
322 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
323 RMPFreePayload(updatedPayload);
326 u_linklist_free(&updatedTableList);
327 OC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT");
331 OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload)
333 OC_LOG(DEBUG, TAG, "RMHandleResponsePayload IN");
334 RM_NULL_CHECK_WITH_RET(respPayload, TAG, "respPayload");
336 // Parse the Payload to get the Gateway ID of neighbouring node.
337 uint32_t gatewayId = 0;
339 u_linklist_t *gatewayTableList = NULL;
340 bool isUpdateSeqNum = false;
342 OCStackResult result = RMPParseResponsePayload(respPayload, &gatewayId, &seqNum,
343 &gatewayTableList, &isUpdateSeqNum);
344 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
345 // Check if the entry is its own.
346 if (gatewayId == g_GatewayID)
348 OC_LOG(INFO, TAG, "-------------->Own entry, continue!!");
349 return OC_STACK_ERROR;
351 // Convert OCDevAddr to endpoint address
352 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS};
353 CopyDevAddrToEndpoint(devAddr, &endpoint);
354 RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
355 destInterfaces.destIntfAddr = endpoint;
358 OC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d",
359 seqNum, isUpdateSeqNum);
360 result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces,
361 &g_routingGatewayTable, isUpdateSeqNum);
362 if (OC_STACK_COMM_ERROR == result)
364 OC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching");
365 // Send a observe request to the gateway.
366 RMSendObserveRequest(devAddr, NULL);
369 else if (OC_STACK_DUPLICATE_REQUEST == result)
371 OC_LOG(ERROR, TAG, "Same sequence number is received");
376 // Check if the payload is for Removal
377 bool doRemoveEntry = false;
379 if (NULL != gatewayTableList && NULL != gatewayTableList->list)
381 RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list);
382 if (headPtr && 0 == headPtr->routeCost)
384 OC_LOG(INFO, TAG, "Remove entry is called");
385 doRemoveEntry = true;
389 // Create a list to add the updated entries and notify the observers
390 u_linklist_t *updatedTableList = u_linklist_create();
391 u_linklist_t *alternativeRouteList = u_linklist_create();
392 OCRepPayload *updatedPayload = NULL;
393 if (false == doRemoveEntry)
395 OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
396 result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
397 if (OC_STACK_OK == result)
399 OC_LOG(INFO, TAG, "Node was added");
400 RTMGatewayId_t gwId = {.gatewayId = gatewayId};
401 RTMGatewayEntry_t newNode;
402 newNode.destination = &gwId;
403 newNode.routeCost = 1;
404 u_linklist_add(updatedTableList, (void *)&newNode);
405 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
407 if (NULL == gatewayTableList)
409 OC_LOG(INFO, TAG, "Received a Discover Payload");
411 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
412 updatedTableList, false,
414 goto sendNotification;
419 // Iterate the Table and get each entry
420 u_linklist_iterator_t *iterTable = NULL;
421 u_linklist_init_iterator(gatewayTableList, &iterTable);
423 while (NULL != iterTable)
425 RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
426 // Check if the entry is its own.
427 if (!entry || entry->destination->gatewayId == g_GatewayID)
429 OC_LOG(INFO, TAG, "Ignore entry, continue!!");
430 u_linklist_get_next(&iterTable);
434 OC_LOG_V(INFO, TAG, "Gateway ID: %u", entry->destination->gatewayId);
435 if (true == doRemoveEntry)
437 // Remove the entry from RTM.
438 RTMGatewayEntry_t *existEntry = NULL;
439 result = RTMRemoveGatewayDestEntry(entry->destination->gatewayId, gatewayId,
440 &destInterfaces, &existEntry,
441 &g_routingGatewayTable);
442 if (OC_STACK_OK != result && NULL != existEntry)
444 u_linklist_add(alternativeRouteList, (void *)existEntry);
449 // Add the entry to RTM.
450 entry->routeCost = entry->routeCost + 1;
451 result = RTMAddGatewayEntry(entry->destination->gatewayId, gatewayId,
452 entry->routeCost, NULL, &g_routingGatewayTable);
455 if (OC_STACK_OK == result)
457 OC_LOG(INFO, TAG, "Gateway was added/removed");
458 u_linklist_add(updatedTableList, (void *)entry);
459 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
461 u_linklist_get_next(&iterTable);
464 if ( 0 < u_linklist_length(alternativeRouteList))
466 OC_LOG(DEBUG, TAG, "Alternative routing found");
467 // Send the notification.
468 OCRepPayload *removeTablePayload = NULL;
470 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
471 alternativeRouteList, false,
472 &removeTablePayload);
473 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
474 result = RMSendNotificationToAll(removeTablePayload);
475 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
476 RMPFreePayload(removeTablePayload);
479 if ( 0 >= u_linklist_length(updatedTableList))
481 OC_LOG_V(DEBUG, TAG, "No updation is needed, Length is %d", u_linklist_length(updatedTableList));
486 if (true == doRemoveEntry)
488 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, updatedTableList,
489 false, &updatedPayload);
493 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
494 updatedTableList, false,
497 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
500 result = RMSendNotificationToAll(updatedPayload);
501 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
502 RMPFreePayload(updatedPayload);
505 u_linklist_free(&updatedTableList);
506 u_linklist_free(&gatewayTableList);
507 u_linklist_free(&alternativeRouteList);
508 OC_LOG(DEBUG, TAG, "RMHandleResponsePayload OUT");
512 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource)
514 OC_LOG(DEBUG, TAG, "RMHandleGETRequest IN");
515 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
516 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
518 OCRepPayload *payload = NULL;
519 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
520 if (OC_STACK_OK != result)
522 OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload failed[%d]", result);
526 // Send a response for GET request
527 result = RMSendResponse(request, resource, payload);
528 if (OC_STACK_OK != result)
530 OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
534 RMPFreePayload(payload);
536 // Send a observe request
537 result = RMSendObserveRequest(&(request->devAddr), NULL);
538 if (OC_STACK_OK != result)
540 OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
542 OC_LOG(DEBUG, TAG, "RMHandleGETRequest OUT");
546 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource)
548 OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest IN");
549 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
550 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
552 // Parse payload and add the gateway entry.
553 if (0 < request->payloadSize)
555 RMHandleRequestPayload(request->devAddr, request->payload, request->payloadSize);
558 // Generate and add observer.
559 OCObservationId obsID = 0;
560 OCStackResult result = RMAddObserver(request, &obsID);
561 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
562 OC_LOG_V(DEBUG, TAG, "Observer ID is %d", obsID);
565 // Get the Routing table from RTM
566 OCRepPayload *payload = NULL;
567 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
568 OC_LOG(DEBUG, TAG, "Construct Routing table payload");
569 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
570 g_routingGatewayTable, true,
572 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
574 result = RMSendResponse(request, resource, payload);
575 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
576 RMPFreePayload(payload);
578 OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest OUT");
582 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource)
584 OC_LOG(DEBUG, TAG, "RMHandleDELETERequest IN");
585 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
586 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
588 uint32_t gatewayId = 0;
589 OCStackResult result = RMPParseRequestPayload(request->payload, request->payloadSize,
591 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
592 OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
594 OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", gatewayId);
596 u_linklist_t *removedGatewayNodes = NULL;
597 result = RTMRemoveGatewayEntry(gatewayId, &removedGatewayNodes, &g_routingGatewayTable);
598 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
600 if (0 < u_linklist_length(removedGatewayNodes))
602 OCRepPayload *resPayloads = NULL;
604 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedGatewayNodes,
605 false, &resPayloads);
606 RTMFreeGatewayRouteTable(&removedGatewayNodes);
607 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
608 result = RMSendNotificationToAll(resPayloads);
609 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
610 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
614 OC_LOG(DEBUG, TAG, "RMHandleDELETERequest OUT");
618 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID)
620 OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
621 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
622 RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
624 // Generate the ObserverID
625 CAEndpoint_t endpoint = {.adapter = 0};
626 CopyDevAddrToEndpoint(&(request->devAddr), &endpoint);
628 // Check if observer is already added.
629 if (true == RTMIsObserverPresent(endpoint, obsID, g_routingGatewayTable))
631 OC_LOG(DEBUG, TAG, "Observer is present");
632 request->observeResult = OC_STACK_OK;
636 OCStackResult result = RMAddObserverToStack(request, obsID);
637 request->observeResult = result;
638 if (OC_STACK_OK == result)
640 OC_LOG(DEBUG, TAG, "Added observer successfully");
642 // Add the observer to the list.
643 result = RTMAddObserver(*obsID, endpoint, &g_routingGatewayTable);
644 if (OC_STACK_OK != result)
646 OC_LOG_V(DEBUG, TAG, "RMAddObserver failed[%d]", result);
649 OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
653 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload)
655 OC_LOG(DEBUG, TAG, "RMSendNotificationToAll IN");
656 RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
658 OCObservationId *obsList = NULL;
660 // Get the complete observer list.
661 RTMGetObserverList(&obsList, &obsLen, g_routingGatewayTable);
662 OCStackResult result = OC_STACK_OK;
663 OC_LOG_V(DEBUG, TAG, "Number of observers is %d", obsLen);
666 // Send notification to the list of observers.
667 OC_LOG_V(DEBUG, TAG, "Sending notification with Sequence Number: %d", g_sequenceNumber);
668 result = RMSendNotificationForListofObservers(obsList, obsLen, payload);
669 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
670 g_aliveTime = RTMGetCurrentTime();
675 OC_LOG(DEBUG, TAG, "RMSendNotificationToAll OUT");
681 if (!g_isRMInitialized)
686 OCStackResult result = OC_STACK_OK;
687 uint64_t currentTime = RTMGetCurrentTime();
688 if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
690 g_aliveTime = currentTime;
691 // Construct a payload with only the current sequence number.
692 OCRepPayload *payload = NULL;
693 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
695 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
697 OC_LOG(DEBUG, TAG, "Sending the alive notification to all");
698 // Send notification for every 15s to all the neighbours.
699 result = RMSendNotificationToAll(payload);
700 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
703 if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
705 OC_LOG(DEBUG, TAG, "Validating the routing table");
706 u_linklist_t *removedEntries = NULL;
707 // Remove the invalid gateway entries.
708 RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
709 if (0 < u_linklist_length(removedEntries))
711 OCRepPayload *resPayloads = NULL;
713 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
714 false, &resPayloads);
715 RTMFreeGatewayRouteTable(&removedEntries);
716 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
717 result = RMSendNotificationToAll(resPayloads);
718 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
719 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
721 g_refreshTableTime = currentTime;
722 g_isValidated = false;
726 if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
728 OC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %u", currentTime);
729 u_linklist_t* invalidInterfaces = NULL;
730 RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
731 if (0 < u_linklist_length(invalidInterfaces))
733 u_linklist_iterator_t *iterTable = NULL;
734 u_linklist_init_iterator(invalidInterfaces, &iterTable);
735 while (NULL != iterTable)
737 RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
740 u_linklist_get_next(&iterTable);
743 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
744 CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
745 RMSendObserveRequest(&devAddr, NULL);
746 u_linklist_get_next(&iterTable);
749 g_isValidated = true;
750 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
751 u_linklist_free(&invalidInterfaces);
758 OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
760 OC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
761 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
762 OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
763 OC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
767 void RMSendDeleteToNeighbourNodes()
769 OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
770 u_linklist_t *neighbourNodes = NULL;
771 RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
773 if (0 >= u_linklist_length(neighbourNodes))
775 OC_LOG(DEBUG, TAG, "No neighbour nodes present");
779 u_linklist_iterator_t *iterTable = NULL;
780 u_linklist_init_iterator(neighbourNodes, &iterTable);
781 while (NULL != iterTable)
784 OCRepPayload *payload = NULL;
785 // Created payload is freed in the OCDoResource() api.
786 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
787 if (OC_STACK_OK != result)
789 OC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
790 u_linklist_free(&neighbourNodes);
794 RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
797 for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
799 RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
800 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
801 CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
802 OC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
803 dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
804 RMSendDeleteRequest(&devAddr, payload);
807 u_linklist_get_next(&iterTable);
810 u_linklist_free(&neighbourNodes);
811 OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
814 uint32_t RMGetGatewayId()
816 if (!g_isRMInitialized)
818 OC_LOG(ERROR, TAG, "RM not initialized");
824 uint16_t RMGetMcastSeqNumber()
826 if (!g_isRMInitialized)
828 OC_LOG(DEBUG, TAG, "RM not initialized");
831 return ++g_mcastsequenceNumber;
835 * This function is lifeline of packet forwarding module, hence we are going to do some serious
836 * handling here. Following are the expectations from this function:
837 * 1) If routing option is not available, forward packet to RI only. else:
838 * 2) If source is empty in routing option, packet is from end device, add an end device entry and
839 * add "GatewayId:ClientId" as source.
840 * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
841 * multicast on other interfaces. Also remove routing Option and forward to RI. (Before
842 * forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
844 * 4) If destination is present in routing option, its unicast packet,
845 * a) If self gatewayId is present in destination and no clientId, remove routing option
847 * b) If self gatewayId and a clientId is present in destination, forward to end device.
848 * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
851 OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
852 bool *selfDestination)
854 RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
855 RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
856 RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
858 bool forward = false;
859 CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
860 CAInfo_t *info = NULL;
863 CARequestInfo_t *msg = message;
865 RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
869 CAResponseInfo_t *msg = message;
871 RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
874 // 1. If routing option is not available, forward packet to RI only.
875 int8_t routeIndex = -1;
876 RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
877 if (-1 >= routeIndex)
879 OC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
880 // Let RI handle this packet.
881 *selfDestination = true;
885 // Get existing values in packet route option.
886 RMRouteOption_t routeOption = {.srcGw = 0};
887 OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
888 if (OC_STACK_OK != res)
890 OC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
891 return OC_STACK_ERROR;
895 * 2) If source is empty in routing option, packet is from end device, add an end device entry
896 * and add "GatewayId:ClientId" as source.
898 if (g_GatewayID == routeOption.srcGw)
900 OC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
901 if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
903 g_mcastsequenceNumber = routeOption.mSeqNum;
906 return OC_STACK_ERROR;
908 else if (0 == routeOption.srcGw)
910 OC_LOG(INFO, RM_TAG, "Source missing in option");
911 // Packet from end device as Gateway will add source in option.
912 uint16_t endpointId = g_EndpointCount + 1;
913 OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
914 if (OC_STACK_OK == res)
916 g_EndpointCount = endpointId;
917 OC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
919 else if (OC_STACK_DUPLICATE_REQUEST == res)
921 OC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
925 OC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
926 return OC_STACK_ERROR;
929 // add source option.
930 routeOption.srcGw = g_GatewayID;
931 routeOption.srcEp = endpointId;
932 OC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
936 * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
937 * multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
938 * caller of this function).
940 if (0 == routeOption.destGw)
942 OC_LOG(INFO, RM_TAG, "Destination missing in option");
943 // This is a multicast packet.
944 if (g_GatewayID == routeOption.srcGw)
946 routeOption.mSeqNum = ++g_mcastsequenceNumber;
950 OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
951 &g_routingGatewayTable);
952 if (OC_STACK_OK != update)
954 // this shouldnt have been forwarded. ignore.
955 OC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
956 routeOption.mSeqNum);
957 return OC_STACK_ERROR;
962 *selfDestination = true;
965 // Send multicast on every adapter except the one from which packet was received
966 // TODO::: support to be added for IP hop.
967 if (sender->adapter != CA_ADAPTER_IP)
969 nextHop.adapter |= CA_ADAPTER_IP;
970 nextHop.flags |= CA_IPV4 | CA_IPV6;
973 if(sender->adapter != CA_ADAPTER_GATT_BTLE)
975 nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
978 if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
980 nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
983 // Only requests are sent as multicast.
986 CARequestInfo_t *msg = message;
987 msg->isMulticast = true;
991 else if (g_GatewayID == routeOption.destGw)
993 OC_LOG(INFO, RM_TAG, "GatewayId found in destination");
995 * This unicast packet either belongs to us or any of our connected end devices
996 * check if packet belongs to end device.
998 if (0 != routeOption.destEp)
1000 // forward packet to the client.
1001 OC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1002 CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1003 g_routingEndpointTable);
1006 OC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1007 return OC_STACK_ERROR;
1010 nextHop = *clientInfo;
1012 *selfDestination = false;
1013 goto rewriteandexit;
1017 // packet is for us.
1018 OC_LOG(INFO, RM_TAG, "Received packet for self");
1020 *selfDestination = true;
1021 goto rewriteandexit;
1027 * This unicast packet belongs to other gateway.
1028 * we only want to print first 4 bytes of packet as readable GatewayId.
1030 OC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1031 RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1034 OC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1035 return OC_STACK_ERROR;
1038 // TODO:: check preferences among multiple interface addresses, for now sending on first one
1039 RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1042 OC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1043 return OC_STACK_ERROR;
1046 nextHop = address->destIntfAddr;
1048 *selfDestination = false;
1049 goto rewriteandexit;
1056 // Don't forward any packet meant for gateway resource.
1057 if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)))
1059 OC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1061 else if (sender->flags & CA_SECURE)
1063 OC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1064 return OC_STACK_ERROR;
1068 // rewrite any changes in routing option.
1069 res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1070 if (OC_STACK_OK != res)
1072 OC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1076 * When forwarding a packet, do not attempt retransmission as its the responsibility of
1077 * packet originator node.
1079 info->skipRetransmission = true;
1082 CARequestInfo_t *msg = message;
1083 CAResult_t caRes = CASendRequest(&nextHop, msg);
1084 if (CA_STATUS_OK != caRes)
1086 OC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1088 if(0 == routeOption.destGw)
1091 * No point going forward as unicast packet could not be forwarded
1092 * not returning error for multicast as we may still let RI process
1095 return OC_STACK_ERROR;
1101 CAResponseInfo_t *msg = message;
1102 CAResult_t caRes = CASendResponse(&nextHop, msg);
1103 if (CA_STATUS_OK != caRes)
1105 OC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1106 caRes, nextHop.addr);
1107 // Since a response is always unicast, return error here.
1108 return OC_STACK_ERROR;
1114 OC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1118 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1119 bool *selfDestination)
1121 if (!g_isRMInitialized)
1123 OC_LOG(ERROR, TAG, "RM not initialized");
1124 *selfDestination = true;
1127 OCStackResult res = RMHandlePacket(true, message, sender, selfDestination);
1131 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1132 bool *selfDestination)
1134 if (!g_isRMInitialized)
1136 OC_LOG(ERROR, TAG, "RM not initialized");
1137 *selfDestination = true;
1140 OCStackResult res = RMHandlePacket(false, message, sender, selfDestination);