Prevent fixes in Routing Manager and CA.
[platform/upstream/iotivity.git] / resource / csdk / routing / src / routingmanager.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 "routingmanager.h"
24 #include "routingmanagerinterface.h"
25 #include "routingtablemanager.h"
26 #include "routingmessageparser.h"
27 #include "oic_malloc.h"
28 #include "oic_string.h"
29 #include "ocrandom.h"
30 #include "ulinklist.h"
31 #include "uarraylist.h"
32 #include "ocstackinternal.h"
33 #include "include/logger.h"
34
35 /**
36  * Logging tag for module name.
37  */
38 #define TAG "RM"
39
40 /**
41  * Tag for printing the logs of forwarding the packet.
42  */
43 #define RM_TAG "RAP"
44
45
46 /**
47  * Unique gateway ID generated before hosting a gateway resource.
48  */
49 uint32_t g_GatewayID = 0;
50
51 /**
52  * Used for assigning unique ID.to endpoint's connected to this gateway
53  */
54 static uint16_t g_EndpointCount = 0;
55
56 /**
57  * Routing table which holds hop entries of Gateways with routeCost.
58  */
59 static u_linklist_t *g_routingGatewayTable = NULL;
60
61 /**
62  * List which holds hop entries with Endpoint information.
63  */
64 static u_linklist_t *g_routingEndpointTable = NULL;
65
66 /**
67  * Current time in microseconds.
68  */
69 static uint64_t g_aliveTime = 0;
70
71 /**
72  * Time to refresh the table entries.
73  */
74 static uint64_t g_refreshTableTime = 0;
75
76 /**
77  * Sequence number for the notification.
78  */
79 static uint32_t g_sequenceNumber = 1;
80
81 /**
82  * To check if the routing table is validated on 25th seconds.
83  */
84 static bool g_isValidated = false;
85
86 /**
87  * Multi cast Sequence number.
88  */
89 static uint16_t g_mcastsequenceNumber = 1;
90
91 /**
92  * To check if RM is initialized.
93  */
94 static bool g_isRMInitialized = false;
95
96 /**
97  * API to handle the GET request received for a Gateway Resource.
98  * @param[in]   request     Request Received.
99  * @param[in]   resource    Resource handle used for sending the response.
100  * @return  ::OC_STACK_OK or Appropriate error code.
101  */
102 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource);
103
104 /**
105  * API to handle the OBSERVE request received for a Gateway Resource.
106  * @param[in,out]   request    Request Received.
107  * @param[in]       resource   Resource handle used for sending the response.
108  * @return  ::OC_STACK_OK or Appropriate error code.
109  */
110 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource);
111
112 /**
113  * API to handle the OBSERVE request received for a Gateway Resource.
114  * @param[in,out]   request    Request Received.
115  * @param[in]       resource   Resource handle used for sending the response.
116  * @return  ::OC_STACK_OK or Appropriate error code.
117  */
118 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource);
119
120 /**
121  * Adds a observer after generating observer ID whenever observe
122  * request is received.
123  * @param[in,out]   request     Request handle of the Observe request.
124  *                              Sets the value of observeResult as OC_STACK_OK
125  *                              if observer is added successfully.
126  * @param[out]      obsID       Observer ID generated for the observer.
127  * @return  ::OC_STACK_OK or Appropriate error code.
128  */
129 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID);
130
131 /**
132  * Send Notification to all the observers.
133  * @param[in]   payload                 Payload to be sent in notification.
134  * @return  ::OC_STACK_OK or Appropriate error code.
135  */
136 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload);
137
138 /**
139  * Send Delete request to all the neighbour nodes.
140  * @return  NONE.
141  */
142 void RMSendDeleteToNeighbourNodes();
143
144 void RMGenerateGatewayID(uint8_t *id, size_t idLen)
145 {
146     OC_LOG(DEBUG, TAG, "RMGenerateGatewayID IN");
147     OCFillRandomMem(id, idLen);
148     OC_LOG(DEBUG, TAG, "RMGenerateGatewayID OUT");
149 }
150 OCStackResult RMInitialize()
151 {
152     OC_LOG(DEBUG, TAG, "RMInitialize IN");
153     if (g_isRMInitialized)
154     {
155         OC_LOG(DEBUG, TAG, "RM already initialized");
156         return OC_STACK_OK;
157     }
158
159     // Initialize the GatewayResource[/oic/gateway].
160     OCStackResult result = RMInitGatewayResource();
161     if (OC_STACK_OK != result)
162     {
163         OC_LOG_V(ERROR, TAG, "RMInitGatewayResource failed[%d]", result);
164         return result;
165     }
166
167     // Generates a 4 byte Gateway ID.
168     RMGenerateGatewayID((uint8_t *)&g_GatewayID, sizeof(g_GatewayID));
169
170     OC_LOG_V(INFO, RM_TAG, "Gateway ID: %u", g_GatewayID);
171
172     // Initialize the Routing table manager.
173     result = RTMInitialize(&g_routingGatewayTable, &g_routingEndpointTable);
174     if (OC_STACK_OK != result)
175     {
176         OC_LOG_V(ERROR, TAG, "RTMInitialize failed[%d]", result);
177         return result;
178     }
179
180     g_isRMInitialized = true;
181
182     // Send a DISCOVER request for the gateway resource.
183     result = RMDiscoverGatewayResource();
184     if (OC_STACK_OK != result)
185     {
186         OC_LOG_V(ERROR, TAG, "RMDiscoverGatewayResource failed[%d]", result);
187         RTMTerminate(&g_routingGatewayTable, &g_routingEndpointTable);
188         return result;
189     }
190
191     // Initialize the timer with the current time.
192     g_aliveTime = RTMGetCurrentTime();
193     g_refreshTableTime = g_aliveTime;
194
195     OC_LOG(DEBUG, TAG, "RMInitialize OUT");
196     return result;
197 }
198
199 OCStackResult RMTerminate()
200 {
201     OC_LOG(DEBUG, TAG, "RMTerminate IN");
202     if (!g_isRMInitialized)
203     {
204         OC_LOG(ERROR, TAG, "RM not initialized");
205         return OC_STACK_ERROR;
206     }
207     // Send DELETE request to neighbour nodes
208     RMSendDeleteToNeighbourNodes();
209
210     OCStackResult result = RTMTerminate(&g_routingGatewayTable, &g_routingEndpointTable);
211     if (OC_STACK_OK != result)
212     {
213         OC_LOG_V(ERROR, TAG, "CARegisterRoutingMessageHandler failed[%d]", result);
214         return result;
215     }
216     g_isRMInitialized = false;
217     OC_LOG(DEBUG, TAG, "RMTerminate OUT");
218     return result;
219 }
220
221 OCStackResult RMHandleGatewayRequest(OCServerRequest *request, const OCResource *resource)
222 {
223     OC_LOG(DEBUG, TAG, "RMHandleGatewayRequest IN");
224
225     if (!g_isRMInitialized)
226     {
227         OC_LOG(ERROR, TAG, "RM not initialized");
228         return OC_STACK_ERROR;
229     }
230
231     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
232     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
233
234     OC_LOG_V(DEBUG, TAG, "Received request of method: %d", request->method);
235
236     if (OC_REST_GET == request->method)
237     {
238         switch((OCObserveAction)request->observationOption)
239         {
240             case OC_OBSERVE_REGISTER:
241                 OC_LOG(DEBUG, TAG, "Received OBSERVE request");
242                 RMHandleOBSERVERequest(request, resource);
243                 break;
244             case OC_OBSERVE_DEREGISTER:
245                 //TODO: Handle this case
246                 OC_LOG(DEBUG, TAG, "Received OBSERVE deregister");
247                 break;
248             case OC_OBSERVE_NO_OPTION:
249                 OC_LOG(DEBUG, TAG, "Received GET request");
250                 RMHandleGETRequest(request, resource);
251                 break;
252             default:
253                 OC_LOG(DEBUG, TAG, "Not Supported by Routing Manager");
254         }
255     }
256     else if (OC_REST_DELETE == request->method)
257     {
258         OC_LOG(DEBUG, TAG, "Received a Delete request");
259         RMHandleDELETERequest(request, resource);
260     }
261     OC_LOG(DEBUG, TAG, "RMHandleGatewayRequest OUT");
262     return OC_STACK_OK;
263 }
264
265 OCStackResult RMHandleRequestPayload(OCDevAddr devAddr, const uint8_t *reqPayload,
266                                      size_t payloadSize)
267 {
268     OC_LOG(DEBUG, TAG, "RMHandleRequestPayload IN");
269     RM_NULL_CHECK_WITH_RET(reqPayload, TAG, "reqPayload");
270
271     uint32_t gatewayId = 0;
272
273     OCStackResult result = RMPParseRequestPayload(reqPayload, payloadSize, &gatewayId);
274     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
275     OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
276     // Check if the entry is its own.
277     if (gatewayId == g_GatewayID)
278     {
279         OC_LOG(INFO, TAG, "Own Request Received!!");
280         return OC_STACK_CONTINUE;
281     }
282
283     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
284     CopyDevAddrToEndpoint(&devAddr, &endpoint);
285
286     OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
287     RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
288     destInterfaces.destIntfAddr = endpoint;
289     result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
290
291     if (OC_STACK_OK != result)
292     {
293         OC_LOG(DEBUG, TAG, "Gateway was not added to the routing table");
294         return result;
295     }
296
297     OC_LOG(INFO, TAG, "Gateway was added");
298     // Create a list to add the updated entries and notify the observers
299     u_linklist_t *updatedTableList = u_linklist_create();
300     if(!updatedTableList)
301     {
302         OC_LOG(DEBUG, TAG, "Failure to notify");
303         return OC_STACK_NO_MEMORY;
304     }
305
306     RTMGatewayId_t gwId = {.gatewayId = gatewayId};
307     RTMGatewayEntry_t newNode;
308     newNode.destination = &gwId;
309     newNode.routeCost = 1;
310     u_linklist_add(updatedTableList, (void *)&newNode);
311     RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
312
313     OCRepPayload *updatedPayload = NULL;
314
315     g_sequenceNumber++;
316     result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
317                                            updatedTableList, false,
318                                            &updatedPayload);
319     if (OC_STACK_OK != result)
320     {
321         OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
322         RMPFreePayload(updatedPayload);
323         goto exit;
324     }
325
326     result = RMSendNotificationToAll(updatedPayload);
327     RMPFreePayload(updatedPayload);
328     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
329
330 exit:
331     u_linklist_free(&updatedTableList);
332     OC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT");
333     return result;
334 }
335
336 OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload)
337 {
338     OC_LOG(DEBUG, TAG, "RMHandleResponsePayload IN");
339     RM_NULL_CHECK_WITH_RET(respPayload, TAG, "respPayload");
340
341     // Parse the Payload to get the Gateway ID of neighbouring node.
342     uint32_t gatewayId = 0;
343     uint32_t seqNum = 0;
344     u_linklist_t *gatewayTableList = NULL;
345     bool isUpdateSeqNum = false;
346
347     OCStackResult result = RMPParseResponsePayload(respPayload, &gatewayId, &seqNum,
348                                                    &gatewayTableList,  &isUpdateSeqNum);
349     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
350     // Check if the entry is its own.
351     if (gatewayId == g_GatewayID)
352     {
353         OC_LOG(INFO, TAG, "-------------->Own entry, continue!!");
354         return OC_STACK_ERROR;
355     }
356     // Convert OCDevAddr to endpoint address
357     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS};
358     CopyDevAddrToEndpoint(devAddr, &endpoint);
359     RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
360     destInterfaces.destIntfAddr = endpoint;
361     if (0 < seqNum)
362     {
363         OC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d",
364                  seqNum, isUpdateSeqNum);
365         result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces,
366                                           &g_routingGatewayTable, isUpdateSeqNum);
367         if (OC_STACK_COMM_ERROR == result)
368         {
369             OC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching");
370             // Send a observe request to the gateway.
371             RMSendObserveRequest(devAddr, NULL);
372             return result;
373         }
374         else if (OC_STACK_DUPLICATE_REQUEST == result)
375         {
376             OC_LOG(ERROR, TAG, "Same sequence number is received");
377             return result;
378         }
379     }
380
381     // Check if the payload is for Removal
382     bool doRemoveEntry = false;
383
384     if (NULL != gatewayTableList && NULL != gatewayTableList->list)
385     {
386         RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list);
387         if (headPtr && 0 == headPtr->routeCost)
388         {
389             OC_LOG(INFO, TAG, "Remove entry is called");
390             doRemoveEntry = true;
391         }
392     }
393
394     // Create a list to add the updated entries and notify the observers
395     u_linklist_t *updatedTableList = u_linklist_create();
396     u_linklist_t *alternativeRouteList = u_linklist_create();
397     OCRepPayload *updatedPayload = NULL;
398     if (false == doRemoveEntry)
399     {
400         OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
401         result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
402         if (OC_STACK_OK == result)
403         {
404             OC_LOG(INFO, TAG, "Node was added");
405             RTMGatewayId_t gwId = {.gatewayId = gatewayId};
406             RTMGatewayEntry_t newNode;
407             newNode.destination = &gwId;
408             newNode.routeCost = 1;
409             u_linklist_add(updatedTableList, (void *)&newNode);
410             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
411
412             if (NULL == gatewayTableList)
413             {
414                 OC_LOG(INFO, TAG, "Received a Discover Payload");
415                 g_sequenceNumber++;
416                 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
417                                                        updatedTableList, false,
418                                                        &updatedPayload);
419                 RM_VERIFY_SUCCESS(result, OC_STACK_OK);
420                 goto sendNotification;
421             }
422         }
423     }
424
425     // Iterate the Table and get each entry
426     u_linklist_iterator_t *iterTable = NULL;
427     u_linklist_init_iterator(gatewayTableList, &iterTable);
428
429     while (NULL != iterTable)
430     {
431         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
432         // Check if the entry is its own.
433         if (!entry || entry->destination->gatewayId == g_GatewayID)
434         {
435             OC_LOG(INFO, TAG, "Ignore entry, continue!!");
436             u_linklist_get_next(&iterTable);
437             continue;
438         }
439
440         OC_LOG_V(INFO, TAG, "Gateway ID: %u", entry->destination->gatewayId);
441         if (true == doRemoveEntry)
442         {
443             // Remove the entry from RTM.
444             RTMGatewayEntry_t *existEntry = NULL;
445             result = RTMRemoveGatewayDestEntry(entry->destination->gatewayId, gatewayId,
446                                                &destInterfaces, &existEntry,
447                                                &g_routingGatewayTable);
448             if (OC_STACK_OK != result && NULL != existEntry)
449             {
450                 u_linklist_add(alternativeRouteList, (void *)existEntry);
451             }
452         }
453         else
454         {
455             // Add the entry to RTM.
456             entry->routeCost = entry->routeCost + 1;
457             result = RTMAddGatewayEntry(entry->destination->gatewayId, gatewayId,
458                                         entry->routeCost, NULL, &g_routingGatewayTable);
459         }
460
461         if (OC_STACK_OK == result)
462         {
463             OC_LOG(INFO, TAG, "Gateway was added/removed");
464             u_linklist_add(updatedTableList, (void *)entry);
465             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
466         }
467         u_linklist_get_next(&iterTable);
468     }
469
470     if ( 0 < u_linklist_length(alternativeRouteList))
471     {
472         OC_LOG(DEBUG, TAG, "Alternative routing found");
473         // Send the notification.
474         OCRepPayload *removeTablePayload = NULL;
475         g_sequenceNumber++;
476         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
477                                                alternativeRouteList, false,
478                                                &removeTablePayload);
479         if (OC_STACK_OK != result)
480         {
481             OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
482             RMPFreePayload(removeTablePayload);
483             goto exit;
484         }
485         result = RMSendNotificationToAll(removeTablePayload);
486         RMPFreePayload(removeTablePayload);
487         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
488     }
489
490     if ( 0 >= u_linklist_length(updatedTableList))
491     {
492         OC_LOG_V(DEBUG, TAG, "No updation is needed, Length is %d",
493                  u_linklist_length(updatedTableList));
494         goto exit;
495     }
496
497     g_sequenceNumber++;
498     if (true == doRemoveEntry)
499     {
500         result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, updatedTableList,
501                                             false, &updatedPayload);
502     }
503     else
504     {
505         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
506                                                updatedTableList, false,
507                                                &updatedPayload);
508     }
509     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
510
511 sendNotification:
512     result = RMSendNotificationToAll(updatedPayload);
513     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
514
515 exit:
516     RMPFreePayload(updatedPayload);
517     RTMFreeGatewayRouteTable(&gatewayTableList);
518     u_linklist_free(&updatedTableList);
519     u_linklist_free(&alternativeRouteList);
520     OC_LOG(DEBUG, TAG, "RMHandleResponsePayload OUT");
521     return OC_STACK_OK;
522 }
523
524 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource)
525 {
526     OC_LOG(DEBUG, TAG, "RMHandleGETRequest IN");
527     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
528     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
529
530     OCRepPayload *payload = NULL;
531     OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
532     if (OC_STACK_OK != result)
533     {
534         OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload failed[%d]", result);
535         return result;
536     }
537
538     // Send a response for GET request
539     result = RMSendResponse(request, resource, payload);
540     if (OC_STACK_OK != result)
541     {
542         OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
543         return result;
544     }
545
546     RMPFreePayload(payload);
547     // Send a observe request
548     result = RMSendObserveRequest(&(request->devAddr), NULL);
549     if (OC_STACK_OK != result)
550     {
551         OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
552     }
553     OC_LOG(DEBUG, TAG, "RMHandleGETRequest OUT");
554     return result;
555 }
556
557 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource)
558 {
559     OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest IN");
560     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
561     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
562
563     // Parse payload and add the gateway entry.
564     if (0 < request->payloadSize)
565     {
566         RMHandleRequestPayload(request->devAddr, request->payload, request->payloadSize);
567     }
568
569     // Generate and add observer.
570     OCObservationId obsID = 0;
571     OCStackResult result = RMAddObserver(request, &obsID);
572     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
573     OC_LOG_V(DEBUG, TAG, "Observer ID is %d", obsID);
574
575
576     // Get the Routing table from RTM
577     OCRepPayload *payload = NULL;
578     RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
579     OC_LOG(DEBUG, TAG, "Construct Routing table payload");
580     result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
581                                            g_routingGatewayTable, true,
582                                            &payload);
583     if (OC_STACK_OK != result)
584     {
585         OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
586         RMPFreePayload(payload);
587         goto exit;
588     }
589
590     result = RMSendResponse(request, resource, payload);
591     RMPFreePayload(payload);
592     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
593 exit:
594     OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest OUT");
595     return result;
596 }
597
598 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource)
599 {
600     OC_LOG(DEBUG, TAG, "RMHandleDELETERequest IN");
601     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
602     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
603
604     uint32_t gatewayId = 0;
605     OCStackResult result = RMPParseRequestPayload(request->payload, request->payloadSize,
606                                                   &gatewayId);
607     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
608     OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
609
610     OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", gatewayId);
611
612     u_linklist_t *removedGatewayNodes = NULL;
613     result = RTMRemoveGatewayEntry(gatewayId, &removedGatewayNodes, &g_routingGatewayTable);
614     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
615
616     if (0 < u_linklist_length(removedGatewayNodes))
617     {
618         OCRepPayload *resPayloads = NULL;
619         g_sequenceNumber++;
620         result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedGatewayNodes,
621                                             false, &resPayloads);
622         if (OC_STACK_OK != result)
623         {
624             OC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
625             RMPFreePayload(resPayloads);
626             goto exit;
627         }
628         result = RMSendNotificationToAll(resPayloads);
629         RMPFreePayload(resPayloads);
630         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
631         RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
632     }
633
634 exit:
635     RTMFreeGatewayRouteTable(&removedGatewayNodes);
636     OC_LOG(DEBUG, TAG, "RMHandleDELETERequest OUT");
637     return result;
638 }
639
640 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID)
641 {
642     OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
643     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
644     RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
645
646     // Generate the ObserverID
647     CAEndpoint_t endpoint = {.adapter = 0};
648     CopyDevAddrToEndpoint(&(request->devAddr), &endpoint);
649
650     // Check if observer is already added.
651     if (true == RTMIsObserverPresent(endpoint, obsID, g_routingGatewayTable))
652     {
653         OC_LOG(DEBUG, TAG, "Observer is present");
654         request->observeResult = OC_STACK_OK;
655         return OC_STACK_OK;
656     }
657
658     OCStackResult result = RMAddObserverToStack(request, obsID);
659     request->observeResult = result;
660     if (OC_STACK_OK == result)
661     {
662         OC_LOG(DEBUG, TAG, "Added observer successfully");
663
664         // Add the observer to the list.
665         result = RTMAddObserver(*obsID, endpoint, &g_routingGatewayTable);
666         if (OC_STACK_OK != result)
667         {
668             OC_LOG_V(DEBUG, TAG, "RMAddObserver failed[%d]", result);
669         }
670     }
671     OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
672     return result;
673 }
674
675 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload)
676 {
677     OC_LOG(DEBUG, TAG, "RMSendNotificationToAll IN");
678     RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
679
680     OCObservationId *obsList = NULL;
681     uint8_t obsLen = 0;
682     // Get the complete observer list.
683     RTMGetObserverList(&obsList, &obsLen, g_routingGatewayTable);
684     OCStackResult result = OC_STACK_OK;
685     OC_LOG_V(DEBUG, TAG, "Number of observers is %d", obsLen);
686     if (0 < obsLen)
687     {
688         // Send notification to the list of observers.
689         OC_LOG_V(DEBUG, TAG, "Sending notification with Sequence Number: %d", g_sequenceNumber);
690         result = RMSendNotificationForListofObservers(obsList, obsLen, payload);
691         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
692         g_aliveTime = RTMGetCurrentTime();
693     }
694
695 exit:
696     OICFree(obsList);
697     OC_LOG(DEBUG, TAG, "RMSendNotificationToAll OUT");
698     return result;
699 }
700
701 void RMProcess()
702 {
703     if (!g_isRMInitialized)
704     {
705         return;
706     }
707
708     OCStackResult result = OC_STACK_OK;
709     uint64_t currentTime = RTMGetCurrentTime();
710     if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
711     {
712         g_aliveTime = currentTime;
713         // Construct a payload with only the current sequence number.
714         OCRepPayload *payload = NULL;
715         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
716                                                false, &payload);
717         if (OC_STACK_OK != result)
718         {
719             OC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
720             RMPFreePayload(payload);
721             goto exit;
722         }
723         OC_LOG(DEBUG, TAG, "Sending the alive notification to all");
724         // Send notification for every 15s to all the neighbours.
725         result = RMSendNotificationToAll(payload);
726         RMPFreePayload(payload);
727         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
728     }
729
730     if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
731     {
732         OC_LOG(DEBUG, TAG, "Validating the routing table");
733         u_linklist_t *removedEntries = NULL;
734         // Remove the invalid gateway entries.
735         RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
736         if (0 < u_linklist_length(removedEntries))
737         {
738             OCRepPayload *resPayloads = NULL;
739             g_sequenceNumber++;
740             result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
741                                                 false, &resPayloads);
742             RTMFreeGatewayRouteTable(&removedEntries);
743             if (OC_STACK_OK != result)
744             {
745                 OC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
746                 RMPFreePayload(resPayloads);
747                 goto exit;
748             }
749             result = RMSendNotificationToAll(resPayloads);
750             RMPFreePayload(resPayloads);
751             RM_VERIFY_SUCCESS(result, OC_STACK_OK);
752             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
753         }
754         g_refreshTableTime = currentTime;
755         g_isValidated = false;
756         u_linklist_free(&removedEntries);
757         goto exit;
758     }
759
760     if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
761     {
762         OC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %u", currentTime);
763         u_linklist_t* invalidInterfaces = NULL;
764         RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
765         if (0 < u_linklist_length(invalidInterfaces))
766         {
767             u_linklist_iterator_t *iterTable = NULL;
768             u_linklist_init_iterator(invalidInterfaces, &iterTable);
769             while (NULL != iterTable)
770             {
771                 RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
772                 if(!entry)
773                 {
774                     u_linklist_get_next(&iterTable);
775                     continue;
776                 }
777                 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
778                 CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
779                 RMSendObserveRequest(&devAddr, NULL);
780                 u_linklist_get_next(&iterTable);
781             }
782         }
783         g_isValidated = true;
784         RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
785         u_linklist_free(&invalidInterfaces);
786     }
787
788 exit:
789     return;
790 }
791
792 OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
793 {
794     OC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
795     OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
796     OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
797     OC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
798     return result;
799 }
800
801 void RMSendDeleteToNeighbourNodes()
802 {
803     OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
804     u_linklist_t *neighbourNodes = NULL;
805     RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
806
807     if (0 >= u_linklist_length(neighbourNodes))
808     {
809         OC_LOG(DEBUG, TAG, "No neighbour nodes present");
810         return;
811     }
812
813     u_linklist_iterator_t *iterTable = NULL;
814     u_linklist_init_iterator(neighbourNodes, &iterTable);
815     while (NULL != iterTable)
816     {
817
818         OCRepPayload *payload = NULL;
819         // Created payload is freed in the OCDoResource() api.
820         OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
821         if (OC_STACK_OK != result)
822         {
823             OC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
824             RMPFreePayload(payload);
825             u_linklist_free(&neighbourNodes);
826             return;
827         }
828
829         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
830         if (entry)
831         {
832             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
833             {
834                 RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
835                 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
836                 CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
837                 OC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
838                          dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
839                 RMSendDeleteRequest(&devAddr, payload);
840             }
841         }
842         RMPFreePayload(payload);
843         u_linklist_get_next(&iterTable);
844     }
845
846     u_linklist_free(&neighbourNodes);
847     OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
848 }
849
850 uint32_t RMGetGatewayId()
851 {
852     if (!g_isRMInitialized)
853     {
854         OC_LOG(ERROR, TAG, "RM not initialized");
855         return 0;
856     }
857     return g_GatewayID;
858 }
859
860 uint16_t RMGetMcastSeqNumber()
861 {
862     if (!g_isRMInitialized)
863     {
864         OC_LOG(DEBUG, TAG, "RM not initialized");
865         return 0;
866     }
867     return ++g_mcastsequenceNumber;
868 }
869
870 /*
871  * This function is lifeline of packet forwarding module, hence we are going to do some serious
872  * handling here. Following are the expectations from this function:
873  * 1) If routing option is not available, forward packet to RI only. else:
874  * 2) If source is empty in routing option, packet is from end device, add an end device entry and
875  *    add "GatewayId:ClientId" as source.
876  * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
877  *    multicast on other interfaces. Also remove routing Option and forward to RI. (Before
878  *    forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
879  *     the packet.)
880  * 4) If destination is present in routing option, its unicast packet,
881  *    a) If self gatewayId is present in destination and no clientId, remove routing option
882  *       and forward to RI.
883  *    b) If self gatewayId and a clientId is present in destination, forward to end device.
884  * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
885  */
886
887 OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
888                              bool *selfDestination)
889 {
890     RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
891     RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
892     RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
893
894     bool forward = false;
895     CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
896     CAInfo_t *info = NULL;
897     if (isRequest)
898     {
899         CARequestInfo_t *msg = message;
900         info = &(msg->info);
901         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
902     }
903     else
904     {
905         CAResponseInfo_t *msg = message;
906         info = &(msg->info);
907         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
908     }
909
910     // 1.  If routing option is not available, forward packet to RI only.
911     int8_t routeIndex = -1;
912     RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
913     if (-1 >= routeIndex)
914     {
915         OC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
916         // Let RI handle this packet.
917         *selfDestination = true;
918         return OC_STACK_OK;
919     }
920
921     // Get existing values in packet route option.
922     RMRouteOption_t routeOption = {.srcGw = 0};
923     OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
924     if (OC_STACK_OK != res)
925     {
926         OC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
927         return OC_STACK_ERROR;
928     }
929
930     /*
931      * 2) If source is empty in routing option, packet is from end device, add an end device entry
932      *  and add "GatewayId:ClientId" as source.
933      */
934     if (g_GatewayID == routeOption.srcGw)
935     {
936         OC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
937         if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
938         {
939             g_mcastsequenceNumber = routeOption.mSeqNum;
940         }
941
942         return OC_STACK_ERROR;
943     }
944     else if (0 == routeOption.srcGw)
945     {
946         OC_LOG(INFO, RM_TAG, "Source missing in option");
947         // Packet from end device as Gateway will add source in option.
948         uint16_t endpointId = g_EndpointCount + 1;
949         OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
950         if (OC_STACK_OK == res)
951         {
952             g_EndpointCount = endpointId;
953             OC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
954         }
955         else if (OC_STACK_DUPLICATE_REQUEST == res)
956         {
957             OC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
958         }
959         else
960         {
961             OC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
962             return OC_STACK_ERROR;
963         }
964
965         // add source option.
966         routeOption.srcGw = g_GatewayID;
967         routeOption.srcEp = endpointId;
968         OC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
969     }
970
971     /*
972      * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
973      *    multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
974      *    caller of this function).
975      */
976     if (0 == routeOption.destGw)
977     {
978         OC_LOG(INFO, RM_TAG, "Destination missing in option");
979         // This is a multicast packet.
980         if (g_GatewayID == routeOption.srcGw)
981         {
982             routeOption.mSeqNum = ++g_mcastsequenceNumber;
983         }
984         else
985         {
986             OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
987                                                            &g_routingGatewayTable);
988             if (OC_STACK_OK != update)
989             {
990                 // this shouldnt have been forwarded. ignore.
991                 OC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
992                          routeOption.mSeqNum);
993                 return OC_STACK_ERROR;
994             }
995         }
996
997         // forward
998         *selfDestination = true;
999         forward = true;
1000
1001         // Send multicast on every adapter except the one from which packet was received
1002         // TODO::: support to be added for IP hop.
1003         if (sender->adapter != CA_ADAPTER_IP)
1004         {
1005             nextHop.adapter |= CA_ADAPTER_IP;
1006             nextHop.flags |= CA_IPV4 | CA_IPV6;
1007         }
1008
1009         if(sender->adapter != CA_ADAPTER_GATT_BTLE)
1010         {
1011             nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
1012         }
1013
1014         if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
1015         {
1016             nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
1017         }
1018
1019         // Only requests are sent as multicast.
1020         if(isRequest)
1021         {
1022             CARequestInfo_t *msg = message;
1023             msg->isMulticast = true;
1024         }
1025         goto  rewriteandexit;
1026     }
1027     else if (g_GatewayID == routeOption.destGw)
1028     {
1029         OC_LOG(INFO, RM_TAG, "GatewayId found in destination");
1030         /*
1031          * This unicast packet either belongs to us or any of our connected end devices
1032          * check if packet belongs to end device.
1033          */
1034         if (0 != routeOption.destEp)
1035         {
1036             // forward packet to the client.
1037             OC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1038             CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1039                                                            g_routingEndpointTable);
1040             if(!clientInfo)
1041             {
1042                 OC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1043                 return OC_STACK_ERROR;
1044             }
1045
1046             nextHop = *clientInfo;
1047             forward = true;
1048             *selfDestination = false;
1049             goto rewriteandexit;
1050         }
1051         else
1052         {
1053             // packet is for us.
1054             OC_LOG(INFO, RM_TAG, "Received packet for self");
1055             forward = false;
1056             *selfDestination = true;
1057             goto rewriteandexit;
1058         }
1059     }
1060     else
1061     {
1062         /*
1063          * This unicast packet belongs to other gateway.
1064          * we only want to print first 4 bytes of packet as readable GatewayId.
1065          */
1066         OC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1067         RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1068         if(!nextHopGw)
1069         {
1070             OC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1071             return OC_STACK_ERROR;
1072         }
1073
1074         // TODO:: check preferences among multiple interface addresses, for now sending on first one
1075         RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1076         if (!address)
1077         {
1078             OC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1079             return OC_STACK_ERROR;
1080         }
1081
1082         nextHop = address->destIntfAddr;
1083         forward = true;
1084         *selfDestination = false;
1085         goto rewriteandexit;
1086     }
1087
1088 rewriteandexit:
1089
1090     if (forward)
1091     {
1092         // Don't forward any packet meant for gateway resource.
1093         if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)))
1094         {
1095             OC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1096         }
1097         else if (sender->flags & CA_SECURE)
1098         {
1099             OC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1100             return OC_STACK_ERROR;
1101         }
1102         else
1103         {
1104             // rewrite any changes in routing option.
1105             res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1106             if (OC_STACK_OK != res)
1107             {
1108                 OC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1109                 return res;
1110             }
1111             /*
1112              * When forwarding a packet, do not attempt retransmission as its the responsibility of
1113              * packet originator node.
1114              */
1115             info->skipRetransmission = true;
1116             if(isRequest)
1117             {
1118                 CARequestInfo_t *msg = message;
1119                 CAResult_t caRes = CASendRequest(&nextHop, msg);
1120                 if (CA_STATUS_OK != caRes)
1121                 {
1122                     OC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1123                              nextHop.addr);
1124                     if(0 == routeOption.destGw)
1125                     {
1126                         /*
1127                          * No point going forward as unicast packet could not be forwarded
1128                          * not returning error for multicast as we may still let RI process
1129                          * this packet.
1130                          */
1131                         return OC_STACK_ERROR;
1132                     }
1133                 }
1134             }
1135             else
1136             {
1137                 CAResponseInfo_t *msg = message;
1138                 CAResult_t caRes = CASendResponse(&nextHop, msg);
1139                 if (CA_STATUS_OK != caRes)
1140                 {
1141                     OC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1142                              caRes, nextHop.addr);
1143                     // Since a response is always unicast, return error here.
1144                     return OC_STACK_ERROR;
1145                 }
1146             }
1147         }
1148     }
1149
1150     OC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1151     return OC_STACK_OK;
1152 }
1153
1154 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1155                               bool *selfDestination)
1156 {
1157     if (!g_isRMInitialized)
1158     {
1159         OC_LOG(ERROR, TAG, "RM not initialized");
1160         *selfDestination = true;
1161         return OC_STACK_OK;
1162     }
1163     OCStackResult res = RMHandlePacket(true, message, sender, selfDestination);
1164     return res;
1165 }
1166
1167 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1168                                bool *selfDestination)
1169 {
1170     if (!g_isRMInitialized)
1171     {
1172         OC_LOG(ERROR, TAG, "RM not initialized");
1173         *selfDestination = true;
1174         return OC_STACK_OK;
1175     }
1176     OCStackResult res = RMHandlePacket(false, message, sender, selfDestination);
1177     return res;
1178 }