View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
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.
18   */
19  package org.apache.hadoop.hbase.util;
20  
21  import java.net.Inet4Address;
22  import java.net.Inet6Address;
23  import java.net.InetAddress;
24  import java.net.InetSocketAddress;
25  import java.net.NetworkInterface;
26  import java.net.SocketException;
27  import java.util.Enumeration;
28  
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  
31  /**
32   * Utility for network addresses, resolving and naming.
33   */
34  @InterfaceAudience.Private
35  public class Addressing {
36    public static final String VALID_PORT_REGEX = "[\\d]+";
37    public static final String HOSTNAME_PORT_SEPARATOR = ":";
38  
39    /**
40     * @param hostAndPort Formatted as <code>&lt;hostname&gt; ':' &lt;port&gt;</code>
41     * @return An InetSocketInstance
42     */
43    public static InetSocketAddress createInetSocketAddressFromHostAndPortStr(
44        final String hostAndPort) {
45      return new InetSocketAddress(parseHostname(hostAndPort), parsePort(hostAndPort));
46    }
47  
48    /**
49     * @param hostname Server hostname
50     * @param port Server port
51     * @return Returns a concatenation of <code>hostname</code> and
52     * <code>port</code> in following
53     * form: <code>&lt;hostname&gt; ':' &lt;port&gt;</code>.  For example, if hostname
54     * is <code>example.org</code> and port is 1234, this method will return
55     * <code>example.org:1234</code>
56     */
57    public static String createHostAndPortStr(final String hostname, final int port) {
58      return hostname + HOSTNAME_PORT_SEPARATOR + port;
59    }
60  
61    /**
62     * @param hostAndPort Formatted as <code>&lt;hostname&gt; ':' &lt;port&gt;</code>
63     * @return The hostname portion of <code>hostAndPort</code>
64     */
65    public static String parseHostname(final String hostAndPort) {
66      int colonIndex = hostAndPort.lastIndexOf(HOSTNAME_PORT_SEPARATOR);
67      if (colonIndex < 0) {
68        throw new IllegalArgumentException("Not a host:port pair: " + hostAndPort);
69      }
70      return hostAndPort.substring(0, colonIndex);
71    }
72  
73    /**
74     * @param hostAndPort Formatted as <code>&lt;hostname&gt; ':' &lt;port&gt;</code>
75     * @return The port portion of <code>hostAndPort</code>
76     */
77    public static int parsePort(final String hostAndPort) {
78      int colonIndex = hostAndPort.lastIndexOf(HOSTNAME_PORT_SEPARATOR);
79      if (colonIndex < 0) {
80        throw new IllegalArgumentException("Not a host:port pair: " + hostAndPort);
81      }
82      return Integer.parseInt(hostAndPort.substring(colonIndex + 1));
83    }
84  
85    public static InetAddress getIpAddress() throws SocketException {
86      return getIpAddress(new AddressSelectionCondition() {
87        @Override
88        public boolean isAcceptableAddress(InetAddress addr) {
89          return addr instanceof Inet4Address || addr instanceof Inet6Address;
90        }
91      });
92    }
93  
94    public static InetAddress getIp4Address() throws SocketException {
95      return getIpAddress(new AddressSelectionCondition() {
96        @Override
97        public boolean isAcceptableAddress(InetAddress addr) {
98          return addr instanceof Inet4Address;
99        }
100     });
101   }
102 
103   public static InetAddress getIp6Address() throws SocketException {
104     return getIpAddress(new AddressSelectionCondition() {
105       @Override
106       public boolean isAcceptableAddress(InetAddress addr) {
107         return addr instanceof Inet6Address;
108       }
109     });
110   }
111 
112   private static InetAddress getIpAddress(AddressSelectionCondition condition) throws
113       SocketException {
114     // Before we connect somewhere, we cannot be sure about what we'd be bound to; however,
115     // we only connect when the message where client ID is, is long constructed. Thus,
116     // just use whichever IP address we can find.
117     Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
118     while (interfaces.hasMoreElements()) {
119       NetworkInterface current = interfaces.nextElement();
120       if (!current.isUp() || current.isLoopback() || current.isVirtual()) continue;
121       Enumeration<InetAddress> addresses = current.getInetAddresses();
122       while (addresses.hasMoreElements()) {
123         InetAddress addr = addresses.nextElement();
124         if (addr.isLoopbackAddress()) continue;
125         if (condition.isAcceptableAddress(addr)) {
126           return addr;
127         }
128       }
129     }
130 
131     throw new SocketException("Can't get our ip address, interfaces are: " + interfaces);
132   }
133 
134   /**
135    * Given an InetAddress, checks to see if the address is a local address, by comparing the address
136    * with all the interfaces on the node.
137    * @param addr address to check if it is local node's address
138    * @return true if the address corresponds to the local node
139    */
140   public static boolean isLocalAddress(InetAddress addr) {
141     // Check if the address is any local or loop back
142     boolean local = addr.isAnyLocalAddress() || addr.isLoopbackAddress();
143 
144     // Check if the address is defined on any interface
145     if (!local) {
146       try {
147         local = NetworkInterface.getByInetAddress(addr) != null;
148       } catch (SocketException e) {
149         local = false;
150       }
151     }
152     return local;
153   }
154 
155   /**
156    * Interface for AddressSelectionCondition to check if address is acceptable
157    */
158   public interface AddressSelectionCondition{
159     /**
160      * Condition on which to accept inet address
161      * @param address to check
162      * @return true to accept this address
163      */
164     public boolean isAcceptableAddress(InetAddress address);
165   }
166 }