398 } |
380 } |
399 |
381 |
400 return result; |
382 return result; |
401 } |
383 } |
402 |
384 |
|
385 static final ExtendedSocketOptions extendedOptions = |
|
386 ExtendedSocketOptions.getInstance(); |
|
387 |
|
388 private static final Set<SocketOption<?>> datagramSocketOptions = datagramSocketOptions(); |
|
389 private static final Set<SocketOption<?>> multicastSocketOptions = multicastSocketOptions(); |
|
390 |
|
391 private static Set<SocketOption<?>> datagramSocketOptions() { |
|
392 HashSet<SocketOption<?>> options = new HashSet<>(); |
|
393 options.add(StandardSocketOptions.SO_SNDBUF); |
|
394 options.add(StandardSocketOptions.SO_RCVBUF); |
|
395 options.add(StandardSocketOptions.SO_REUSEADDR); |
|
396 options.add(StandardSocketOptions.IP_TOS); |
|
397 if (isReusePortAvailable()) |
|
398 options.add(StandardSocketOptions.SO_REUSEPORT); |
|
399 options.addAll(ExtendedSocketOptions.datagramSocketOptions()); |
|
400 return Collections.unmodifiableSet(options); |
|
401 } |
|
402 |
|
403 private static Set<SocketOption<?>> multicastSocketOptions() { |
|
404 HashSet<SocketOption<?>> options = new HashSet<>(); |
|
405 options.add(StandardSocketOptions.SO_SNDBUF); |
|
406 options.add(StandardSocketOptions.SO_RCVBUF); |
|
407 options.add(StandardSocketOptions.SO_REUSEADDR); |
|
408 options.add(StandardSocketOptions.IP_TOS); |
|
409 options.add(StandardSocketOptions.IP_MULTICAST_IF); |
|
410 options.add(StandardSocketOptions.IP_MULTICAST_TTL); |
|
411 options.add(StandardSocketOptions.IP_MULTICAST_LOOP); |
|
412 if (isReusePortAvailable()) |
|
413 options.add(StandardSocketOptions.SO_REUSEPORT); |
|
414 options.addAll(ExtendedSocketOptions.datagramSocketOptions()); |
|
415 return Collections.unmodifiableSet(options); |
|
416 } |
|
417 |
|
418 @Override |
|
419 protected Set<SocketOption<?>> supportedOptions() { |
|
420 if (getDatagramSocket() instanceof MulticastSocket) |
|
421 return multicastSocketOptions; |
|
422 else |
|
423 return datagramSocketOptions; |
|
424 } |
|
425 |
|
426 @Override |
|
427 protected <T> void setOption(SocketOption<T> name, T value) throws IOException { |
|
428 Objects.requireNonNull(name); |
|
429 if (!supportedOptions().contains(name)) |
|
430 throw new UnsupportedOperationException("'" + name + "' not supported"); |
|
431 |
|
432 if (!name.type().isInstance(value)) |
|
433 throw new IllegalArgumentException("Invalid value '" + value + "'"); |
|
434 |
|
435 if (isClosed()) |
|
436 throw new SocketException("Socket closed"); |
|
437 |
|
438 if (name == StandardSocketOptions.SO_SNDBUF) { |
|
439 if (((Integer)value).intValue() < 0) |
|
440 throw new IllegalArgumentException("Invalid send buffer size:" + value); |
|
441 setOption(SocketOptions.SO_SNDBUF, value); |
|
442 } else if (name == StandardSocketOptions.SO_RCVBUF) { |
|
443 if (((Integer)value).intValue() < 0) |
|
444 throw new IllegalArgumentException("Invalid recv buffer size:" + value); |
|
445 setOption(SocketOptions.SO_RCVBUF, value); |
|
446 } else if (name == StandardSocketOptions.SO_REUSEADDR) { |
|
447 setOption(SocketOptions.SO_REUSEADDR, value); |
|
448 } else if (name == StandardSocketOptions.SO_REUSEPORT) { |
|
449 setOption(SocketOptions.SO_REUSEPORT, 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.IP_MULTICAST_IF ) { |
|
456 setOption(SocketOptions.IP_MULTICAST_IF2, value); |
|
457 } else if (name == StandardSocketOptions.IP_MULTICAST_TTL) { |
|
458 int i = ((Integer)value).intValue(); |
|
459 if (i < 0 || i > 255) |
|
460 throw new IllegalArgumentException("Invalid TTL/hop value: " + value); |
|
461 setTimeToLive((Integer)value); |
|
462 } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP) { |
|
463 setOption(SocketOptions.IP_MULTICAST_LOOP, value); |
|
464 } else if (extendedOptions.isOptionSupported(name)) { |
|
465 extendedOptions.setOption(fd, name, value); |
|
466 } else { |
|
467 throw new AssertionError("unknown option :" + name); |
|
468 } |
|
469 } |
|
470 |
|
471 @Override |
|
472 @SuppressWarnings("unchecked") |
|
473 protected <T> T getOption(SocketOption<T> name) throws IOException { |
|
474 Objects.requireNonNull(name); |
|
475 if (!supportedOptions().contains(name)) |
|
476 throw new UnsupportedOperationException("'" + name + "' not supported"); |
|
477 |
|
478 if (isClosed()) |
|
479 throw new SocketException("Socket closed"); |
|
480 |
|
481 if (name == StandardSocketOptions.SO_SNDBUF) { |
|
482 return (T) getOption(SocketOptions.SO_SNDBUF); |
|
483 } else if (name == StandardSocketOptions.SO_RCVBUF) { |
|
484 return (T) getOption(SocketOptions.SO_RCVBUF); |
|
485 } else if (name == StandardSocketOptions.SO_REUSEADDR) { |
|
486 return (T) getOption(SocketOptions.SO_REUSEADDR); |
|
487 } else if (name == StandardSocketOptions.SO_REUSEPORT) { |
|
488 return (T) getOption(SocketOptions.SO_REUSEPORT); |
|
489 } else if (name == StandardSocketOptions.IP_TOS) { |
|
490 return (T) getOption(SocketOptions.IP_TOS); |
|
491 } else if (name == StandardSocketOptions.IP_MULTICAST_IF) { |
|
492 return (T) getOption(SocketOptions.IP_MULTICAST_IF2); |
|
493 } else if (name == StandardSocketOptions.IP_MULTICAST_TTL) { |
|
494 return (T) ((Integer) getTimeToLive()); |
|
495 } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP) { |
|
496 return (T) getOption(SocketOptions.IP_MULTICAST_LOOP); |
|
497 } else if (extendedOptions.isOptionSupported(name)) { |
|
498 return (T) extendedOptions.getOption(fd, name); |
|
499 } else { |
|
500 throw new AssertionError("unknown option: " + name); |
|
501 } |
|
502 } |
|
503 |
403 protected abstract void datagramSocketCreate() throws SocketException; |
504 protected abstract void datagramSocketCreate() throws SocketException; |
404 protected abstract void datagramSocketClose(); |
505 protected abstract void datagramSocketClose(); |
405 protected abstract void socketSetOption(int opt, Object val) |
506 protected abstract void socketSetOption(int opt, Object val) |
406 throws SocketException; |
507 throws SocketException; |
407 protected abstract Object socketGetOption(int opt) throws SocketException; |
508 protected abstract Object socketGetOption(int opt) throws SocketException; |