File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\util\NetUtils.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.util;
8
9 import java.io.IOException;
10 import java.net.BindException;
11 import java.net.Inet6Address;
12 import java.net.InetAddress;
13 import java.net.InetSocketAddress;
14 import java.net.ServerSocket;
15 import java.net.Socket;
16 import java.net.UnknownHostException;
17 import org.h2.constant.ErrorCode;
18 import org.h2.constant.SysProperties;
19 import org.h2.message.DbException;
20 import org.h2.security.CipherFactory;
21
22 /**
23 * This utility class contains socket helper functions.
24 */
25 public class NetUtils {
26
27 private static final int CACHE_MILLIS = 1000;
28 private static InetAddress cachedBindAddress;
29 private static String cachedLocalAddress;
30 private static long cachedLocalAddressTime;
31
32 private NetUtils() {
33 // utility class
34 }
35
36 /**
37 * Create a loopback socket (a socket that is connected to localhost) on
38 * this port.
39 *
40 * @param port the port
41 * @param ssl if SSL should be used
42 * @return the socket
43 */
44 public static Socket createLoopbackSocket(int port, boolean ssl) throws IOException {
45 InetAddress address = getBindAddress();
46 if (address == null) {
47 address = InetAddress.getLocalHost();
48 }
49 try {
50 return createSocket(getHostAddress(address), port, ssl);
51 } catch (IOException e) {
52 try {
53 return createSocket("localhost", port, ssl);
54 } catch (IOException e2) {
55 // throw the original exception
56 throw e;
57 }
58 }
59 }
60
61 /**
62 * Get the host address. This method adds '[' and ']' if required for
63 * Inet6Address that contain a ':'.
64 *
65 * @param address the address
66 * @return the host address
67 */
68 private static String getHostAddress(InetAddress address) {
69 String host = address.getHostAddress();
70 if (address instanceof Inet6Address) {
71 if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
72 host = "[" + host + "]";
73 }
74 }
75 return host;
76 }
77
78 /**
79 * Create a client socket that is connected to the given address and port.
80 *
81 * @param server to connect to (including an optional port)
82 * @param defaultPort the default port (if not specified in the server
83 * address)
84 * @param ssl if SSL should be used
85 * @return the socket
86 */
87 public static Socket createSocket(String server, int defaultPort, boolean ssl) throws IOException {
88 int port = defaultPort;
89 // IPv6: RFC 2732 format is '[a:b:c:d:e:f:g:h]' or
90 // '[a:b:c:d:e:f:g:h]:port'
91 // RFC 2396 format is 'a.b.c.d' or 'a.b.c.d:port' or 'hostname' or
92 // 'hostname:port'
93 int startIndex = server.startsWith("[") ? server.indexOf(']') : 0;
94 int idx = server.indexOf(':', startIndex);
95 if (idx >= 0) {
96 port = Integer.decode(server.substring(idx + 1));
97 server = server.substring(0, idx);
98 }
99 InetAddress address = InetAddress.getByName(server);
100 return createSocket(address, port, ssl);
101 }
102
103 /**
104 * Create a client socket that is connected to the given address and port.
105 *
106 * @param address the address to connect to
107 * @param port the port
108 * @param ssl if SSL should be used
109 * @return the socket
110 */
111 public static Socket createSocket(InetAddress address, int port, boolean ssl) throws IOException {
112 long start = System.currentTimeMillis();
113 for (int i = 0;; i++) {
114 try {
115 if (ssl) {
116 return CipherFactory.createSocket(address, port);
117 }
118 Socket socket = new Socket();
119 socket.connect(new InetSocketAddress(address, port),
120 SysProperties.SOCKET_CONNECT_TIMEOUT);
121 return socket;
122 } catch (IOException e) {
123 if (System.currentTimeMillis() - start >= SysProperties.SOCKET_CONNECT_TIMEOUT) {
124 // either it was a connect timeout,
125 // or list of different exceptions
126 throw e;
127 }
128 if (i >= SysProperties.SOCKET_CONNECT_RETRY) {
129 throw e;
130 }
131 // wait a bit and retry
132 try {
133 // sleep at most 256 ms
134 long sleep = Math.min(256, i * i);
135 Thread.sleep(sleep);
136 } catch (InterruptedException e2) {
137 // ignore
138 }
139 }
140 }
141 }
142
143 /**
144 * Create a server socket. The system property h2.bindAddress is used if
145 * set.
146 *
147 * @param port the port to listen on
148 * @param ssl if SSL should be used
149 * @return the server socket
150 */
151 public static ServerSocket createServerSocket(int port, boolean ssl) {
152 try {
153 return createServerSocketTry(port, ssl);
154 } catch (Exception e) {
155 // try again
156 return createServerSocketTry(port, ssl);
157 }
158 }
159
160 /**
161 * Get the bind address if the system property h2.bindAddress is set, or
162 * null if not.
163 *
164 * @return the bind address
165 */
166 private static InetAddress getBindAddress() throws UnknownHostException {
167 String host = SysProperties.BIND_ADDRESS;
168 if (host == null || host.length() == 0) {
169 return null;
170 }
171 synchronized (NetUtils.class) {
172 if (cachedBindAddress == null) {
173 cachedBindAddress = InetAddress.getByName(host);
174 }
175 }
176 return cachedBindAddress;
177 }
178
179 private static ServerSocket createServerSocketTry(int port, boolean ssl) {
180 try {
181 InetAddress bindAddress = getBindAddress();
182 if (ssl) {
183 return CipherFactory.createServerSocket(port, bindAddress);
184 }
185 if (bindAddress == null) {
186 return new ServerSocket(port);
187 }
188 return new ServerSocket(port, 0, bindAddress);
189 } catch (BindException be) {
190 throw DbException.get(ErrorCode.EXCEPTION_OPENING_PORT_2,
191 be, "" + port, be.toString());
192 } catch (IOException e) {
193 throw DbException.convertIOException(e, "port: " + port + " ssl: " + ssl);
194 }
195 }
196
197 /**
198 * Check if a socket is connected to a local address.
199 *
200 * @param socket the socket
201 * @return true if it is
202 */
203 public static boolean isLocalAddress(Socket socket) throws UnknownHostException {
204 InetAddress test = socket.getInetAddress();
205 if (test.isLoopbackAddress()) {
206 return true;
207 }
208 InetAddress localhost = InetAddress.getLocalHost();
209 // localhost.getCanonicalHostName() is very very slow
210 String host = localhost.getHostAddress();
211 for (InetAddress addr : InetAddress.getAllByName(host)) {
212 if (test.equals(addr)) {
213 return true;
214 }
215 }
216 return false;
217 }
218
219 /**
220 * Close a server socket and ignore any exceptions.
221 *
222 * @param socket the socket
223 * @return null
224 */
225 public static ServerSocket closeSilently(ServerSocket socket) {
226 if (socket != null) {
227 try {
228 socket.close();
229 } catch (IOException e) {
230 // ignore
231 }
232 }
233 return null;
234 }
235
236 /**
237 * Get the local host address as a string.
238 * For performance, the result is cached for one second.
239 *
240 * @return the local host address
241 */
242 public static synchronized String getLocalAddress() {
243 long now = System.currentTimeMillis();
244 if (cachedLocalAddress != null) {
245 if (cachedLocalAddressTime + CACHE_MILLIS > now) {
246 return cachedLocalAddress;
247 }
248 }
249 InetAddress bind = null;
250 boolean useLocalhost = false;
251 try {
252 bind = getBindAddress();
253 if (bind == null) {
254 useLocalhost = true;
255 }
256 } catch (UnknownHostException e) {
257 // ignore
258 }
259 if (useLocalhost) {
260 try {
261 bind = InetAddress.getLocalHost();
262 } catch (UnknownHostException e) {
263 throw DbException.convert(e);
264 }
265 }
266 String address = bind == null ? "localhost" : getHostAddress(bind);
267 if (address.equals("127.0.0.1")) {
268 address = "localhost";
269 }
270 cachedLocalAddress = address;
271 cachedLocalAddressTime = now;
272 return address;
273 }
274
275 }
276