103 throws IOException |
127 throws IOException |
104 { |
128 { |
105 translateException(x, false); |
129 translateException(x, false); |
106 } |
130 } |
107 |
131 |
|
132 /** |
|
133 * Returns any IPv4 address of the given network interface, or |
|
134 * null if the interface does not have any IPv4 addresses. |
|
135 */ |
|
136 static Inet4Address anyInet4Address(final NetworkInterface interf) { |
|
137 return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() { |
|
138 public Inet4Address run() { |
|
139 Enumeration<InetAddress> addrs = interf.getInetAddresses(); |
|
140 while (addrs.hasMoreElements()) { |
|
141 InetAddress addr = addrs.nextElement(); |
|
142 if (addr instanceof Inet4Address) { |
|
143 return (Inet4Address)addr; |
|
144 } |
|
145 } |
|
146 return null; |
|
147 } |
|
148 }); |
|
149 } |
|
150 |
|
151 /** |
|
152 * Returns an IPv4 address as an int. |
|
153 */ |
|
154 static int inet4AsInt(InetAddress ia) { |
|
155 if (ia instanceof Inet4Address) { |
|
156 byte[] addr = ia.getAddress(); |
|
157 int address = addr[3] & 0xFF; |
|
158 address |= ((addr[2] << 8) & 0xFF00); |
|
159 address |= ((addr[1] << 16) & 0xFF0000); |
|
160 address |= ((addr[0] << 24) & 0xFF000000); |
|
161 return address; |
|
162 } |
|
163 throw new AssertionError("Should not reach here"); |
|
164 } |
|
165 |
|
166 /** |
|
167 * Returns an InetAddress from the given IPv4 address |
|
168 * represented as an int. |
|
169 */ |
|
170 static InetAddress inet4FromInt(int address) { |
|
171 byte[] addr = new byte[4]; |
|
172 addr[0] = (byte) ((address >>> 24) & 0xFF); |
|
173 addr[1] = (byte) ((address >>> 16) & 0xFF); |
|
174 addr[2] = (byte) ((address >>> 8) & 0xFF); |
|
175 addr[3] = (byte) (address & 0xFF); |
|
176 try { |
|
177 return InetAddress.getByAddress(addr); |
|
178 } catch (UnknownHostException uhe) { |
|
179 throw new AssertionError("Should not reach here"); |
|
180 } |
|
181 } |
|
182 |
|
183 /** |
|
184 * Returns an IPv6 address as a byte array |
|
185 */ |
|
186 static byte[] inet6AsByteArray(InetAddress ia) { |
|
187 if (ia instanceof Inet6Address) { |
|
188 return ia.getAddress(); |
|
189 } |
|
190 |
|
191 // need to construct IPv4-mapped address |
|
192 if (ia instanceof Inet4Address) { |
|
193 byte[] ip4address = ia.getAddress(); |
|
194 byte[] address = new byte[16]; |
|
195 address[10] = (byte)0xff; |
|
196 address[11] = (byte)0xff; |
|
197 address[12] = ip4address[0]; |
|
198 address[13] = ip4address[1]; |
|
199 address[14] = ip4address[2]; |
|
200 address[15] = ip4address[3]; |
|
201 return address; |
|
202 } |
|
203 |
|
204 throw new AssertionError("Should not reach here"); |
|
205 } |
|
206 |
|
207 // -- Socket options |
|
208 |
|
209 static void setSocketOption(FileDescriptor fd, ProtocolFamily family, |
|
210 SocketOption name, Object value) |
|
211 throws IOException |
|
212 { |
|
213 if (value == null) |
|
214 throw new IllegalArgumentException("Invalid option value"); |
|
215 |
|
216 // only simple values supported by this method |
|
217 Class<?> type = name.type(); |
|
218 if (type != Integer.class && type != Boolean.class) |
|
219 throw new AssertionError("Should not reach here"); |
|
220 |
|
221 // special handling |
|
222 if (name == StandardSocketOption.SO_RCVBUF || |
|
223 name == StandardSocketOption.SO_SNDBUF) |
|
224 { |
|
225 int i = ((Integer)value).intValue(); |
|
226 if (i < 0) |
|
227 throw new IllegalArgumentException("Invalid send/receive buffer size"); |
|
228 } |
|
229 if (name == StandardSocketOption.SO_LINGER) { |
|
230 int i = ((Integer)value).intValue(); |
|
231 if (i < 0) |
|
232 value = Integer.valueOf(-1); |
|
233 if (i > 65535) |
|
234 value = Integer.valueOf(65535); |
|
235 } |
|
236 if (name == StandardSocketOption.IP_TOS) { |
|
237 int i = ((Integer)value).intValue(); |
|
238 if (i < 0 || i > 255) |
|
239 throw new IllegalArgumentException("Invalid IP_TOS value"); |
|
240 } |
|
241 if (name == StandardSocketOption.IP_MULTICAST_TTL) { |
|
242 int i = ((Integer)value).intValue(); |
|
243 if (i < 0 || i > 255) |
|
244 throw new IllegalArgumentException("Invalid TTL/hop value"); |
|
245 } |
|
246 |
|
247 // map option name to platform level/name |
|
248 OptionKey key = SocketOptionRegistry.findOption(name, family); |
|
249 if (key == null) |
|
250 throw new AssertionError("Option not found"); |
|
251 |
|
252 int arg; |
|
253 if (type == Integer.class) { |
|
254 arg = ((Integer)value).intValue(); |
|
255 } else { |
|
256 boolean b = ((Boolean)value).booleanValue(); |
|
257 arg = (b) ? 1 : 0; |
|
258 } |
|
259 |
|
260 boolean mayNeedConversion = (family == UNSPEC); |
|
261 setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg); |
|
262 } |
|
263 |
|
264 static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, |
|
265 SocketOption name) |
|
266 throws IOException |
|
267 { |
|
268 Class<?> type = name.type(); |
|
269 |
|
270 // only simple values supported by this method |
|
271 if (type != Integer.class && type != Boolean.class) |
|
272 throw new AssertionError("Should not reach here"); |
|
273 |
|
274 // map option name to platform level/name |
|
275 OptionKey key = SocketOptionRegistry.findOption(name, family); |
|
276 if (key == null) |
|
277 throw new AssertionError("Option not found"); |
|
278 |
|
279 boolean mayNeedConversion = (family == UNSPEC); |
|
280 int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name()); |
|
281 |
|
282 if (type == Integer.class) { |
|
283 return Integer.valueOf(value); |
|
284 } else { |
|
285 return (value == 0) ? Boolean.FALSE : Boolean.TRUE; |
|
286 } |
|
287 } |
108 |
288 |
109 // -- Socket operations -- |
289 // -- Socket operations -- |
110 |
290 |
|
291 static native boolean isIPv6Available0(); |
|
292 |
111 static FileDescriptor socket(boolean stream) { |
293 static FileDescriptor socket(boolean stream) { |
112 return IOUtil.newFD(socket0(stream, false)); |
294 return socket(UNSPEC, stream); |
|
295 } |
|
296 |
|
297 static FileDescriptor socket(ProtocolFamily family, boolean stream) { |
|
298 boolean preferIPv6 = isIPv6Available() && |
|
299 (family != StandardProtocolFamily.INET); |
|
300 return IOUtil.newFD(socket0(preferIPv6, stream, false)); |
113 } |
301 } |
114 |
302 |
115 static FileDescriptor serverSocket(boolean stream) { |
303 static FileDescriptor serverSocket(boolean stream) { |
116 return IOUtil.newFD(socket0(stream, true)); |
304 return IOUtil.newFD(socket0(isIPv6Available(), stream, true)); |
117 } |
305 } |
118 |
306 |
119 // Due to oddities SO_REUSEADDR on windows reuse is ignored |
307 // Due to oddities SO_REUSEADDR on windows reuse is ignored |
120 private static native int socket0(boolean stream, boolean reuse); |
308 private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse); |
121 |
309 |
122 static native void bind(FileDescriptor fd, InetAddress addr, int port) |
310 static void bind(FileDescriptor fd, InetAddress addr, int port) |
123 throws IOException; |
311 throws IOException |
124 |
312 { |
125 static native int connect(FileDescriptor fd, |
313 bind(UNSPEC, fd, addr, port); |
126 InetAddress remote, |
314 } |
127 int remotePort, |
315 |
128 int trafficClass) |
316 static void bind(ProtocolFamily family, FileDescriptor fd, |
129 throws IOException; |
317 InetAddress addr, int port) throws IOException |
130 |
318 { |
|
319 boolean preferIPv6 = isIPv6Available() && |
|
320 (family != StandardProtocolFamily.INET); |
|
321 bind0(preferIPv6, fd, addr, port); |
|
322 } |
|
323 |
|
324 private static native void bind0(boolean preferIPv6, FileDescriptor fd, |
|
325 InetAddress addr, int port) |
|
326 throws IOException; |
|
327 |
|
328 static native void listen(FileDescriptor fd, int backlog) throws IOException; |
|
329 |
|
330 static int connect(FileDescriptor fd, InetAddress remote, int remotePort) |
|
331 throws IOException |
|
332 { |
|
333 return connect(UNSPEC, fd, remote, remotePort); |
|
334 } |
|
335 |
|
336 static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) |
|
337 throws IOException |
|
338 { |
|
339 boolean preferIPv6 = isIPv6Available() && |
|
340 (family != StandardProtocolFamily.INET); |
|
341 return connect0(preferIPv6, fd, remote, remotePort); |
|
342 } |
|
343 |
|
344 private static native int connect0(boolean preferIPv6, |
|
345 FileDescriptor fd, |
|
346 InetAddress remote, |
|
347 int remotePort) |
|
348 throws IOException; |
|
349 |
|
350 |
|
351 public final static int SHUT_RD = 0; |
|
352 public final static int SHUT_WR = 1; |
|
353 public final static int SHUT_RDWR = 2; |
|
354 |
|
355 static native void shutdown(FileDescriptor fd, int how) throws IOException; |
131 |
356 |
132 private static native int localPort(FileDescriptor fd) |
357 private static native int localPort(FileDescriptor fd) |
133 throws IOException; |
358 throws IOException; |
134 |
359 |
135 private static native InetAddress localInetAddress(FileDescriptor fd) |
360 private static native InetAddress localInetAddress(FileDescriptor fd) |
136 throws IOException; |
361 throws IOException; |
137 |
362 |
138 static InetSocketAddress localAddress(FileDescriptor fd) { |
363 static InetSocketAddress localAddress(FileDescriptor fd) |
139 try { |
364 throws IOException |
140 return new InetSocketAddress(localInetAddress(fd), |
365 { |
141 localPort(fd)); |
366 return new InetSocketAddress(localInetAddress(fd), localPort(fd)); |
142 } catch (IOException x) { |
367 } |
143 throw new Error(x); // Can't happen |
368 |
144 } |
369 private static native int remotePort(FileDescriptor fd) |
145 } |
370 throws IOException; |
146 |
371 |
147 static int localPortNumber(FileDescriptor fd) { |
372 private static native InetAddress remoteInetAddress(FileDescriptor fd) |
148 try { |
373 throws IOException; |
149 return localPort(fd); |
374 |
150 } catch (IOException x) { |
375 static InetSocketAddress remoteAddress(FileDescriptor fd) |
151 throw new Error(x); // Can't happen |
376 throws IOException |
152 } |
377 { |
153 } |
378 return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd)); |
154 |
379 } |
155 private static native int getIntOption0(FileDescriptor fd, int opt) |
380 |
156 throws IOException; |
381 private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, |
157 |
382 int level, int opt) |
158 static int getIntOption(FileDescriptor fd, int opt) |
383 throws IOException; |
159 throws IOException |
384 |
160 { |
385 private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, |
161 return getIntOption0(fd, opt); |
386 int level, int opt, int arg) |
162 } |
387 throws IOException; |
163 |
388 |
164 |
389 // -- Multicast support -- |
165 private static native void setIntOption0(FileDescriptor fd, |
390 |
166 int opt, int arg) |
391 |
167 throws IOException; |
392 /** |
168 |
393 * Join IPv4 multicast group |
169 static void setIntOption(FileDescriptor fd, int opt, int arg) |
394 */ |
170 throws IOException |
395 static int join4(FileDescriptor fd, int group, int interf, int source) |
171 { |
396 throws IOException |
172 setIntOption0(fd, opt, arg); |
397 { |
173 } |
398 return joinOrDrop4(true, fd, group, interf, source); |
|
399 } |
|
400 |
|
401 /** |
|
402 * Drop membership of IPv4 multicast group |
|
403 */ |
|
404 static void drop4(FileDescriptor fd, int group, int interf, int source) |
|
405 throws IOException |
|
406 { |
|
407 joinOrDrop4(false, fd, group, interf, source); |
|
408 } |
|
409 |
|
410 private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source) |
|
411 throws IOException; |
|
412 |
|
413 /** |
|
414 * Block IPv4 source |
|
415 */ |
|
416 static int block4(FileDescriptor fd, int group, int interf, int source) |
|
417 throws IOException |
|
418 { |
|
419 return blockOrUnblock4(true, fd, group, interf, source); |
|
420 } |
|
421 |
|
422 /** |
|
423 * Unblock IPv6 source |
|
424 */ |
|
425 static void unblock4(FileDescriptor fd, int group, int interf, int source) |
|
426 throws IOException |
|
427 { |
|
428 blockOrUnblock4(false, fd, group, interf, source); |
|
429 } |
|
430 |
|
431 private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group, |
|
432 int interf, int source) |
|
433 throws IOException; |
|
434 |
|
435 /** |
|
436 * Join IPv6 multicast group |
|
437 */ |
|
438 static int join6(FileDescriptor fd, byte[] group, int index, byte[] source) |
|
439 throws IOException |
|
440 { |
|
441 return joinOrDrop6(true, fd, group, index, source); |
|
442 } |
|
443 |
|
444 /** |
|
445 * Drop membership of IPv6 multicast group |
|
446 */ |
|
447 static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source) |
|
448 throws IOException |
|
449 { |
|
450 joinOrDrop6(false, fd, group, index, source); |
|
451 } |
|
452 |
|
453 private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source) |
|
454 throws IOException; |
|
455 |
|
456 /** |
|
457 * Block IPv6 source |
|
458 */ |
|
459 static int block6(FileDescriptor fd, byte[] group, int index, byte[] source) |
|
460 throws IOException |
|
461 { |
|
462 return blockOrUnblock6(true, fd, group, index, source); |
|
463 } |
|
464 |
|
465 /** |
|
466 * Unblock IPv6 source |
|
467 */ |
|
468 static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source) |
|
469 throws IOException |
|
470 { |
|
471 blockOrUnblock6(false, fd, group, index, source); |
|
472 } |
|
473 |
|
474 static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source) |
|
475 throws IOException; |
|
476 |
|
477 static native void setInterface4(FileDescriptor fd, int interf) throws IOException; |
|
478 |
|
479 static native int getInterface4(FileDescriptor fd) throws IOException; |
|
480 |
|
481 static native void setInterface6(FileDescriptor fd, int index) throws IOException; |
|
482 |
|
483 static native int getInterface6(FileDescriptor fd) throws IOException; |
174 |
484 |
175 private static native void initIDs(); |
485 private static native void initIDs(); |
176 |
486 |
177 static { |
487 static { |
178 Util.load(); |
488 Util.load(); |