1 /* ****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
23 #include "routingutility.h"
24 #include "routingmanager.h"
25 #include "oic_malloc.h"
26 #include "include/logger.h"
29 * Logging tag for module name.
31 #define TAG "OIC_RM_UTIL"
34 * Tag for printing the logs of forwarding the packet.
36 #define RM_TAG "OIC_RM_RAP"
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.
45 #define DEFAULT_ROUTE_OPTION_LEN 1
48 * Minimum routing option data length is
49 * Msg Type(1 bytes) + length of src address(1byte) + length of destination address(1byte) +
52 #define MIN_ROUTE_OPTION_LEN 5
55 * Acknowledge message type is denoted as 01000000
57 #define ACK_MESSAGE_TYPE (1 << 6)
60 * Reset message type is denoted as 10000000
62 #define RST_MESSAGE_TYPE (1 << 7)
65 * Normal message type is denoted as 11000000
67 #define NORMAL_MESSAGE_TYPE (3 << 6)
72 static OCMode g_rmStackMode = OC_CLIENT;
74 void RMSetStackMode(OCMode mode)
79 // destination and source are <GatewayId><ClientId> here, where ClientId is optional.
80 OCStackResult RMAddInfo(const char *destination, void *message, bool isRequest,
83 OIC_LOG(DEBUG, TAG, "IN");
84 RM_NULL_CHECK_WITH_RET(message, TAG, "options");
86 CAHeaderOption_t **options = NULL;
87 uint8_t *numOptions = NULL;
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");
99 CAResponseInfo_t *respMsg = message;
100 if ('\0' == destination[0] && (CA_EMPTY == respMsg->result))
102 OIC_LOG(DEBUG, TAG, "Response is for an Endpoint, No need to add the routing Option");
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");
112 CAHeaderOption_t *optionPtr = NULL;
115 RMGetRouteOptionIndex(*options, *numOptions, &index);
119 OIC_LOG(INFO, TAG, "Route option is present");
120 optionPtr = *options;
124 OIC_LOG(INFO, TAG, "Route option is not present");
126 optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
129 OIC_LOG(ERROR, TAG, "OICCalloc failed");
130 return OC_STACK_NO_MEMORY;
133 memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
136 OCStackResult res = OC_STACK_OK;
137 RMRouteOption_t routeOption = {.destGw = 0};
138 if (*numOptions != index)
140 OIC_LOG(INFO, TAG, "Route option is already present");
141 res = RMParseRouteOption(&optionPtr[index], &routeOption);
142 if (OC_STACK_OK != res)
144 OIC_LOG(ERROR, TAG, "RMParseRouteOption failed");
145 return OC_STACK_ERROR;
151 CAResponseInfo_t *respMsg = message;
152 if (CA_EMPTY == respMsg->result && CA_MSG_ACKNOWLEDGE == respMsg->info.type)
154 OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH ACKNOWLEDGEMENT");
155 routeOption.msgType = ACK;
156 if (OC_SERVER == g_rmStackMode)
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;
165 OIC_LOG(DEBUG, TAG, "Send a POST request");
172 else if (CA_EMPTY == respMsg->result && CA_MSG_RESET == respMsg->info.type)
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;
183 memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
184 memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
185 sizeof(routeOption.destEp));
188 #ifdef ROUTING_GATEWAY
189 // A gateway is supposed to add its ID as source.
190 uint32_t gatewayId = RMGetGatewayId();
193 memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
196 if(!routeOption.destGw)
198 routeOption.mSeqNum = RMGetMcastSeqNumber();
202 res = RMCreateRouteOption(&routeOption, optionPtr + index);
203 if (OC_STACK_OK != res)
205 OIC_LOG(ERROR, TAG, "Creation of routing option failed");
210 if ((*numOptions) == index )
212 (*numOptions) = (*numOptions) + 1;
214 *options = optionPtr;
217 OIC_LOG(DEBUG, TAG, "OUT");
221 OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
222 CAEndpoint_t *endpoint)
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");
230 if (0 >= *numOptions)
232 OIC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
233 return OC_STACK_ERROR;
236 int8_t routeIndex = -1;
237 RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
239 if (-1 >= routeIndex)
241 OIC_LOG(DEBUG, TAG, "Nothing to remove.");
245 // Update Endpoint with source address from RM header option.
246 if (DEFAULT_ROUTE_OPTION_LEN < (*options + routeIndex)->optionLength )
249 uint16_t count = sizeof(dLen) + DEFAULT_ROUTE_OPTION_LEN;
250 memcpy(&dLen, (*options + routeIndex)->optionData + DEFAULT_ROUTE_OPTION_LEN, sizeof(dLen));
253 memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
254 count += sizeof(sLen);
257 memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
259 OIC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]",
260 *((uint32_t *)endpoint->routeData), sLen);
262 count += GATEWAY_ID_LENGTH;
264 if (GATEWAY_ID_LENGTH < sLen)
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)));
274 // Remove route option from header.
275 for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
277 memcpy((*options) + i, (*options)+i+1, sizeof(**options));
279 *numOptions = (*numOptions) - 1;
281 if (0 == *numOptions)
283 // Remove route option.
287 OIC_LOG(DEBUG, TAG, "OUT");
291 void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
293 OIC_LOG(DEBUG, TAG, "IN");
294 RM_NULL_CHECK_VOID(index, TAG, "index");
298 OIC_LOG(INFO, TAG, "No existing options");
302 for (uint32_t i = 0; i < numOptions; i++)
304 OIC_LOG_V(DEBUG, TAG, "Request- optionID: %u", options[i].optionID);
305 if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
307 OIC_LOG_V(INFO, TAG, "Found Option at %d", i);
312 OIC_LOG(DEBUG, TAG, "OUT");
315 OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
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");
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);
326 OIC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
328 unsigned int totalLength = 0;
329 uint8_t *tempData = NULL;
331 if (0 == dLen && 0 == sLen)
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)
338 OIC_LOG(ERROR, RM_TAG, "Calloc failed");
339 return OC_STACK_NO_MEMORY;
342 if (ACK == optValue->msgType)
344 OIC_LOG(DEBUG, RM_TAG, "OptValue ACK Message Type");
345 memset(tempData, ACK_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
347 else if (RST == optValue->msgType)
349 OIC_LOG(DEBUG, RM_TAG, "OptValue RST Message Type");
350 memset(tempData, RST_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
354 OIC_LOG(DEBUG, RM_TAG, "OptValue NOR Message Type");
355 memset(tempData, NORMAL_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
360 totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
361 tempData = OICCalloc(totalLength, sizeof(char));
362 if (NULL == tempData)
364 OIC_LOG(ERROR, RM_TAG, "Calloc failed");
365 return OC_STACK_NO_MEMORY;
368 if (ACK == optValue->msgType)
370 OIC_LOG(DEBUG, RM_TAG, "OptValue ACK Message Type");
371 memset(tempData, ACK_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
373 else if (RST == optValue->msgType)
375 OIC_LOG(DEBUG, RM_TAG, "OptValue RST Message Type");
376 memset(tempData, RST_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
380 OIC_LOG(DEBUG, RM_TAG, "OptValue NOR Message Type");
381 memset(tempData, NORMAL_MESSAGE_TYPE, DEFAULT_ROUTE_OPTION_LEN);
384 memcpy(tempData + DEFAULT_ROUTE_OPTION_LEN, &dLen, sizeof(dLen));
385 unsigned int count = sizeof(dLen) + DEFAULT_ROUTE_OPTION_LEN;
388 if (optValue->destGw)
390 memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
391 count += GATEWAY_ID_LENGTH;
394 if (optValue->destEp)
396 memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
397 count += ENDPOINT_ID_LENGTH;
401 memcpy(tempData + count, &sLen, sizeof(sLen));
402 count += sizeof(sLen);
407 memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
408 count += GATEWAY_ID_LENGTH;
413 memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
414 count += ENDPOINT_ID_LENGTH;
418 memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
421 memcpy(options->optionData, tempData, totalLength);
423 options->optionID = RM_OPTION_MESSAGE_SWITCHING;
424 options->optionLength = totalLength;
426 OIC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
429 OIC_LOG(DEBUG, RM_TAG, "OUT");
433 OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
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)
440 OIC_LOG(ERROR, RM_TAG, "Option data is not present");
441 return OC_STACK_ERROR;
444 OIC_LOG_V(DEBUG, RM_TAG, "Option Length is %d", options->optionLength);
446 memcpy(&mType, options->optionData, sizeof(mType));
448 if (ACK_MESSAGE_TYPE == mType)
450 OIC_LOG(INFO, RM_TAG, "ACK_MESSAGE_TYPE");
451 optValue->msgType = ACK;
453 else if (RST_MESSAGE_TYPE == mType)
455 OIC_LOG(INFO, RM_TAG, "RST_MESSAGE_TYPE");
456 optValue->msgType = RST;
458 else if (NORMAL_MESSAGE_TYPE == mType)
460 OIC_LOG(INFO, RM_TAG, "NOR_MESSAGE_TYPE");
461 optValue->msgType = NOR;
464 if (DEFAULT_ROUTE_OPTION_LEN == options->optionLength)
466 OIC_LOG(INFO, RM_TAG, "No source and destination are present");
471 uint16_t count = DEFAULT_ROUTE_OPTION_LEN;
472 memcpy(&dLen, options->optionData + count, sizeof(dLen));
473 count += sizeof(dLen);
476 memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
477 count += GATEWAY_ID_LENGTH;
479 if (GATEWAY_ID_LENGTH < dLen)
481 memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
482 count += ENDPOINT_ID_LENGTH;
487 memcpy(&sLen, options->optionData + count, sizeof(sLen));
488 count += sizeof(sLen);
491 memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
492 count += GATEWAY_ID_LENGTH;
494 if (GATEWAY_ID_LENGTH < sLen)
496 memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
497 count += ENDPOINT_ID_LENGTH;
500 memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
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");