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