33 import java.security.AccessController; |
33 import java.security.AccessController; |
34 import java.security.PrivilegedActionException; |
34 import java.security.PrivilegedActionException; |
35 import java.security.PrivilegedExceptionAction; |
35 import java.security.PrivilegedExceptionAction; |
36 import java.util.Collections; |
36 import java.util.Collections; |
37 import java.util.HashSet; |
37 import java.util.HashSet; |
|
38 import java.util.Objects; |
38 import java.util.Set; |
39 import java.util.Set; |
39 |
40 |
40 import sun.net.ConnectionResetException; |
41 import sun.net.ConnectionResetException; |
41 import sun.net.NetHooks; |
42 import sun.net.NetHooks; |
42 import sun.net.PlatformSocketImpl; |
43 import sun.net.PlatformSocketImpl; |
43 import sun.net.ResourceManager; |
44 import sun.net.ResourceManager; |
|
45 import sun.net.ext.ExtendedSocketOptions; |
44 import sun.net.util.SocketExceptions; |
46 import sun.net.util.SocketExceptions; |
45 |
47 |
46 /** |
48 /** |
47 * Default Socket Implementation. This implementation does |
49 * Default Socket Implementation. This implementation does |
48 * not implement any security checks. |
50 * not implement any security checks. |
389 ret = socketGetOption(opt, null); |
374 ret = socketGetOption(opt, null); |
390 return Boolean.valueOf(ret != -1); |
375 return Boolean.valueOf(ret != -1); |
391 // should never get here |
376 // should never get here |
392 default: |
377 default: |
393 return null; |
378 return null; |
|
379 } |
|
380 } |
|
381 |
|
382 static final ExtendedSocketOptions extendedOptions = |
|
383 ExtendedSocketOptions.getInstance(); |
|
384 |
|
385 private static final Set<SocketOption<?>> clientSocketOptions = clientSocketOptions(); |
|
386 private static final Set<SocketOption<?>> serverSocketOptions = serverSocketOptions(); |
|
387 |
|
388 private static Set<SocketOption<?>> clientSocketOptions() { |
|
389 HashSet<SocketOption<?>> options = new HashSet<>(); |
|
390 options.add(StandardSocketOptions.SO_KEEPALIVE); |
|
391 options.add(StandardSocketOptions.SO_SNDBUF); |
|
392 options.add(StandardSocketOptions.SO_RCVBUF); |
|
393 options.add(StandardSocketOptions.SO_REUSEADDR); |
|
394 options.add(StandardSocketOptions.SO_LINGER); |
|
395 options.add(StandardSocketOptions.IP_TOS); |
|
396 options.add(StandardSocketOptions.TCP_NODELAY); |
|
397 if (isReusePortAvailable()) |
|
398 options.add(StandardSocketOptions.SO_REUSEPORT); |
|
399 options.addAll(ExtendedSocketOptions.clientSocketOptions()); |
|
400 return Collections.unmodifiableSet(options); |
|
401 } |
|
402 |
|
403 private static Set<SocketOption<?>> serverSocketOptions() { |
|
404 HashSet<SocketOption<?>> options = new HashSet<>(); |
|
405 options.add(StandardSocketOptions.SO_RCVBUF); |
|
406 options.add(StandardSocketOptions.SO_REUSEADDR); |
|
407 options.add(StandardSocketOptions.IP_TOS); |
|
408 if (isReusePortAvailable()) |
|
409 options.add(StandardSocketOptions.SO_REUSEPORT); |
|
410 options.addAll(ExtendedSocketOptions.serverSocketOptions()); |
|
411 return Collections.unmodifiableSet(options); |
|
412 } |
|
413 |
|
414 @Override |
|
415 protected Set<SocketOption<?>> supportedOptions() { |
|
416 if (isServer) |
|
417 return serverSocketOptions; |
|
418 else |
|
419 return clientSocketOptions; |
|
420 } |
|
421 |
|
422 @Override |
|
423 protected <T> void setOption(SocketOption<T> name, T value) throws IOException { |
|
424 Objects.requireNonNull(name); |
|
425 if (!supportedOptions().contains(name)) |
|
426 throw new UnsupportedOperationException("'" + name + "' not supported"); |
|
427 |
|
428 if (!name.type().isInstance(value)) |
|
429 throw new IllegalArgumentException("Invalid value '" + value + "'"); |
|
430 |
|
431 if (isClosedOrPending()) |
|
432 throw new SocketException("Socket closed"); |
|
433 |
|
434 if (name == StandardSocketOptions.SO_KEEPALIVE) { |
|
435 setOption(SocketOptions.SO_KEEPALIVE, value); |
|
436 } else if (name == StandardSocketOptions.SO_SNDBUF) { |
|
437 if (((Integer)value).intValue() < 0) |
|
438 throw new IllegalArgumentException("Invalid send buffer size:" + value); |
|
439 setOption(SocketOptions.SO_SNDBUF, value); |
|
440 } else if (name == StandardSocketOptions.SO_RCVBUF) { |
|
441 if (((Integer)value).intValue() < 0) |
|
442 throw new IllegalArgumentException("Invalid recv buffer size:" + value); |
|
443 setOption(SocketOptions.SO_RCVBUF, value); |
|
444 } else if (name == StandardSocketOptions.SO_REUSEADDR) { |
|
445 setOption(SocketOptions.SO_REUSEADDR, value); |
|
446 } else if (name == StandardSocketOptions.SO_REUSEPORT) { |
|
447 setOption(SocketOptions.SO_REUSEPORT, value); |
|
448 } else if (name == StandardSocketOptions.SO_LINGER ) { |
|
449 setOption(SocketOptions.SO_LINGER, value); |
|
450 } else if (name == StandardSocketOptions.IP_TOS) { |
|
451 int i = ((Integer)value).intValue(); |
|
452 if (i < 0 || i > 255) |
|
453 throw new IllegalArgumentException("Invalid IP_TOS value: " + value); |
|
454 setOption(SocketOptions.IP_TOS, value); |
|
455 } else if (name == StandardSocketOptions.TCP_NODELAY) { |
|
456 setOption(SocketOptions.TCP_NODELAY, value); |
|
457 } else if (extendedOptions.isOptionSupported(name)) { |
|
458 extendedOptions.setOption(fd, name, value); |
|
459 } else { |
|
460 throw new AssertionError("unknown option: " + name); |
|
461 } |
|
462 } |
|
463 |
|
464 @Override |
|
465 @SuppressWarnings("unchecked") |
|
466 protected <T> T getOption(SocketOption<T> name) throws IOException { |
|
467 Objects.requireNonNull(name); |
|
468 if (!supportedOptions().contains(name)) |
|
469 throw new UnsupportedOperationException("'" + name + "' not supported"); |
|
470 |
|
471 if (isClosedOrPending()) |
|
472 throw new SocketException("Socket closed"); |
|
473 |
|
474 if (name == StandardSocketOptions.SO_KEEPALIVE) { |
|
475 return (T)getOption(SocketOptions.SO_KEEPALIVE); |
|
476 } else if (name == StandardSocketOptions.SO_SNDBUF) { |
|
477 return (T)getOption(SocketOptions.SO_SNDBUF); |
|
478 } else if (name == StandardSocketOptions.SO_RCVBUF) { |
|
479 return (T)getOption(SocketOptions.SO_RCVBUF); |
|
480 } else if (name == StandardSocketOptions.SO_REUSEADDR) { |
|
481 return (T)getOption(SocketOptions.SO_REUSEADDR); |
|
482 } else if (name == StandardSocketOptions.SO_REUSEPORT) { |
|
483 return (T)getOption(SocketOptions.SO_REUSEPORT); |
|
484 } else if (name == StandardSocketOptions.SO_LINGER) { |
|
485 return (T)getOption(SocketOptions.SO_LINGER); |
|
486 } else if (name == StandardSocketOptions.IP_TOS) { |
|
487 return (T)getOption(SocketOptions.IP_TOS); |
|
488 } else if (name == StandardSocketOptions.TCP_NODELAY) { |
|
489 return (T)getOption(SocketOptions.TCP_NODELAY); |
|
490 } else if (extendedOptions.isOptionSupported(name)) { |
|
491 return (T) extendedOptions.getOption(fd, name); |
|
492 } else { |
|
493 throw new AssertionError("unknown option: " + name); |
394 } |
494 } |
395 } |
495 } |
396 |
496 |
397 /** |
497 /** |
398 * The workhorse of the connection operation. Tries several times to |
498 * The workhorse of the connection operation. Tries several times to |