Imported Upstream version 1.0.1
[platform/upstream/iotivity.git] / resource / csdk / routing / src / routingutility.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 "routingutility.h"
24 #include "routingmanager.h"
25 #include "oic_malloc.h"
26 #include "include/logger.h"
27
28 /**
29  * Logging tag for module name.
30  */
31 #define TAG "RM_UTIL"
32
33 /**
34  * Tag for printing the logs of forwarding the packet.
35  */
36 #define RM_TAG "RAP"
37
38 /**
39  * Minimum routing option data length is
40  * length of src address(1byte) + length of destination address(1byte) + hop count(2bytes)
41  */
42 #define MIN_ROUTE_OPTION_LEN 4
43
44 // destination and source are <GatewayId><ClientId> here, where ClientId is optional.
45 OCStackResult RMAddInfo(const char *destination, CAHeaderOption_t **options,
46                         uint8_t *numOptions)
47 {
48     OC_LOG(DEBUG, TAG, "IN");
49     RM_NULL_CHECK_WITH_RET(options, TAG, "options");
50     RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
51
52     CAHeaderOption_t *optionPtr = NULL;
53     int8_t index = -1;
54
55     RMGetRouteOptionIndex(*options, *numOptions, &index);
56
57     if (-1 < index)
58     {
59         OC_LOG(INFO, TAG, "Route option is present");
60         optionPtr = *options;
61     }
62     else
63     {
64         OC_LOG(INFO, TAG, "Route option is not present");
65         index = *numOptions;
66         optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
67         if (!optionPtr)
68         {
69             OC_LOG(ERROR, TAG, "OICCalloc failed");
70             return OC_STACK_NO_MEMORY;
71         }
72
73         memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
74     }
75
76     OCStackResult res = OC_STACK_OK;
77     RMRouteOption_t routeOption = {.destGw = 0};
78     if (*numOptions != index)
79     {
80         OC_LOG(INFO, TAG, "Route option is already present");
81         res = RMParseRouteOption(&optionPtr[index], &routeOption);
82         if (OC_STACK_OK != res)
83         {
84             OC_LOG(ERROR, TAG, "RMParseRouteOption failed");
85             return OC_STACK_ERROR;
86         }
87     }
88
89     if(destination)
90     {
91         memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
92         memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
93                sizeof(routeOption.destEp));
94     }
95
96 #ifdef ROUTING_GATEWAY
97     // A gateway is supposed to add its ID as source.
98     uint32_t gatewayId = RMGetGatewayId();
99     if (gatewayId)
100     {
101         memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
102     }
103
104     if(!routeOption.destGw)
105     {
106         routeOption.mSeqNum = RMGetMcastSeqNumber();
107     }
108 #endif
109
110     res = RMCreateRouteOption(&routeOption, optionPtr + index);
111     if (OC_STACK_OK != res)
112     {
113         OC_LOG(ERROR, TAG, "Creation of routing option failed");
114         OICFree(optionPtr);
115         return res;
116     }
117
118     if ((*numOptions) == index )
119     {
120         (*numOptions) = (*numOptions) + 1;
121         OICFree(*options);
122         *options = optionPtr;
123     }
124
125     OC_LOG(DEBUG, TAG, "OUT");
126     return OC_STACK_OK;
127 }
128
129 OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
130                            CAEndpoint_t *endpoint)
131 {
132     OC_LOG(DEBUG, TAG, "IN");
133     RM_NULL_CHECK_WITH_RET(options, TAG, "options");
134     RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option");
135     RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
136     RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint");
137
138     if (0 >= *numOptions)
139     {
140         OC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
141         return OC_STACK_ERROR;
142     }
143
144     int8_t routeIndex = -1;
145     RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
146
147     if (-1 >= routeIndex)
148     {
149         OC_LOG(DEBUG, TAG, "Nothing to remove.");
150         return OC_STACK_OK;
151     }
152
153     // Update Endpoint with source address from RM header option.
154     if (0 != (*options + routeIndex)->optionLength)
155     {
156         uint8_t dLen = 0;
157         uint16_t count = sizeof(dLen);
158         memcpy(&dLen, (*options + routeIndex)->optionData, sizeof(dLen));
159         count += dLen;
160         uint8_t sLen = 0;
161         memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
162         count += sizeof(sLen);
163         if (0 < sLen)
164         {
165             memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
166                    GATEWAY_ID_LENGTH);
167             OC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]",
168                      *((uint32_t *)endpoint->routeData), sLen);
169
170             count += GATEWAY_ID_LENGTH;
171
172             if (GATEWAY_ID_LENGTH < sLen)
173             {
174                 memcpy(endpoint->routeData + GATEWAY_ID_LENGTH,
175                        (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH);
176                 OC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint",
177                          *((uint16_t *)(endpoint->routeData + GATEWAY_ID_LENGTH)));
178             }
179         }
180     }
181
182     // Remove route option from header.
183     for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
184     {
185         memcpy((*options) + i, (*options)+i+1, sizeof(**options));
186     }
187     *numOptions = (*numOptions) - 1;
188
189     if (0 == *numOptions)
190     {
191         // Remove route option.
192         OICFree(*options);
193         *options = NULL;
194     }
195     OC_LOG(DEBUG, TAG, "OUT");
196     return OC_STACK_OK;
197 }
198
199 void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
200 {
201     OC_LOG(DEBUG, TAG, "IN");
202     RM_NULL_CHECK_VOID(options, TAG, "options");
203     RM_NULL_CHECK_VOID(index, TAG, "index");
204     for (uint32_t i = 0; i < numOptions; i++)
205     {
206         OC_LOG_V(DEBUG, TAG, "Request- optionID: %u", options[i].optionID);
207         if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
208         {
209             OC_LOG_V(INFO, TAG, "Found Option at %d", i);
210             *index = i;
211             break;
212         }
213     }
214     OC_LOG(DEBUG, TAG, "OUT");
215 }
216
217 OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
218 {
219     OC_LOG(DEBUG, RM_TAG, "IN");
220     RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
221     RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
222
223     uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) +
224                         (optValue->destEp ? ENDPOINT_ID_LENGTH:0);
225     uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) +
226                         (optValue->srcEp ? ENDPOINT_ID_LENGTH:0);
227
228     OC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
229     unsigned int totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
230     void *tempData = OICCalloc(totalLength, sizeof(char));
231     if (NULL == tempData)
232     {
233         OC_LOG(ERROR, RM_TAG, "Calloc failed");
234         return OC_STACK_NO_MEMORY;
235     }
236     memcpy(tempData, &dLen, sizeof(dLen));
237     unsigned int count = sizeof(dLen);
238     if (0 < dLen)
239     {
240         if (optValue->destGw)
241         {
242             memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
243             count += GATEWAY_ID_LENGTH;
244         }
245
246         if (optValue->destEp)
247         {
248             memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
249             count += ENDPOINT_ID_LENGTH;
250         }
251     }
252
253     memcpy(tempData + count, &sLen, sizeof(sLen));
254     count += sizeof(sLen);
255     if (0 < sLen)
256     {
257         if (optValue->srcGw)
258         {
259             memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
260             count += GATEWAY_ID_LENGTH;
261         }
262
263         if (optValue->srcEp)
264         {
265             memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
266             count += ENDPOINT_ID_LENGTH;
267         }
268     }
269
270     memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
271     memcpy(options->optionData, tempData, totalLength);
272
273     options->optionID = RM_OPTION_MESSAGE_SWITCHING;
274     options->optionLength = totalLength;
275
276     OC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
277
278     OICFree(tempData);
279     OC_LOG(DEBUG, RM_TAG, "OUT");
280     return OC_STACK_OK;
281 }
282
283 OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
284 {
285     OC_LOG(DEBUG, RM_TAG, "IN");
286     RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
287     RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
288     if (0 == options->optionLength)
289     {
290         OC_LOG(ERROR, RM_TAG, "Option data is not present");
291         return OC_STACK_ERROR;
292     }
293
294     uint8_t dLen = 0 ;
295     uint16_t count = sizeof(dLen);
296     memcpy(&dLen, options->optionData, sizeof(dLen));
297     if (0 < dLen)
298     {
299         memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
300         count += GATEWAY_ID_LENGTH;
301
302         if (GATEWAY_ID_LENGTH < dLen)
303         {
304             memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
305             count += ENDPOINT_ID_LENGTH;
306         }
307     }
308
309     uint8_t sLen = 0;
310     memcpy(&sLen, options->optionData + count, sizeof(sLen));
311     count += sizeof(sLen);
312     if (0 < sLen)
313     {
314         memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
315         count += GATEWAY_ID_LENGTH;
316
317         if (GATEWAY_ID_LENGTH < sLen)
318         {
319             memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
320             count += ENDPOINT_ID_LENGTH;
321         }
322     }
323     memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
324
325     OC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum);
326     OC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp);
327     OC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp);
328     OC_LOG(DEBUG, RM_TAG, "OUT");
329     return OC_STACK_OK;
330 }