001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import java.net.Inet4Address; 021import java.net.Inet6Address; 022import java.net.InetAddress; 023import java.net.InetSocketAddress; 024import java.net.NetworkInterface; 025import java.net.SocketException; 026import java.util.Enumeration; 027import org.apache.yetus.audience.InterfaceAudience; 028 029/** 030 * Utility for network addresses, resolving and naming. 031 */ 032@InterfaceAudience.Private 033public class Addressing { 034 public static final String VALID_PORT_REGEX = "[\\d]+"; 035 public static final String HOSTNAME_PORT_SEPARATOR = ":"; 036 037 /** 038 * Create a socket address 039 * @param hostAndPort Formatted as <code><hostname> ':' <port></code> 040 * @return An InetSocketInstance 041 */ 042 public static InetSocketAddress 043 createInetSocketAddressFromHostAndPortStr(final String hostAndPort) { 044 return new InetSocketAddress(parseHostname(hostAndPort), parsePort(hostAndPort)); 045 } 046 047 /** 048 * Create a host-and-port string 049 * @param hostname Server hostname 050 * @param port Server port 051 * @return Returns a concatenation of <code>hostname</code> and <code>port</code> in following 052 * form: <code><hostname> ':' <port></code>. For example, if hostname is 053 * <code>example.org</code> and port is 1234, this method will return 054 * <code>example.org:1234</code> 055 */ 056 public static String createHostAndPortStr(final String hostname, final int port) { 057 return hostname + HOSTNAME_PORT_SEPARATOR + port; 058 } 059 060 /** 061 * Parse the hostname portion of a host-and-port string 062 * @param hostAndPort Formatted as <code><hostname> ':' <port></code> 063 * @return The hostname portion of <code>hostAndPort</code> 064 */ 065 public static String parseHostname(final String hostAndPort) { 066 int colonIndex = hostAndPort.lastIndexOf(HOSTNAME_PORT_SEPARATOR); 067 if (colonIndex < 0) { 068 throw new IllegalArgumentException("Not a host:port pair: " + hostAndPort); 069 } 070 return hostAndPort.substring(0, colonIndex); 071 } 072 073 /** 074 * Parse the port portion of a host-and-port string 075 * @param hostAndPort Formatted as <code><hostname> ':' <port></code> 076 * @return The port portion of <code>hostAndPort</code> 077 */ 078 public static int parsePort(final String hostAndPort) { 079 int colonIndex = hostAndPort.lastIndexOf(HOSTNAME_PORT_SEPARATOR); 080 if (colonIndex < 0) { 081 throw new IllegalArgumentException("Not a host:port pair: " + hostAndPort); 082 } 083 return Integer.parseInt(hostAndPort.substring(colonIndex + 1)); 084 } 085 086 public static InetAddress getIpAddress() throws SocketException { 087 return getIpAddress(new AddressSelectionCondition() { 088 @Override 089 public boolean isAcceptableAddress(InetAddress addr) { 090 return addr instanceof Inet4Address || addr instanceof Inet6Address; 091 } 092 }); 093 } 094 095 public static InetAddress getIp4Address() throws SocketException { 096 return getIpAddress(new AddressSelectionCondition() { 097 @Override 098 public boolean isAcceptableAddress(InetAddress addr) { 099 return addr instanceof Inet4Address; 100 } 101 }); 102 } 103 104 public static InetAddress getIp6Address() throws SocketException { 105 return getIpAddress(new AddressSelectionCondition() { 106 @Override 107 public boolean isAcceptableAddress(InetAddress addr) { 108 return addr instanceof Inet6Address; 109 } 110 }); 111 } 112 113 private static InetAddress getIpAddress(AddressSelectionCondition condition) 114 throws SocketException { 115 // Before we connect somewhere, we cannot be sure about what we'd be bound to; however, 116 // we only connect when the message where client ID is, is long constructed. Thus, 117 // just use whichever IP address we can find. 118 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); 119 while (interfaces.hasMoreElements()) { 120 NetworkInterface current = interfaces.nextElement(); 121 if (!current.isUp() || current.isLoopback() || current.isVirtual()) continue; 122 Enumeration<InetAddress> addresses = current.getInetAddresses(); 123 while (addresses.hasMoreElements()) { 124 InetAddress addr = addresses.nextElement(); 125 if (addr.isLoopbackAddress()) continue; 126 if (condition.isAcceptableAddress(addr)) { 127 return addr; 128 } 129 } 130 } 131 132 throw new SocketException("Can't get our ip address, interfaces are: " + interfaces); 133 } 134 135 /** 136 * Given an InetAddress, checks to see if the address is a local address, by comparing the address 137 * with all the interfaces on the node. 138 * @param addr address to check if it is local node's address 139 * @return true if the address corresponds to the local node 140 */ 141 public static boolean isLocalAddress(InetAddress addr) { 142 // Check if the address is any local or loop back 143 boolean local = addr.isAnyLocalAddress() || addr.isLoopbackAddress(); 144 145 // Check if the address is defined on any interface 146 if (!local) { 147 try { 148 local = NetworkInterface.getByInetAddress(addr) != null; 149 } catch (SocketException e) { 150 local = false; 151 } 152 } 153 return local; 154 } 155 156 /** 157 * Given an InetSocketAddress object returns a String represent of it. This is a util method for 158 * Java 17. The toString() function of InetSocketAddress will flag the unresolved address with a 159 * substring in the string, which will result in unexpected problem. We should use this util 160 * function to get the string when we not sure whether the input address is resolved or not. 161 * @param address address to convert to a "host:port" String. 162 * @return the String represent of the given address, like "foo:1234". 163 */ 164 public static String inetSocketAddress2String(InetSocketAddress address) { 165 return address.isUnresolved() 166 ? address.toString().replace("/<unresolved>", "") 167 : address.toString(); 168 } 169 170 /** Interface for AddressSelectionCondition to check if address is acceptable */ 171 public interface AddressSelectionCondition { 172 /** 173 * Condition on which to accept inet address 174 * @param address to check 175 * @return true to accept this address 176 */ 177 public boolean isAcceptableAddress(InetAddress address); 178 } 179}