All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.servicetalk.utils.internal.NetworkUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 2018, 2021-2022 Apple Inc. and the ServiceTalk project authors
 *
 * 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.
 */
/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you 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.
 */
package io.servicetalk.utils.internal;

import static io.servicetalk.buffer.api.CharSequences.indexOf;

/**
 * Network-related utilities.
 * 

* This class borrowed some of its methods from * NetUtil class * which was part of Netty. */ public final class NetworkUtils { private NetworkUtils() { // no instances } /** * Takes a string and parses it to see if it is a valid IPV4 address. * * @param ip the IP-address to validate * @return true, if the string represents an IPV4 address in dotted notation, false otherwise. */ public static boolean isValidIpV4Address(final CharSequence ip) { return isValidIpV4Address(ip, 0, ip.length()); } /** * Takes a string and parses it to see if it is a valid IPV4 address. * * @param ip the IP-address to validate * @param from the index in {@code ip} to start validation (inclusive). * @param toExclusive the index in {@code ip} to end validation (exclusive). * @return true, if the string represents an IPV4 address in dotted notation, false otherwise. */ private static boolean isValidIpV4Address(final CharSequence ip, int from, int toExclusive) { int len = toExclusive - from; int i; return len <= 15 && len >= 7 && (i = indexOf(ip, '.', from + 1)) > 0 && isValidIpV4Word(ip, from, i) && (i = indexOf(ip, '.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) && (i = indexOf(ip, '.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) && isValidIpV4Word(ip, i + 1, toExclusive); } /** * Takes a string and parses it to see if it is a valid IPV6 address. * * @param ip the IP-address to validate * @return true, if the string represents an IPV6 address */ public static boolean isValidIpV6Address(final CharSequence ip) { int end = ip.length(); if (end < 2) { return false; } // strip "[]" int start; char c = ip.charAt(0); if (c == '[') { end--; if (ip.charAt(end) != ']') { // must have a close ] return false; } start = 1; c = ip.charAt(1); } else { start = 0; } int colons; int compressBegin; if (c == ':') { // an IPv6 address can start with "::" or with a number if (ip.charAt(start + 1) != ':') { return false; } colons = 2; compressBegin = start; start += 2; } else { colons = 0; compressBegin = -1; } int wordLen = 0; loop: for (int i = start; i < end; i++) { c = ip.charAt(i); if (isValidHexChar(c)) { if (wordLen < 4) { wordLen++; continue; } return false; } switch (c) { case ':': if (colons > 7) { return false; } if (ip.charAt(i - 1) == ':') { if (compressBegin >= 0) { return false; } compressBegin = i - 1; } else { wordLen = 0; } colons++; break; case '.': // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d // check a normal case (6 single colons) if (compressBegin < 0 && colons != 6 || // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an // IPv4 ending, otherwise 7 :'s is bad (colons == 7 && compressBegin >= start || colons > 7)) { return false; } // Verify this address is of the correct structure to contain an IPv4 address. // It must be IPv4-Mapped or IPv4-Compatible // (see https://tools.ietf.org/html/rfc4291#section-2.5.5). final int ipv4Start = i - wordLen; int j = ipv4Start - 2; // index of character before the previous ':'. if (isValidIPv4MappedChar(ip.charAt(j))) { if (!isValidIPv4MappedChar(ip.charAt(j - 1)) || !isValidIPv4MappedChar(ip.charAt(j - 2)) || !isValidIPv4MappedChar(ip.charAt(j - 3))) { return false; } j -= 5; } for (; j >= start; --j) { final char tmpChar = ip.charAt(j); if (tmpChar != '0' && tmpChar != ':') { return false; } } // 7 - is minimum IPv4 address length int ipv4End = indexOf(ip, '%', ipv4Start + 7); if (ipv4End < 0) { ipv4End = end; } return isValidIpV4Address(ip, ipv4Start, ipv4End); case '%': // strip the interface name/index after the percent sign end = i; break loop; default: return false; } } // normal case without compression if (compressBegin < 0) { return colons == 7 && wordLen > 0; } return compressBegin + 2 == end || // 8 colons is valid only if compression in start or end wordLen > 0 && (colons < 8 || compressBegin <= start); } private static boolean isValidIpV4Word(final CharSequence word, final int from, final int toExclusive) { final int len = toExclusive - from; final char c0; final char c1; final char c2; if (len < 1 || len > 3 || (c0 = word.charAt(from)) < '0') { return false; } if (len == 3) { return (c1 = word.charAt(from + 1)) >= '0' && (c2 = word.charAt(from + 2)) >= '0' && (c0 <= '1' && c1 <= '9' && c2 <= '9' || c0 == '2' && c1 <= '5' && (c2 <= '5' || c1 < '5' && c2 <= '9')); } return c0 <= '9' && (len == 1 || isValidNumericChar(word.charAt(from + 1))); } private static boolean isValidHexChar(final char c) { return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'; } private static boolean isValidNumericChar(final char c) { return c >= '0' && c <= '9'; } private static boolean isValidIPv4MappedChar(final char c) { return c == 'f' || c == 'F'; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy