1 /*
2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.net;
26
27 import java.io.FileDescriptor;
28 import java.io.IOException;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.Set;
32
33 import sun.net.ResourceManager;
34 import sun.security.action.GetPropertyAction;
35
36 /**
37 * Abstract datagram and multicast socket implementation base class.
38 * Note: This is not a public class, so that applets cannot call
39 * into the implementation directly and hence cannot bypass the
40 * security checks present in the DatagramSocket and MulticastSocket
41 * classes.
42 *
43 * @author Pavani Diwanji
44 */
45
46 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
47 {
48 /* timeout value for receive() */
49 int timeout = 0;
50 boolean connected = false;
51 private int trafficClass = 0;
52 protected InetAddress connectedAddress = null;
53 private int connectedPort = -1;
71 return null;
72 }
73 });
74 }
75
76 private static volatile boolean checkedReusePort;
77 private static volatile boolean isReusePortAvailable;
78
79 /**
80 * Tells whether SO_REUSEPORT is supported.
81 */
82 static boolean isReusePortAvailable() {
83 if (!checkedReusePort) {
84 isReusePortAvailable = isReusePortAvailable0();
85 checkedReusePort = true;
86 }
87 return isReusePortAvailable;
88 }
89
90 /**
91 * Returns a set of SocketOptions supported by this impl and by this impl's
92 * socket (Socket or ServerSocket)
93 *
94 * @return a Set of SocketOptions
95 */
96 @Override
97 protected Set<SocketOption<?>> supportedOptions() {
98 Set<SocketOption<?>> options;
99 if (isReusePortAvailable()) {
100 options = new HashSet<>();
101 options.addAll(super.supportedOptions());
102 options.add(StandardSocketOptions.SO_REUSEPORT);
103 options = Collections.unmodifiableSet(options);
104 } else {
105 options = super.supportedOptions();
106 }
107 return options;
108 }
109
110 /**
111 * Creates a datagram socket
112 */
113 protected synchronized void create() throws SocketException {
114 ResourceManager.beforeUdpCreate();
115 fd = new FileDescriptor();
116 try {
117 datagramSocketCreate();
118 SocketCleanable.register(fd);
119 } catch (SocketException ioe) {
120 ResourceManager.afterUdpClose();
121 fd = null;
122 throw ioe;
123 }
124 }
125
126 /**
127 * Binds a datagram socket to a local port.
128 */
129 protected synchronized void bind(int lport, InetAddress laddr)
130 throws SocketException {
381 case SO_RCVBUF:
382 case SO_SNDBUF:
383 case IP_MULTICAST_LOOP:
384 case SO_REUSEADDR:
385 case SO_BROADCAST:
386 result = socketGetOption(optID);
387 break;
388
389 case SO_REUSEPORT:
390 if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
391 throw new UnsupportedOperationException("unsupported option");
392 }
393 result = socketGetOption(optID);
394 break;
395
396 default:
397 throw new SocketException("invalid option: " + optID);
398 }
399
400 return result;
401 }
402
403 protected abstract void datagramSocketCreate() throws SocketException;
404 protected abstract void datagramSocketClose();
405 protected abstract void socketSetOption(int opt, Object val)
406 throws SocketException;
407 protected abstract Object socketGetOption(int opt) throws SocketException;
408
409 protected abstract void connect0(InetAddress address, int port) throws SocketException;
410 protected abstract void disconnect0(int family);
411
412 protected boolean nativeConnectDisabled() {
413 return connectDisabled;
414 }
415
416 abstract int dataAvailable();
417 private static native boolean isReusePortAvailable0();
418 }
|
1 /*
2 * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.net;
26
27 import java.io.FileDescriptor;
28 import java.io.IOException;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.Objects;
32 import java.util.Set;
33
34 import sun.net.ResourceManager;
35 import sun.net.ext.ExtendedSocketOptions;
36 import sun.security.action.GetPropertyAction;
37
38 /**
39 * Abstract datagram and multicast socket implementation base class.
40 * Note: This is not a public class, so that applets cannot call
41 * into the implementation directly and hence cannot bypass the
42 * security checks present in the DatagramSocket and MulticastSocket
43 * classes.
44 *
45 * @author Pavani Diwanji
46 */
47
48 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
49 {
50 /* timeout value for receive() */
51 int timeout = 0;
52 boolean connected = false;
53 private int trafficClass = 0;
54 protected InetAddress connectedAddress = null;
55 private int connectedPort = -1;
73 return null;
74 }
75 });
76 }
77
78 private static volatile boolean checkedReusePort;
79 private static volatile boolean isReusePortAvailable;
80
81 /**
82 * Tells whether SO_REUSEPORT is supported.
83 */
84 static boolean isReusePortAvailable() {
85 if (!checkedReusePort) {
86 isReusePortAvailable = isReusePortAvailable0();
87 checkedReusePort = true;
88 }
89 return isReusePortAvailable;
90 }
91
92 /**
93 * Creates a datagram socket
94 */
95 protected synchronized void create() throws SocketException {
96 ResourceManager.beforeUdpCreate();
97 fd = new FileDescriptor();
98 try {
99 datagramSocketCreate();
100 SocketCleanable.register(fd);
101 } catch (SocketException ioe) {
102 ResourceManager.afterUdpClose();
103 fd = null;
104 throw ioe;
105 }
106 }
107
108 /**
109 * Binds a datagram socket to a local port.
110 */
111 protected synchronized void bind(int lport, InetAddress laddr)
112 throws SocketException {
363 case SO_RCVBUF:
364 case SO_SNDBUF:
365 case IP_MULTICAST_LOOP:
366 case SO_REUSEADDR:
367 case SO_BROADCAST:
368 result = socketGetOption(optID);
369 break;
370
371 case SO_REUSEPORT:
372 if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
373 throw new UnsupportedOperationException("unsupported option");
374 }
375 result = socketGetOption(optID);
376 break;
377
378 default:
379 throw new SocketException("invalid option: " + optID);
380 }
381
382 return result;
383 }
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
504 protected abstract void datagramSocketCreate() throws SocketException;
505 protected abstract void datagramSocketClose();
506 protected abstract void socketSetOption(int opt, Object val)
507 throws SocketException;
508 protected abstract Object socketGetOption(int opt) throws SocketException;
509
510 protected abstract void connect0(InetAddress address, int port) throws SocketException;
511 protected abstract void disconnect0(int family);
512
513 protected boolean nativeConnectDisabled() {
514 return connectDisabled;
515 }
516
517 abstract int dataAvailable();
518 private static native boolean isReusePortAvailable0();
519 }
|