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 * Minimum routing option data length is
40 * length of src address(1byte) + length of destination address(1byte) +
41 * Seq Num(2bytes) + Msg Type(1 bytes)
43 #define MIN_ROUTE_OPTION_LEN 5
48 static OCMode g_rmStackMode = OC_CLIENT;
50 void RMSetStackMode(OCMode mode)
55 // destination and source are <GatewayId><ClientId> here, where ClientId is optional.
56 OCStackResult RMAddInfo(const char *destination, void *message, bool isRequest,
59 OIC_LOG(DEBUG, TAG, "IN");
60 RM_NULL_CHECK_WITH_RET(message, TAG, "options");
62 CAHeaderOption_t **options = NULL;
63 uint8_t *numOptions = NULL;
67 CARequestInfo_t *requestMsg = message;
68 options = &(requestMsg->info.options);
69 RM_NULL_CHECK_WITH_RET(options, TAG, "options");
70 numOptions = &(requestMsg->info.numOptions);
71 RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
75 CAResponseInfo_t *respMsg = message;
76 if ('\0' == destination[0] && (CA_EMPTY == respMsg->result))
78 OIC_LOG(DEBUG, TAG, "Response is for an Endpoint, No need to add the routing Option");
81 options = &(respMsg->info.options);
82 RM_NULL_CHECK_WITH_RET(options, TAG, "options");
83 numOptions = &(respMsg->info.numOptions);
84 RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
88 CAHeaderOption_t *optionPtr = NULL;
91 RMGetRouteOptionIndex(*options, *numOptions, &index);
95 OIC_LOG(INFO, TAG, "Route option is present");
100 OIC_LOG(INFO, TAG, "Route option is not present");
102 optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
105 OIC_LOG(ERROR, TAG, "OICCalloc failed");
106 return OC_STACK_NO_MEMORY;
109 memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
112 OCStackResult res = OC_STACK_OK;
113 RMRouteOption_t routeOption = {.destGw = 0};
114 if (*numOptions != index)
116 OIC_LOG(INFO, TAG, "Route option is already present");
117 res = RMParseRouteOption(&optionPtr[index], &routeOption);
118 if (OC_STACK_OK != res)
120 OIC_LOG(ERROR, TAG, "RMParseRouteOption failed");
121 return OC_STACK_ERROR;
127 CAResponseInfo_t *respMsg = message;
128 if (CA_EMPTY == respMsg->result && CA_MSG_ACKNOWLEDGE == respMsg->info.type)
130 OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH ACKNOWLEDGEMENT");
131 routeOption.msgType = ACK;
132 if (OC_SERVER == g_rmStackMode)
134 OIC_LOG(DEBUG, TAG, "This is server mode");
135 // Send the Empty message in the response with adding the MSGType in Route option.
136 respMsg->info.type = CA_MSG_NONCONFIRM;
137 respMsg->result = CA_CONTENT;
141 OIC_LOG(DEBUG, TAG, "Send a POST request");
148 else if (CA_EMPTY == respMsg->result && CA_MSG_RESET == respMsg->info.type)
150 OIC_LOG(DEBUG, TAG, "CA_EMPTY WITH RESET");
151 routeOption.msgType = RST;
152 respMsg->info.type = CA_MSG_NONCONFIRM;
153 respMsg->result = CA_CONTENT;
159 memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
160 memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
161 sizeof(routeOption.destEp));
164 #ifdef ROUTING_GATEWAY
165 // A gateway is supposed to add its ID as source.
166 uint32_t gatewayId = RMGetGatewayId();
169 memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
172 if(!routeOption.destGw)
174 routeOption.mSeqNum = RMGetMcastSeqNumber();
178 res = RMCreateRouteOption(&routeOption, optionPtr + index);
179 if (OC_STACK_OK != res)
181 OIC_LOG(ERROR, TAG, "Creation of routing option failed");
186 if ((*numOptions) == index )
188 (*numOptions) = (*numOptions) + 1;
190 *options = optionPtr;
193 OIC_LOG(DEBUG, TAG, "OUT");
197 OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
198 CAEndpoint_t *endpoint)
200 OIC_LOG(DEBUG, TAG, "IN");
201 RM_NULL_CHECK_WITH_RET(options, TAG, "options");
202 RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option");
203 RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
204 RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint");
206 if (0 >= *numOptions)
208 OIC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
209 return OC_STACK_ERROR;
212 int8_t routeIndex = -1;
213 RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
215 if (-1 >= routeIndex)
217 OIC_LOG(DEBUG, TAG, "Nothing to remove.");
221 // Update Endpoint with source address from RM header option.
222 if (0 != (*options + routeIndex)->optionLength)
225 uint16_t count = sizeof(dLen);
226 memcpy(&dLen, (*options + routeIndex)->optionData, sizeof(dLen));
229 memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
230 count += sizeof(sLen);
233 memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
235 OIC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]",
236 *((uint32_t *)endpoint->routeData), sLen);
238 count += GATEWAY_ID_LENGTH;
240 if (GATEWAY_ID_LENGTH < sLen)
242 memcpy(endpoint->routeData + GATEWAY_ID_LENGTH,
243 (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH);
244 OIC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint",
245 *((uint16_t *)(endpoint->routeData + GATEWAY_ID_LENGTH)));
250 // Remove route option from header.
251 for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
253 memcpy((*options) + i, (*options)+i+1, sizeof(**options));
255 *numOptions = (*numOptions) - 1;
257 if (0 == *numOptions)
259 // Remove route option.
263 OIC_LOG(DEBUG, TAG, "OUT");
267 void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
269 OIC_LOG(DEBUG, TAG, "IN");
270 RM_NULL_CHECK_VOID(options, TAG, "options");
271 RM_NULL_CHECK_VOID(index, TAG, "index");
272 for (uint32_t i = 0; i < numOptions; i++)
274 OIC_LOG_V(DEBUG, TAG, "Request- optionID: %u", options[i].optionID);
275 if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
277 OIC_LOG_V(INFO, TAG, "Found Option at %d", i);
282 OIC_LOG(DEBUG, TAG, "OUT");
285 OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
287 OIC_LOG(DEBUG, RM_TAG, "IN");
288 RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
289 RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
291 uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) +
292 (optValue->destEp ? ENDPOINT_ID_LENGTH:0);
293 uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) +
294 (optValue->srcEp ? ENDPOINT_ID_LENGTH:0);
296 OIC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
297 unsigned int totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
298 void *tempData = OICCalloc(totalLength, sizeof(char));
299 if (NULL == tempData)
301 OIC_LOG(ERROR, RM_TAG, "Calloc failed");
302 return OC_STACK_NO_MEMORY;
304 memcpy(tempData, &dLen, sizeof(dLen));
305 unsigned int count = sizeof(dLen);
308 if (optValue->destGw)
310 memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
311 count += GATEWAY_ID_LENGTH;
314 if (optValue->destEp)
316 memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
317 count += ENDPOINT_ID_LENGTH;
321 memcpy(tempData + count, &sLen, sizeof(sLen));
322 count += sizeof(sLen);
327 memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
328 count += GATEWAY_ID_LENGTH;
333 memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
334 count += ENDPOINT_ID_LENGTH;
338 memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
339 count += sizeof(optValue->mSeqNum);
340 memcpy(tempData + count, &optValue->msgType, sizeof(optValue->msgType));
341 memcpy(options->optionData, tempData, totalLength);
343 options->optionID = RM_OPTION_MESSAGE_SWITCHING;
344 options->optionLength = totalLength;
346 OIC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
349 OIC_LOG(DEBUG, RM_TAG, "OUT");
353 OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
355 OIC_LOG(DEBUG, RM_TAG, "IN");
356 RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
357 RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
358 if (0 == options->optionLength)
360 OIC_LOG(ERROR, RM_TAG, "Option data is not present");
361 return OC_STACK_ERROR;
365 uint16_t count = sizeof(dLen);
366 memcpy(&dLen, options->optionData, sizeof(dLen));
369 memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
370 count += GATEWAY_ID_LENGTH;
372 if (GATEWAY_ID_LENGTH < dLen)
374 memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
375 count += ENDPOINT_ID_LENGTH;
380 memcpy(&sLen, options->optionData + count, sizeof(sLen));
381 count += sizeof(sLen);
384 memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
385 count += GATEWAY_ID_LENGTH;
387 if (GATEWAY_ID_LENGTH < sLen)
389 memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
390 count += ENDPOINT_ID_LENGTH;
393 memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
394 count += sizeof(optValue->mSeqNum);
395 memcpy(&optValue->msgType, options->optionData + count, sizeof(optValue->msgType));
397 OIC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum);
398 OIC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp);
399 OIC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp);
400 OIC_LOG_V(INFO, RM_TAG, "Message Type is [%u]", optValue->msgType);
401 OIC_LOG(DEBUG, RM_TAG, "OUT");