Merge branch 'master' into resource-encapsulation
[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     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
320
321     result = RMSendNotificationToAll(updatedPayload);
322     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
323     RMPFreePayload(updatedPayload);
324
325 exit:
326     u_linklist_free(&updatedTableList);
327     OC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT");
328     return result;
329 }
330
331 OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload)
332 {
333     OC_LOG(DEBUG, TAG, "RMHandleResponsePayload IN");
334     RM_NULL_CHECK_WITH_RET(respPayload, TAG, "respPayload");
335
336     // Parse the Payload to get the Gateway ID of neighbouring node.
337     uint32_t gatewayId = 0;
338     uint32_t seqNum = 0;
339     u_linklist_t *gatewayTableList = NULL;
340     bool isUpdateSeqNum = false;
341
342     OCStackResult result = RMPParseResponsePayload(respPayload, &gatewayId, &seqNum,
343                                                    &gatewayTableList,  &isUpdateSeqNum);
344     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
345     // Check if the entry is its own.
346     if (gatewayId == g_GatewayID)
347     {
348         OC_LOG(INFO, TAG, "-------------->Own entry, continue!!");
349         return OC_STACK_ERROR;
350     }
351     // Convert OCDevAddr to endpoint address
352     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS};
353     CopyDevAddrToEndpoint(devAddr, &endpoint);
354     RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
355     destInterfaces.destIntfAddr = endpoint;
356     if (0 < seqNum)
357     {
358         OC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d",
359                  seqNum, isUpdateSeqNum);
360         result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces,
361                                           &g_routingGatewayTable, isUpdateSeqNum);
362         if (OC_STACK_COMM_ERROR == result)
363         {
364             OC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching");
365             // Send a observe request to the gateway.
366             RMSendObserveRequest(devAddr, NULL);
367             return result;
368         }
369         else if (OC_STACK_DUPLICATE_REQUEST == result)
370         {
371             OC_LOG(ERROR, TAG, "Same sequence number is received");
372             return result;
373         }
374     }
375
376     // Check if the payload is for Removal
377     bool doRemoveEntry = false;
378
379     if (NULL != gatewayTableList && NULL != gatewayTableList->list)
380     {
381         RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list);
382         if (headPtr && 0 == headPtr->routeCost)
383         {
384             OC_LOG(INFO, TAG, "Remove entry is called");
385             doRemoveEntry = true;
386         }
387     }
388
389     // Create a list to add the updated entries and notify the observers
390     u_linklist_t *updatedTableList = u_linklist_create();
391     u_linklist_t *alternativeRouteList = u_linklist_create();
392     OCRepPayload *updatedPayload = NULL;
393     if (false == doRemoveEntry)
394     {
395         OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
396         result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
397         if (OC_STACK_OK == result)
398         {
399             OC_LOG(INFO, TAG, "Node was added");
400             RTMGatewayId_t gwId = {.gatewayId = gatewayId};
401             RTMGatewayEntry_t newNode;
402             newNode.destination = &gwId;
403             newNode.routeCost = 1;
404             u_linklist_add(updatedTableList, (void *)&newNode);
405             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
406
407             if (NULL == gatewayTableList)
408             {
409                 OC_LOG(INFO, TAG, "Received a Discover Payload");
410                 g_sequenceNumber++;
411                 result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
412                                                        updatedTableList, false,
413                                                        &updatedPayload);
414                 goto sendNotification;
415             }
416         }
417     }
418
419     // Iterate the Table and get each entry
420     u_linklist_iterator_t *iterTable = NULL;
421     u_linklist_init_iterator(gatewayTableList, &iterTable);
422
423     while (NULL != iterTable)
424     {
425         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
426         // Check if the entry is its own.
427         if (!entry || entry->destination->gatewayId == g_GatewayID)
428         {
429             OC_LOG(INFO, TAG, "Ignore entry, continue!!");
430             u_linklist_get_next(&iterTable);
431             continue;
432         }
433
434         OC_LOG_V(INFO, TAG, "Gateway ID: %u", entry->destination->gatewayId);
435         if (true == doRemoveEntry)
436         {
437             // Remove the entry from RTM.
438             RTMGatewayEntry_t *existEntry = NULL;
439             result = RTMRemoveGatewayDestEntry(entry->destination->gatewayId, gatewayId,
440                                                &destInterfaces, &existEntry,
441                                                &g_routingGatewayTable);
442             if (OC_STACK_OK != result && NULL != existEntry)
443             {
444                 u_linklist_add(alternativeRouteList, (void *)existEntry);
445             }
446         }
447         else
448         {
449             // Add the entry to RTM.
450             entry->routeCost = entry->routeCost + 1;
451             result = RTMAddGatewayEntry(entry->destination->gatewayId, gatewayId,
452                                         entry->routeCost, NULL, &g_routingGatewayTable);
453         }
454
455         if (OC_STACK_OK == result)
456         {
457             OC_LOG(INFO, TAG, "Gateway was added/removed");
458             u_linklist_add(updatedTableList, (void *)entry);
459             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
460         }
461         u_linklist_get_next(&iterTable);
462     }
463
464     if ( 0 < u_linklist_length(alternativeRouteList))
465     {
466         OC_LOG(DEBUG, TAG, "Alternative routing found");
467         // Send the notification.
468         OCRepPayload *removeTablePayload = NULL;
469         g_sequenceNumber++;
470         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
471                                                alternativeRouteList, false,
472                                                &removeTablePayload);
473         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
474         result = RMSendNotificationToAll(removeTablePayload);
475         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
476         RMPFreePayload(removeTablePayload);
477     }
478
479     if ( 0 >= u_linklist_length(updatedTableList))
480     {
481         OC_LOG_V(DEBUG, TAG, "No updation is needed, Length is %d", u_linklist_length(updatedTableList));
482         goto exit;
483     }
484
485     g_sequenceNumber++;
486     if (true == doRemoveEntry)
487     {
488         result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, updatedTableList,
489                                             false, &updatedPayload);
490     }
491     else
492     {
493         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
494                                                updatedTableList, false,
495                                                &updatedPayload);
496     }
497     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
498
499 sendNotification:
500     result = RMSendNotificationToAll(updatedPayload);
501     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
502     RMPFreePayload(updatedPayload);
503
504 exit:
505     u_linklist_free(&updatedTableList);
506     u_linklist_free(&gatewayTableList);
507     u_linklist_free(&alternativeRouteList);
508     OC_LOG(DEBUG, TAG, "RMHandleResponsePayload OUT");
509     return OC_STACK_OK;
510 }
511
512 OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource)
513 {
514     OC_LOG(DEBUG, TAG, "RMHandleGETRequest IN");
515     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
516     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
517
518     OCRepPayload *payload = NULL;
519     OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
520     if (OC_STACK_OK != result)
521     {
522         OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload failed[%d]", result);
523         return result;
524     }
525
526     // Send a response for GET request
527     result = RMSendResponse(request, resource, payload);
528     if (OC_STACK_OK != result)
529     {
530         OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
531         return result;
532     }
533
534     RMPFreePayload(payload);
535
536     // Send a observe request
537     result = RMSendObserveRequest(&(request->devAddr), NULL);
538     if (OC_STACK_OK != result)
539     {
540         OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
541     }
542     OC_LOG(DEBUG, TAG, "RMHandleGETRequest OUT");
543     return result;
544 }
545
546 OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource)
547 {
548     OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest IN");
549     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
550     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
551
552     // Parse payload and add the gateway entry.
553     if (0 < request->payloadSize)
554     {
555         RMHandleRequestPayload(request->devAddr, request->payload, request->payloadSize);
556     }
557
558     // Generate and add observer.
559     OCObservationId obsID = 0;
560     OCStackResult result = RMAddObserver(request, &obsID);
561     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
562     OC_LOG_V(DEBUG, TAG, "Observer ID is %d", obsID);
563
564
565     // Get the Routing table from RTM
566     OCRepPayload *payload = NULL;
567     RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
568     OC_LOG(DEBUG, TAG, "Construct Routing table payload");
569     result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
570                                            g_routingGatewayTable, true,
571                                            &payload);
572     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
573
574     result = RMSendResponse(request, resource, payload);
575     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
576     RMPFreePayload(payload);
577 exit:
578     OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest OUT");
579     return result;
580 }
581
582 OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource)
583 {
584     OC_LOG(DEBUG, TAG, "RMHandleDELETERequest IN");
585     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
586     RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
587
588     uint32_t gatewayId = 0;
589     OCStackResult result = RMPParseRequestPayload(request->payload, request->payloadSize,
590                                                   &gatewayId);
591     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
592     OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
593
594     OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", gatewayId);
595
596     u_linklist_t *removedGatewayNodes = NULL;
597     result = RTMRemoveGatewayEntry(gatewayId, &removedGatewayNodes, &g_routingGatewayTable);
598     RM_VERIFY_SUCCESS(result, OC_STACK_OK);
599
600     if (0 < u_linklist_length(removedGatewayNodes))
601     {
602         OCRepPayload *resPayloads = NULL;
603         g_sequenceNumber++;
604         result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedGatewayNodes,
605                                             false, &resPayloads);
606         RTMFreeGatewayRouteTable(&removedGatewayNodes);
607         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
608         result = RMSendNotificationToAll(resPayloads);
609         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
610         RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
611     }
612
613 exit:
614     OC_LOG(DEBUG, TAG, "RMHandleDELETERequest OUT");
615     return result;
616 }
617
618 OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID)
619 {
620     OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
621     RM_NULL_CHECK_WITH_RET(request, TAG, "request");
622     RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
623
624     // Generate the ObserverID
625     CAEndpoint_t endpoint = {.adapter = 0};
626     CopyDevAddrToEndpoint(&(request->devAddr), &endpoint);
627
628     // Check if observer is already added.
629     if (true == RTMIsObserverPresent(endpoint, obsID, g_routingGatewayTable))
630     {
631         OC_LOG(DEBUG, TAG, "Observer is present");
632         request->observeResult = OC_STACK_OK;
633         return OC_STACK_OK;
634     }
635
636     OCStackResult result = RMAddObserverToStack(request, obsID);
637     request->observeResult = result;
638     if (OC_STACK_OK == result)
639     {
640         OC_LOG(DEBUG, TAG, "Added observer successfully");
641
642         // Add the observer to the list.
643         result = RTMAddObserver(*obsID, endpoint, &g_routingGatewayTable);
644         if (OC_STACK_OK != result)
645         {
646             OC_LOG_V(DEBUG, TAG, "RMAddObserver failed[%d]", result);
647         }
648     }
649     OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
650     return result;
651 }
652
653 OCStackResult RMSendNotificationToAll(const OCRepPayload *payload)
654 {
655     OC_LOG(DEBUG, TAG, "RMSendNotificationToAll IN");
656     RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
657
658     OCObservationId *obsList = NULL;
659     uint8_t obsLen = 0;
660     // Get the complete observer list.
661     RTMGetObserverList(&obsList, &obsLen, g_routingGatewayTable);
662     OCStackResult result = OC_STACK_OK;
663     OC_LOG_V(DEBUG, TAG, "Number of observers is %d", obsLen);
664     if (0 < obsLen)
665     {
666         // Send notification to the list of observers.
667         OC_LOG_V(DEBUG, TAG, "Sending notification with Sequence Number: %d", g_sequenceNumber);
668         result = RMSendNotificationForListofObservers(obsList, obsLen, payload);
669         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
670         g_aliveTime = RTMGetCurrentTime();
671     }
672
673 exit:
674     OICFree(obsList);
675     OC_LOG(DEBUG, TAG, "RMSendNotificationToAll OUT");
676     return result;
677 }
678
679 void RMProcess()
680 {
681     if (!g_isRMInitialized)
682     {
683         return;
684     }
685
686     OCStackResult result = OC_STACK_OK;
687     uint64_t currentTime = RTMGetCurrentTime();
688     if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
689     {
690         g_aliveTime = currentTime;
691         // Construct a payload with only the current sequence number.
692         OCRepPayload *payload = NULL;
693         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
694                                                false, &payload);
695         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
696
697         OC_LOG(DEBUG, TAG, "Sending the alive notification to all");
698         // Send notification for every 15s to all the neighbours.
699         result = RMSendNotificationToAll(payload);
700         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
701     }
702
703     if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
704     {
705         OC_LOG(DEBUG, TAG, "Validating the routing table");
706         u_linklist_t *removedEntries = NULL;
707         // Remove the invalid gateway entries.
708         RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
709         if (0 < u_linklist_length(removedEntries))
710         {
711             OCRepPayload *resPayloads = NULL;
712             g_sequenceNumber++;
713             result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
714                                                 false, &resPayloads);
715             RTMFreeGatewayRouteTable(&removedEntries);
716             RM_VERIFY_SUCCESS(result, OC_STACK_OK);
717             result = RMSendNotificationToAll(resPayloads);
718             RM_VERIFY_SUCCESS(result, OC_STACK_OK);
719             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
720         }
721         g_refreshTableTime = currentTime;
722         g_isValidated = false;
723         goto exit;
724     }
725
726     if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
727     {
728         OC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %u", currentTime);
729         u_linklist_t* invalidInterfaces = NULL;
730         RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
731         if (0 < u_linklist_length(invalidInterfaces))
732         {
733             u_linklist_iterator_t *iterTable = NULL;
734             u_linklist_init_iterator(invalidInterfaces, &iterTable);
735             while (NULL != iterTable)
736             {
737                 RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
738                 if(!entry)
739                 {
740                     u_linklist_get_next(&iterTable);
741                     continue;
742                 }
743                 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
744                 CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
745                 RMSendObserveRequest(&devAddr, NULL);
746                 u_linklist_get_next(&iterTable);
747             }
748         }
749         g_isValidated = true;
750         RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
751         u_linklist_free(&invalidInterfaces);
752     }
753
754 exit:
755     return;
756 }
757
758 OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
759 {
760     OC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
761     OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
762     OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
763     OC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
764     return result;
765 }
766
767 void RMSendDeleteToNeighbourNodes()
768 {
769     OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
770     u_linklist_t *neighbourNodes = NULL;
771     RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
772
773     if (0 >= u_linklist_length(neighbourNodes))
774     {
775         OC_LOG(DEBUG, TAG, "No neighbour nodes present");
776         return;
777     }
778
779     u_linklist_iterator_t *iterTable = NULL;
780     u_linklist_init_iterator(neighbourNodes, &iterTable);
781     while (NULL != iterTable)
782     {
783
784         OCRepPayload *payload = NULL;
785         // Created payload is freed in the OCDoResource() api.
786         OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
787         if (OC_STACK_OK != result)
788         {
789             OC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
790             u_linklist_free(&neighbourNodes);
791             return;
792         }
793
794         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
795         if (entry)
796         {
797             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
798             {
799                 RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
800                 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
801                 CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
802                 OC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
803                          dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
804                 RMSendDeleteRequest(&devAddr, payload);
805             }
806         }
807         u_linklist_get_next(&iterTable);
808     }
809
810     u_linklist_free(&neighbourNodes);
811     OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
812 }
813
814 uint32_t RMGetGatewayId()
815 {
816     if (!g_isRMInitialized)
817     {
818         OC_LOG(ERROR, TAG, "RM not initialized");
819         return 0;
820     }
821     return g_GatewayID;
822 }
823
824 uint16_t RMGetMcastSeqNumber()
825 {
826     if (!g_isRMInitialized)
827     {
828         OC_LOG(DEBUG, TAG, "RM not initialized");
829         return 0;
830     }
831     return ++g_mcastsequenceNumber;
832 }
833
834 /*
835  * This function is lifeline of packet forwarding module, hence we are going to do some serious
836  * handling here. Following are the expectations from this function:
837  * 1) If routing option is not available, forward packet to RI only. else:
838  * 2) If source is empty in routing option, packet is from end device, add an end device entry and
839  *    add "GatewayId:ClientId" as source.
840  * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
841  *    multicast on other interfaces. Also remove routing Option and forward to RI. (Before
842  *    forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
843  *     the packet.)
844  * 4) If destination is present in routing option, its unicast packet,
845  *    a) If self gatewayId is present in destination and no clientId, remove routing option
846  *       and forward to RI.
847  *    b) If self gatewayId and a clientId is present in destination, forward to end device.
848  * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
849  */
850
851 OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
852                              bool *selfDestination)
853 {
854     RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
855     RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
856     RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
857
858     bool forward = false;
859     CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
860     CAInfo_t *info = NULL;
861     if (isRequest)
862     {
863         CARequestInfo_t *msg = message;
864         info = &(msg->info);
865         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
866     }
867     else
868     {
869         CAResponseInfo_t *msg = message;
870         info = &(msg->info);
871         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
872     }
873
874     // 1.  If routing option is not available, forward packet to RI only.
875     int8_t routeIndex = -1;
876     RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
877     if (-1 >= routeIndex)
878     {
879         OC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
880         // Let RI handle this packet.
881         *selfDestination = true;
882         return OC_STACK_OK;
883     }
884
885     // Get existing values in packet route option.
886     RMRouteOption_t routeOption = {.srcGw = 0};
887     OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
888     if (OC_STACK_OK != res)
889     {
890         OC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
891         return OC_STACK_ERROR;
892     }
893
894     /*
895      * 2) If source is empty in routing option, packet is from end device, add an end device entry
896      *  and add "GatewayId:ClientId" as source.
897      */
898     if (g_GatewayID == routeOption.srcGw)
899     {
900         OC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
901         if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
902         {
903             g_mcastsequenceNumber = routeOption.mSeqNum;
904         }
905
906         return OC_STACK_ERROR;
907     }
908     else if (0 == routeOption.srcGw)
909     {
910         OC_LOG(INFO, RM_TAG, "Source missing in option");
911         // Packet from end device as Gateway will add source in option.
912         uint16_t endpointId = g_EndpointCount + 1;
913         OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
914         if (OC_STACK_OK == res)
915         {
916             g_EndpointCount = endpointId;
917             OC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
918         }
919         else if (OC_STACK_DUPLICATE_REQUEST == res)
920         {
921             OC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
922         }
923         else
924         {
925             OC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
926             return OC_STACK_ERROR;
927         }
928
929         // add source option.
930         routeOption.srcGw = g_GatewayID;
931         routeOption.srcEp = endpointId;
932         OC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
933     }
934
935     /*
936      * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
937      *    multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
938      *    caller of this function).
939      */
940     if (0 == routeOption.destGw)
941     {
942         OC_LOG(INFO, RM_TAG, "Destination missing in option");
943         // This is a multicast packet.
944         if (g_GatewayID == routeOption.srcGw)
945         {
946             routeOption.mSeqNum = ++g_mcastsequenceNumber;
947         }
948         else
949         {
950             OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
951                                                            &g_routingGatewayTable);
952             if (OC_STACK_OK != update)
953             {
954                 // this shouldnt have been forwarded. ignore.
955                 OC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
956                          routeOption.mSeqNum);
957                 return OC_STACK_ERROR;
958             }
959         }
960
961         // forward
962         *selfDestination = true;
963         forward = true;
964
965         // Send multicast on every adapter except the one from which packet was received
966         // TODO::: support to be added for IP hop.
967         if (sender->adapter != CA_ADAPTER_IP)
968         {
969             nextHop.adapter |= CA_ADAPTER_IP;
970             nextHop.flags |= CA_IPV4 | CA_IPV6;
971         }
972
973         if(sender->adapter != CA_ADAPTER_GATT_BTLE)
974         {
975             nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
976         }
977
978         if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
979         {
980             nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
981         }
982
983         // Only requests are sent as multicast.
984         if(isRequest)
985         {
986             CARequestInfo_t *msg = message;
987             msg->isMulticast = true;
988         }
989         goto  rewriteandexit;
990     }
991     else if (g_GatewayID == routeOption.destGw)
992     {
993         OC_LOG(INFO, RM_TAG, "GatewayId found in destination");
994         /*
995          * This unicast packet either belongs to us or any of our connected end devices
996          * check if packet belongs to end device.
997          */
998         if (0 != routeOption.destEp)
999         {
1000             // forward packet to the client.
1001             OC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1002             CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1003                                                            g_routingEndpointTable);
1004             if(!clientInfo)
1005             {
1006                 OC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1007                 return OC_STACK_ERROR;
1008             }
1009
1010             nextHop = *clientInfo;
1011             forward = true;
1012             *selfDestination = false;
1013             goto rewriteandexit;
1014         }
1015         else
1016         {
1017             // packet is for us.
1018             OC_LOG(INFO, RM_TAG, "Received packet for self");
1019             forward = false;
1020             *selfDestination = true;
1021             goto rewriteandexit;
1022         }
1023     }
1024     else
1025     {
1026         /*
1027          * This unicast packet belongs to other gateway.
1028          * we only want to print first 4 bytes of packet as readable GatewayId.
1029          */
1030         OC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1031         RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1032         if(!nextHopGw)
1033         {
1034             OC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1035             return OC_STACK_ERROR;
1036         }
1037
1038         // TODO:: check preferences among multiple interface addresses, for now sending on first one
1039         RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1040         if (!address)
1041         {
1042             OC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1043             return OC_STACK_ERROR;
1044         }
1045
1046         nextHop = address->destIntfAddr;
1047         forward = true;
1048         *selfDestination = false;
1049         goto rewriteandexit;
1050     }
1051
1052 rewriteandexit:
1053
1054     if (forward)
1055     {
1056         // Don't forward any packet meant for gateway resource.
1057         if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)))
1058         {
1059             OC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1060         }
1061         else if (sender->flags & CA_SECURE)
1062         {
1063             OC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1064             return OC_STACK_ERROR;
1065         }
1066         else
1067         {
1068             // rewrite any changes in routing option.
1069             res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1070             if (OC_STACK_OK != res)
1071             {
1072                 OC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1073                 return res;
1074             }
1075             /*
1076              * When forwarding a packet, do not attempt retransmission as its the responsibility of
1077              * packet originator node.
1078              */
1079             info->skipRetransmission = true;
1080             if(isRequest)
1081             {
1082                 CARequestInfo_t *msg = message;
1083                 CAResult_t caRes = CASendRequest(&nextHop, msg);
1084                 if (CA_STATUS_OK != caRes)
1085                 {
1086                     OC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1087                              nextHop.addr);
1088                     if(0 == routeOption.destGw)
1089                     {
1090                         /*
1091                          * No point going forward as unicast packet could not be forwarded
1092                          * not returning error for multicast as we may still let RI process
1093                          * this packet.
1094                          */
1095                         return OC_STACK_ERROR;
1096                     }
1097                 }
1098             }
1099             else
1100             {
1101                 CAResponseInfo_t *msg = message;
1102                 CAResult_t caRes = CASendResponse(&nextHop, msg);
1103                 if (CA_STATUS_OK != caRes)
1104                 {
1105                     OC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1106                              caRes, nextHop.addr);
1107                     // Since a response is always unicast, return error here.
1108                     return OC_STACK_ERROR;
1109                 }
1110             }
1111         }
1112     }
1113
1114     OC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1115     return OC_STACK_OK;
1116 }
1117
1118 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1119                               bool *selfDestination)
1120 {
1121     if (!g_isRMInitialized)
1122     {
1123         OC_LOG(ERROR, TAG, "RM not initialized");
1124         *selfDestination = true;
1125         return OC_STACK_OK;
1126     }
1127     OCStackResult res = RMHandlePacket(true, message, sender, selfDestination);
1128     return res;
1129 }
1130
1131 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1132                                bool *selfDestination)
1133 {
1134     if (!g_isRMInitialized)
1135     {
1136         OC_LOG(ERROR, TAG, "RM not initialized");
1137         *selfDestination = true;
1138         return OC_STACK_OK;
1139     }
1140     OCStackResult res = RMHandlePacket(false, message, sender, selfDestination);
1141     return res;
1142 }