9f87d2fd0b5cf98219b5804120f84e1147ff75e5
[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 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, bool *isEmptyMsg)
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     bool isEMPTYPacket = false;
917     CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
918     CAInfo_t *info = NULL;
919     if (isRequest)
920     {
921         CARequestInfo_t *msg = message;
922         info = &(msg->info);
923         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
924     }
925     else
926     {
927         CAResponseInfo_t *msg = message;
928         info = &(msg->info);
929         RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
930     }
931
932     // 1.  If routing option is not available, forward packet to RI only.
933     int8_t routeIndex = -1;
934     RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
935     if (-1 >= routeIndex)
936     {
937         OIC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
938         // Let RI handle this packet.
939         *selfDestination = true;
940         return OC_STACK_OK;
941     }
942
943     // Get existing values in packet route option.
944     RMRouteOption_t routeOption = {.srcGw = 0};
945     OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
946     if (OC_STACK_OK != res)
947     {
948         OIC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
949         return OC_STACK_ERROR;
950     }
951
952     /*
953      * 2) If source is empty in routing option, packet is from end device, add an end device entry
954      *  and add "GatewayId:ClientId" as source.
955      */
956     if (g_GatewayID == routeOption.srcGw)
957     {
958         OIC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
959         if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
960         {
961             g_mcastsequenceNumber = routeOption.mSeqNum;
962         }
963
964         return OC_STACK_ERROR;
965     }
966     else if (0 == routeOption.srcGw)
967     {
968         OIC_LOG(INFO, RM_TAG, "Source missing in option");
969         // Packet from end device as Gateway will add source in option.
970         uint16_t endpointId = g_EndpointCount + 1;
971         OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
972         if (OC_STACK_OK == res)
973         {
974             g_EndpointCount = endpointId;
975             OIC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
976         }
977         else if (OC_STACK_DUPLICATE_REQUEST == res)
978         {
979             OIC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
980         }
981         else
982         {
983             OIC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
984             return OC_STACK_ERROR;
985         }
986
987         // add source option.
988         routeOption.srcGw = g_GatewayID;
989         routeOption.srcEp = endpointId;
990         OIC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
991     }
992
993     /*
994      * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
995      *    multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
996      *    caller of this function).
997      */
998     if (0 == routeOption.destGw)
999     {
1000         OIC_LOG(INFO, RM_TAG, "Destination missing in option");
1001         // This is a multicast packet.
1002         if (g_GatewayID == routeOption.srcGw)
1003         {
1004             routeOption.mSeqNum = ++g_mcastsequenceNumber;
1005         }
1006         else
1007         {
1008             OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
1009                                                            &g_routingGatewayTable);
1010             if (OC_STACK_OK != update)
1011             {
1012                 // this shouldnt have been forwarded. ignore.
1013                 OIC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
1014                          routeOption.mSeqNum);
1015                 return OC_STACK_ERROR;
1016             }
1017         }
1018
1019         // forward
1020         *selfDestination = true;
1021         forward = true;
1022
1023         // Send multicast on every adapter except the one from which packet was received
1024         // TODO::: support to be added for IP hop.
1025         if (sender->adapter != CA_ADAPTER_IP)
1026         {
1027             nextHop.adapter |= CA_ADAPTER_IP;
1028             nextHop.flags |= CA_IPV4 | CA_IPV6;
1029         }
1030
1031         if(sender->adapter != CA_ADAPTER_GATT_BTLE)
1032         {
1033             nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
1034         }
1035
1036         if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
1037         {
1038             nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
1039         }
1040
1041         // Only requests are sent as multicast.
1042         if(isRequest)
1043         {
1044             CARequestInfo_t *msg = message;
1045             msg->isMulticast = true;
1046         }
1047         goto  rewriteandexit;
1048     }
1049     else if (g_GatewayID == routeOption.destGw)
1050     {
1051         OIC_LOG(INFO, RM_TAG, "GatewayId found in destination");
1052
1053         // Check the MSGType of RouteOption to find if the packet is EMPTY packet.
1054         if (ACK == routeOption.msgType || RST == routeOption.msgType)
1055         {
1056             isEMPTYPacket = true;
1057         }
1058
1059         /*
1060          * This unicast packet either belongs to us or any of our connected end devices
1061          * check if packet belongs to end device.
1062          */
1063         if (0 != routeOption.destEp)
1064         {
1065             // forward packet to the client.
1066             OIC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
1067             CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
1068                                                            g_routingEndpointTable);
1069             if(!clientInfo)
1070             {
1071                 OIC_LOG(ERROR, RM_TAG, "Failed to get Client info");
1072                 return OC_STACK_ERROR;
1073             }
1074
1075             nextHop = *clientInfo;
1076             forward = true;
1077             *selfDestination = false;
1078             goto rewriteandexit;
1079         }
1080         else
1081         {
1082             // packet is for us.
1083             OIC_LOG(INFO, RM_TAG, "Received packet for self");
1084             forward = false;
1085             *selfDestination = true;
1086             goto rewriteandexit;
1087         }
1088     }
1089     else
1090     {
1091         /*
1092          * This unicast packet belongs to other gateway.
1093          * we only want to print first 4 bytes of packet as readable GatewayId.
1094          */
1095         OIC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
1096         RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
1097         if(!nextHopGw)
1098         {
1099             OIC_LOG(ERROR, RM_TAG, "Failed to get next hop");
1100             return OC_STACK_ERROR;
1101         }
1102
1103         // TODO:: check preferences among multiple interface addresses, for now sending on first one
1104         RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
1105         if (!address)
1106         {
1107             OIC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
1108             return OC_STACK_ERROR;
1109         }
1110
1111         nextHop = address->destIntfAddr;
1112         forward = true;
1113         *selfDestination = false;
1114         goto rewriteandexit;
1115     }
1116
1117 rewriteandexit:
1118
1119     if (forward)
1120     {
1121         // Don't forward any packet meant for gateway resource.
1122         if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)) &&
1123             (ACK != routeOption.msgType))
1124         {
1125             OIC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
1126         }
1127         else if (sender->flags & CA_SECURE)
1128         {
1129             OIC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
1130             return OC_STACK_ERROR;
1131         }
1132         else if (isEMPTYPacket)
1133         {
1134             OIC_LOG(DEBUG, TAG, "The message to be Forwarded is a EMPTY message");
1135             CAResponseInfo_t responseMessage = {.result = CA_EMPTY};
1136             if (ACK == routeOption.msgType)
1137             {
1138                 responseMessage.info.type = CA_MSG_ACKNOWLEDGE;
1139             }
1140             else
1141             {
1142                 responseMessage.info.type = CA_MSG_RESET;
1143             }
1144
1145             responseMessage.info.messageId = info->messageId;
1146             responseMessage.info.dataType = CA_RESPONSE_DATA;
1147
1148             CAResult_t caRes = CASendResponse(&nextHop, &responseMessage);
1149             if (CA_STATUS_OK != caRes)
1150             {
1151                 OIC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1152                          caRes, nextHop.addr);
1153                 // Since a response is always unicast, return error here.
1154                 return OC_STACK_ERROR;
1155             }
1156         }
1157         else
1158         {
1159             // rewrite any changes in routing option.
1160             res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
1161             if (OC_STACK_OK != res)
1162             {
1163                 OIC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
1164                 return res;
1165             }
1166             /*
1167              * When forwarding a packet, do not attempt retransmission as its the responsibility of
1168              * packet originator node.
1169              */
1170             info->skipRetransmission = true;
1171             if(isRequest)
1172             {
1173                 CARequestInfo_t *msg = message;
1174                 msg->info.dataType = CA_REQUEST_DATA;
1175                 CAResult_t caRes = CASendRequest(&nextHop, msg);
1176                 if (CA_STATUS_OK != caRes)
1177                 {
1178                     OIC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
1179                              nextHop.addr);
1180                     if(0 == routeOption.destGw)
1181                     {
1182                         /*
1183                          * No point going forward as unicast packet could not be forwarded
1184                          * not returning error for multicast as we may still let RI process
1185                          * this packet.
1186                          */
1187                         return OC_STACK_ERROR;
1188                     }
1189                 }
1190             }
1191             else
1192             {
1193                 CAResponseInfo_t *msg = message;
1194                 msg->info.dataType = CA_RESPONSE_DATA;
1195                 CAResult_t caRes = CASendResponse(&nextHop, msg);
1196                 if (CA_STATUS_OK != caRes)
1197                 {
1198                     OIC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
1199                              caRes, nextHop.addr);
1200                     // Since a response is always unicast, return error here.
1201                     return OC_STACK_ERROR;
1202                 }
1203             }
1204         }
1205     }
1206     else
1207     {
1208         if (isEMPTYPacket)
1209         {
1210             if (isRequest)
1211             {
1212                 OIC_LOG(DEBUG, TAG, "POST message with type ACK in Route Option");
1213                 if (NULL != isEmptyMsg)
1214                 {
1215                     *isEmptyMsg = true;
1216                 }
1217             }
1218             else
1219             {
1220                 OIC_LOG(DEBUG, TAG, "Response for EMPTY message is received");
1221                 CAResponseInfo_t *msg = message;
1222                 if (ACK == (MSGType)routeOption.msgType)
1223                 {
1224                     msg->info.type = CA_MSG_ACKNOWLEDGE;
1225                 }
1226                 else
1227                 {
1228                     msg->info.type = CA_MSG_RESET;
1229                 }
1230                 msg->result = CA_EMPTY;
1231                 OICFree(msg->info.token);
1232                 msg->info.token = NULL;
1233                 msg->info.tokenLength = 0;
1234             }
1235         }
1236     }
1237
1238     OIC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
1239     return OC_STACK_OK;
1240 }
1241
1242 OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
1243                               bool *selfDestination, bool *isEmptyMsg)
1244 {
1245     if (!g_isRMInitialized)
1246     {
1247         OIC_LOG(INFO, TAG, "RM not initialized");
1248         *selfDestination = true;
1249         return OC_STACK_OK;
1250     }
1251     OCStackResult res = RMHandlePacket(true, message, sender, selfDestination, isEmptyMsg);
1252     return res;
1253 }
1254
1255 OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
1256                                bool *selfDestination)
1257 {
1258     if (!g_isRMInitialized)
1259     {
1260         OIC_LOG(INFO, TAG, "RM not initialized");
1261         *selfDestination = true;
1262         return OC_STACK_OK;
1263     }
1264     OCStackResult res = RMHandlePacket(false, message, sender, selfDestination, NULL);
1265     return res;
1266 }