Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / routing / src / routingtablemanager.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include "routingtablemanager.h"
24 #include "routingutility.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "include/logger.h"
28
29 /**
30  * Logging tag for module name.
31  */
32 #define TAG "OIC_RM_TM"
33
34 /**
35  * Tag for printing the Routing table.
36  */
37 #define RM_TAG "OIC_RM_RAP"
38
39
40 /**
41  * Initial Length of observer list.
42  */
43 #define MAX_OBSERVER_LIST_LENGTH 10
44
45 static const uint64_t USECS_PER_SEC = 1000000;
46
47 OCStackResult RTMInitialize(u_linklist_t **gatewayTable, u_linklist_t **endpointTable)
48 {
49     OIC_LOG(DEBUG, TAG, "RTMInitialize IN");
50     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
51     RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
52     if (NULL == *gatewayTable)
53     {
54         *gatewayTable = u_linklist_create();
55         if (NULL == *gatewayTable)
56         {
57             OIC_LOG(ERROR, TAG, "Creating Routing Table failed");
58             RTMTerminate(gatewayTable, endpointTable);
59             return OC_STACK_ERROR;
60         }
61     }
62
63     if (NULL == *endpointTable)
64     {
65         *endpointTable = u_linklist_create();
66         if (NULL == *endpointTable)
67         {
68            OIC_LOG(ERROR, TAG, "Creating Routing Table failed");
69             RTMTerminate(gatewayTable, endpointTable);
70            return OC_STACK_ERROR;
71         }
72     }
73     OIC_LOG(DEBUG, TAG, "RTMInitialize OUT");
74     return OC_STACK_OK;
75 }
76
77 /*
78  * Freeing every char pointer and array list of gateway entry here and frees the table.
79  */
80 OCStackResult RTMFreeGatewayRouteTable(u_linklist_t **gatewayTable)
81 {
82     OIC_LOG(DEBUG, TAG, "RTMFreeGatewayRouteTable IN");
83     if (NULL == gatewayTable || NULL == *gatewayTable)
84     {
85         return OC_STACK_OK;
86     }
87
88     u_linklist_iterator_t *iterTable = NULL;
89     u_linklist_init_iterator(*gatewayTable, &iterTable);
90     while (NULL != iterTable)
91     {
92         RTMGatewayEntry_t *hop = u_linklist_get_data(iterTable);
93         if (NULL != hop && NULL != hop->destination)
94         {
95             while (u_arraylist_length(hop->destination->destIntfAddr) > 0)
96             {
97                 if (NULL != hop->destination)
98                 {
99                     RTMDestIntfInfo_t *data = u_arraylist_remove(hop->destination->destIntfAddr, 0);
100                     OICFree(data);
101                 }
102             }
103             u_arraylist_free(&(hop->destination->destIntfAddr));
104             OICFree(hop->destination);
105             // No need to free next hop as it is already freed during it's gateway free
106             OICFree(hop);
107         }
108
109         OCStackResult ret = u_linklist_remove(*gatewayTable, &iterTable);
110         if (OC_STACK_OK != ret)
111         {
112            OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
113            return OC_STACK_ERROR;
114         }
115     }
116     u_linklist_free(gatewayTable);
117     OIC_LOG(DEBUG, TAG, "RTMFreeGatewayRouteTable OUT");
118     return OC_STACK_OK;
119 }
120
121 /*
122  * Freeing every char pointer of endpoint entry here frees the table.
123  */
124 OCStackResult RTMFreeEndpointRouteTable(u_linklist_t **endpointTable)
125 {
126     OIC_LOG(DEBUG, TAG, "IN");
127     if (NULL == endpointTable || NULL == *endpointTable)
128     {
129         return OC_STACK_OK;
130     }
131
132     u_linklist_iterator_t *iterTable = NULL;
133     u_linklist_init_iterator(*endpointTable, &iterTable);
134     while (NULL != iterTable)
135     {
136         RTMEndpointEntry_t *hop = u_linklist_get_data(iterTable);
137         if (NULL != hop)
138         {
139             OICFree(hop);
140         }
141
142         OCStackResult ret = u_linklist_remove(*endpointTable, &iterTable);
143         if (OC_STACK_OK != ret)
144         {
145             OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
146             return OC_STACK_ERROR;
147         }
148     }
149     u_linklist_free(endpointTable);
150     OIC_LOG(DEBUG, TAG, "OUT");
151     return OC_STACK_OK;
152 }
153
154 OCStackResult RTMFreeGatewayIdList(u_linklist_t **gatewayIdTable)
155 {
156     OIC_LOG(DEBUG, TAG, "IN");
157     if (NULL == gatewayIdTable || NULL == *gatewayIdTable)
158     {
159         return OC_STACK_OK;
160     }
161
162     u_linklist_iterator_t *iterTable = NULL;
163     u_linklist_init_iterator(*gatewayIdTable, &iterTable);
164     while (iterTable != NULL)
165     {
166         RTMGatewayId_t *hop = u_linklist_get_data(iterTable);
167         if (NULL != hop)
168         {
169             while (u_arraylist_length(hop->destIntfAddr) > 0)
170             {
171                RTMDestIntfInfo_t *data = u_arraylist_remove(hop->destIntfAddr, 0);
172                OICFree(data);
173             }
174             u_arraylist_free(&(hop->destIntfAddr));
175             OICFree(hop);
176
177             OCStackResult ret = u_linklist_remove(*gatewayIdTable, &iterTable);
178             if (OC_STACK_OK != ret)
179             {
180                OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
181                return OC_STACK_ERROR;
182             }
183         }
184         else
185         {
186             OCStackResult res = u_linklist_remove(*gatewayIdTable, &iterTable);
187             if (OC_STACK_OK != res)
188             {
189                 OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
190                 return OC_STACK_ERROR;
191             }
192         }
193     }
194     OIC_LOG(DEBUG, TAG, "OUT");
195     return OC_STACK_OK;
196 }
197
198 /*
199  * Freeing memory first and then Freeing linked list for gateway and endpoint.
200  */
201 OCStackResult RTMTerminate(u_linklist_t **gatewayTable, u_linklist_t **endpointTable)
202 {
203     OIC_LOG(DEBUG, TAG, "IN");
204
205     OCStackResult ret = RTMFreeGatewayRouteTable(gatewayTable);
206     if (OC_STACK_OK != ret)
207     {
208         OIC_LOG(ERROR, TAG, "Deleting Gateway Routing Table failed");
209     }
210     if (NULL != *gatewayTable)
211     {
212         *gatewayTable = NULL;
213     }
214
215     ret = RTMFreeEndpointRouteTable(endpointTable);
216     if (OC_STACK_OK != ret)
217     {
218         OIC_LOG(ERROR, TAG, "Deleting Endpoint Routing Table failed");
219     }
220     if (NULL != *endpointTable)
221     {
222         *endpointTable = NULL;
223     }
224     OIC_LOG(DEBUG, TAG, "OUT");
225     return OC_STACK_OK;
226 }
227
228 /*
229  * Checks if destination gateway to be added is already present and update if present or
230  * adds new entry if not present.
231  * Adds Entry to head if route cost is 1.
232  * Adds Entry to Tail if route cost is > 1.
233  * Checks for Gateway id Memory and assigns to next hop address to achieve better memory usage.
234  */
235 OCStackResult RTMAddGatewayEntry(uint32_t gatewayId, uint32_t nextHop, uint32_t routeCost,
236                                  const RTMDestIntfInfo_t *destInterfaces, u_linklist_t **gatewayTable)
237 {
238     OIC_LOG(DEBUG, TAG, "IN");
239     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
240     if (NULL == *gatewayTable)
241     {
242         *gatewayTable = u_linklist_create();
243         if (NULL == *gatewayTable)
244         {
245             OIC_LOG(ERROR, TAG, "u_linklist_create failed");
246             return OC_STACK_NO_MEMORY;
247         }
248     }
249
250     if (1 == routeCost && 0 != nextHop)
251     {
252         OIC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop should be 0 for route cost 1");
253         return OC_STACK_ERROR;
254     }
255
256     if (0 == routeCost)
257     {
258         OIC_LOG(ERROR, TAG, "Adding Gateway Failed as Route cost shouldnot be less than 1");
259         return OC_STACK_ERROR;
260     }
261
262     u_linklist_iterator_t *destNode = NULL;
263     RTMGatewayId_t *gatewayNodeMap = NULL;   // Gateway id ponter can be mapped to NextHop of entry.
264
265     u_linklist_iterator_t *iterTable = NULL;
266     u_linklist_init_iterator(*gatewayTable, &iterTable);
267     // Iterate over gateway list to find if already entry with this gatewayid is present.
268     while (NULL != iterTable)
269     {
270         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
271         if (NULL == entry)
272         {
273             break;
274         }
275
276         // To save node with same gateway id (To update entry instead of add new entry).
277         if (NULL == destNode && NULL != entry->destination &&
278             (gatewayId == entry->destination->gatewayId))
279         {
280             destNode = iterTable;
281         }
282
283         // To find pointer of gateway id for a node provided next hop equals to existing gateway id.
284         if (0 != nextHop && NULL != entry->destination &&
285             nextHop == entry->destination->gatewayId)
286         {
287             gatewayNodeMap = entry->destination;
288         }
289
290         if (NULL != destNode && NULL != gatewayNodeMap)
291         {
292             break;
293         }
294
295         u_linklist_get_next(&iterTable);
296     }
297
298     if (1 < routeCost && NULL == gatewayNodeMap)
299     {
300         OIC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop is invalid");
301         return OC_STACK_ERROR;
302     }
303
304     //Logic to update entry if it is already destination present or to add new entry.
305     if (NULL != destNode)
306     {
307         RTMGatewayEntry_t *entry = u_linklist_get_data(destNode);
308
309         if (NULL != entry  && 1 == entry->routeCost && 0 == nextHop)
310         {
311             if (NULL == destInterfaces)
312             {
313                 OIC_LOG(ERROR, TAG, "Not Adding Gateway destInterfaces is NULL");
314                 return OC_STACK_ERROR;
315             }
316             OCStackResult update = RTMUpdateDestinationIntfAdr(gatewayId, *destInterfaces, true,
317                                                                gatewayTable);
318             if (OC_STACK_OK != update)
319             {
320                 OIC_LOG(ERROR, TAG, "RTMUpdateDestinationIntfAdr failed");
321             }
322             return update;
323         }
324         else if (NULL != entry  && entry->routeCost >= routeCost)
325         {
326             if (entry->routeCost == routeCost && NULL != entry->nextHop &&
327                 (nextHop == entry->nextHop->gatewayId))
328             {
329                 OIC_LOG(ERROR, TAG, "Not Adding Gateway As it is Duplicate request");
330                 return OC_STACK_DUPLICATE_REQUEST;
331             }
332
333             //Mapped nextHop gateway to another entries having gateway as destination.
334             if (NULL != gatewayNodeMap)
335             {
336                 entry->destination->gatewayId = gatewayId;
337                 entry->nextHop = gatewayNodeMap;
338                 entry->destination->destIntfAddr = NULL;
339                 entry->routeCost = routeCost;
340             }
341             else if (0 == nextHop)
342             {
343                 entry->routeCost = 1;
344                 // Entry can't be updated if Next hop is not same as existing Destinations of Table.
345                 OIC_LOG(DEBUG, TAG, "Updating the gateway");
346                 entry->nextHop = NULL;
347                 entry->destination->destIntfAddr = u_arraylist_create();
348                 if (NULL == entry->destination->destIntfAddr)
349                 {
350                     OIC_LOG(ERROR, TAG, "Failed to create array list");
351                     return OC_STACK_ERROR;
352                 }
353
354                 RTMDestIntfInfo_t *destAdr =
355                     (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
356                 if (NULL == destAdr)
357                 {
358                     OIC_LOG(ERROR, TAG, "Failed to Calloc destAdr");
359                     return OC_STACK_ERROR;
360                 }
361
362                 *destAdr = *destInterfaces;
363                 destAdr->timeElapsed = RTMGetCurrentTime();
364                 destAdr->isValid = true;
365                 bool result =
366                     u_arraylist_add(entry->destination->destIntfAddr, (void *)destAdr);
367                 if (!result)
368                 {
369                     OIC_LOG(ERROR, TAG, "Adding node to head failed");
370                     OICFree(destAdr);
371                     return OC_STACK_ERROR;
372                 }
373             }
374             else
375             {
376                 OIC_LOG(ERROR, TAG, "Adding Gateway Failed as Next hop is invalid");
377                 return OC_STACK_ERROR;
378             }
379
380         }
381         else if (NULL != entry  && entry->routeCost < routeCost)
382         {
383             OIC_LOG(ERROR, TAG, "Adding Gateway Failed as Route cost is more than old");
384             return OC_STACK_ERROR;
385         }
386
387         // Logic to add updated node to Head of list as route cost is 1.
388         if (1 == routeCost && NULL != entry)
389         {
390             OCStackResult res = u_linklist_remove(*gatewayTable, &destNode);
391             if (OC_STACK_OK != res)
392             {
393                 OIC_LOG(ERROR, TAG, "Removing node failed");
394             }
395             else
396             {
397                 res = u_linklist_add_head(*gatewayTable, (void *)entry);
398                 if (OC_STACK_OK != res)
399                 {
400                     OIC_LOG(ERROR, TAG, "Adding node to head failed");
401                 }
402             }
403         }
404     }
405     else
406     {
407         // Filling new Entry
408         RTMGatewayEntry_t *hopEntry = (RTMGatewayEntry_t *)OICCalloc(1, sizeof(RTMGatewayEntry_t));
409         if (NULL == hopEntry)
410         {
411             OIC_LOG(ERROR, TAG, "Calloc failed for hop entry");
412             return OC_STACK_ERROR;
413         }
414
415         hopEntry->destination = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
416         if (NULL == hopEntry->destination)
417         {
418             OIC_LOG(ERROR, TAG, "Calloc failed for hop entry destination");
419             OICFree(hopEntry);
420             return OC_STACK_ERROR;
421         }
422
423         hopEntry->destination->gatewayId = gatewayId;
424         if (NULL != destInterfaces && strlen((*destInterfaces).destIntfAddr.addr) > 0)
425         {
426             hopEntry->destination->destIntfAddr = u_arraylist_create();
427             RTMDestIntfInfo_t *destAdr =
428                 (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
429             if (NULL == destAdr)
430             {
431                 OIC_LOG(ERROR, TAG, "Calloc failed for destAdr");
432                 u_arraylist_free(&(hopEntry->destination->destIntfAddr));
433                 OICFree(hopEntry->destination);
434                 OICFree(hopEntry);
435                 return OC_STACK_ERROR;
436             }
437
438             *destAdr = *destInterfaces;
439             destAdr->timeElapsed = RTMGetCurrentTime();
440             destAdr->isValid = true;
441             u_arraylist_add(hopEntry->destination->destIntfAddr, (void *)destAdr);
442         }
443         else
444         {
445             hopEntry->destination->destIntfAddr = NULL;
446         }
447
448         hopEntry->routeCost = routeCost;
449         // Mapped nextHop gateway to another entries having gateway as destination.
450         if (NULL != gatewayNodeMap)
451         {
452             hopEntry->nextHop = gatewayNodeMap;
453         }
454         else if (1 == routeCost)
455         {
456             hopEntry->nextHop = NULL;
457         }
458         else
459         {
460             OIC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop is invalid");
461             while (u_arraylist_length(hopEntry->destination->destIntfAddr) > 0)
462             {
463                 RTMDestIntfInfo_t *data =
464                     u_arraylist_remove(hopEntry->destination->destIntfAddr, 0);
465                 OICFree(data);
466             }
467             u_arraylist_free(&(hopEntry->destination->destIntfAddr));
468             OICFree(hopEntry->destination);
469             OICFree(hopEntry);
470
471             return OC_STACK_ERROR;
472         }
473
474         OCStackResult ret = OC_STACK_OK;
475         if (hopEntry->routeCost == 1)
476         {
477             ret = u_linklist_add_head(*gatewayTable, (void *)hopEntry);
478         }
479         else
480         {
481             ret = u_linklist_add(*gatewayTable, (void *)hopEntry);
482         }
483
484         if (OC_STACK_OK != ret)
485         {
486             OIC_LOG(ERROR, TAG, "Adding Gateway Entry to Routing Table failed");
487             while (u_arraylist_length(hopEntry->destination->destIntfAddr) > 0)
488             {
489                 RTMDestIntfInfo_t *data = u_arraylist_remove(hopEntry->destination->destIntfAddr, 0);
490                 OICFree(data);
491             }
492             u_arraylist_free(&(hopEntry->destination->destIntfAddr));
493             OICFree(hopEntry->destination);
494             OICFree(hopEntry);
495             return OC_STACK_ERROR;
496         }
497     }
498     OIC_LOG(DEBUG, TAG, "OUT");
499     return OC_STACK_OK;
500 }
501
502 OCStackResult RTMAddEndpointEntry(uint16_t *endpointId, const CAEndpoint_t *destAddr,
503                                   u_linklist_t **endpointTable)
504 {
505     OIC_LOG(DEBUG, TAG, "IN");
506     RM_NULL_CHECK_WITH_RET(endpointId, TAG, "endpointId");
507     RM_NULL_CHECK_WITH_RET(destAddr, TAG, "destAddr");
508     RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
509     if (NULL == *endpointTable)
510     {
511         *endpointTable = u_linklist_create();
512         if (NULL == *endpointTable)
513         {
514             OIC_LOG(ERROR, TAG, "u_linklist_create failed");
515             return OC_STACK_NO_MEMORY;
516         }
517     }
518
519     u_linklist_iterator_t *iterTable = NULL;
520     u_linklist_init_iterator(*endpointTable, &iterTable);
521     // Iterate over gateway list to find if already entry with this gatewayid is present.
522     while (NULL != iterTable)
523     {
524         RTMEndpointEntry_t *entry =
525             (RTMEndpointEntry_t *) u_linklist_get_data(iterTable);
526
527         if (NULL != entry && (0 == memcmp(destAddr->addr, entry->destIntfAddr.addr,
528                               strlen(entry->destIntfAddr.addr)))
529             && destAddr->port == entry->destIntfAddr.port)
530         {
531             *endpointId = entry->endpointId;
532             OIC_LOG(ERROR, TAG, "Adding failed as Enpoint Entry Already present in Table");
533             return OC_STACK_DUPLICATE_REQUEST;
534         }
535         u_linklist_get_next(&iterTable);
536     }
537
538     // Filling Entry.
539     RTMEndpointEntry_t *hopEntry = (RTMEndpointEntry_t *)OICCalloc(1, sizeof(RTMEndpointEntry_t));
540
541     if (NULL == hopEntry)
542     {
543        OIC_LOG(ERROR, TAG, "Malloc failed for hop entry");
544        return OC_STACK_ERROR;
545     }
546
547     hopEntry->endpointId = *endpointId;
548     hopEntry->destIntfAddr = *destAddr;
549
550     OCStackResult ret = u_linklist_add(*endpointTable, (void *)hopEntry);
551     if (OC_STACK_OK != ret)
552     {
553        OIC_LOG(ERROR, TAG, "Adding Enpoint Entry to Routing Table failed");
554        OICFree(hopEntry);
555        return OC_STACK_ERROR;
556     }
557     OIC_LOG(DEBUG, TAG, "OUT");
558     return OC_STACK_OK;
559 }
560
561 OCStackResult RTMAddObserver(uint32_t obsID, CAEndpoint_t devAddr, u_linklist_t **gatewayTable)
562 {
563     OIC_LOG(DEBUG, TAG, "IN");
564     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
565     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
566
567     u_linklist_iterator_t *iterTable = NULL;
568     u_linklist_init_iterator(*gatewayTable, &iterTable);
569     while (NULL != iterTable)
570     {
571         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
572
573         for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
574         {
575             RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
576             if (NULL != destCheck &&
577                 (0 == memcmp(destCheck->destIntfAddr.addr, devAddr.addr, strlen(devAddr.addr)))
578                 && devAddr.port == destCheck->destIntfAddr.port)
579             {
580                 destCheck->observerId = obsID;
581                 OIC_LOG(DEBUG, TAG, "OUT");
582                 return OC_STACK_OK;
583             }
584         }
585         u_linklist_get_next(&iterTable);
586     }
587     OIC_LOG(DEBUG, TAG, "OUT");
588     return OC_STACK_ERROR;
589 }
590
591 bool RTMIsObserverPresent(CAEndpoint_t devAddr, OCObservationId *obsID,
592                           const u_linklist_t *gatewayTable)
593 {
594     OIC_LOG(DEBUG, TAG, "IN");
595     if (NULL == obsID)
596     {
597         OIC_LOG(ERROR, TAG, "obsID is null");
598         return false;
599     }
600
601     if (NULL == gatewayTable)
602     {
603         OIC_LOG(ERROR, TAG, "gatewayTable is null");
604         return false;
605     }
606
607     u_linklist_iterator_t *iterTable = NULL;
608     u_linklist_init_iterator(gatewayTable, &iterTable);
609     while (NULL != iterTable)
610     {
611         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
612         if (NULL == entry || NULL == entry->destination)
613         {
614             OIC_LOG(ERROR, TAG, "entry is NULL");
615             return false;
616         }
617         for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
618         {
619             RTMDestIntfInfo_t *destCheck =
620                 u_arraylist_get(entry->destination->destIntfAddr, i);
621             if (NULL != destCheck && (0 == memcmp(destCheck->destIntfAddr.addr, devAddr.addr,
622                                       strlen(devAddr.addr)))
623                 && devAddr.port == destCheck->destIntfAddr.port && 0 != destCheck->observerId)
624             {
625                 *obsID = destCheck->observerId;
626                 OIC_LOG(DEBUG, TAG, "OUT");
627                 return true;
628             }
629         }
630         u_linklist_get_next(&iterTable);
631     }
632     OIC_LOG(DEBUG, TAG, "OUT");
633     return false;
634 }
635
636 OCStackResult RTMRemoveGatewayEntry(uint32_t gatewayId, u_linklist_t **removedGatewayNodes,
637                                     u_linklist_t **gatewayTable)
638 {
639     OIC_LOG(DEBUG, TAG, "IN");
640     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
641     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
642
643     u_linklist_iterator_t *iterTable = NULL;
644
645     // if link list is not null we can directly add removed nodes to it instead of creating everytime.
646     if (NULL == *removedGatewayNodes)
647     {
648         *removedGatewayNodes = u_linklist_create();
649         if (NULL == *removedGatewayNodes)
650         {
651             OIC_LOG(ERROR, TAG, "u_linklist_create failed");
652             return OC_STACK_NO_MEMORY;
653         }
654     }
655     OCStackResult ret = OC_STACK_OK;
656     u_linklist_init_iterator(*gatewayTable, &iterTable);
657     while (NULL != iterTable)
658     {
659         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
660         if (NULL == entry || NULL == entry->destination)
661         {
662             u_linklist_get_next(&iterTable);
663             continue;
664         }
665
666         if (gatewayId == entry->destination->gatewayId || (NULL != entry->nextHop &&
667             (gatewayId == entry->nextHop->gatewayId)))
668         {
669             OIC_LOG_V(DEBUG, TAG, "Removing the gateway entry: %u", entry->destination->gatewayId);
670             ret = u_linklist_remove(*gatewayTable, &iterTable);
671             if (OC_STACK_OK != ret)
672             {
673                OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
674                return OC_STACK_ERROR;
675             }
676             else
677             {
678                 u_linklist_add(*removedGatewayNodes, (void *)entry);
679             }
680         }
681         else
682         {
683             u_linklist_get_next(&iterTable);
684         }
685     }
686     OIC_LOG(DEBUG, TAG, "RTMRemoveGatewayEntry OUT");
687     return OC_STACK_OK;
688 }
689
690 OCStackResult RTMRemoveGatewayDestEntry(uint32_t gatewayId, uint32_t nextHop,
691                                         const RTMDestIntfInfo_t *destInfAdr,
692                                         RTMGatewayEntry_t **existEntry, u_linklist_t **gatewayTable)
693 {
694     OIC_LOG(DEBUG, TAG, "IN");
695     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
696     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
697     RM_NULL_CHECK_WITH_RET(destInfAdr, TAG, "destInfAdr");
698
699     u_linklist_iterator_t *iterTable = NULL;
700
701     OCStackResult ret = -1;
702     u_linklist_init_iterator(*gatewayTable, &iterTable);
703     while (NULL != iterTable)
704     {
705         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
706         if (NULL == entry)
707         {
708             u_linklist_get_next(&iterTable);
709             continue;
710         }
711
712         // Update the time for NextHop entry.
713         if (NULL != entry->destination && nextHop == entry->destination->gatewayId)
714         {
715             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
716             {
717                 RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
718                 if(!destCheck)
719                 {
720                     continue;
721                 }
722                 if (0 == memcmp(destCheck->destIntfAddr.addr, destInfAdr->destIntfAddr.addr,
723                     strlen(destInfAdr->destIntfAddr.addr))
724                     && destInfAdr->destIntfAddr.port == destCheck->destIntfAddr.port)
725                 {
726                     destCheck->timeElapsed =  RTMGetCurrentTime();
727                     break;
728                 }
729             }
730         }
731
732         // Remove node with given gatewayid and nextHop if not found update exist entry.
733         if (NULL != entry->destination && (gatewayId == entry->destination->gatewayId))
734         {
735             OIC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", entry->destination->gatewayId);
736             if (NULL != entry->nextHop && nextHop == entry->nextHop->gatewayId)
737             {
738                 ret = u_linklist_remove(*gatewayTable, &iterTable);
739                 if (OC_STACK_OK != ret)
740                 {
741                    OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
742                    return OC_STACK_ERROR;
743                 }
744                 OICFree(entry);
745                 return OC_STACK_OK;
746             }
747
748             *existEntry = entry;
749             OIC_LOG(DEBUG, TAG, "OUT");
750             return OC_STACK_ERROR;
751         }
752
753         u_linklist_get_next(&iterTable);
754     }
755     OIC_LOG(DEBUG, TAG, "OUT");
756     return OC_STACK_ERROR;
757 }
758
759 OCStackResult RTMRemoveEndpointEntry(uint16_t endpointId, u_linklist_t **endpointTable)
760 {
761     OIC_LOG(DEBUG, TAG, "IN");
762     RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
763     RM_NULL_CHECK_WITH_RET(*endpointTable, TAG, "*endpointTable");
764
765     u_linklist_iterator_t *iterTable = NULL;
766     u_linklist_init_iterator(*endpointTable, &iterTable);
767     while (NULL != iterTable)
768     {
769         RTMEndpointEntry_t *entry = u_linklist_get_data(iterTable);
770         if (NULL !=  entry && endpointId == entry->endpointId)
771         {
772             OCStackResult ret = u_linklist_remove(*endpointTable, &iterTable);
773             if (OC_STACK_OK != ret)
774             {
775                OIC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
776                return OC_STACK_ERROR;
777             }
778             OICFree(entry);
779         }
780         else
781         {
782             u_linklist_get_next(&iterTable);
783         }
784     }
785     OIC_LOG(DEBUG, TAG, "OUT");
786     return OC_STACK_OK;
787 }
788
789 OCStackResult RTMRemoveGateways(u_linklist_t **gatewayTable)
790 {
791     OIC_LOG(DEBUG, TAG, "IN");
792
793     if (NULL == gatewayTable || NULL == *gatewayTable)
794     {
795         OIC_LOG(DEBUG, TAG, "OUT");
796         return OC_STACK_OK;
797     }
798
799     OCStackResult ret = RTMFreeGatewayRouteTable(gatewayTable);
800     if (OC_STACK_OK != ret)
801     {
802         OIC_LOG(ERROR, TAG, "Removing Gateways failed");
803         return ret;
804     }
805     OIC_LOG(DEBUG, TAG, "OUT");
806     return OC_STACK_OK;
807 }
808
809 OCStackResult RTMRemoveEndpoints(u_linklist_t **endpointTable)
810 {
811     OIC_LOG(DEBUG, TAG, "IN");
812     if (NULL == endpointTable || NULL == *endpointTable)
813     {
814         OIC_LOG(DEBUG, TAG, "OUT");
815         return OC_STACK_OK;
816     }
817
818     OCStackResult ret = RTMFreeEndpointRouteTable(endpointTable);
819     if (OC_STACK_OK != ret)
820     {
821         OIC_LOG(ERROR, TAG, "Freeing Endpoints failed");
822         return OC_STACK_ERROR;
823     }
824     OIC_LOG(DEBUG, TAG, "OUT");
825     return OC_STACK_OK;
826 }
827
828 void RTMFreeGateway(RTMGatewayId_t *gateway, u_linklist_t **gatewayTable)
829 {
830     OIC_LOG(DEBUG, TAG, "IN");
831     RM_NULL_CHECK_VOID(gateway, TAG, "gateway");
832     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
833     RM_NULL_CHECK_VOID(*gatewayTable, TAG, "*gatewayTable");
834     while (0 < u_arraylist_length(gateway->destIntfAddr))
835     {
836         void *data = u_arraylist_remove(gateway->destIntfAddr, 0);
837         OICFree(data);
838     }
839     u_arraylist_free(&(gateway->destIntfAddr));
840     OICFree(gateway);
841     OIC_LOG(DEBUG, TAG, "OUT");
842 }
843
844 void RTMGetNeighbours(u_linklist_t **neighbourNodes, const u_linklist_t *gatewayTable)
845 {
846     OIC_LOG(DEBUG, TAG, "IN");
847     RM_NULL_CHECK_VOID(neighbourNodes, TAG, "neighbourNodes");
848     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
849
850     *neighbourNodes = u_linklist_create();
851     if (NULL == *neighbourNodes)
852     {
853         OIC_LOG(ERROR, TAG, "u_linklist_create failed");
854         return;
855     }
856     u_linklist_iterator_t *iterTable = NULL;
857     u_linklist_init_iterator(gatewayTable, &iterTable);
858     while (NULL != iterTable)
859     {
860         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
861         if (NULL != entry && 1 == entry->routeCost)
862         {
863             u_linklist_add(*neighbourNodes, (void *)entry);
864         }
865         else if (NULL != entry && 1 < entry->routeCost)
866         {
867             OIC_LOG(DEBUG, TAG, "OUT");
868             return;
869         }
870
871         u_linklist_get_next(&iterTable);
872     }
873     OIC_LOG(DEBUG, TAG, "OUT");
874 }
875
876 RTMGatewayId_t *RTMGetNextHop(uint32_t gatewayId, const u_linklist_t *gatewayTable)
877 {
878     OIC_LOG(DEBUG, TAG, "IN");
879     if (0 == gatewayId)
880     {
881         OIC_LOG(ERROR, TAG, "gatewayId is invalid");
882         return NULL;
883     }
884
885     if (NULL == gatewayTable)
886     {
887         OIC_LOG(ERROR, TAG, "gatewayTable is null");
888         return NULL;
889     }
890
891     u_linklist_iterator_t *iterTable = NULL;
892     u_linklist_init_iterator(gatewayTable, &iterTable);
893     while (NULL != iterTable)
894     {
895         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
896         if (NULL != entry && gatewayId == entry->destination->gatewayId)
897         {
898             if (1 == entry->routeCost)
899             {
900                 OIC_LOG(DEBUG, TAG, "OUT");
901                 return entry->destination;
902             }
903             OIC_LOG(DEBUG, TAG, "OUT");
904             return entry->nextHop;
905         }
906         u_linklist_get_next(&iterTable);
907     }
908     OIC_LOG(DEBUG, TAG, "OUT");
909     return NULL;
910 }
911
912 CAEndpoint_t *RTMGetEndpointEntry(uint16_t endpointId, const u_linklist_t *endpointTable)
913 {
914     OIC_LOG(DEBUG, TAG, "IN");
915     if (NULL == endpointTable)
916     {
917         OIC_LOG(ERROR, TAG, "endpointTable is null");
918         return NULL;
919     }
920
921     u_linklist_iterator_t *iterTable = NULL;
922     u_linklist_init_iterator(endpointTable, &iterTable);
923
924     while (NULL != iterTable)
925     {
926         RTMEndpointEntry_t *entry = u_linklist_get_data(iterTable);
927         if (NULL != entry && (endpointId == entry->endpointId))
928         {
929             OIC_LOG(DEBUG, TAG, "OUT");
930             return &(entry->destIntfAddr);
931         }
932         u_linklist_get_next(&iterTable);
933     }
934     OIC_LOG(DEBUG, TAG, "OUT");
935     return NULL;
936 }
937
938 void RTMGetObserverList(OCObservationId **obsList, uint8_t *obsListLen,
939                         const u_linklist_t *gatewayTable)
940 {
941     OIC_LOG(DEBUG, TAG, "IN");
942     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
943     RM_NULL_CHECK_VOID(obsList, TAG, "obsList");
944
945     *obsList = (OCObservationId *) OICCalloc(MAX_OBSERVER_LIST_LENGTH, sizeof(OCObservationId));
946     if (!(*obsList))
947     {
948         OIC_LOG(ERROR, TAG, "out of memory");
949         return;
950     }
951
952     u_linklist_iterator_t *iterTable = NULL;
953     u_linklist_init_iterator(gatewayTable, &iterTable);
954     uint8_t len = 0;
955     while (NULL != iterTable)
956     {
957         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
958         if (0 < u_arraylist_length(entry->destination->destIntfAddr))
959         {
960             RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, 0);
961             if (NULL == destCheck)
962             {
963                 OIC_LOG(ERROR, TAG, "destCheck is null");
964                 return;
965             }
966             if (0 != destCheck->observerId)
967             {
968                 OIC_LOG_V(DEBUG, TAG, "Observer ID is %d", destCheck->observerId);
969                 *(*obsList + len) = destCheck->observerId;
970                 len++;
971             }
972             if (MAX_OBSERVER_LIST_LENGTH < len)
973             {
974                 *obsList = (OCObservationId *) OICRealloc((void *)*obsList,
975                            (sizeof(OCObservationId) * (len + 1)));
976             }
977         }
978         u_linklist_get_next(&iterTable);
979     }
980
981     *obsListLen = len;
982     OIC_LOG(DEBUG, TAG, "OUT");
983 }
984
985 OCStackResult RTMUpdateDestinationIntfAdr(uint32_t gatewayId, RTMDestIntfInfo_t destInterfaces,
986                                           bool addAdr, u_linklist_t **gatewayTable)
987 {
988     OIC_LOG(DEBUG, TAG, "IN");
989     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
990     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
991
992     u_linklist_iterator_t *iterTable = NULL;
993     u_linklist_init_iterator(*gatewayTable, &iterTable);
994     while (NULL != iterTable)
995     {
996         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
997         if (NULL != entry && NULL != entry->destination &&
998             gatewayId == entry->destination->gatewayId)
999         {
1000             if (addAdr)
1001             {
1002                 for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1003                 {
1004                     RTMDestIntfInfo_t *destCheck =
1005                         u_arraylist_get(entry->destination->destIntfAddr, i);
1006                     if (NULL == destCheck)
1007                     {
1008                         OIC_LOG(ERROR, TAG, "Destination adr get failed");
1009                         continue;
1010                     }
1011
1012                     if (0 == memcmp(destCheck->destIntfAddr.addr, destInterfaces.destIntfAddr.addr,
1013                         strlen(destInterfaces.destIntfAddr.addr))
1014                         && destInterfaces.destIntfAddr.port == destCheck->destIntfAddr.port)
1015                     {
1016                         destCheck->timeElapsed = RTMGetCurrentTime();
1017                         destCheck->isValid = true;
1018                         OIC_LOG(ERROR, TAG, "destInterfaces already present");
1019                         return OC_STACK_ERROR;
1020                     }
1021                 }
1022
1023                 RTMDestIntfInfo_t *destAdr =
1024                         (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
1025                 if (NULL == destAdr)
1026                 {
1027                     OIC_LOG(ERROR, TAG, "Calloc destAdr failed");
1028                     return OC_STACK_ERROR;
1029                 }
1030                 *destAdr = destInterfaces;
1031                 destAdr->timeElapsed = RTMGetCurrentTime();
1032                 destAdr->isValid = true;
1033                 bool result =
1034                     u_arraylist_add(entry->destination->destIntfAddr, (void *)destAdr);
1035                 if (!result)
1036                 {
1037                     OIC_LOG(ERROR, TAG, "Updating Destinterface address failed");
1038                     OICFree(destAdr);
1039                     return OC_STACK_ERROR;
1040                 }
1041                 OIC_LOG(DEBUG, TAG, "OUT");
1042                 return OC_STACK_DUPLICATE_REQUEST;
1043             }
1044
1045             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1046             {
1047                 RTMDestIntfInfo_t *removeAdr =
1048                     u_arraylist_get(entry->destination->destIntfAddr, i);
1049                 if (!removeAdr)
1050                 {
1051                     continue;
1052                 }
1053                 if (0 == memcmp(removeAdr->destIntfAddr.addr, destInterfaces.destIntfAddr.addr,
1054                     strlen(destInterfaces.destIntfAddr.addr))
1055                     && destInterfaces.destIntfAddr.port == removeAdr->destIntfAddr.port)
1056                 {
1057                     RTMDestIntfInfo_t *data =
1058                         u_arraylist_remove(entry->destination->destIntfAddr, i);
1059                     OICFree(data);
1060                     break;
1061                 }
1062             }
1063         }
1064         u_linklist_get_next(&iterTable);
1065     }
1066     OIC_LOG(DEBUG, TAG, "OUT");
1067     return OC_STACK_OK;
1068 }
1069
1070 OCStackResult RTMUpdateMcastSeqNumber(uint32_t gatewayId, uint16_t seqNum,
1071                                       u_linklist_t **gatewayTable)
1072 {
1073     OIC_LOG(DEBUG, TAG, "IN");
1074     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1075     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1076
1077     u_linklist_iterator_t *iterTable = NULL;
1078     u_linklist_init_iterator(*gatewayTable, &iterTable);
1079     while (NULL != iterTable)
1080     {
1081         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
1082         if (NULL != entry && NULL != entry->destination &&
1083             gatewayId == entry->destination->gatewayId)
1084         {
1085             if (0 == entry->mcastMessageSeqNum || entry->mcastMessageSeqNum < seqNum)
1086             {
1087                 entry->mcastMessageSeqNum = seqNum;
1088                 return OC_STACK_OK;
1089             }
1090             else if (entry->mcastMessageSeqNum == seqNum)
1091             {
1092                 return OC_STACK_DUPLICATE_REQUEST;
1093             }
1094             else
1095             {
1096                 return OC_STACK_COMM_ERROR;
1097             }
1098         }
1099         u_linklist_get_next(&iterTable);
1100     }
1101     OIC_LOG(DEBUG, TAG, "OUT");
1102     return OC_STACK_OK;
1103 }
1104
1105 uint64_t RTMGetCurrentTime()
1106 {
1107     uint64_t currentTime = 0;
1108
1109 #ifdef __ANDROID__
1110     struct timespec getTs;
1111
1112     clock_gettime(CLOCK_MONOTONIC, &getTs);
1113
1114     currentTime = getTs.tv_sec;
1115 #elif defined __ARDUINO__
1116     currentTime = millis() / 1000;
1117 #else
1118 #if _POSIX_TIMERS > 0
1119     struct timespec ts;
1120     clock_gettime(CLOCK_MONOTONIC, &ts);
1121     currentTime = ts.tv_sec;
1122 #else
1123     struct timeval tv;
1124     gettimeofday(&tv, NULL);
1125     currentTime = tv.tv_sec;
1126 #endif
1127 #endif
1128     return currentTime;
1129 }
1130
1131 OCStackResult RTMUpdateDestAddrValidity(u_linklist_t **invalidTable, u_linklist_t **gatewayTable)
1132 {
1133     OIC_LOG(DEBUG, TAG, "IN");
1134     RM_NULL_CHECK_WITH_RET(invalidTable, TAG, "invalidTable");
1135     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1136     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1137
1138     *invalidTable = u_linklist_create();
1139     if (NULL == *invalidTable)
1140     {
1141         OIC_LOG(ERROR, TAG, "u_linklist_create failed");
1142         return OC_STACK_NO_MEMORY;
1143     }
1144
1145     u_linklist_iterator_t *iterTable = NULL;
1146     uint64_t presentTime = RTMGetCurrentTime();
1147
1148     u_linklist_init_iterator(*gatewayTable, &iterTable);
1149     while (NULL != iterTable)
1150     {
1151         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
1152         if (NULL == entry)
1153         {
1154             u_linklist_get_next(&iterTable);
1155             continue;
1156         }
1157         else if (1 == entry->routeCost)
1158         {
1159             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1160             {
1161                 RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
1162                 if (!destCheck)
1163                 {
1164                     continue;
1165                 }
1166                 if (GATEWAY_ALIVE_TIMEOUT < (presentTime - destCheck->timeElapsed))
1167                 {
1168                     destCheck->isValid = false;
1169                     u_linklist_add(*invalidTable, (void *)destCheck);
1170                 }
1171             }
1172         }
1173         else if (1 < entry->routeCost)
1174         {
1175             break;
1176         }
1177         u_linklist_get_next(&iterTable);
1178     }
1179     OIC_LOG(DEBUG, TAG, "OUT");
1180     return OC_STACK_OK;
1181 }
1182
1183 OCStackResult RTMRemoveInvalidGateways(u_linklist_t **invalidTable, u_linklist_t **gatewayTable)
1184 {
1185     OIC_LOG(DEBUG, TAG, "IN");
1186     RM_NULL_CHECK_WITH_RET(invalidTable, TAG, "invalidTable");
1187     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1188     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1189
1190     *invalidTable = u_linklist_create();
1191     if (NULL == *invalidTable)
1192     {
1193         OIC_LOG(ERROR, TAG, "u_linklist_create failed");
1194         return OC_STACK_NO_MEMORY;
1195     }
1196
1197     u_linklist_iterator_t *iterTable = NULL;
1198     u_linklist_init_iterator(*gatewayTable, &iterTable);
1199     while (iterTable != NULL)
1200     {
1201         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
1202
1203         if (NULL == entry)
1204         {
1205             u_linklist_get_next(&iterTable);
1206             continue;
1207         }
1208         else if (NULL != entry->destination && (1 == entry->routeCost))
1209         {
1210             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1211             {
1212                 RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
1213                 if (!destCheck && !destCheck->isValid)
1214                 {
1215                     void *data = u_arraylist_remove(entry->destination->destIntfAddr, i);
1216                     OICFree(data);
1217                     i--;
1218                 }
1219             }
1220
1221             if (0 == u_arraylist_length(entry->destination->destIntfAddr))
1222             {
1223                 u_arraylist_free(&(entry->destination->destIntfAddr));
1224                 OCStackResult res =
1225                     RTMRemoveGatewayEntry(entry->destination->gatewayId, invalidTable, gatewayTable);
1226                 if (OC_STACK_OK != res)
1227                 {
1228                     OIC_LOG(ERROR, TAG, "Removing Entries failed");
1229                     return OC_STACK_ERROR;
1230                 }
1231                 u_linklist_get_next(&iterTable);
1232             }
1233             else
1234             {
1235                 u_linklist_get_next(&iterTable);
1236             }
1237         }
1238         else if (1 < entry->routeCost)
1239         {
1240             break;
1241         }
1242         else
1243         {
1244             u_linklist_get_next(&iterTable);
1245         }
1246     }
1247     OIC_LOG(DEBUG, TAG, "OUT");
1248     return OC_STACK_OK;
1249 }
1250
1251 OCStackResult RTMUpdateEntryParameters(uint32_t gatewayId, uint32_t seqNum,
1252                                        const RTMDestIntfInfo_t *destAdr, u_linklist_t **gatewayTable,
1253                                        bool forceUpdate)
1254 {
1255     OIC_LOG(DEBUG, TAG, "IN");
1256     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1257     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1258     RM_NULL_CHECK_WITH_RET(destAdr, TAG, "destAdr");
1259
1260     u_linklist_iterator_t *iterTable = NULL;
1261     u_linklist_init_iterator(*gatewayTable, &iterTable);
1262     while (NULL != iterTable)
1263     {
1264         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
1265
1266         if (NULL == entry)
1267         {
1268             u_linklist_get_next(&iterTable);
1269             continue;
1270         }
1271         if (NULL != entry->destination && gatewayId == entry->destination->gatewayId)
1272         {
1273             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1274             {
1275                 RTMDestIntfInfo_t *destCheck =
1276                     u_arraylist_get(entry->destination->destIntfAddr, i);
1277                 if (NULL != destCheck &&
1278                     (0 == memcmp(destCheck->destIntfAddr.addr, destAdr->destIntfAddr.addr,
1279                      strlen(destAdr->destIntfAddr.addr)))
1280                      && destAdr->destIntfAddr.port == destCheck->destIntfAddr.port)
1281                 {
1282                     destCheck->timeElapsed = RTMGetCurrentTime();
1283                     destCheck->isValid = true;
1284                 }
1285             }
1286
1287             if (0 != entry->seqNum && seqNum == entry->seqNum)
1288             {
1289                 return OC_STACK_DUPLICATE_REQUEST;
1290             }
1291             else if (0 != entry->seqNum && seqNum != ((entry->seqNum) + 1) && !forceUpdate)
1292             {
1293                 return OC_STACK_COMM_ERROR;
1294             }
1295             else
1296             {
1297                 entry->seqNum = seqNum;
1298                 OIC_LOG(DEBUG, TAG, "OUT");
1299                 return OC_STACK_OK;
1300             }
1301         }
1302         u_linklist_get_next(&iterTable);
1303     }
1304     OIC_LOG(DEBUG, TAG, "OUT");
1305     return OC_STACK_OK;
1306 }
1307
1308 void RTMPrintTable(const u_linklist_t *gatewayTable, const u_linklist_t *endpointTable)
1309 {
1310     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
1311     OIC_LOG(DEBUG, RM_TAG, "=================Gateway List table============================\n");
1312     u_linklist_iterator_t *iterTable = NULL;
1313     u_linklist_init_iterator(gatewayTable, &iterTable);
1314     while (NULL != iterTable)
1315     {
1316         RTMGatewayEntry_t *hop =
1317             (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
1318         if (NULL == hop)
1319         {
1320             OIC_LOG(ERROR, RM_TAG, "Printing Table Failed");
1321             return;
1322         }
1323         if (NULL == hop->nextHop || 0 == hop->nextHop->gatewayId)
1324         {
1325             OIC_LOG_V(DEBUG, RM_TAG, "\nDestination : %u\nNextHop : (null)\nHopCount : %d",
1326                      hop->destination->gatewayId, hop->routeCost);
1327             OIC_LOG_V(DEBUG, RM_TAG, "\nSequence Number :%u", hop->seqNum);
1328         }
1329         else
1330         {
1331             OIC_LOG_V(DEBUG, RM_TAG, "\nDestination : %u\nNextHop : %u\nHopCount : %d",
1332                      hop->destination->gatewayId, hop->nextHop->gatewayId, hop->routeCost);
1333             OIC_LOG_V(DEBUG, RM_TAG, "\nSequence Number :%u", hop->seqNum);
1334         }
1335         if (1 == hop->routeCost && NULL != hop->destination &&
1336             hop->destination->destIntfAddr != NULL)
1337         {
1338             for (uint32_t i = 0; i < u_arraylist_length(hop->destination->destIntfAddr); i++)
1339             {
1340                 RTMDestIntfInfo_t *dest = u_arraylist_get(hop->destination->destIntfAddr, i);
1341                 if (NULL != dest)
1342                 {
1343                     OIC_LOG_V(DEBUG, RM_TAG, "\nDestination interface addresses: %s Port : %d Obs ID: %d",
1344                              dest->destIntfAddr.addr, dest->destIntfAddr.port, dest->observerId);
1345                     OIC_LOG_V(DEBUG, RM_TAG, "Validity: %d", dest->isValid);
1346                 }
1347             }
1348         }
1349         OIC_LOG(DEBUG, RM_TAG, "********************************************\n");
1350         u_linklist_get_next(&iterTable);
1351     }
1352
1353     OIC_LOG(DEBUG, RM_TAG, "=================Endpoint List table============================\n");
1354     u_linklist_iterator_t *iterEndpointTable = NULL;
1355     u_linklist_init_iterator(endpointTable, &iterEndpointTable);
1356
1357     // Iterate over endpoint list to find if already entry for gatewayid is present.
1358     while (NULL != iterEndpointTable)
1359     {
1360         RTMEndpointEntry_t *hop =
1361             (RTMEndpointEntry_t *) u_linklist_get_data(iterEndpointTable);
1362         if (NULL == hop)
1363         {
1364             OIC_LOG(ERROR, RM_TAG, "Printing Table Failed");
1365             return;
1366         }
1367         OIC_LOG_V(DEBUG, RM_TAG, "EndpointId : %u\naddr : %s Port : %d",
1368                   hop->endpointId, hop->destIntfAddr.addr, hop->destIntfAddr.port);
1369
1370         OIC_LOG(DEBUG, RM_TAG, "********************************************\n");
1371         u_linklist_get_next(&iterEndpointTable);
1372     }
1373 }