OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue) { OIC_LOG(DEBUG, RM_TAG, "IN"); RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options"); RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue"); if (0 == options->optionLength) { OIC_LOG(ERROR, RM_TAG, "Option data is not present"); return OC_STACK_ERROR; } uint8_t dLen = 0 ; uint16_t count = sizeof(dLen); memcpy(&dLen, options->optionData, sizeof(dLen)); if (0 < dLen) { memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH); count += GATEWAY_ID_LENGTH; if (GATEWAY_ID_LENGTH < dLen) { memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH); count += ENDPOINT_ID_LENGTH; } } uint8_t sLen = 0; memcpy(&sLen, options->optionData + count, sizeof(sLen)); count += sizeof(sLen); if (0 < sLen) { memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH); count += GATEWAY_ID_LENGTH; if (GATEWAY_ID_LENGTH < sLen) { memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH); count += ENDPOINT_ID_LENGTH; } } memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum)); OIC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum); OIC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp); OIC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp); OIC_LOG(DEBUG, RM_TAG, "OUT"); return OC_STACK_OK; }
OCStackResult RMHandleGatewayRequest(OCServerRequest *request, const OCResource *resource) { OIC_LOG(DEBUG, TAG, "RMHandleGatewayRequest IN"); if (!g_isRMInitialized) { OIC_LOG(ERROR, TAG, "RM not initialized"); return OC_STACK_ERROR; } RM_NULL_CHECK_WITH_RET(request, TAG, "request"); RM_NULL_CHECK_WITH_RET(resource, TAG, "resource"); OIC_LOG_V(DEBUG, TAG, "Received request of method: %d", request->method); if (OC_REST_GET == request->method) { switch((OCObserveAction)request->observationOption) { case OC_OBSERVE_REGISTER: OIC_LOG(DEBUG, TAG, "Received OBSERVE request"); RMHandleOBSERVERequest(request, resource); break; case OC_OBSERVE_DEREGISTER: //TODO: Handle this case OIC_LOG(DEBUG, TAG, "Received OBSERVE deregister"); break; case OC_OBSERVE_NO_OPTION: OIC_LOG(DEBUG, TAG, "Received GET request"); RMHandleGETRequest(request, resource); break; default: OIC_LOG(DEBUG, TAG, "Not Supported by Routing Manager"); } } else if (OC_REST_DELETE == request->method) { OIC_LOG(DEBUG, TAG, "Received a Delete request"); RMHandleDELETERequest(request, resource); } OIC_LOG(DEBUG, TAG, "RMHandleGatewayRequest OUT"); return OC_STACK_OK; }
OCStackResult RMHandleRequestPayload(OCDevAddr devAddr, const uint8_t *reqPayload, size_t payloadSize) { OIC_LOG(DEBUG, TAG, "RMHandleRequestPayload IN"); RM_NULL_CHECK_WITH_RET(reqPayload, TAG, "reqPayload"); uint32_t gatewayId = 0; OCStackResult result = RMPParseRequestPayload(reqPayload, payloadSize, &gatewayId); RM_VERIFY_SUCCESS(result, OC_STACK_OK); OIC_LOG(INFO, TAG, "RMPParseRequestPayload is success"); // Check if the entry is its own. if (gatewayId == g_GatewayID) { OIC_LOG(INFO, TAG, "Own Request Received!!"); return OC_STACK_CONTINUE; } CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER}; CopyDevAddrToEndpoint(&devAddr, &endpoint); OIC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId); RTMDestIntfInfo_t destInterfaces = {.observerId = 0}; destInterfaces.destIntfAddr = endpoint; result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable); if (OC_STACK_OK != result) { OIC_LOG(DEBUG, TAG, "Gateway was not added to the routing table"); return result; } OIC_LOG(INFO, TAG, "Gateway was added"); // Create a list to add the updated entries and notify the observers u_linklist_t *updatedTableList = u_linklist_create(); if(!updatedTableList) { OIC_LOG(DEBUG, TAG, "Failure to notify"); return OC_STACK_NO_MEMORY; } RTMGatewayId_t gwId = {.gatewayId = gatewayId}; RTMGatewayEntry_t newNode; newNode.destination = &gwId; newNode.routeCost = 1; u_linklist_add(updatedTableList, (void *)&newNode); RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable); OCRepPayload *updatedPayload = NULL; g_sequenceNumber++; result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, updatedTableList, false, &updatedPayload); if (OC_STACK_OK != result) { OIC_LOG_V(ERROR, TAG, "RMPConstructObserveResPayload failed[%d]", result); RMPFreePayload(updatedPayload); goto exit; } result = RMSendNotificationToAll(updatedPayload); RMPFreePayload(updatedPayload); RM_VERIFY_SUCCESS(result, OC_STACK_OK); exit: u_linklist_free(&updatedTableList); OIC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT"); return result; } OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload) { OIC_LOG(DEBUG, TAG, "RMHandleResponsePayload IN"); RM_NULL_CHECK_WITH_RET(respPayload, TAG, "respPayload"); // Parse the Payload to get the Gateway ID of neighbouring node. uint32_t gatewayId = 0; uint32_t seqNum = 0; u_linklist_t *gatewayTableList = NULL; bool isUpdateSeqNum = false; OCStackResult result = RMPParseResponsePayload(respPayload, &gatewayId, &seqNum, &gatewayTableList, &isUpdateSeqNum); RM_VERIFY_SUCCESS(result, OC_STACK_OK); // Check if the entry is its own. if (gatewayId == g_GatewayID) { OIC_LOG(INFO, TAG, "-------------->Own entry, continue!!"); RTMFreeGatewayRouteTable(&gatewayTableList); return OC_STACK_ERROR; } // Convert OCDevAddr to endpoint address CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS}; CopyDevAddrToEndpoint(devAddr, &endpoint); RTMDestIntfInfo_t destInterfaces = {.observerId = 0}; destInterfaces.destIntfAddr = endpoint; if (0 < seqNum) { OIC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d", seqNum, isUpdateSeqNum); result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces, &g_routingGatewayTable, isUpdateSeqNum); if (OC_STACK_COMM_ERROR == result) { OIC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching"); // Send a observe request to the gateway. RMSendObserveRequest(devAddr, NULL); RTMFreeGatewayRouteTable(&gatewayTableList); return result; } else if (OC_STACK_DUPLICATE_REQUEST == result) { OIC_LOG(ERROR, TAG, "Same sequence number is received"); RTMFreeGatewayRouteTable(&gatewayTableList); return result; } } // Check if the payload is for Removal bool doRemoveEntry = false; if (NULL != gatewayTableList && NULL != gatewayTableList->list) { RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list); if (headPtr && 0 == headPtr->routeCost) { OIC_LOG(INFO, TAG, "Remove entry is called"); doRemoveEntry = true; } } // Create a list to add the updated entries and notify the observers u_linklist_t *updatedTableList = u_linklist_create(); if(!updatedTableList) { OIC_LOG(DEBUG, TAG, "Failed to allocate memory"); return OC_STACK_NO_MEMORY; } u_linklist_t *alternativeRouteList = u_linklist_create(); if(!alternativeRouteList) { OIC_LOG(DEBUG, TAG, "Failed to allocate memory"); return OC_STACK_NO_MEMORY; } OCRepPayload *updatedPayload = NULL; if (false == doRemoveEntry) { OIC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId); result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable); if (OC_STACK_OK == result) { OIC_LOG(INFO, TAG, "Node was added"); RTMGatewayId_t gwId = {.gatewayId = gatewayId}; RTMGatewayEntry_t newNode; newNode.destination = &gwId; newNode.routeCost = 1; u_linklist_add(updatedTableList, (void *)&newNode); RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable); if (NULL == gatewayTableList) { OIC_LOG(INFO, TAG, "Received a Discover Payload"); g_sequenceNumber++; result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, updatedTableList, false, &updatedPayload); RM_VERIFY_SUCCESS(result, OC_STACK_OK); goto sendNotification; } } }
// destination and source are <GatewayId><ClientId> here, where ClientId is optional. OCStackResult RMAddInfo(const char *destination, CAHeaderOption_t **options, uint8_t *numOptions) { OIC_LOG(DEBUG, TAG, "IN"); RM_NULL_CHECK_WITH_RET(options, TAG, "options"); RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions"); CAHeaderOption_t *optionPtr = NULL; int8_t index = -1; RMGetRouteOptionIndex(*options, *numOptions, &index); if (-1 < index) { OIC_LOG(INFO, TAG, "Route option is present"); optionPtr = *options; } else { OIC_LOG(INFO, TAG, "Route option is not present"); index = *numOptions; optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t)); if (!optionPtr) { OIC_LOG(ERROR, TAG, "OICCalloc failed"); return OC_STACK_NO_MEMORY; } memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions)); } OCStackResult res = OC_STACK_OK; RMRouteOption_t routeOption = {.destGw = 0}; if (*numOptions != index) { OIC_LOG(INFO, TAG, "Route option is already present"); res = RMParseRouteOption(&optionPtr[index], &routeOption); if (OC_STACK_OK != res) { OIC_LOG(ERROR, TAG, "RMParseRouteOption failed"); return OC_STACK_ERROR; } } if(destination) { memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw)); memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw), sizeof(routeOption.destEp)); } #ifdef ROUTING_GATEWAY // A gateway is supposed to add its ID as source. uint32_t gatewayId = RMGetGatewayId(); if (gatewayId) { memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw)); } if(!routeOption.destGw) { routeOption.mSeqNum = RMGetMcastSeqNumber(); } #endif res = RMCreateRouteOption(&routeOption, optionPtr + index); if (OC_STACK_OK != res) { OIC_LOG(ERROR, TAG, "Creation of routing option failed"); OICFree(optionPtr); return res; } if ((*numOptions) == index ) { (*numOptions) = (*numOptions) + 1; OICFree(*options); *options = optionPtr; } OIC_LOG(DEBUG, TAG, "OUT"); return OC_STACK_OK; } OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions, CAEndpoint_t *endpoint) { OIC_LOG(DEBUG, TAG, "IN"); RM_NULL_CHECK_WITH_RET(options, TAG, "options"); RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option"); RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions"); RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint"); if (0 >= *numOptions) { OIC_LOG(ERROR, TAG, "Invalid arguement: numOptions"); return OC_STACK_ERROR; } int8_t routeIndex = -1; RMGetRouteOptionIndex(*options, *numOptions, &routeIndex); if (-1 >= routeIndex) { OIC_LOG(DEBUG, TAG, "Nothing to remove."); return OC_STACK_OK; } // Update Endpoint with source address from RM header option. if (0 != (*options + routeIndex)->optionLength) { uint8_t dLen = 0; uint16_t count = sizeof(dLen); memcpy(&dLen, (*options + routeIndex)->optionData, sizeof(dLen)); count += dLen; uint8_t sLen = 0; memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen)); count += sizeof(sLen); if (0 < sLen) { memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count, GATEWAY_ID_LENGTH); OIC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]", *((uint32_t *)endpoint->routeData), sLen); count += GATEWAY_ID_LENGTH; if (GATEWAY_ID_LENGTH < sLen) { memcpy(endpoint->routeData + GATEWAY_ID_LENGTH, (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH); OIC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint", *((uint16_t *)(endpoint->routeData + GATEWAY_ID_LENGTH))); } } } // Remove route option from header. for (uint8_t i = routeIndex; i < (*numOptions)-1; i++) { memcpy((*options) + i, (*options)+i+1, sizeof(**options)); } *numOptions = (*numOptions) - 1; if (0 == *numOptions) { // Remove route option. OICFree(*options); *options = NULL; } OIC_LOG(DEBUG, TAG, "OUT"); return OC_STACK_OK; }
OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options) { OIC_LOG(DEBUG, RM_TAG, "IN"); RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue"); RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options"); uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) + (optValue->destEp ? ENDPOINT_ID_LENGTH:0); uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) + (optValue->srcEp ? ENDPOINT_ID_LENGTH:0); OIC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen); unsigned int totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen; void *tempData = OICCalloc(totalLength, sizeof(char)); if (NULL == tempData) { OIC_LOG(ERROR, RM_TAG, "Calloc failed"); return OC_STACK_NO_MEMORY; } memcpy(tempData, &dLen, sizeof(dLen)); unsigned int count = sizeof(dLen); if (0 < dLen) { if (optValue->destGw) { memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH); count += GATEWAY_ID_LENGTH; } if (optValue->destEp) { memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH); count += ENDPOINT_ID_LENGTH; } } memcpy(tempData + count, &sLen, sizeof(sLen)); count += sizeof(sLen); if (0 < sLen) { if (optValue->srcGw) { memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH); count += GATEWAY_ID_LENGTH; } if (optValue->srcEp) { memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH); count += ENDPOINT_ID_LENGTH; } } memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum)); memcpy(options->optionData, tempData, totalLength); options->optionID = RM_OPTION_MESSAGE_SWITCHING; options->optionLength = totalLength; OIC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength); OICFree(tempData); OIC_LOG(DEBUG, RM_TAG, "OUT"); return OC_STACK_OK; }