6900e664b080bd87ed0c605d1db5509cdf4b4d97
[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 "OIC_RM_UTIL"
32
33 /**
34  * Tag for printing the logs of forwarding the packet.
35  */
36 #define RM_TAG "OIC_RM_RAP"
37
38 /**
39  * Default routing option data length is 1 byte with any of the following values.
40  * 00 - source and destination address is not present.
41  * 01 - source and destination address is present with message type as ACK.
42  * 10 - source and destination address is present with message type as RESET.
43  * 11 - source and destination address is present with message type as NORMAL.
44  */
45 #define DEFAULT_ROUTE_OPTION_LEN 1
46
47 /**
48  * Minimum routing option data length is
49  * Msg Type(1 bytes) + length of src address(1byte) + length of destination address(1byte) +
50  * Seq Num(2bytes)
51  */
52 #define MIN_ROUTE_OPTION_LEN 5
53
54 /**
55  * Acknowledge message type is denoted as 01000000
56  */
57 #define ACK_MESSAGE_TYPE (1 << 6)
58
59 /**
60  * Reset message type is denoted as 10000000
61  */
62 #define RST_MESSAGE_TYPE (1 << 7)
63
64 /**
65  * Normal message type is denoted as 11000000
66  */
67 #define NORMAL_MESSAGE_TYPE (3 << 6)
68
69 /**
70  * Stack mode.
71  */
72 static OCMode g_rmStackMode = OC_CLIENT;
73
74 void RMSetStackMode(OCMode mode)
75 {
76     g_rmStackMode = mode;
77 }
78
79 // destination and source are <GatewayId><ClientId> here, where ClientId is optional.
80 OCStackResult RMAddInfo(const char *destination, void *message, bool isRequest,
81                         bool *doPost)
82 {
83     OIC_LOG(DEBUG, TAG, "IN");
84     RM_NULL_CHECK_WITH_RET(message, TAG, "options");
85
86     CAHeaderOption_t **options = NULL;
87     uint8_t *numOptions = NULL;
88
89     if (isRequest)
90     {
91         CARequestInfo_t *requestMsg = message;
92         options = &(requestMsg->info.options);
93         RM_NULL_CHECK_WITH_RET(options, TAG, "options");
94         numOptions = &(requestMsg->info.numOptions);
95         RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
96     }
97     else
98     {
99         CAResponseInfo_t *respMsg = message;
100         if ('\0' == destination[0] && (CA_EMPTY == respMsg->result))
101         {
102             OIC_LOG(DEBUG, TAG, "Response is for an Endpoint, No need to add the routing Option");
103             return OC_STACK_OK;
104         }
105         options = &(respMsg->info.options);
106         RM_NULL_CHECK_WITH_RET(options, TAG, "options");
107         numOptions = &(respMsg->info.numOptions);
108         RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
109     }
110
111
112     CAHeaderOption_t *optionPtr = NULL;
113     int8_t index = -1;
114
115     RMGetRouteOptionIndex(*options, *numOptions, &index);
116
117     if (-1 < index)
118     {
119         OIC_LOG(INFO, TAG, "Route option is present");
120         optionPtr = *options;
121     }
122     else
123     {
124         OIC_LOG(INFO, TAG, "Route option is not present");
125         index = *numOptions;
126         optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
127         if (!optionPtr)
128         {
129             OIC_LOG(ERROR, TAG, "OICCalloc failed");
130             return OC_STACK_NO_MEMORY;
131         }
132
133         memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
134     }
135
136     OCStackResult res = OC_STACK_OK;
137     RMRouteOption_t routeOption = {.destGw = 0};
138     if (*numOptions != index)
139     {
140         OIC_LOG(INFO, TAG, "Route option is already present");
141         res = RMParseRouteOption(&optionPtr[index], &routeOption);
142         if (OC_STACK_OK != res)
143         {
144             OIC_LOG(ERROR, TAG, "RMParseRouteOption failed");
145             return OC_STACK_ERROR;
146         }
147     }
148
149     if (!isRequest)
150     {
151         CAResponseInfo_t *respMsg = message;
152         if (CA_EMPTY == respMsg->result && CA_MSG_ACKNOWLEDGE == respMsg->info.type)
153         {
154             OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH ACKNOWLEDGEMENT");
155             routeOption.msgType = ACK;
156             if (OC_SERVER == g_rmStackMode)
157             {
158                 OIC_LOG(DEBUG, TAG, "This is server mode");
159                 // Send the Empty message in the response with adding the MSGType in Route option.
160                 respMsg->info.type = CA_MSG_NONCONFIRM;
161                 respMsg->result = CA_CONTENT;
162             }
163             else
164             {
165                 OIC_LOG(DEBUG, TAG, "Send a POST request");
166                 if (NULL != doPost)
167                 {
168                     *doPost = true;
169                 }
170             }
171         }
172         else if (CA_EMPTY == respMsg->result && CA_MSG_RESET == respMsg->info.type)
173         {
174             OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH RESET");
175             routeOption.msgType = RST;
176             respMsg->info.type = CA_MSG_NONCONFIRM;
177             respMsg->result = CA_CONTENT;
178         }
179     }
180
181     if(destination)
182     {
183         memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
184         memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
185                sizeof(routeOption.destEp));
186     }
187
188 #ifdef ROUTING_GATEWAY
189     // A gateway is supposed to add its ID as source.
190     uint32_t gatewayId = RMGetGatewayId();
191     if (gatewayId)
192     {
193         memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
194     }
195
196     if(!routeOption.destGw)
197     {
198         routeOption.mSeqNum = RMGetMcastSeqNumber();
199     }
200 #endif
201
202     res = RMCreateRouteOption(&routeOption, optionPtr + index);
203     if (OC_STACK_OK != res)
204     {
205         OIC_LOG(ERROR, TAG, "Creation of routing option failed");
206         OICFree(optionPtr);
207         return res;
208     }
209
210     if ((*numOptions) == index )
211     {
212         (*numOptions) = (*numOptions) + 1;
213         OICFree(*options);
214         *options = optionPtr;
215     }
216
217     OIC_LOG(DEBUG, TAG, "OUT");
218     return OC_STACK_OK;
219 }
220
221 OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
222                            CAEndpoint_t *endpoint)
223 {
224     OIC_LOG(DEBUG, TAG, "IN");
225     RM_NULL_CHECK_WITH_RET(options, TAG, "options");
226     RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option");
227     RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
228     RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint");
229
230     if (0 >= *numOptions)
231     {
232         OIC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
233         return OC_STACK_ERROR;
234     }
235
236     int8_t routeIndex = -1;
237     RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
238
239     if (-1 >= routeIndex)
240     {
241         OIC_LOG(DEBUG, TAG, "Nothing to remove.");
242         return OC_STACK_OK;
243     }
244
245     // Update Endpoint with source address from RM header option.
246     if (DEFAULT_ROUTE_OPTION_LEN < (*options + routeIndex)->optionLength )
247     {
248         uint8_t dLen = 0;
249         uint16_t count = sizeof(dLen) + DEFAULT_ROUTE_OPTION_LEN;
250         memcpy(&dLen, (*options + routeIndex)->optionData + DEFAULT_ROUTE_OPTION_LEN, sizeof(dLen));
251         count += dLen;
252         uint8_t sLen = 0;
253         memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
254         count += sizeof(sLen);
255         if (0 < sLen)
256         {
257             memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
258                    GATEWAY_ID_LENGTH);
259             OIC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]",
260                      *((uint32_t *)endpoint->routeData), sLen);
261
262             count += GATEWAY_ID_LENGTH;
263
264             if (GATEWAY_ID_LENGTH < sLen)
265             {
266                 memcpy(endpoint->routeData + GATEWAY_ID_LENGTH,
267                        (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH);
268                 OIC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint",
269                          *((uint16_t *)(endpoint->routeData + GATEWAY_ID_LENGTH)));
270             }
271         }
272     }
273
274     // Remove route option from header.
275     for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
276     {
277         memcpy((*options) + i, (*options)+i+1, sizeof(**options));
278     }
279     *numOptions = (*numOptions) - 1;
280
281     if (0 == *numOptions)
282     {
283         // Remove route option.
284         OICFree(*options);
285         *options = NULL;
286     }
287     OIC_LOG(DEBUG, TAG, "OUT");
288     return OC_STACK_OK;
289 }
290
291 void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
292 {
293     OIC_LOG(DEBUG, TAG, "IN");
294     RM_NULL_CHECK_VOID(index, TAG, "index");
295
296     if (NULL == options)
297     {
298         OIC_LOG(INFO, TAG, "No existing options");
299         return;
300     }
301
302     for (uint32_t i = 0; i < numOptions; i++)
303     {
304         OIC_LOG_V(DEBUG, TAG, "Request- optionID: %u", options[i].optionID);
305         if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
306         {
307             OIC_LOG_V(INFO, TAG, "Found Option at %d", i);
308             *index = i;
309             break;
310         }
311     }
312     OIC_LOG(DEBUG, TAG, "OUT");
313 }
314
315 OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
316 {
317     OIC_LOG(DEBUG, RM_TAG, "IN");
318     RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
319     RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
320
321     uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) +
322                         (optValue->destEp ? ENDPOINT_ID_LENGTH:0);
323     uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) +
324                         (optValue->srcEp ? ENDPOINT_ID_LENGTH:0);
325
326     OIC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
327
328     unsigned int totalLength = 0;
329     uint8_t *tempData = NULL;
330
331     if (0 == dLen && 0 == sLen)
332     {
333         OIC_LOG(DEBUG, RM_TAG, "Source and destination is not present");
334         totalLength = DEFAULT_ROUTE_OPTION_LEN;
335         tempData = OICCalloc(totalLength, sizeof(char));
336         if (NULL == tempData)
337         {
338             OIC_LOG(ERROR, RM_TAG, "Calloc failed");
339             return OC_STACK_NO_MEMORY;
340         }
341
342         if (ACK == optValue->msgType)
343         {
344             OIC_LOG(DEBUG, RM_TAG, "OptValue ACK Message Type");
345             memset(tempData, ACK_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
346         }
347         else if (RST == optValue->msgType)
348         {
349             OIC_LOG(DEBUG, RM_TAG, "OptValue RST Message Type");
350             memset(tempData, RST_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
351         }
352         else
353         {
354             OIC_LOG(DEBUG, RM_TAG, "OptValue NOR Message Type");
355             memset(tempData, NORMAL_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
356         }
357     }
358     else
359     {
360         totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
361         tempData = OICCalloc(totalLength, sizeof(char));
362         if (NULL == tempData)
363         {
364             OIC_LOG(ERROR, RM_TAG, "Calloc failed");
365             return OC_STACK_NO_MEMORY;
366         }
367
368         if (ACK == optValue->msgType)
369         {
370             OIC_LOG(DEBUG, RM_TAG, "OptValue ACK Message Type");
371             memset(tempData, ACK_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
372         }
373         else if (RST == optValue->msgType)
374         {
375             OIC_LOG(DEBUG, RM_TAG, "OptValue RST Message Type");
376             memset(tempData, RST_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
377         }
378         else
379         {
380             OIC_LOG(DEBUG, RM_TAG, "OptValue NOR Message Type");
381             memset(tempData, NORMAL_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
382         }
383
384         memcpy(tempData + DEFAULT_ROUTE_OPTION_LEN, &dLen, sizeof(dLen));
385         unsigned int count = sizeof(dLen) + DEFAULT_ROUTE_OPTION_LEN;
386         if (0 < dLen)
387         {
388             if (optValue->destGw)
389             {
390                 memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
391                 count += GATEWAY_ID_LENGTH;
392             }
393
394             if (optValue->destEp)
395             {
396                 memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
397                 count += ENDPOINT_ID_LENGTH;
398             }
399         }
400
401         memcpy(tempData + count, &sLen, sizeof(sLen));
402         count += sizeof(sLen);
403         if (0 < sLen)
404         {
405             if (optValue->srcGw)
406             {
407                 memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
408                 count += GATEWAY_ID_LENGTH;
409             }
410
411             if (optValue->srcEp)
412             {
413                 memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
414                 count += ENDPOINT_ID_LENGTH;
415             }
416         }
417
418         memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
419     }
420
421     memcpy(options->optionData, tempData, totalLength);
422
423     options->optionID = RM_OPTION_MESSAGE_SWITCHING;
424     options->optionLength = totalLength;
425
426     OIC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
427
428     OICFree(tempData);
429     OIC_LOG(DEBUG, RM_TAG, "OUT");
430     return OC_STACK_OK;
431 }
432
433 OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
434 {
435     OIC_LOG(DEBUG, RM_TAG, "IN");
436     RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
437     RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
438     if (0 == options->optionLength)
439     {
440         OIC_LOG(ERROR, RM_TAG, "Option data is not present");
441         return OC_STACK_ERROR;
442     }
443
444     OIC_LOG_V(DEBUG, RM_TAG, "Option Length is %d", options->optionLength);
445     uint8_t mType = 0;
446     memcpy(&mType, options->optionData, sizeof(mType));
447
448     if (ACK_MESSAGE_TYPE == mType)
449     {
450         OIC_LOG(INFO, RM_TAG, "ACK_MESSAGE_TYPE");
451         optValue->msgType = ACK;
452     }
453     else if (RST_MESSAGE_TYPE == mType)
454     {
455         OIC_LOG(INFO, RM_TAG, "RST_MESSAGE_TYPE");
456         optValue->msgType = RST;
457     }
458     else if (NORMAL_MESSAGE_TYPE == mType)
459     {
460         OIC_LOG(INFO, RM_TAG, "NOR_MESSAGE_TYPE");
461         optValue->msgType = NOR;
462     }
463
464     if (DEFAULT_ROUTE_OPTION_LEN == options->optionLength)
465     {
466         OIC_LOG(INFO, RM_TAG, "No source and destination are present");
467     }
468     else
469     {
470         uint8_t dLen = 0 ;
471         uint16_t count = DEFAULT_ROUTE_OPTION_LEN;
472         memcpy(&dLen, options->optionData + count, sizeof(dLen));
473         count += sizeof(dLen);
474         if (0 < dLen)
475         {
476             memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
477             count += GATEWAY_ID_LENGTH;
478
479             if (GATEWAY_ID_LENGTH < dLen)
480             {
481                 memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
482                 count += ENDPOINT_ID_LENGTH;
483             }
484         }
485
486         uint8_t sLen = 0;
487         memcpy(&sLen, options->optionData + count, sizeof(sLen));
488         count += sizeof(sLen);
489         if (0 < sLen)
490         {
491             memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
492             count += GATEWAY_ID_LENGTH;
493
494             if (GATEWAY_ID_LENGTH < sLen)
495             {
496                 memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
497                 count += ENDPOINT_ID_LENGTH;
498             }
499         }
500         memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
501     }
502
503     OIC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum);
504     OIC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp);
505     OIC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp);
506     OIC_LOG_V(INFO, RM_TAG, "Message Type is [%u]", optValue->msgType);
507     OIC_LOG(DEBUG, RM_TAG, "OUT");
508     return OC_STACK_OK;
509 }