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
26 package java.net;
27
28 import java.io.IOException;
29 import java.io.UncheckedIOException;
30 import java.nio.channels.DatagramChannel;
31 import java.security.AccessController;
32 import java.security.PrivilegedExceptionAction;
33 import java.util.Objects;
34 import java.util.Set;
35 import java.util.Collections;
36
37 /**
38 * This class represents a socket for sending and receiving datagram packets.
39 *
40 * <p>A datagram socket is the sending or receiving point for a packet
41 * delivery service. Each packet sent or received on a datagram socket
42 * is individually addressed and routed. Multiple packets sent from
43 * one machine to another may be routed differently, and may arrive in
44 * any order.
45 *
46 * <p> Where possible, a newly constructed {@code DatagramSocket} has the
47 * {@link StandardSocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
107 * can be useful when using a plain {@code DatagramSocket} to send datagrams to a
108 * multicast group.
109 *
110 * @author Pavani Diwanji
111 * @see java.net.DatagramPacket
112 * @see java.nio.channels.DatagramChannel
113 * @since 1.0
114 */
115 public class DatagramSocket implements java.io.Closeable {
116 /**
117 * Various states of this socket.
118 */
119 private boolean bound = false;
120 private boolean closed = false;
121 private volatile boolean created;
122 private final Object closeLock = new Object();
123
124 /*
125 * The implementation of this DatagramSocket.
126 */
127 private final DatagramSocketImpl impl;
128
129 /**
130 * Are we using an older DatagramSocketImpl?
131 */
132 final boolean oldImpl;
133
134 /**
135 * Set when a socket is ST_CONNECTED until we are certain
136 * that any packets which might have been received prior
137 * to calling connect() but not read by the application
138 * have been read. During this time we check the source
139 * address of all packets received to be sure they are from
140 * the connected destination. Other packets are read but
141 * silently dropped.
142 */
143 private boolean explicitFilter = false;
144 private int bytesLeftToFilter;
145 /*
146 * Connection state:
235 *
236 * @throws SocketException if the socket could not be opened,
237 * or the socket could not bind to the specified local port.
238 * @throws SecurityException if a security manager exists and its
239 * {@code checkListen} method doesn't allow the operation.
240 *
241 * @see SecurityManager#checkListen
242 */
243 public DatagramSocket() throws SocketException {
244 this(new InetSocketAddress(0));
245 }
246
247 /**
248 * Creates an unbound datagram socket with the specified
249 * DatagramSocketImpl.
250 *
251 * @param impl an instance of a <B>DatagramSocketImpl</B>
252 * the subclass wishes to use on the DatagramSocket.
253 * @since 1.4
254 */
255 protected DatagramSocket(DatagramSocketImpl impl) {
256 if (impl == null)
257 throw new NullPointerException();
258 this.impl = impl;
259 this.oldImpl = checkOldImpl(impl);
260 }
261
262 /**
263 * Creates a datagram socket, bound to the specified local
264 * socket address.
265 * <p>
266 * If, if the address is {@code null}, creates an unbound socket.
267 *
268 * <p>If there is a security manager,
269 * its {@code checkListen} method is first called
270 * with the port from the socket address
271 * as its argument to ensure the operation is allowed.
272 * This could result in a SecurityException.
273 *
274 * @param bindaddr local socket address to bind, or {@code null}
275 * for an unbound socket.
276 *
277 * @throws SocketException if the socket could not be opened,
278 * or the socket could not bind to the specified local port.
279 * @throws SecurityException if a security manager exists and its
280 * {@code checkListen} method doesn't allow the operation.
281 *
282 * @see SecurityManager#checkListen
283 * @since 1.4
284 */
285 public DatagramSocket(SocketAddress bindaddr) throws SocketException {
286 // Special case initialization for the DatagramChannel socket adaptor.
287 if (this instanceof sun.nio.ch.DatagramSocketAdaptor) {
288 this.impl = null; // no DatagramSocketImpl
289 this.oldImpl = false;
290 return;
291 }
292
293 // create a datagram socket.
294 boolean multicast = (this instanceof MulticastSocket);
295 this.impl = createImpl(multicast);
296 // creates the udp socket
297 impl.create();
298 created = true;
299 this.oldImpl = checkOldImpl(impl);
300 if (bindaddr != null) {
301 try {
302 bind(bindaddr);
303 } finally {
304 if (!isBound())
305 close();
306 }
307 }
308 }
309
310 /**
311 * Constructs a datagram socket and binds it to the specified port
312 * on the local host machine. The socket will be bound to the
346 *
347 * @param port local port to use
348 * @param laddr local address to bind
349 *
350 * @throws SocketException if the socket could not be opened,
351 * or the socket could not bind to the specified local port.
352 * @throws SecurityException if a security manager exists and its
353 * {@code checkListen} method doesn't allow the operation.
354 *
355 * @see SecurityManager#checkListen
356 * @since 1.1
357 */
358 public DatagramSocket(int port, InetAddress laddr) throws SocketException {
359 this(new InetSocketAddress(laddr, port));
360 }
361
362 /**
363 * Return true if the given DatagramSocketImpl is an "old" impl. An old impl
364 * is one that doesn't implement the abstract methods added in Java SE 1.4.
365 */
366 private static boolean checkOldImpl(DatagramSocketImpl impl) {
367 // DatagramSocketImpl.peekData() is a protected method, therefore we need to use
368 // getDeclaredMethod, therefore we need permission to access the member
369 try {
370 AccessController.doPrivileged(
371 new PrivilegedExceptionAction<>() {
372 public Void run() throws NoSuchMethodException {
373 Class<?>[] cl = new Class<?>[1];
374 cl[0] = DatagramPacket.class;
375 impl.getClass().getDeclaredMethod("peekData", cl);
376 return null;
377 }
378 });
379 return false;
380 } catch (java.security.PrivilegedActionException e) {
381 return true;
382 }
383 }
384
385 static Class<?> implClass = null;
386
387 /**
388 * Creates a DatagramSocketImpl.
389 * @param multicast true if the DatagramSocketImpl is for a MulticastSocket
390 */
391 private static DatagramSocketImpl createImpl(boolean multicast) throws SocketException {
392 DatagramSocketImpl impl;
393 DatagramSocketImplFactory factory = DatagramSocket.factory;
394 if (factory != null) {
395 impl = factory.createDatagramSocketImpl();
396 } else {
397 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(multicast);
398 }
399 return impl;
400 }
401
402 /**
403 * Return the {@code DatagramSocketImpl} attached to this socket,
404 * creating the socket if not already created.
405 *
406 * @return the {@code DatagramSocketImpl} attached to that
407 * DatagramSocket
408 * @throws SocketException if creating the socket fails
409 * @since 1.4
410 */
411 final DatagramSocketImpl getImpl() throws SocketException {
412 if (!created) {
413 synchronized (this) {
414 if (!created) {
415 impl.create();
416 created = true;
417 }
418 }
419 }
420 return impl;
421 }
422
423 /**
424 * Binds this DatagramSocket to a specific address and port.
425 * <p>
426 * If the address is {@code null}, then the system will pick up
427 * an ephemeral port and a valid local address to bind the socket.
428 *
429 * @param addr The address and port to bind to.
430 * @throws SocketException if any error happens during the bind, or if the
431 * socket is already bound.
1486 private static Set<SocketOption<?>> options;
1487 private static boolean optionsSet = false;
1488
1489 /**
1490 * Returns a set of the socket options supported by this socket.
1491 *
1492 * This method will continue to return the set of options even after
1493 * the socket has been closed.
1494 *
1495 * @return A set of the socket options supported by this socket. This set
1496 * may be empty if the socket's DatagramSocketImpl cannot be created.
1497 *
1498 * @since 9
1499 */
1500 public Set<SocketOption<?>> supportedOptions() {
1501 synchronized(DatagramSocket.class) {
1502 if (optionsSet) {
1503 return options;
1504 }
1505 try {
1506 DatagramSocketImpl impl = getImpl();
1507 options = Collections.unmodifiableSet(impl.supportedOptions());
1508 } catch (IOException e) {
1509 options = Collections.emptySet();
1510 }
1511 optionsSet = true;
1512 return options;
1513 }
1514 }
1515 }
|
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
26 package java.net;
27
28 import java.io.FileDescriptor;
29 import java.io.IOException;
30 import java.io.UncheckedIOException;
31 import java.nio.channels.DatagramChannel;
32 import java.security.AccessController;
33 import java.security.PrivilegedExceptionAction;
34 import java.util.Objects;
35 import java.util.Set;
36 import java.util.Collections;
37
38 /**
39 * This class represents a socket for sending and receiving datagram packets.
40 *
41 * <p>A datagram socket is the sending or receiving point for a packet
42 * delivery service. Each packet sent or received on a datagram socket
43 * is individually addressed and routed. Multiple packets sent from
44 * one machine to another may be routed differently, and may arrive in
45 * any order.
46 *
47 * <p> Where possible, a newly constructed {@code DatagramSocket} has the
48 * {@link StandardSocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
108 * can be useful when using a plain {@code DatagramSocket} to send datagrams to a
109 * multicast group.
110 *
111 * @author Pavani Diwanji
112 * @see java.net.DatagramPacket
113 * @see java.nio.channels.DatagramChannel
114 * @since 1.0
115 */
116 public class DatagramSocket implements java.io.Closeable {
117 /**
118 * Various states of this socket.
119 */
120 private boolean bound = false;
121 private boolean closed = false;
122 private volatile boolean created;
123 private final Object closeLock = new Object();
124
125 /*
126 * The implementation of this DatagramSocket.
127 */
128 @SuppressWarnings("deprecation")
129 private final DatagramSocketImpl impl;
130
131 /**
132 * Are we using an older DatagramSocketImpl?
133 */
134 final boolean oldImpl;
135
136 /**
137 * Set when a socket is ST_CONNECTED until we are certain
138 * that any packets which might have been received prior
139 * to calling connect() but not read by the application
140 * have been read. During this time we check the source
141 * address of all packets received to be sure they are from
142 * the connected destination. Other packets are read but
143 * silently dropped.
144 */
145 private boolean explicitFilter = false;
146 private int bytesLeftToFilter;
147 /*
148 * Connection state:
237 *
238 * @throws SocketException if the socket could not be opened,
239 * or the socket could not bind to the specified local port.
240 * @throws SecurityException if a security manager exists and its
241 * {@code checkListen} method doesn't allow the operation.
242 *
243 * @see SecurityManager#checkListen
244 */
245 public DatagramSocket() throws SocketException {
246 this(new InetSocketAddress(0));
247 }
248
249 /**
250 * Creates an unbound datagram socket with the specified
251 * DatagramSocketImpl.
252 *
253 * @param impl an instance of a <B>DatagramSocketImpl</B>
254 * the subclass wishes to use on the DatagramSocket.
255 * @since 1.4
256 */
257 protected DatagramSocket(@SuppressWarnings("deprecation")DatagramSocketImpl impl) {
258 if (impl == null)
259 throw new NullPointerException();
260 this.impl = impl;
261 this.oldImpl = checkOldImpl(impl);
262 }
263
264 /**
265 * Creates a datagram socket, bound to the specified local
266 * socket address.
267 * <p>
268 * If, if the address is {@code null}, creates an unbound socket.
269 *
270 * <p>If there is a security manager,
271 * its {@code checkListen} method is first called
272 * with the port from the socket address
273 * as its argument to ensure the operation is allowed.
274 * This could result in a SecurityException.
275 *
276 * @param bindaddr local socket address to bind, or {@code null}
277 * for an unbound socket.
278 *
279 * @throws SocketException if the socket could not be opened,
280 * or the socket could not bind to the specified local port.
281 * @throws SecurityException if a security manager exists and its
282 * {@code checkListen} method doesn't allow the operation.
283 *
284 * @see SecurityManager#checkListen
285 * @since 1.4
286 */
287 public DatagramSocket(SocketAddress bindaddr) throws SocketException {
288 // create a datagram socket.
289 boolean multicast = (this instanceof MulticastSocket);
290 this.impl = createImpl(multicast);
291 // creates the udp socket
292 impl.create();
293 created = true;
294 this.oldImpl = checkOldImpl(impl);
295 if (bindaddr != null) {
296 try {
297 bind(bindaddr);
298 } finally {
299 if (!isBound())
300 close();
301 }
302 }
303 }
304
305 /**
306 * Constructs a datagram socket and binds it to the specified port
307 * on the local host machine. The socket will be bound to the
341 *
342 * @param port local port to use
343 * @param laddr local address to bind
344 *
345 * @throws SocketException if the socket could not be opened,
346 * or the socket could not bind to the specified local port.
347 * @throws SecurityException if a security manager exists and its
348 * {@code checkListen} method doesn't allow the operation.
349 *
350 * @see SecurityManager#checkListen
351 * @since 1.1
352 */
353 public DatagramSocket(int port, InetAddress laddr) throws SocketException {
354 this(new InetSocketAddress(laddr, port));
355 }
356
357 /**
358 * Return true if the given DatagramSocketImpl is an "old" impl. An old impl
359 * is one that doesn't implement the abstract methods added in Java SE 1.4.
360 */
361 private static boolean checkOldImpl(@SuppressWarnings("deprecation")DatagramSocketImpl impl) {
362 // DatagramSocketImpl.peekData() is a protected method, therefore we need to use
363 // getDeclaredMethod, therefore we need permission to access the member
364 try {
365 AccessController.doPrivileged(
366 new PrivilegedExceptionAction<>() {
367 public Void run() throws NoSuchMethodException {
368 Class<?>[] cl = new Class<?>[1];
369 cl[0] = DatagramPacket.class;
370 impl.getClass().getDeclaredMethod("peekData", cl);
371 return null;
372 }
373 });
374 return false;
375 } catch (java.security.PrivilegedActionException e) {
376 return true;
377 }
378 }
379
380 static Class<?> implClass = null;
381
382 /**
383 * Creates a DatagramSocketImpl.
384 * @param multicast true if the DatagramSocketImpl is for a MulticastSocket
385 */
386 @SuppressWarnings("deprecation")
387 private static DatagramSocketImpl createImpl(boolean multicast) throws SocketException {
388 DatagramSocketImpl impl;
389 DatagramSocketImplFactory factory = DatagramSocket.factory;
390 if (factory != null) {
391 impl = factory.createDatagramSocketImpl();
392 } else {
393 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(multicast);
394 }
395 return impl;
396 }
397
398 /**
399 * Return the {@code DatagramSocketImpl} attached to this socket,
400 * creating the socket if not already created.
401 *
402 * @return the {@code DatagramSocketImpl} attached to that
403 * DatagramSocket
404 * @throws SocketException if creating the socket fails
405 * @since 1.4
406 */
407 final @SuppressWarnings("deprecation")DatagramSocketImpl getImpl() throws SocketException {
408 if (!created) {
409 synchronized (this) {
410 if (!created) {
411 impl.create();
412 created = true;
413 }
414 }
415 }
416 return impl;
417 }
418
419 /**
420 * Binds this DatagramSocket to a specific address and port.
421 * <p>
422 * If the address is {@code null}, then the system will pick up
423 * an ephemeral port and a valid local address to bind the socket.
424 *
425 * @param addr The address and port to bind to.
426 * @throws SocketException if any error happens during the bind, or if the
427 * socket is already bound.
1482 private static Set<SocketOption<?>> options;
1483 private static boolean optionsSet = false;
1484
1485 /**
1486 * Returns a set of the socket options supported by this socket.
1487 *
1488 * This method will continue to return the set of options even after
1489 * the socket has been closed.
1490 *
1491 * @return A set of the socket options supported by this socket. This set
1492 * may be empty if the socket's DatagramSocketImpl cannot be created.
1493 *
1494 * @since 9
1495 */
1496 public Set<SocketOption<?>> supportedOptions() {
1497 synchronized(DatagramSocket.class) {
1498 if (optionsSet) {
1499 return options;
1500 }
1501 try {
1502 @SuppressWarnings("deprecation")DatagramSocketImpl impl = getImpl();
1503 options = Collections.unmodifiableSet(impl.supportedOptions());
1504 } catch (IOException e) {
1505 options = Collections.emptySet();
1506 }
1507 optionsSet = true;
1508 return options;
1509 }
1510 }
1511
1512 /**
1513 * An instance of a {@code DatagramSocketImpl} whose methods all throw an
1514 * {@UncheckedIOException}.
1515 *
1516 * <p> Suitable for use by subclasses of {@code DatagramSocket} and
1517 * {@code MulticastSocket}, that wish to provide their own <b>complete</b>
1518 * implementation, without delegating to the enclosing {@code impl} class.
1519 * For example:
1520 *
1521 * <pre>{@code
1522 * class CustomDatagramSocket extends DatagramSocket {
1523 * CustomDatagramSocket() {
1524 * super(DatagramSocket.THROWING_DGRM_IMPL);
1525 * }
1526 *
1527 * // override of all methods of DatagramSocket ...
1528 * }
1529 * }</pre>
1530 */
1531 // TODO: find a better name
1532 @SuppressWarnings("deprecation")
1533 protected static final DatagramSocketImpl THROWING_DGRM_IMPL = new DatagramSocketImpl() {
1534 private final void throwUncheckedIOException() {
1535 throw new UncheckedIOException(new IOException("unimplemented"));
1536 }
1537 @Override protected void create() { throwUncheckedIOException(); }
1538 @Override protected void bind(int p, InetAddress a) { throwUncheckedIOException(); }
1539 @Override protected void send(DatagramPacket p) { throwUncheckedIOException(); }
1540 @Override protected void connect(InetAddress a, int p) { throwUncheckedIOException(); }
1541 @Override protected void disconnect() { throwUncheckedIOException(); }
1542 @Override protected int getLocalPort() { throwUncheckedIOException(); return 0; }
1543 @Override protected FileDescriptor getFileDescriptor() { throwUncheckedIOException(); return null; }
1544 @Override protected int peek(InetAddress i) { throwUncheckedIOException(); return 0; }
1545 @Override protected int peekData(DatagramPacket p) { throwUncheckedIOException(); return 0; }
1546 @Override protected void receive(DatagramPacket p) { throwUncheckedIOException(); }
1547 @Override protected void setTTL(byte ttl) { throwUncheckedIOException(); }
1548 @Override protected byte getTTL() { throwUncheckedIOException(); return 0; }
1549 @Override protected void setTimeToLive(int ttl) { throwUncheckedIOException(); }
1550 @Override protected int getTimeToLive() { throwUncheckedIOException(); return 0; }
1551 @Override protected void join(InetAddress a) { throwUncheckedIOException(); }
1552 @Override protected void leave(InetAddress a) { throwUncheckedIOException(); }
1553 @Override protected void joinGroup(SocketAddress a,
1554 NetworkInterface b) { throwUncheckedIOException(); }
1555 @Override protected void leaveGroup(SocketAddress a,
1556 NetworkInterface b) { throwUncheckedIOException(); }
1557 @Override protected void close() { throwUncheckedIOException(); }
1558 @Override public void setOption(int o, Object v) { throwUncheckedIOException(); }
1559 @Override public Object getOption(int o) { throwUncheckedIOException(); return null; }
1560 @Override protected <T> void setOption(SocketOption<T> n, T v) { throwUncheckedIOException(); }
1561 @Override protected <T> T getOption(SocketOption<T> n) { throwUncheckedIOException(); return null; }
1562 @Override protected Set<SocketOption<?>> supportedOptions() { throwUncheckedIOException(); return null; }
1563 };
1564 }
|