// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License./*** @file IPLocator.cpp**/#include <cstdint>#include <cstring>#include <exception>#include <regex>#include <set>#include <string>#include <asio.hpp>#include <fastdds/dds/log/Log.hpp>#include <fastdds/rtps/common/Types.hpp>#include <fastdds/rtps/common/Locator.hpp>#include <fastdds/utils/IPLocator.hpp>#include <fastdds/utils/IPFinder.hpp>#include <rtps/transport/shared_mem/SHMLocator.hpp>namespace eprosima {namespace fastdds {namespace rtps {static const std::regex IPv4_REGEX("^(?:(?:0*25[0-5]|0*2[0-4][0-9]|0*[01]?[0-9][0-9]?)\\.){3}""(?:0*25[0-5]|0*2[0-4][0-9]|0*[01]?[0-9][0-9]?)$");static const std::regex IPv6_QUARTET_REGEX("^(?:[A-Fa-f0-9]){0,4}$");static const std::regex ETHERNET_REGEX("^([0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5})$");Locator Locator::create_locator(int32_t kind,const std::string& address,uint32_t port){SHMLocator::Type shm_type = SHMLocator::Type::UNICAST;Locator locator;locator.kind = LOCATOR_KIND_INVALID;locator.set_Invalid_Address();locator.port = 0;switch (kind){case LOCATOR_KIND_TCPv4:case LOCATOR_KIND_UDPv4:case LOCATOR_KIND_TCPv6:case LOCATOR_KIND_UDPv6:IPLocator::createLocator(kind, address, port, locator);break;case LOCATOR_KIND_SHM:shm_type = address == "M" ? SHMLocator::Type::MULTICAST : SHMLocator::Type::UNICAST;locator = SHMLocator::create_locator(port, shm_type);break;case LOCATOR_KIND_ETHERNET:if (std::regex_match(address, ETHERNET_REGEX)){locator.kind = LOCATOR_KIND_ETHERNET;locator.port = port;locator.address[0] = 0xFF;for (size_t i = 0; i < 6; ++i){std::string byte_string = address.substr(i * 3, 2);try{locator.address[10 + i] = static_cast<octet>(std::stoul(byte_string, nullptr, 16));}catch (const std::exception&){EPROSIMA_LOG_WARNING(IP_LOCATOR,"Ethernet address " << address << " error format. Expected XX:XX:XX:XX:XX:XX");locator.kind = LOCATOR_KIND_INVALID;locator.port = 0;LOCATOR_ADDRESS_INVALID(locator.address);break;}}}else{EPROSIMA_LOG_WARNING(IP_LOCATOR,"Ethernet address " << address << " error format. Expected XX:XX:XX:XX:XX:XX");locator.kind = LOCATOR_KIND_INVALID;locator.port = 0;LOCATOR_ADDRESS_INVALID(locator.address);}break;default:EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to create a locator with unsupported kind: " << kind);break;}return locator;}// Factoryvoid IPLocator::createLocator(int32_t kindin,const std::string& address,uint32_t portin,Locator_t& locator){locator.kind = kindin;locator.port = portin;LOCATOR_ADDRESS_INVALID(locator.address);switch (kindin){case LOCATOR_KIND_TCPv4:case LOCATOR_KIND_UDPv4:{setIPv4(locator, address);break;}case LOCATOR_KIND_TCPv6:case LOCATOR_KIND_UDPv6:{setIPv6(locator, address);break;}}}// IPv4bool IPLocator::setIPv4(Locator_t& locator,const unsigned char* addr){if (locator.kind != LOCATOR_KIND_TCPv4 && locator.kind != LOCATOR_KIND_UDPv4){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv4 in a non IPv4 Locator");return false;}memcpy(&locator.address[12], addr, 4 * sizeof(char));return true;}bool IPLocator::setIPv4(Locator_t& locator,octet o1,octet o2,octet o3,octet o4){if (locator.kind != LOCATOR_KIND_TCPv4 && locator.kind != LOCATOR_KIND_UDPv4){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv4 in a non IPv4 Locator");return false;}locator.address[12] = o1;locator.address[13] = o2;locator.address[14] = o3;locator.address[15] = o4;return true;}bool IPLocator::setIPv4(Locator_t& locator,const std::string& ipv4){if (locator.kind != LOCATOR_KIND_TCPv4 && locator.kind != LOCATOR_KIND_UDPv4){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv4 in a non IPv4 Locator");return false;}// This function do not set address to 0 in case it fails// Be careful, do not set all IP to 0 because WAN and LAN could be set beforehandstd::string s(ipv4);if (!IPLocator::isIPv4(s)){// Attempt DNS resolutionauto response = IPLocator::resolveNameDNS(s);// Use the first valid IPv4 address that we can findif (response.first.size() > 0){s = response.first.begin()->data();// Redundant check for extra security (here a custom regex is used instead of asio's verification)if (!IPLocator::isIPv4(s)){EPROSIMA_LOG_WARNING(IP_LOCATOR, "DNS name [" << ipv4 << "] resolved into wrong IPv4 format: " << s);return false;}}else{EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name");return false;}}std::stringstream ss(s);uint32_t a;uint32_t b;uint32_t c;uint32_t d; //to store the 4 intschar ch; //to temporarily store the '.'if (ss >> a >> ch >> b >> ch >> c >> ch >> d){if (a > 255 || b > 255 || c > 255 || d > 255){return false;}locator.address[12] = (octet)a;locator.address[13] = (octet)b;locator.address[14] = (octet)c;locator.address[15] = (octet)d;// If there are more info to read, it failsreturn ss.rdbuf()->in_avail() == 0;}EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name");return false;}bool IPLocator::setIPv4(Locator_t& destlocator,const Locator_t& origlocator){if (destlocator.kind != LOCATOR_KIND_TCPv4 && destlocator.kind != LOCATOR_KIND_UDPv4){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv4 in a non IPv4 Locator");return false;}return setIPv4(destlocator, getIPv4(origlocator));}const octet* IPLocator::getIPv4(const Locator_t& locator){return static_cast<const octet*>(&locator.address[12]);}bool IPLocator::hasIPv4(const Locator_t& locator){if (!(locator.kind == LOCATOR_KIND_UDPv4 || locator.kind == LOCATOR_KIND_TCPv4)){return false;}return !(isEmpty(locator));}std::string IPLocator::toIPv4string(const Locator_t& locator){std::stringstream ss;ss << (int)locator.address[12] << "."<< (int)locator.address[13] << "."<< (int)locator.address[14] << "."<< (int)locator.address[15];return ss.str();}bool IPLocator::copyIPv4(const Locator_t& locator,unsigned char* dest){memcpy(dest, &(locator.address[12]), 4 * sizeof(char));return true;}bool IPLocator::copyIPv4(const Locator_t& locator,Locator_t& dest){return copyIPv4(locator, &(dest.address[12]));}// IPv6bool IPLocator::setIPv6(Locator_t& locator,const unsigned char* addr){if (locator.kind != LOCATOR_KIND_TCPv6 && locator.kind != LOCATOR_KIND_UDPv6){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv6 in a non IPv6 Locator");return false;}memcpy(locator.address, addr, 16 * sizeof(char));return true;}bool IPLocator::setIPv6(Locator_t& locator,uint16_t group0,uint16_t group1,uint16_t group2,uint16_t group3,uint16_t group4,uint16_t group5,uint16_t group6,uint16_t group7){if (locator.kind != LOCATOR_KIND_TCPv6 && locator.kind != LOCATOR_KIND_UDPv6){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv6 in a non IPv6 Locator");return false;}locator.address[0] = (octet)(group0 >> 8);locator.address[1] = (octet)group0;locator.address[2] = (octet)(group1 >> 8);locator.address[3] = (octet)group1;locator.address[4] = (octet)(group2 >> 8);locator.address[5] = (octet)group2;locator.address[6] = (octet)(group3 >> 8);locator.address[7] = (octet)group3;locator.address[8] = (octet)(group4 >> 8);locator.address[9] = (octet)group4;locator.address[10] = (octet)(group5 >> 8);locator.address[11] = (octet)group5;locator.address[12] = (octet)(group6 >> 8);locator.address[13] = (octet)group6;locator.address[14] = (octet)(group7 >> 8);locator.address[15] = (octet)group7;return true;}bool IPLocator::setIPv6(Locator_t& locator,const std::string& ipv6){/* An IPv6 must contain 16 bytes of information* These bytes are given by a string of 8 numbers of 4 digits in hexadecimal format separed by ':'* The string to store this info is not unique, as it could be transform in two different ways:* 1. Erasing leading zeros forwarding each number* 00X = X* 2. Encapsulating following blocks of zeros as leaving empty an space* X:0000:0000:Y = X::Y** This function implements the following:* 1. Check if the string is in correct format : IPv6isCorrect* 2. Analyze the string to know if:* - it starts with blocks of zeros* - it ends with blocks of zeros* - it has blocks of zeros in the middle* and it stores the size of the zeros block to build the address afterwards* 3. Build the bytes array by reading the string or either filling with 0 the zero blocks* */if (locator.kind != LOCATOR_KIND_TCPv6 && locator.kind != LOCATOR_KIND_UDPv6){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv6 in a non IPv6 Locator");return false;}std::string s(ipv6);if (!IPLocator::isIPv6(s)){// Attempt DNS resolutionauto response = IPLocator::resolveNameDNS(s);// Use the first valid IPv6 address that we can findif (response.second.size() > 0){s = response.second.begin()->data();// Redundant check for extra security (here a custom regex is used instead of asio's verification)if (!IPLocator::isIPv6(s)){EPROSIMA_LOG_WARNING(IP_LOCATOR, "DNS name [" << ipv6 << "] resolved into wrong IPv6 format: " << s);return false;}}else{EPROSIMA_LOG_WARNING(IP_LOCATOR,"IPv6 " << s << " error format. Expected well defined address or valid DNS name");return false;}}LOCATOR_ADDRESS_INVALID(locator.address);uint16_t count = (uint16_t) std::count_if( s.begin(), s.end(), []( char c ){return c == ':';}); // C type cast to avoid Windows warningsuint16_t initial_zeros = 0;uint16_t final_zeros = 0;uint16_t position_zeros = 0;uint16_t number_zeros = 0;size_t aux;size_t aux_prev; // This must be size_t as string::npos could change value depending on size_t size// Check whether is a zero block and whereif (s.front() == ':'){// First element equal : -> starts with zerosif (s.back() == ':'){// Empty string (correct ipv6 format)initial_zeros = 16;}else{// Calculate number of 0 blocks by the number of ':'// 2 ':' at the beginning => - 2// 7 std : => 7 - count// 2 bytes per string => * 2initial_zeros = (7 - (count - 2)) * 2;}}else if (s.back() == ':'){// Last element equal : -> ends with zeros// It does not start with :: (previous if)final_zeros = (7 - (count - 2)) * 2;}else{// It does not starts or ends with zeros, but it could have :: in the middle or not have itaux_prev = s.size(); // Aux could be 1 so this number must be unreacheableaux = s.find(':'); // Index of first ':'// Look for "::" will loop string twice// Therefore, we use this loop that will go over less or equal oncewhile (aux != std::string::npos){if (aux_prev == aux - 1){// Found "::"". Store the size of the blocknumber_zeros = (7 - (count - 1)) * 2;break;}// Not "::" found, keep searching in next ':'position_zeros += 2; // It stores the point where the 0 block isaux_prev = aux;aux = s.find(':', aux + 1);}}char punct;std::stringstream ss;ss << std::hex << s;uint16_t i;uint32_t input_aux; // It cannot be uint16_t or we could not find whether the input number is bigger than allowed// Build the bytes string knowing already if there is a zero block, where and which sizeif (initial_zeros != 0){// Zero block at the begginningfor (i = 0; i < initial_zeros;){locator.address[i++] = 0;}ss >> punct;for (; i < 16;){ss >> punct >> input_aux;if (input_aux >= 65536){EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)");return false;}locator.address[i++] = octet(input_aux >> 8);locator.address[i++] = octet(input_aux & 0xFF);}// In the case of empty ip it would be still a ':' without parsingif (initial_zeros == 16){ss >> punct;}}else if (final_zeros != 0){// Zero block at the endfor (i = 0; i < 16 - final_zeros;){ss >> input_aux >> punct;if (input_aux >= 65536){EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)");return false;}locator.address[i++] = octet(input_aux >> 8);locator.address[i++] = octet(input_aux & 0xFF);}ss >> punct;for (; i < 16;){locator.address[i++] = 0;}}else if (number_zeros != 0){// Zero block in the middlefor (i = 0; i < position_zeros;){ss >> input_aux >> punct;if (input_aux >= 65536){EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)");return false;}locator.address[i++] = octet(input_aux >> 8);locator.address[i++] = octet(input_aux & 0xFF);}for (; i < position_zeros + number_zeros;){locator.address[i++] = 0;}for (; i < 16;){ss >> punct >> input_aux;if (input_aux >= 65536){EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)");return false;}locator.address[i++] = octet(input_aux >> 8);locator.address[i++] = octet(input_aux & 0xFF);}}else{// No zero blockss >> input_aux;locator.address[0] = octet(input_aux >> 8);locator.address[1] = octet(input_aux & 0xFF);for (i = 2; i < 16;){ss >> punct >> input_aux;if (input_aux >= 65536){EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv6 " << s << " has values higher than expected (65536)");return false;}locator.address[i++] = octet(input_aux >> 8);locator.address[i++] = octet(input_aux & 0xFF);}}return ss.rdbuf()->in_avail() == 0;}bool IPLocator::setIPv6(Locator_t& destlocator,const Locator_t& origlocator){if (destlocator.kind != LOCATOR_KIND_TCPv6 && destlocator.kind != LOCATOR_KIND_UDPv6){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set an IPv6 in a non IPv6 Locator");return false;}return setIPv6(destlocator, getIPv6(origlocator));}const octet* IPLocator::getIPv6(const Locator_t& locator){return locator.address;}bool IPLocator::hasIPv6(const Locator_t& locator){if (!(locator.kind == LOCATOR_KIND_UDPv6 || locator.kind == LOCATOR_KIND_TCPv6)){return false;}return !(isEmpty(locator));}std::string IPLocator::toIPv6string(const Locator_t& locator){/* RFC 5952 Recommendation* 4.1 No leading zeros before each block* 4.2.1 Shorten as much as possible (do not leave 0 blocks at sides of ::)* 4.2.2 No collapse size 1 blocks* 4.2.3 Collapse the largest block (or the first one in case of tie)* 4.3 Lowercase*/int max_block_index = 0;int max_block_size = 0;int actual_block_index = 0;int actual_block_size = 0;// 4.1, 4.3 By default using << std::hexstd::stringstream ss;ss << std::hex;bool compress = false;// First calculate if any 0 block must be collapsed and which onefor (int i = 0; i != 16; i += 2){if (locator.address[i] == 0 && locator.address[i + 1] == 0){// 4.2.1 Shorten if it has already shortened the previous blockif (compress){++actual_block_size;}else{compress = true;actual_block_index = i;actual_block_size = 1;}}else{if (compress){compress = false;// 4.2.3 Choose the largest blockif (actual_block_size > max_block_size){max_block_index = actual_block_index;max_block_size = actual_block_size;}}}}// In case the last block is the one to compressif (compress && actual_block_size > max_block_size){max_block_index = actual_block_index;max_block_size = actual_block_size;}// Use compress variable to know if there will be compression// 4.2.2 compress only if block size > 1compress = max_block_size >= 2;// Case that first block is compressedif (compress && max_block_index == 0){ss << ":";}for (int i = 0; i != 16; i += 2){// If it is after compress index and not all blocks has been compressed, compress itif (compress && i >= max_block_index && max_block_size > 0){// Reduce number of blocks to compress--max_block_size;// Last block prints second :if (max_block_size == 0){ss << ":";}continue;}// Stream the following blockauto field = (locator.address[i] << 8) + locator.address[i + 1];if (i != 14){ss << field << ":";}else{ss << field;}}return ss.str();}bool IPLocator::copyIPv6(const Locator_t& locator,unsigned char* dest){memcpy(dest, locator.address, 16 * sizeof(char));return true;}// Abstract from IPv4 and IPv6bool IPLocator::ip(Locator_t& locator,const std::string& ip){if (locator.kind == LOCATOR_KIND_TCPv4 ||locator.kind == LOCATOR_KIND_UDPv4){return setIPv4(locator, ip);}else if (locator.kind == LOCATOR_KIND_TCPv6 ||locator.kind == LOCATOR_KIND_UDPv6){return setIPv6(locator, ip);}return false;}std::string IPLocator::ip_to_string(const Locator_t& locator){if (locator.kind == LOCATOR_KIND_TCPv4 ||locator.kind == LOCATOR_KIND_UDPv4){return toIPv4string(locator);}else if (locator.kind == LOCATOR_KIND_TCPv6 ||locator.kind == LOCATOR_KIND_UDPv6){return toIPv6string(locator);}return "";}// TCPbool IPLocator::setLogicalPort(Locator_t& locator,uint16_t port){uint16_t* loc_logical = reinterpret_cast<uint16_t*>(&locator.port);#if FASTDDS_IS_BIG_ENDIAN_TARGETloc_logical[0] = port; // Logical port is stored at 0th and 1st bytes of port#elseloc_logical[1] = port; // Logical port is stored at 2nd and 3rd bytes of port#endif // if FASTDDS_IS_BIG_ENDIAN_TARGETreturn port != 0;}uint16_t IPLocator::getLogicalPort(const Locator_t& locator){const uint16_t* loc_logical = reinterpret_cast<const uint16_t*>(&locator.port);#if FASTDDS_IS_BIG_ENDIAN_TARGETreturn loc_logical[0];#elsereturn loc_logical[1];#endif // if FASTDDS_IS_BIG_ENDIAN_TARGET}bool IPLocator::setPhysicalPort(Locator_t& locator,uint16_t port){uint16_t* loc_physical = reinterpret_cast<uint16_t*>(&locator.port);#if FASTDDS_IS_BIG_ENDIAN_TARGETloc_physical[1] = port; // Physical port is stored at 0 and 1st bytes of port#elseloc_physical[0] = port; // Physical port is stored at 0 and 1st bytes of port#endif // if FASTDDS_IS_BIG_ENDIAN_TARGETreturn port != 0;}uint16_t IPLocator::getPhysicalPort(const Locator_t& locator){const uint16_t* loc_physical = reinterpret_cast<const uint16_t*>(&locator.port);#if FASTDDS_IS_BIG_ENDIAN_TARGETreturn loc_physical[1];#elsereturn loc_physical[0];#endif // if FASTDDS_IS_BIG_ENDIAN_TARGET}// TCPv4bool IPLocator::setWan(Locator_t& locator,octet o1,octet o2,octet o3,octet o4){locator.address[8] = o1;locator.address[9] = o2;locator.address[10] = o3;locator.address[11] = o4;return true;}bool IPLocator::setWan(Locator_t& locator,const std::string& wan){if (locator.kind != LOCATOR_KIND_TCPv4){EPROSIMA_LOG_WARNING(IP_LOCATOR, "Trying to set WAN address in a non TCP-IPv4 Locator");return false;}std::string s(wan);if (!IPLocator::isIPv4(s)){// Attempt DNS resolutionauto response = IPLocator::resolveNameDNS(s);// Use the first valid IPv4 address that we can findif (response.first.size() > 0){s = response.first.begin()->data();// Redundant check for extra security (here a custom regex is used instead of asio's verification)if (!IPLocator::isIPv4(s)){EPROSIMA_LOG_WARNING(IP_LOCATOR, "DNS name [" << wan << "] resolved into wrong IPv4 format: " << s);return false;}}else{EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name");return false;}}std::stringstream ss(s);int a, b, c, d; //to store the 4 intschar ch; //to temporarily store the '.'if ( ss >> a >> ch >> b >> ch >> c >> ch >> d){locator.address[8] = (octet)a;locator.address[9] = (octet)b;locator.address[10] = (octet)c;locator.address[11] = (octet)d;return true;}EPROSIMA_LOG_WARNING(IP_LOCATOR, "IPv4 " << s << " error format. Expected X.X.X.X or valid DNS name");return false;}const octet* IPLocator::getWan(const Locator_t& locator){return static_cast<const octet*>(&locator.address[8]);}bool IPLocator::hasWan(const Locator_t& locator){return locator.kind == LOCATOR_KIND_TCPv4 && // TCPv6 doesn't use WAN(locator.address[8] != 0 ||locator.address[9] != 0 ||locator.address[10] != 0 ||locator.address[11] != 0);}std::string IPLocator::toWanstring(const Locator_t& locator){std::stringstream ss;ss << (int)locator.address[8] << "."<< (int)locator.address[9] << "."<< (int)locator.address[10] << "."<< (int)locator.address[11];return ss.str();}Locator_t IPLocator::WanToLanLocator(const Locator_t& locator){Locator_t out(locator);std::memcpy(out.address + 12, out.address + 8, 4 * sizeof(octet));std::memset(out.address + 8, 0, 4 * sizeof(octet));return out;}bool IPLocator::setLanID(Locator_t& locator,const std::string& lanId){if (locator.kind == LOCATOR_KIND_TCPv4){std::stringstream ss(lanId);int a, b, c, d, e, f, g, h; //to store the 8 intschar ch; //to temporarily store the '.'if ( ss >> a >> ch >> b >> ch >> c >> ch >> d >> ch >> e >> ch >> f >> ch >> g >> ch >> h){locator.address[0] = (octet)a;locator.address[1] = (octet)b;locator.address[2] = (octet)c;locator.address[3] = (octet)d;locator.address[4] = (octet)e;locator.address[5] = (octet)f;locator.address[6] = (octet)g;locator.address[7] = (octet)h;return true;}}return false;}const octet* IPLocator::getLanID(const Locator_t& locator){return static_cast<const octet*>(&locator.address[0]);}std::string IPLocator::toLanIDstring(const Locator_t& locator){if (locator.kind != LOCATOR_KIND_TCPv4){return "";}std::stringstream ss;ss << (int)locator.address[0] << "."<< (int)locator.address[1] << "."<< (int)locator.address[2] << "."<< (int)locator.address[3] << "."<< (int)locator.address[4] << "."<< (int)locator.address[5] << "."<< (int)locator.address[6] << "."<< (int)locator.address[7];return ss.str();}Locator_t IPLocator::toPhysicalLocator(const Locator_t& locator){Locator_t result = locator;setLogicalPort(result, 0);return result;}bool IPLocator::ip_equals_wan(const Locator_t& locator){return hasWan(locator) &&locator.address[8] == locator.address[12] &&locator.address[9] == locator.address[13] &&locator.address[10] == locator.address[14] &&locator.address[11] == locator.address[15];}// Commonbool IPLocator::setPortRTPS(Locator_t& locator,uint16_t port){if (locator.kind == LOCATOR_KIND_UDPv4 || locator.kind == LOCATOR_KIND_UDPv6){return setPhysicalPort(locator, port);}else if (locator.kind == LOCATOR_KIND_TCPv4 || locator.kind == LOCATOR_KIND_TCPv6){return setLogicalPort(locator, port);}return false;}uint16_t IPLocator::getPortRTPS(Locator_t& locator){if (locator.kind == LOCATOR_KIND_UDPv4 || locator.kind == LOCATOR_KIND_UDPv6){return getPhysicalPort(locator);}else if (locator.kind == LOCATOR_KIND_TCPv4 || locator.kind == LOCATOR_KIND_TCPv6){return getLogicalPort(locator);}return 0;}bool IPLocator::isLocal(const Locator_t& locator){if (locator.kind == LOCATOR_KIND_UDPv4|| locator.kind == LOCATOR_KIND_TCPv4){return locator.address[12] == 127&& locator.address[13] == 0&& locator.address[14] == 0&& locator.address[15] == 1;}else{return locator.address[0] == 0&& locator.address[1] == 0&& locator.address[2] == 0&& locator.address[3] == 0&& locator.address[4] == 0&& locator.address[5] == 0&& locator.address[6] == 0&& locator.address[7] == 0&& locator.address[8] == 0&& locator.address[9] == 0&& locator.address[10] == 0&& locator.address[11] == 0&& locator.address[12] == 0&& locator.address[13] == 0&& locator.address[14] == 0&& locator.address[15] == 1;}}bool IPLocator::isAny(const Locator_t& locator){if (locator.kind == LOCATOR_KIND_UDPv4|| locator.kind == LOCATOR_KIND_TCPv4){return locator.address[12] == 0 &&locator.address[13] == 0 &&locator.address[14] == 0 &&locator.address[15] == 0;}else{return locator.address[0] == 0 &&locator.address[1] == 0 &&locator.address[2] == 0 &&locator.address[3] == 0 &&locator.address[4] == 0 &&locator.address[5] == 0 &&locator.address[6] == 0 &&locator.address[7] == 0 &&locator.address[8] == 0 &&locator.address[9] == 0 &&locator.address[10] == 0 &&locator.address[11] == 0 &&locator.address[12] == 0 &&locator.address[13] == 0 &&locator.address[14] == 0 &&locator.address[15] == 0;}}bool IPLocator::compareAddress(const Locator_t& loc1,const Locator_t& loc2,bool fullAddress){if (loc1.kind != loc2.kind){return false;}if (!fullAddress && (loc1.kind == LOCATOR_KIND_UDPv4 || loc1.kind == LOCATOR_KIND_TCPv4)){return memcmp(&loc1.address[12], &loc2.address[12], 4) == 0;}else{return memcmp(loc1.address, loc2.address, 16) == 0;}}bool IPLocator::copy_address(const Locator_t& loc1,Locator_t& loc2){if (loc1.kind != loc2.kind){return false;}if (loc1.kind == LOCATOR_KIND_UDPv4 || loc1.kind == LOCATOR_KIND_TCPv4){copyIPv4(loc1, loc2);return true;}else if (loc1.kind == LOCATOR_KIND_UDPv6 || loc1.kind == LOCATOR_KIND_TCPv6){return copyIPv6(loc1, loc2.address);}return false;}bool IPLocator::compareAddressAndPhysicalPort(const Locator_t& loc1,const Locator_t& loc2){return compareAddress(loc1, loc2, true) && (getPhysicalPort(loc1) == getPhysicalPort(loc2));}std::string IPLocator::to_string(const Locator_t& loc){std::stringstream ss;ss << loc;return ss.str();}// UDPbool IPLocator::isMulticast(const Locator_t& locator){if (locator.kind == LOCATOR_KIND_TCPv4|| locator.kind == LOCATOR_KIND_TCPv6){return false;}if (locator.kind == LOCATOR_KIND_UDPv4){return locator.address[12] >= 224 &&locator.address[12] <= 239;}else{return locator.address[0] == 0xFF;}}bool IPLocator::isEmpty(const Locator_t& locator){switch (locator.kind){case LOCATOR_KIND_TCPv4:case LOCATOR_KIND_UDPv4:{return IPLocator::isEmpty(locator, 12);}default:{return IPLocator::isEmpty(locator, 0);}}}bool IPLocator::isEmpty(const Locator_t& locator,uint16_t index){Locator_t aux_locator;LOCATOR_INVALID(aux_locator);for (int i = index; i < 16; ++i){if (locator.address[i] != aux_locator.address[i]){return false;}}return true;}bool IPLocator::IPv6isCorrect(const std::string& ipv6){// IPv6 addresses may have the interface ID added as in 'fe80::92f0:f536:e3cc:11c6%wlp2s0'std::string::size_type pos;pos = ipv6.find('%');std::string address = ipv6.substr(0, pos);/* An incorrect IPv6 format could be because:* 1. it has not ':' - bad format* 2. it has just one ':' - not enough info* 3. it has more than 8 ':' - too much info* 4. it has 8 ':' - it could only happen if it starts or ends with "::", if not is too much bytes* 5. it has more than one "::" - impossible to build the ip because unknown size of zero blocks* 6. it starts with ':' - it must be doble ("::") - bad format* 7. it ends with ':' - it must be doble ("::") - bad format* */std::ptrdiff_t count = std::count_if( address.begin(), address.end(), []( char c ){return c == ':';});// proper number of :if (count < 2 || count > 8){return false;}// only case of 8 : is with a :: at the beginning or endif (count == 8 && (address.front() != ':' && address.back() != ':')){return false;}// only one :: is allowedsize_t ind = address.find("::");if (ind != std::string::npos){if (address.find("::", ind + 1) != std::string::npos){return false;}}// does not start with only one ':'if (address.front() == ':' && address.at(1) != ':'){return false;}// does not end with only one ':'if (address.back() == ':' && address.at(address.size() - 2) != ':'){return false;}// every number inside must not exceed ffff// do not accept any IPv6 with non valid charactersstd::stringstream s(address);// If we counted X ':', we have to process X+1 quartetswhile (count-- >= 0){std::stringbuf sb_value;char punct;s.get(sb_value, ':');if (!std::regex_match(sb_value.str(), IPv6_QUARTET_REGEX)){return false;}if (sb_value.str().empty()){// If nothing was copied to the output (for example, with '::'), failbit is sets.clear();}// Get ':'s >> punct;}return true;}bool IPLocator::setIPv4address(Locator_t& destlocator,const std::string& lan,const std::string& wan,const std::string& ipv4){if (setLanID(destlocator, lan) && setWan(destlocator, wan) && setIPv4(destlocator, ipv4)){return true;}LOCATOR_ADDRESS_INVALID(destlocator.address);return false;}std::pair<std::set<std::string>, std::set<std::string>> IPLocator::resolveNameDNS(const std::string& address_name){// Using code from// https://subscription.packtpub.com/book/application_development/9781783986545/1/ch01lvl1sec13/resolving-a-dns-namestd::set<std::string> ipv4_results;std::set<std::string> ipv6_results;// Create an instance of io contextasio::io_context ioc;// Create a resolver instanceasio::ip::tcp::resolver resolver(ioc);// Used to store information about error that happens during the resolution process.asio::error_code ec;// Make the DNS petitionauto results = resolver.resolve(address_name,"",asio::ip::resolver_base::numeric_service,ec);// Handling errors if any.if (ec){// Failed to resolve the DNS name. Breaking execution.EPROSIMA_LOG_WARNING(IP_LOCATOR, "Error " << ec.message() << " when execution the DNS request");return std::make_pair(ipv4_results, ipv6_results);}for (const auto& entry : results){const auto& addr = entry.endpoint().address();EPROSIMA_LOG_INFO(IP_LOCATOR,"IP " << addr << " found by DNS request to address " << address_name);// Check whether the ip get is v4 or v6if (addr.is_v4()){ipv4_results.insert(addr.to_string());}else{ipv6_results.insert(addr.to_string());}}return std::make_pair(ipv4_results, ipv6_results);}bool IPLocator::isIPv4(const std::string& address){return std::regex_match(address, IPv4_REGEX);}bool IPLocator::isIPv6(const std::string& address){return IPLocator::IPv6isCorrect(address);}} // namespace rtps} // namespace fastdds} // namespace eprosima
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。