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 if (OC_STACK_OK != result)
321 OC_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 OC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT");
336 OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload)
338 OC_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 OC_LOG(INFO, TAG, "-------------->Own entry, continue!!");
354 return OC_STACK_ERROR;
356 // Convert OCDevAddr to endpoint address
357 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS};
358 CopyDevAddrToEndpoint(devAddr, &endpoint);
359 RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
360 destInterfaces.destIntfAddr = endpoint;
363 OC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d",
364 seqNum, isUpdateSeqNum);
365 result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces,
366 &g_routingGatewayTable, isUpdateSeqNum);
367 if (OC_STACK_COMM_ERROR == result)
369 OC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching");
370 // Send a observe request to the gateway.
371 RMSendObserveRequest(devAddr, NULL);
374 else if (OC_STACK_DUPLICATE_REQUEST == result)
376 OC_LOG(ERROR, TAG, "Same sequence number is received");
381 // Check if the payload is for Removal
382 bool doRemoveEntry = false;
384 if (NULL != gatewayTableList && NULL != gatewayTableList->list)
386 RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list);
387 if (headPtr && 0 == headPtr->routeCost)
389 OC_LOG(INFO, TAG, "Remove entry is called");
390 doRemoveEntry = true;
394 // Create a list to add the updated entries and notify the observers
395 u_linklist_t *updatedTableList = u_linklist_create();
396 u_linklist_t *alternativeRouteList = u_linklist_create();
397 OCRepPayload *updatedPayload = NULL;
398 if (false == doRemoveEntry)
400 OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
401 result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
402 if (OC_STACK_OK == result)
404 OC_LOG(INFO, TAG, "Node was added");
405 RTMGatewayId_t gwId = {.gatewayId = gatewayId};
406 RTMGatewayEntry_t newNode;
407 newNode.destination = &gwId;
408 newNode.routeCost = 1;
409 u_linklist_add(updatedTableList, (void *)&newNode);
410 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
412 if (NULL == gatewayTableList)
414 OC_LOG(INFO, TAG, "Received a Discover Payload");
416 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
417 updatedTableList, false,
419 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
420 goto sendNotification;
425 // Iterate the Table and get each entry
426 u_linklist_iterator_t *iterTable = NULL;
427 u_linklist_init_iterator(gatewayTableList, &iterTable);
429 while (NULL != iterTable)
431 RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
432 // Check if the entry is its own.
433 if (!entry || entry->destination->gatewayId == g_GatewayID)
435 OC_LOG(INFO, TAG, "Ignore entry, continue!!");
436 u_linklist_get_next(&iterTable);
440 OC_LOG_V(INFO, TAG, "Gateway ID: %u", entry->destination->gatewayId);
441 if (true == doRemoveEntry)
443 // Remove the entry from RTM.
444 RTMGatewayEntry_t *existEntry = NULL;
445 result = RTMRemoveGatewayDestEntry(entry->destination->gatewayId, gatewayId,
446 &destInterfaces, &existEntry,
447 &g_routingGatewayTable);
448 if (OC_STACK_OK != result && NULL != existEntry)
450 u_linklist_add(alternativeRouteList, (void *)existEntry);
455 // Add the entry to RTM.
456 entry->routeCost = entry->routeCost + 1;
457 result = RTMAddGatewayEntry(entry->destination->gatewayId, gatewayId,
458 entry->routeCost, NULL, &g_routingGatewayTable);
461 if (OC_STACK_OK == result)
463 OC_LOG(INFO, TAG, "Gateway was added/removed");
464 u_linklist_add(updatedTableList, (void *)entry);
465 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
467 u_linklist_get_next(&iterTable);
470 if ( 0 < u_linklist_length(alternativeRouteList))
472 OC_LOG(DEBUG, TAG, "Alternative routing found");
473 // Send the notification.
474 OCRepPayload *removeTablePayload = NULL;
476 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
477 alternativeRouteList, false,
478 &removeTablePayload);
479 if (OC_STACK_OK != result)
481 OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
482 RMPFreePayload(removeTablePayload);
485 result = RMSendNotificationToAll(removeTablePayload);
486 RMPFreePayload(removeTablePayload);
487 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
490 if ( 0 >= u_linklist_length(updatedTableList))
492 OC_LOG_V(DEBUG, TAG, "No updation is needed, Length is %d",
493 u_linklist_length(updatedTableList));
498 if (true == doRemoveEntry)
500 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, updatedTableList,
501 false, &updatedPayload);
505 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
506 updatedTableList, false,
509 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
512 result = RMSendNotificationToAll(updatedPayload);
513 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
516 RMPFreePayload(updatedPayload);
517 RTMFreeGatewayRouteTable(&gatewayTableList);
518 u_linklist_free(&updatedTableList);
519 u_linklist_free(&alternativeRouteList);
520 OC_LOG(DEBUG, TAG, "RMHandleResponsePayload OUT");
524 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource)
526 OC_LOG(DEBUG, TAG, "RMHandleGETRequest IN");
527 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
528 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
530 OCRepPayload *payload = NULL;
531 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
532 if (OC_STACK_OK != result)
534 OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload failed[%d]", result);
538 // Send a response for GET request
539 result = RMSendResponse(request, resource, payload);
540 if (OC_STACK_OK != result)
542 OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
546 RMPFreePayload(payload);
547 // Send a observe request
548 result = RMSendObserveRequest(&(request->devAddr), NULL);
549 if (OC_STACK_OK != result)
551 OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
553 OC_LOG(DEBUG, TAG, "RMHandleGETRequest OUT");
557 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource)
559 OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest IN");
560 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
561 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
563 // Parse payload and add the gateway entry.
564 if (0 < request->payloadSize)
566 RMHandleRequestPayload(request->devAddr, request->payload, request->payloadSize);
569 // Generate and add observer.
570 OCObservationId obsID = 0;
571 OCStackResult result = RMAddObserver(request, &obsID);
572 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
573 OC_LOG_V(DEBUG, TAG, "Observer ID is %d", obsID);
576 // Get the Routing table from RTM
577 OCRepPayload *payload = NULL;
578 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
579 OC_LOG(DEBUG, TAG, "Construct Routing table payload");
580 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
581 g_routingGatewayTable, true,
583 if (OC_STACK_OK != result)
585 OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
586 RMPFreePayload(payload);
590 result = RMSendResponse(request, resource, payload);
591 RMPFreePayload(payload);
592 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
594 OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest OUT");
598 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource)
600 OC_LOG(DEBUG, TAG, "RMHandleDELETERequest IN");
601 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
602 RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
604 uint32_t gatewayId = 0;
605 OCStackResult result = RMPParseRequestPayload(request->payload, request->payloadSize,
607 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
608 OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
610 OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", gatewayId);
612 u_linklist_t *removedGatewayNodes = NULL;
613 result = RTMRemoveGatewayEntry(gatewayId, &removedGatewayNodes, &g_routingGatewayTable);
614 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
616 if (0 < u_linklist_length(removedGatewayNodes))
618 OCRepPayload *resPayloads = NULL;
620 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedGatewayNodes,
621 false, &resPayloads);
622 if (OC_STACK_OK != result)
624 OC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
625 RMPFreePayload(resPayloads);
628 result = RMSendNotificationToAll(resPayloads);
629 RMPFreePayload(resPayloads);
630 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
631 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
635 RTMFreeGatewayRouteTable(&removedGatewayNodes);
636 OC_LOG(DEBUG, TAG, "RMHandleDELETERequest OUT");
640 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID)
642 OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
643 RM_NULL_CHECK_WITH_RET(request, TAG, "request");
644 RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
646 // Generate the ObserverID
647 CAEndpoint_t endpoint = {.adapter = 0};
648 CopyDevAddrToEndpoint(&(request->devAddr), &endpoint);
650 // Check if observer is already added.
651 if (true == RTMIsObserverPresent(endpoint, obsID, g_routingGatewayTable))
653 OC_LOG(DEBUG, TAG, "Observer is present");
654 request->observeResult = OC_STACK_OK;
658 OCStackResult result = RMAddObserverToStack(request, obsID);
659 request->observeResult = result;
660 if (OC_STACK_OK == result)
662 OC_LOG(DEBUG, TAG, "Added observer successfully");
664 // Add the observer to the list.
665 result = RTMAddObserver(*obsID, endpoint, &g_routingGatewayTable);
666 if (OC_STACK_OK != result)
668 OC_LOG_V(DEBUG, TAG, "RMAddObserver failed[%d]", result);
671 OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
675 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload)
677 OC_LOG(DEBUG, TAG, "RMSendNotificationToAll IN");
678 RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
680 OCObservationId *obsList = NULL;
682 // Get the complete observer list.
683 RTMGetObserverList(&obsList, &obsLen, g_routingGatewayTable);
684 OCStackResult result = OC_STACK_OK;
685 OC_LOG_V(DEBUG, TAG, "Number of observers is %d", obsLen);
688 // Send notification to the list of observers.
689 OC_LOG_V(DEBUG, TAG, "Sending notification with Sequence Number: %d", g_sequenceNumber);
690 result = RMSendNotificationForListofObservers(obsList, obsLen, payload);
691 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
692 g_aliveTime = RTMGetCurrentTime();
697 OC_LOG(DEBUG, TAG, "RMSendNotificationToAll OUT");
703 if (!g_isRMInitialized)
708 OCStackResult result = OC_STACK_OK;
709 uint64_t currentTime = RTMGetCurrentTime();
710 if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
712 g_aliveTime = currentTime;
713 // Construct a payload with only the current sequence number.
714 OCRepPayload *payload = NULL;
715 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
717 if (OC_STACK_OK != result)
719 OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
720 RMPFreePayload(payload);
723 OC_LOG(DEBUG, TAG, "Sending the alive notification to all");
724 // Send notification for every 15s to all the neighbours.
725 result = RMSendNotificationToAll(payload);
726 RMPFreePayload(payload);
727 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
730 if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
732 OC_LOG(DEBUG, TAG, "Validating the routing table");
733 u_linklist_t *removedEntries = NULL;
734 // Remove the invalid gateway entries.
735 RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
736 if (0 < u_linklist_length(removedEntries))
738 OCRepPayload *resPayloads = NULL;
740 result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
741 false, &resPayloads);
742 RTMFreeGatewayRouteTable(&removedEntries);
743 if (OC_STACK_OK != result)
745 OC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
746 RMPFreePayload(resPayloads);
749 result = RMSendNotificationToAll(resPayloads);
750 RMPFreePayload(resPayloads);
751 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
752 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
754 g_refreshTableTime = currentTime;
755 g_isValidated = false;
756 u_linklist_free(&removedEntries);
760 if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
762 OC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %u", currentTime);
763 u_linklist_t* invalidInterfaces = NULL;
764 RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
765 if (0 < u_linklist_length(invalidInterfaces))
767 u_linklist_iterator_t *iterTable = NULL;
768 u_linklist_init_iterator(invalidInterfaces, &iterTable);
769 while (NULL != iterTable)
771 RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
774 u_linklist_get_next(&iterTable);
777 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
778 CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
779 RMSendObserveRequest(&devAddr, NULL);
780 u_linklist_get_next(&iterTable);
783 g_isValidated = true;
784 RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
785 u_linklist_free(&invalidInterfaces);
792 OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
794 OC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
795 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
796 OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
797 OC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
801 void RMSendDeleteToNeighbourNodes()
803 OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
804 u_linklist_t *neighbourNodes = NULL;
805 RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
807 if (0 >= u_linklist_length(neighbourNodes))
809 OC_LOG(DEBUG, TAG, "No neighbour nodes present");
813 u_linklist_iterator_t *iterTable = NULL;
814 u_linklist_init_iterator(neighbourNodes, &iterTable);
815 while (NULL != iterTable)
818 OCRepPayload *payload = NULL;
819 // Created payload is freed in the OCDoResource() api.
820 OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
821 if (OC_STACK_OK != result)
823 OC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
824 RMPFreePayload(payload);
825 u_linklist_free(&neighbourNodes);
829 RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
832 for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
834 RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
835 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
836 CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
837 OC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
838 dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
839 RMSendDeleteRequest(&devAddr, payload);
842 RMPFreePayload(payload);
843 u_linklist_get_next(&iterTable);
846 u_linklist_free(&neighbourNodes);
847 OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
850 uint32_t RMGetGatewayId()
852 if (!g_isRMInitialized)
854 OC_LOG(ERROR, TAG, "RM not initialized");
860 uint16_t RMGetMcastSeqNumber()
862 if (!g_isRMInitialized)
864 OC_LOG(DEBUG, TAG, "RM not initialized");
867 return ++g_mcastsequenceNumber;
871 * This function is lifeline of packet forwarding module, hence we are going to do some serious
872 * handling here. Following are the expectations from this function:
873 * 1) If routing option is not available, forward packet to RI only. else:
874 * 2) If source is empty in routing option, packet is from end device, add an end device entry and
875 * add "GatewayId:ClientId" as source.
876 * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
877 * multicast on other interfaces. Also remove routing Option and forward to RI. (Before
878 * forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
880 * 4) If destination is present in routing option, its unicast packet,
881 * a) If self gatewayId is present in destination and no clientId, remove routing option
883 * b) If self gatewayId and a clientId is present in destination, forward to end device.
884 * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
887 OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
888 bool *selfDestination)
890 RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
891 RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
892 RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
894 bool forward = false;
895 CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
896 CAInfo_t *info = NULL;
899 CARequestInfo_t *msg = message;
901 RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
905 CAResponseInfo_t *msg = message;
907 RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
910 // 1. If routing option is not available, forward packet to RI only.
911 int8_t routeIndex = -1;
912 RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
913 if (-1 >= routeIndex)
915 OC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
916 // Let RI handle this packet.
917 *selfDestination = true;
921 // Get existing values in packet route option.
922 RMRouteOption_t routeOption = {.srcGw = 0};
923 OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
924 if (OC_STACK_OK != res)
926 OC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
927 return OC_STACK_ERROR;
931 * 2) If source is empty in routing option, packet is from end device, add an end device entry
932 * and add "GatewayId:ClientId" as source.
934 if (g_GatewayID == routeOption.srcGw)
936 OC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
937 if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
939 g_mcastsequenceNumber = routeOption.mSeqNum;
942 return OC_STACK_ERROR;
944 else if (0 == routeOption.srcGw)
946 OC_LOG(INFO, RM_TAG, "Source missing in option");
947 // Packet from end device as Gateway will add source in option.
948 uint16_t endpointId = g_EndpointCount + 1;
949 OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
950 if (OC_STACK_OK == res)
952 g_EndpointCount = endpointId;
953 OC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
955 else if (OC_STACK_DUPLICATE_REQUEST == res)
957 OC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
961 OC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
962 return OC_STACK_ERROR;
965 // add source option.
966 routeOption.srcGw = g_GatewayID;
967 routeOption.srcEp = endpointId;
968 OC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
972 * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
973 * multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
974 * caller of this function).
976 if (0 == routeOption.destGw)
978 OC_LOG(INFO, RM_TAG, "Destination missing in option");
979 // This is a multicast packet.
980 if (g_GatewayID == routeOption.srcGw)
982 routeOption.mSeqNum = ++g_mcastsequenceNumber;
986 OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
987 &g_routingGatewayTable);
988 if (OC_STACK_OK != update)
990 // this shouldnt have been forwarded. ignore.
991 OC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
992 routeOption.mSeqNum);
993 return OC_STACK_ERROR;
998 *selfDestination = true;
1001 // Send multicast on every adapter except the one from which packet was received
1002 // TODO::: support to be added for IP hop.
1003 if (sender->adapter != CA_ADAPTER_IP)
1005 nextHop.adapter |= CA_ADAPTER_IP;
1006 nextHop.flags |= CA_IPV4 | CA_IPV6;
1009 if(sender->adapter != CA_ADAPTER_GATT_BTLE)
1011 nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
1014 if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
1016 nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
1019 // Only requests are sent as multicast.
1022 CARequestInfo_t *msg = message;
1023 msg->isMulticast = true;
1025 goto rewriteandexit;
1027 else if (g_GatewayID == routeOption.destGw)
1029 OC_LOG(INFO, RM_TAG, "GatewayId found in destination");
1031 * This unicast packet either belongs to us or any of our connected end devices
1032 * check if packet belongs to end device.
1034 if (0 != routeOption.destEp)
1036 // forward packet to the client.
1037 OC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1038 CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1039 g_routingEndpointTable);
1042 OC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1043 return OC_STACK_ERROR;
1046 nextHop = *clientInfo;
1048 *selfDestination = false;
1049 goto rewriteandexit;
1053 // packet is for us.
1054 OC_LOG(INFO, RM_TAG, "Received packet for self");
1056 *selfDestination = true;
1057 goto rewriteandexit;
1063 * This unicast packet belongs to other gateway.
1064 * we only want to print first 4 bytes of packet as readable GatewayId.
1066 OC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1067 RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1070 OC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1071 return OC_STACK_ERROR;
1074 // TODO:: check preferences among multiple interface addresses, for now sending on first one
1075 RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1078 OC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1079 return OC_STACK_ERROR;
1082 nextHop = address->destIntfAddr;
1084 *selfDestination = false;
1085 goto rewriteandexit;
1092 // Don't forward any packet meant for gateway resource.
1093 if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)))
1095 OC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1097 else if (sender->flags & CA_SECURE)
1099 OC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1100 return OC_STACK_ERROR;
1104 // rewrite any changes in routing option.
1105 res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1106 if (OC_STACK_OK != res)
1108 OC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1112 * When forwarding a packet, do not attempt retransmission as its the responsibility of
1113 * packet originator node.
1115 info->skipRetransmission = true;
1118 CARequestInfo_t *msg = message;
1119 CAResult_t caRes = CASendRequest(&nextHop, msg);
1120 if (CA_STATUS_OK != caRes)
1122 OC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1124 if(0 == routeOption.destGw)
1127 * No point going forward as unicast packet could not be forwarded
1128 * not returning error for multicast as we may still let RI process
1131 return OC_STACK_ERROR;
1137 CAResponseInfo_t *msg = message;
1138 CAResult_t caRes = CASendResponse(&nextHop, msg);
1139 if (CA_STATUS_OK != caRes)
1141 OC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1142 caRes, nextHop.addr);
1143 // Since a response is always unicast, return error here.
1144 return OC_STACK_ERROR;
1150 OC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1154 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1155 bool *selfDestination)
1157 if (!g_isRMInitialized)
1159 OC_LOG(ERROR, TAG, "RM not initialized");
1160 *selfDestination = true;
1163 OCStackResult res = RMHandlePacket(true, message, sender, selfDestination);
1167 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1168 bool *selfDestination)
1170 if (!g_isRMInitialized)
1172 OC_LOG(ERROR, TAG, "RM not initialized");
1173 *selfDestination = true;
1176 OCStackResult res = RMHandlePacket(false, message, sender, selfDestination);