fb4afac64e1bf7a25029a2dfd1e849e2506b0bd4
[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 static 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 #ifdef WITH_PROCESS_EVENT
718 static void compareAndApplyTimeout(uint32_t *nextEventTime,
719                                    uint64_t timeoutSec)
720 {
721     uint32_t timeoutMs = timeoutSec * MS_PER_SEC;
722     if (timeoutMs < *nextEventTime)
723     {
724         *nextEventTime = timeoutMs;
725     }
726 }
727
728 void RMProcess(uint32_t *nextEventTime)
729 #else   // WITH_PROCESS_EVENT
730 void RMProcess(void)
731 #endif  // !WITH_PROCESS_EVENT
732 {
733     if (!g_isRMInitialized)
734     {
735         return;
736     }
737
738     OCStackResult result = OC_STACK_OK;
739     uint64_t currentTime = RTMGetCurrentTime();
740     if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
741     {
742         g_aliveTime = currentTime;
743         // Construct a payload with only the current sequence number.
744         OCRepPayload *payload = NULL;
745         result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
746                                                false, &payload);
747         if (OC_STACK_OK != result)
748         {
749             OIC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result);
750             RMPFreePayload(payload);
751             goto exit;
752         }
753         OIC_LOG(DEBUG, TAG, "Sending the alive notification to all");
754         // Send notification for every 15s to all the neighbours.
755         result = RMSendNotificationToAll(payload);
756         RMPFreePayload(payload);
757         RM_VERIFY_SUCCESS(result, OC_STACK_OK);
758 #ifdef WITH_PROCESS_EVENT
759         compareAndApplyTimeout(nextEventTime, GATEWAY_ALIVE_TIMEOUT);
760 #endif // WITH_PROCESS_EVENT
761     }
762 #ifdef WITH_PROCESS_EVENT
763     else
764     {
765         compareAndApplyTimeout(nextEventTime,
766             GATEWAY_ALIVE_TIMEOUT - (currentTime - g_aliveTime));
767     }
768 #endif // WITH_PROCESS_EVENT
769
770     if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
771     {
772         OIC_LOG(DEBUG, TAG, "Validating the routing table");
773         u_linklist_t *removedEntries = NULL;
774         // Remove the invalid gateway entries.
775         RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
776         if (0 < u_linklist_length(removedEntries))
777         {
778             OCRepPayload *resPayloads = NULL;
779             g_sequenceNumber++;
780             result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
781                                                 false, &resPayloads);
782             RTMFreeGatewayRouteTable(&removedEntries);
783             if (OC_STACK_OK != result)
784             {
785                 OIC_LOG_V(ERROR, TAG, "RMPConstructRemovalPayload failed[%d]", result);
786                 RMPFreePayload(resPayloads);
787                 goto exit;
788             }
789             result = RMSendNotificationToAll(resPayloads);
790             RMPFreePayload(resPayloads);
791             RM_VERIFY_SUCCESS(result, OC_STACK_OK);
792             RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
793         }
794         g_refreshTableTime = currentTime;
795         g_isValidated = false;
796         u_linklist_free(&removedEntries);
797 #ifdef WITH_PROCESS_EVENT
798         compareAndApplyTimeout(nextEventTime, ROUTINGTABLE_VALIDATION_TIMEOUT);
799 #endif // WITH_PROCESS_EVENT
800         goto exit;
801     }
802 #ifdef WITH_PROCESS_EVENT
803     else
804     {
805         compareAndApplyTimeout(nextEventTime,
806             ROUTINGTABLE_VALIDATION_TIMEOUT - (currentTime - g_refreshTableTime));
807     }
808 #endif // WITH_PROCESS_EVENT
809
810     if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
811     {
812         OIC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %llu", currentTime);
813         u_linklist_t* invalidInterfaces = NULL;
814         RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
815         if (0 < u_linklist_length(invalidInterfaces))
816         {
817             u_linklist_iterator_t *iterTable = NULL;
818             u_linklist_init_iterator(invalidInterfaces, &iterTable);
819             while (NULL != iterTable)
820             {
821                 RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
822                 if(!entry)
823                 {
824                     u_linklist_get_next(&iterTable);
825                     continue;
826                 }
827                 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
828                 CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
829                 RMSendObserveRequest(&devAddr, NULL);
830                 u_linklist_get_next(&iterTable);
831             }
832         }
833         g_isValidated = true;
834         RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
835         u_linklist_free(&invalidInterfaces);
836 #ifdef WITH_PROCESS_EVENT
837         compareAndApplyTimeout(nextEventTime, ROUTINGTABLE_REFRESH_TIMEOUT);
838 #endif // WITH_PROCESS_EVENT
839     }
840 #ifdef WITH_PROCESS_EVENT
841     else
842     {
843         compareAndApplyTimeout(nextEventTime,
844             ROUTINGTABLE_REFRESH_TIMEOUT - (currentTime - g_refreshTableTime));
845     }
846 #endif // WITH_PROCESS_EVENT
847
848 exit:
849     return;
850 }
851
852 OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
853 {
854     OIC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
855     OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
856     OIC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
857     OIC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
858     return result;
859 }
860
861 void RMSendDeleteToNeighbourNodes()
862 {
863     OIC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
864     u_linklist_t *neighbourNodes = NULL;
865     RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
866
867     if (0 >= u_linklist_length(neighbourNodes))
868     {
869         OIC_LOG(DEBUG, TAG, "No neighbour nodes present");
870         return;
871     }
872
873     u_linklist_iterator_t *iterTable = NULL;
874     u_linklist_init_iterator(neighbourNodes, &iterTable);
875     while (NULL != iterTable)
876     {
877
878         OCRepPayload *payload = NULL;
879         // Created payload is freed in the OCDoResource() api.
880         OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
881         if (OC_STACK_OK != result)
882         {
883             OIC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
884             RMPFreePayload(payload);
885             u_linklist_free(&neighbourNodes);
886             return;
887         }
888
889         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
890         if (entry)
891         {
892             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
893             {
894                 RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
895                 if (!dest)
896                 {
897                     OIC_LOG(ERROR, RM_TAG, "Failed to get dest address");
898                     continue;
899                 }
900                 OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
901                 CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
902                 OIC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
903                          dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
904                 RMSendDeleteRequest(&devAddr, payload);
905             }
906         }
907
908         u_linklist_get_next(&iterTable);
909     }
910
911     u_linklist_free(&neighbourNodes);
912     OIC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
913 }
914
915 uint32_t RMGetGatewayId()
916 {
917     if (!g_isRMInitialized)
918     {
919         OIC_LOG(ERROR, TAG, "RM not initialized");
920         return 0;
921     }
922     return g_GatewayID;
923 }
924
925 uint16_t RMGetMcastSeqNumber()
926 {
927     if (!g_isRMInitialized)
928     {
929         OIC_LOG(DEBUG, TAG, "RM not initialized");
930         return 0;
931     }
932     return ++g_mcastsequenceNumber;
933 }
934
935 /*
936  * This function is lifeline of packet forwarding module, hence we are going to do some serious
937  * handling here. Following are the expectations from this function:
938  * 1) If routing option is not available, forward packet to RI only. else:
939  * 2) If source is empty in routing option, packet is from end device, add an end device entry and
940  *    add "GatewayId:ClientId" as source.
941  * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
942  *    multicast on other interfaces. Also remove routing Option and forward to RI. (Before
943  *    forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
944  *     the packet.)
945  * 4) If destination is present in routing option, its unicast packet,
946  *    a) If self gatewayId is present in destination and no clientId, remove routing option
947  *       and forward to RI.
948  *    b) If self gatewayId and a clientId is present in destination, forward to end device.
949  * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
950  */
951
952 OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
953                              bool *selfDestination, bool *isEmptyMsg)
954 {
955     RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
956     RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
957     RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
958
959     bool forward = false;
960     bool isEMPTYPacket = false;
961     CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
962     CAInfo_t *info = NULL;
963     if (isRequest)
964     {
965         CARequestInfo_t *msg = message;
966         info = &(msg->info);
967         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
968     }
969     else
970     {
971         CAResponseInfo_t *msg = message;
972         info = &(msg->info);
973         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
974     }
975
976     // 1.  If routing option is not available, forward packet to RI only.
977     int8_t routeIndex = -1;
978     RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
979     if (-1 >= routeIndex)
980     {
981         OIC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
982         // Let RI handle this packet.
983         *selfDestination = true;
984         return OC_STACK_OK;
985     }
986
987     // Get existing values in packet route option.
988     RMRouteOption_t routeOption = {.srcGw = 0};
989     OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
990     if (OC_STACK_OK != res)
991     {
992         OIC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
993         return OC_STACK_ERROR;
994     }
995
996     /*
997      * 2) If source is empty in routing option, packet is from end device, add an end device entry
998      *  and add "GatewayId:ClientId" as source.
999      */
1000     if (g_GatewayID == routeOption.srcGw)
1001     {
1002         OIC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
1003         if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
1004         {
1005             g_mcastsequenceNumber = routeOption.mSeqNum;
1006         }
1007
1008         return OC_STACK_ERROR;
1009     }
1010     else if (0 == routeOption.srcGw)
1011     {
1012         OIC_LOG(INFO, RM_TAG, "Source missing in option");
1013         // Packet from end device as Gateway will add source in option.
1014         uint16_t endpointId = g_EndpointCount + 1;
1015         OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
1016         if (OC_STACK_OK == res)
1017         {
1018             g_EndpointCount = endpointId;
1019             OIC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
1020         }
1021         else if (OC_STACK_DUPLICATE_REQUEST == res)
1022         {
1023             OIC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
1024         }
1025         else
1026         {
1027             OIC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
1028             return OC_STACK_ERROR;
1029         }
1030
1031         // add source option.
1032         routeOption.srcGw = g_GatewayID;
1033         routeOption.srcEp = endpointId;
1034         OIC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
1035     }
1036
1037     /*
1038      * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
1039      *    multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
1040      *    caller of this function).
1041      */
1042     if (0 == routeOption.destGw)
1043     {
1044         OIC_LOG(INFO, RM_TAG, "Destination missing in option");
1045         // This is a multicast packet.
1046         if (g_GatewayID == routeOption.srcGw)
1047         {
1048             routeOption.mSeqNum = ++g_mcastsequenceNumber;
1049         }
1050         else
1051         {
1052             OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
1053                                                            &g_routingGatewayTable);
1054             if (OC_STACK_OK != update)
1055             {
1056                 // this shouldnt have been forwarded. ignore.
1057                 OIC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
1058                          routeOption.mSeqNum);
1059                 return OC_STACK_ERROR;
1060             }
1061         }
1062
1063         // forward
1064         *selfDestination = true;
1065         forward = true;
1066
1067         // Send multicast on every adapter except the one from which packet was received
1068         // TODO::: support to be added for IP hop.
1069         if (sender->adapter != CA_ADAPTER_IP)
1070         {
1071             nextHop.adapter |= CA_ADAPTER_IP;
1072             nextHop.flags |= CA_IPV4 | CA_IPV6;
1073         }
1074
1075         if(sender->adapter != CA_ADAPTER_GATT_BTLE)
1076         {
1077             nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
1078         }
1079
1080         if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
1081         {
1082             nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
1083         }
1084
1085         // Only requests are sent as multicast.
1086         if(isRequest)
1087         {
1088             CARequestInfo_t *msg = message;
1089             msg->isMulticast = true;
1090         }
1091         goto  rewriteandexit;
1092     }
1093     else if (g_GatewayID == routeOption.destGw)
1094     {
1095         OIC_LOG(INFO, RM_TAG, "GatewayId found in destination");
1096
1097         // Check the MSGType of RouteOption to find if the packet is EMPTY packet.
1098         if (ACK == routeOption.msgType || RST == routeOption.msgType)
1099         {
1100             isEMPTYPacket = true;
1101         }
1102
1103         /*
1104          * This unicast packet either belongs to us or any of our connected end devices
1105          * check if packet belongs to end device.
1106          */
1107         if (0 != routeOption.destEp)
1108         {
1109             // forward packet to the client.
1110             OIC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1111             CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1112                                                            g_routingEndpointTable);
1113             if(!clientInfo)
1114             {
1115                 OIC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1116                 return OC_STACK_ERROR;
1117             }
1118
1119             nextHop = *clientInfo;
1120             forward = true;
1121             *selfDestination = false;
1122             goto rewriteandexit;
1123         }
1124         else
1125         {
1126             // packet is for us.
1127             OIC_LOG(INFO, RM_TAG, "Received packet for self");
1128             forward = false;
1129             *selfDestination = true;
1130             goto rewriteandexit;
1131         }
1132     }
1133     else
1134     {
1135         /*
1136          * This unicast packet belongs to other gateway.
1137          * we only want to print first 4 bytes of packet as readable GatewayId.
1138          */
1139         OIC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1140         RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1141         if(!nextHopGw)
1142         {
1143             OIC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1144             return OC_STACK_ERROR;
1145         }
1146
1147         // TODO:: check preferences among multiple interface addresses, for now sending on first one
1148         RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1149         if (!address)
1150         {
1151             OIC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1152             return OC_STACK_ERROR;
1153         }
1154
1155         nextHop = address->destIntfAddr;
1156         forward = true;
1157         *selfDestination = false;
1158         goto rewriteandexit;
1159     }
1160
1161 rewriteandexit:
1162
1163     if (forward)
1164     {
1165         // Don't forward any packet meant for gateway resource.
1166         if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)) &&
1167             (ACK != routeOption.msgType))
1168         {
1169             OIC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1170         }
1171         else if (sender->flags & CA_SECURE)
1172         {
1173             OIC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1174             return OC_STACK_ERROR;
1175         }
1176         else if (isEMPTYPacket)
1177         {
1178             OIC_LOG(DEBUG, TAG, "The message to be Forwarded is a EMPTY message");
1179             CAResponseInfo_t responseMessage = {.result = CA_EMPTY};
1180             if (ACK == routeOption.msgType)
1181             {
1182                 responseMessage.info.type = CA_MSG_ACKNOWLEDGE;
1183             }
1184             else
1185             {
1186                 responseMessage.info.type = CA_MSG_RESET;
1187             }
1188
1189             responseMessage.info.messageId = info->messageId;
1190             responseMessage.info.dataType = CA_RESPONSE_DATA;
1191
1192             CAResult_t caRes = CASendResponse(&nextHop, &responseMessage);
1193             if (CA_STATUS_OK != caRes)
1194             {
1195                 OIC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1196                          caRes, nextHop.addr);
1197                 // Since a response is always unicast, return error here.
1198                 return OC_STACK_ERROR;
1199             }
1200         }
1201         else
1202         {
1203             // rewrite any changes in routing option.
1204             res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1205             if (OC_STACK_OK != res)
1206             {
1207                 OIC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1208                 return res;
1209             }
1210             /*
1211              * When forwarding a packet, do not attempt retransmission as its the responsibility of
1212              * packet originator node.
1213              */
1214             info->skipRetransmission = true;
1215             if(isRequest)
1216             {
1217                 CARequestInfo_t *msg = message;
1218                 msg->info.dataType = CA_REQUEST_DATA;
1219                 CAResult_t caRes = CASendRequest(&nextHop, msg);
1220                 if (CA_STATUS_OK != caRes)
1221                 {
1222                     OIC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1223                              nextHop.addr);
1224                     if(0 == routeOption.destGw)
1225                     {
1226                         /*
1227                          * No point going forward as unicast packet could not be forwarded
1228                          * not returning error for multicast as we may still let RI process
1229                          * this packet.
1230                          */
1231                         return OC_STACK_ERROR;
1232                     }
1233                 }
1234             }
1235             else
1236             {
1237                 CAResponseInfo_t *msg = message;
1238                 msg->info.dataType = CA_RESPONSE_DATA;
1239                 CAResult_t caRes = CASendResponse(&nextHop, msg);
1240                 if (CA_STATUS_OK != caRes)
1241                 {
1242                     OIC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1243                              caRes, nextHop.addr);
1244                     // Since a response is always unicast, return error here.
1245                     return OC_STACK_ERROR;
1246                 }
1247             }
1248         }
1249     }
1250     else
1251     {
1252         if (isEMPTYPacket)
1253         {
1254             if (isRequest)
1255             {
1256                 OIC_LOG(DEBUG, TAG, "POST message with type ACK in Route Option");
1257                 if (NULL != isEmptyMsg)
1258                 {
1259                     *isEmptyMsg = true;
1260                 }
1261             }
1262             else
1263             {
1264                 OIC_LOG(DEBUG, TAG, "Response for EMPTY message is received");
1265                 CAResponseInfo_t *msg = message;
1266                 if (ACK == (MSGType)routeOption.msgType)
1267                 {
1268                     msg->info.type = CA_MSG_ACKNOWLEDGE;
1269                 }
1270                 else
1271                 {
1272                     msg->info.type = CA_MSG_RESET;
1273                 }
1274                 msg->result = CA_EMPTY;
1275                 OICFree(msg->info.token);
1276                 msg->info.token = NULL;
1277                 msg->info.tokenLength = 0;
1278             }
1279         }
1280     }
1281
1282     OIC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1283     return OC_STACK_OK;
1284 }
1285
1286 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1287                               bool *selfDestination, bool *isEmptyMsg)
1288 {
1289     if (!g_isRMInitialized)
1290     {
1291         OIC_LOG(INFO, TAG, "RM not initialized");
1292         *selfDestination = true;
1293         return OC_STACK_OK;
1294     }
1295     OCStackResult res = RMHandlePacket(true, message, sender, selfDestination, isEmptyMsg);
1296     return res;
1297 }
1298
1299 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1300                                bool *selfDestination)
1301 {
1302     if (!g_isRMInitialized)
1303     {
1304         OIC_LOG(INFO, TAG, "RM not initialized");
1305         *selfDestination = true;
1306         return OC_STACK_OK;
1307     }
1308     OCStackResult res = RMHandlePacket(false, message, sender, selfDestination, NULL);
1309     return res;
1310 }