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