1 /*
2 * Copyright (c) 1995, 2010, 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
26 package java.net;
27
28 import java.io.FileDescriptor;
29 import java.io.IOException;
30 import java.io.InterruptedIOException;
31 import java.nio.channels.DatagramChannel;
32 import java.security.AccessController;
33 import java.security.PrivilegedExceptionAction;
34
35 /**
36 * This class represents a socket for sending and receiving datagram packets.
37 *
38 * <p>A datagram socket is the sending or receiving point for a packet
39 * delivery service. Each packet sent or received on a datagram socket
40 * is individually addressed and routed. Multiple packets sent from
41 * one machine to another may be routed differently, and may arrive in
42 * any order.
43 *
44 * <p> Where possible, a newly constructed {@code DatagramSocket} has the
45 * {@link SocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
46 * to allow the transmission of broadcast datagrams. In order to receive
47 * broadcast packets a DatagramSocket should be bound to the wildcard address.
48 * In some implementations, broadcast packets may also be received when
49 * a DatagramSocket is bound to a more specific address.
50 * <p>
51 * Example:
52 * <code>
53 * DatagramSocket s = new DatagramSocket(null);
54 * s.bind(new InetSocketAddress(8888));
55 * </code>
56 * Which is equivalent to:
57 * <code>
58 * DatagramSocket s = new DatagramSocket(8888);
59 * </code>
60 * Both cases will create a DatagramSocket able to receive broadcasts on
61 * UDP port 8888.
62 *
63 * @author Pavani Diwanji
64 * @see java.net.DatagramPacket
65 * @see java.nio.channels.DatagramChannel
66 * @since JDK1.0
67 */
68 public
69 class DatagramSocket implements java.io.Closeable {
70 /**
71 * Various states of this socket.
72 */
73 private boolean created = false;
74 private boolean bound = false;
75 private boolean closed = false;
76 private Object closeLock = new Object();
77
78 /*
79 * The implementation of this DatagramSocket.
80 */
81 DatagramSocketImpl impl;
82
83 /**
84 * Are we using an older DatagramSocketImpl?
85 */
86 boolean oldImpl = false;
87
88 /*
89 * Connection state:
90 * ST_NOT_CONNECTED = socket not connected
91 * ST_CONNECTED = socket connected
92 * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
93 */
94 static final int ST_NOT_CONNECTED = 0;
95 static final int ST_CONNECTED = 1;
96 static final int ST_CONNECTED_NO_IMPL = 2;
97
98 int connectState = ST_NOT_CONNECTED;
99
100 /*
101 * Connected address & port
102 */
103 InetAddress connectedAddress = null;
104 int connectedPort = -1;
105
106 /**
107 * Connects this socket to a remote socket address (IP address + port number).
108 * Binds socket if not already bound.
109 * <p>
110 * @param addr The remote address.
111 * @param port The remote port
112 * @throws SocketException if binding the socket fails.
113 */
114 private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
115 if (port < 0 || port > 0xFFFF) {
116 throw new IllegalArgumentException("connect: " + port);
117 }
118 if (address == null) {
119 throw new IllegalArgumentException("connect: null address");
120 }
121 checkAddress (address, "connect");
122 if (isClosed())
123 return;
124 SecurityManager security = System.getSecurityManager();
125 if (security != null) {
126 if (address.isMulticastAddress()) {
127 security.checkMulticast(address);
128 } else {
129 security.checkConnect(address.getHostAddress(), port);
130 security.checkAccept(address.getHostAddress(), port);
131 }
132 }
133
134 if (!isBound())
135 bind(new InetSocketAddress(0));
136
137 // old impls do not support connect/disconnect
138 if (oldImpl) {
139 connectState = ST_CONNECTED_NO_IMPL;
140 } else {
141 try {
142 getImpl().connect(address, port);
143
144 // socket is now connected by the impl
145 connectState = ST_CONNECTED;
146 } catch (SocketException se) {
147
148 // connection will be emulated by DatagramSocket
149 connectState = ST_CONNECTED_NO_IMPL;
150 }
151 }
152
153 connectedAddress = address;
154 connectedPort = port;
155 }
156
157
158 /**
159 * Constructs a datagram socket and binds it to any available port
160 * on the local host machine. The socket will be bound to the
161 * {@link InetAddress#isAnyLocalAddress wildcard} address,
162 * an IP address chosen by the kernel.
163 *
164 * <p>If there is a security manager,
165 * its <code>checkListen</code> method is first called
166 * with 0 as its argument to ensure the operation is allowed.
167 * This could result in a SecurityException.
168 *
169 * @exception SocketException if the socket could not be opened,
170 * or the socket could not bind to the specified local port.
171 * @exception SecurityException if a security manager exists and its
172 * <code>checkListen</code> method doesn't allow the operation.
173 *
174 * @see SecurityManager#checkListen
175 */
176 public DatagramSocket() throws SocketException {
177 // create a datagram socket.
178 createImpl();
179 try {
180 bind(new InetSocketAddress(0));
181 } catch (SocketException se) {
182 throw se;
183 } catch(IOException e) {
184 throw new SocketException(e.getMessage());
185 }
186 }
187
188 /**
189 * Creates an unbound datagram socket with the specified
190 * DatagramSocketImpl.
191 *
192 * @param impl an instance of a <B>DatagramSocketImpl</B>
193 * the subclass wishes to use on the DatagramSocket.
194 * @since 1.4
195 */
196 protected DatagramSocket(DatagramSocketImpl impl) {
197 if (impl == null)
198 throw new NullPointerException();
199 this.impl = impl;
200 checkOldImpl();
201 }
202
203 /**
204 * Creates a datagram socket, bound to the specified local
205 * socket address.
206 * <p>
207 * If, if the address is <code>null</code>, creates an unbound socket.
208 * <p>
209 * <p>If there is a security manager,
210 * its <code>checkListen</code> method is first called
211 * with the port from the socket address
212 * as its argument to ensure the operation is allowed.
213 * This could result in a SecurityException.
214 *
215 * @param bindaddr local socket address to bind, or <code>null</code>
216 * for an unbound socket.
217 *
218 * @exception SocketException if the socket could not be opened,
219 * or the socket could not bind to the specified local port.
220 * @exception SecurityException if a security manager exists and its
221 * <code>checkListen</code> method doesn't allow the operation.
222 *
223 * @see SecurityManager#checkListen
224 * @since 1.4
225 */
226 public DatagramSocket(SocketAddress bindaddr) throws SocketException {
227 // create a datagram socket.
228 createImpl();
229 if (bindaddr != null) {
230 bind(bindaddr);
231 }
232 }
233
234 /**
235 * Constructs a datagram socket and binds it to the specified port
236 * on the local host machine. The socket will be bound to the
237 * {@link InetAddress#isAnyLocalAddress wildcard} address,
238 * an IP address chosen by the kernel.
239 *
240 * <p>If there is a security manager,
241 * its <code>checkListen</code> method is first called
242 * with the <code>port</code> argument
243 * as its argument to ensure the operation is allowed.
244 * This could result in a SecurityException.
245 *
246 * @param port port to use.
247 * @exception SocketException if the socket could not be opened,
248 * or the socket could not bind to the specified local port.
249 * @exception SecurityException if a security manager exists and its
250 * <code>checkListen</code> method doesn't allow the operation.
251 *
252 * @see SecurityManager#checkListen
253 */
254 public DatagramSocket(int port) throws SocketException {
255 this(port, null);
256 }
257
258 /**
259 * Creates a datagram socket, bound to the specified local
260 * address. The local port must be between 0 and 65535 inclusive.
261 * If the IP address is 0.0.0.0, the socket will be bound to the
262 * {@link InetAddress#isAnyLocalAddress wildcard} address,
263 * an IP address chosen by the kernel.
264 *
265 * <p>If there is a security manager,
266 * its <code>checkListen</code> method is first called
267 * with the <code>port</code> argument
268 * as its argument to ensure the operation is allowed.
269 * This could result in a SecurityException.
270 *
271 * @param port local port to use
272 * @param laddr local address to bind
273 *
274 * @exception SocketException if the socket could not be opened,
275 * or the socket could not bind to the specified local port.
276 * @exception SecurityException if a security manager exists and its
277 * <code>checkListen</code> method doesn't allow the operation.
278 *
279 * @see SecurityManager#checkListen
280 * @since JDK1.1
281 */
282 public DatagramSocket(int port, InetAddress laddr) throws SocketException {
283 this(new InetSocketAddress(laddr, port));
284 }
285
286 private void checkOldImpl() {
287 if (impl == null)
288 return;
289 // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
290 // getDeclaredMethod, therefore we need permission to access the member
291 try {
292 AccessController.doPrivileged(
293 new PrivilegedExceptionAction<Void>() {
294 public Void run() throws NoSuchMethodException {
295 Class[] cl = new Class[1];
296 cl[0] = DatagramPacket.class;
297 impl.getClass().getDeclaredMethod("peekData", cl);
298 return null;
299 }
300 });
301 } catch (java.security.PrivilegedActionException e) {
302 oldImpl = true;
303 }
304 }
305
306 static Class implClass = null;
307
308 void createImpl() throws SocketException {
309 if (impl == null) {
310 if (factory != null) {
311 impl = factory.createDatagramSocketImpl();
312 checkOldImpl();
313 } else {
314 boolean isMulticast = (this instanceof MulticastSocket) ? true : false;
315 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast);
316
317 checkOldImpl();
318 }
319 }
320 // creates a udp socket
321 impl.create();
322 created = true;
323 }
324
325 /**
326 * Get the <code>DatagramSocketImpl</code> attached to this socket,
327 * creating it if necessary.
328 *
329 * @return the <code>DatagramSocketImpl</code> attached to that
330 * DatagramSocket
331 * @throws SocketException if creation fails.
332 * @since 1.4
333 */
334 DatagramSocketImpl getImpl() throws SocketException {
335 if (!created)
336 createImpl();
337 return impl;
338 }
339
340 /**
341 * Binds this DatagramSocket to a specific address & port.
342 * <p>
343 * If the address is <code>null</code>, then the system will pick up
344 * an ephemeral port and a valid local address to bind the socket.
345 *<p>
346 * @param addr The address & port to bind to.
347 * @throws SocketException if any error happens during the bind, or if the
348 * socket is already bound.
349 * @throws SecurityException if a security manager exists and its
350 * <code>checkListen</code> method doesn't allow the operation.
351 * @throws IllegalArgumentException if addr is a SocketAddress subclass
352 * not supported by this socket.
353 * @since 1.4
354 */
355 public synchronized void bind(SocketAddress addr) throws SocketException {
356 if (isClosed())
357 throw new SocketException("Socket is closed");
358 if (isBound())
359 throw new SocketException("already bound");
360 if (addr == null)
361 addr = new InetSocketAddress(0);
362 if (!(addr instanceof InetSocketAddress))
363 throw new IllegalArgumentException("Unsupported address type!");
364 InetSocketAddress epoint = (InetSocketAddress) addr;
365 if (epoint.isUnresolved())
366 throw new SocketException("Unresolved address");
367 InetAddress iaddr = epoint.getAddress();
368 int port = epoint.getPort();
369 checkAddress(iaddr, "bind");
370 SecurityManager sec = System.getSecurityManager();
371 if (sec != null) {
372 sec.checkListen(port);
373 }
374 try {
375 getImpl().bind(port, iaddr);
376 } catch (SocketException e) {
377 getImpl().close();
378 throw e;
379 }
380 bound = true;
381 }
382
383 void checkAddress (InetAddress addr, String op) {
384 if (addr == null) {
385 return;
386 }
387 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
388 throw new IllegalArgumentException(op + ": invalid address type");
389 }
390 }
391
392 /**
393 * Connects the socket to a remote address for this socket. When a
394 * socket is connected to a remote address, packets may only be
395 * sent to or received from that address. By default a datagram
396 * socket is not connected.
397 *
398 * <p>If the remote destination to which the socket is connected does not
399 * exist, or is otherwise unreachable, and if an ICMP destination unreachable
400 * packet has been received for that address, then a subsequent call to
401 * send or receive may throw a PortUnreachableException. Note, there is no
402 * guarantee that the exception will be thrown.
403 *
404 * <p> If a security manager has been installed then it is invoked to check
405 * access to the remote address. Specifically, if the given {@code address}
406 * is a {@link InetAddress#isMulticastAddress multicast address},
407 * the security manager's {@link
408 * java.lang.SecurityManager#checkMulticast(InetAddress)
409 * checkMulticast} method is invoked with the given {@code address}.
410 * Otherwise, the security manager's {@link
411 * java.lang.SecurityManager#checkConnect(String,int) checkConnect}
412 * and {@link java.lang.SecurityManager#checkAccept checkAccept} methods
413 * are invoked, with the given {@code address} and {@code port}, to
414 * verify that datagrams are permitted to be sent and received
415 * respectively.
416 *
417 * <p> When a socket is connected, {@link #receive receive} and
418 * {@link #send send} <b>will not perform any security checks</b>
419 * on incoming and outgoing packets, other than matching the packet's
420 * and the socket's address and port. On a send operation, if the
421 * packet's address is set and the packet's address and the socket's
422 * address do not match, an {@code IllegalArgumentException} will be
423 * thrown. A socket connected to a multicast address may only be used
424 * to send packets.
425 *
426 * @param address the remote address for the socket
427 *
428 * @param port the remote port for the socket.
429 *
430 * @throws IllegalArgumentException
431 * if the address is null, or the port is out of range.
432 *
433 * @throws SecurityException
434 * if a security manager has been installed and it does
435 * not permit access to the given remote address
436 *
437 * @see #disconnect
438 */
439 public void connect(InetAddress address, int port) {
440 try {
441 connectInternal(address, port);
442 } catch (SocketException se) {
443 throw new Error("connect failed", se);
444 }
445 }
446
447 /**
448 * Connects this socket to a remote socket address (IP address + port number).
449 *
450 * <p> If given an {@link InetSocketAddress InetSocketAddress}, this method
451 * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)}
452 * with the the given socket addresses IP address and port number.
453 *
454 * @param addr The remote address.
455 *
456 * @throws SocketException
457 * if the connect fails
458 *
459 * @throws IllegalArgumentException
460 * if {@code addr} is {@code null}, or {@code addr} is a SocketAddress
461 * subclass not supported by this socket
462 *
463 * @throws SecurityException
464 * if a security manager has been installed and it does
465 * not permit access to the given remote address
466 *
467 * @since 1.4
468 */
469 public void connect(SocketAddress addr) throws SocketException {
470 if (addr == null)
471 throw new IllegalArgumentException("Address can't be null");
472 if (!(addr instanceof InetSocketAddress))
473 throw new IllegalArgumentException("Unsupported address type");
474 InetSocketAddress epoint = (InetSocketAddress) addr;
475 if (epoint.isUnresolved())
476 throw new SocketException("Unresolved address");
477 connectInternal(epoint.getAddress(), epoint.getPort());
478 }
479
480 /**
481 * Disconnects the socket. If the socket is closed or not connected,
482 * then this method has no effect.
483 *
484 * @see #connect
485 */
486 public void disconnect() {
487 synchronized (this) {
488 if (isClosed())
489 return;
490 if (connectState == ST_CONNECTED) {
491 impl.disconnect ();
492 }
493 connectedAddress = null;
494 connectedPort = -1;
495 connectState = ST_NOT_CONNECTED;
496 }
497 }
498
499 /**
500 * Returns the binding state of the socket.
501 * <p>
502 * If the socket was bound prior to being {@link #close closed},
503 * then this method will continue to return <code>true</code>
504 * after the socket is closed.
505 *
506 * @return true if the socket successfully bound to an address
507 * @since 1.4
508 */
509 public boolean isBound() {
510 return bound;
511 }
512
513 /**
514 * Returns the connection state of the socket.
515 * <p>
516 * If the socket was connected prior to being {@link #close closed},
517 * then this method will continue to return <code>true</code>
518 * after the socket is closed.
519 *
520 * @return true if the socket successfully connected to a server
521 * @since 1.4
522 */
523 public boolean isConnected() {
524 return connectState != ST_NOT_CONNECTED;
525 }
526
527 /**
528 * Returns the address to which this socket is connected. Returns
529 * <code>null</code> if the socket is not connected.
530 * <p>
531 * If the socket was connected prior to being {@link #close closed},
532 * then this method will continue to return the connected address
533 * after the socket is closed.
534 *
535 * @return the address to which this socket is connected.
536 */
537 public InetAddress getInetAddress() {
538 return connectedAddress;
539 }
540
541 /**
542 * Returns the port number to which this socket is connected.
543 * Returns <code>-1</code> if the socket is not connected.
544 * <p>
545 * If the socket was connected prior to being {@link #close closed},
546 * then this method will continue to return the connected port number
547 * after the socket is closed.
548 *
549 * @return the port number to which this socket is connected.
550 */
551 public int getPort() {
552 return connectedPort;
553 }
554
555 /**
556 * Returns the address of the endpoint this socket is connected to, or
557 * <code>null</code> if it is unconnected.
558 * <p>
559 * If the socket was connected prior to being {@link #close closed},
560 * then this method will continue to return the connected address
561 * after the socket is closed.
562 *
563 * @return a <code>SocketAddress</code> representing the remote
564 * endpoint of this socket, or <code>null</code> if it is
565 * not connected yet.
566 * @see #getInetAddress()
567 * @see #getPort()
568 * @see #connect(SocketAddress)
569 * @since 1.4
570 */
571 public SocketAddress getRemoteSocketAddress() {
572 if (!isConnected())
573 return null;
574 return new InetSocketAddress(getInetAddress(), getPort());
575 }
576
577 /**
578 * Returns the address of the endpoint this socket is bound to.
579 *
580 * @return a <code>SocketAddress</code> representing the local endpoint of this
581 * socket, or <code>null</code> if it is closed or not bound yet.
582 * @see #getLocalAddress()
583 * @see #getLocalPort()
584 * @see #bind(SocketAddress)
585 * @since 1.4
586 */
587
588 public SocketAddress getLocalSocketAddress() {
589 if (isClosed())
590 return null;
591 if (!isBound())
592 return null;
593 return new InetSocketAddress(getLocalAddress(), getLocalPort());
594 }
595
596 /**
597 * Sends a datagram packet from this socket. The
598 * <code>DatagramPacket</code> includes information indicating the
599 * data to be sent, its length, the IP address of the remote host,
600 * and the port number on the remote host.
601 *
602 * <p>If there is a security manager, and the socket is not currently
603 * connected to a remote address, this method first performs some
604 * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
605 * is true, this method calls the
606 * security manager's <code>checkMulticast</code> method
607 * with <code>p.getAddress()</code> as its argument.
608 * If the evaluation of that expression is false,
609 * this method instead calls the security manager's
610 * <code>checkConnect</code> method with arguments
611 * <code>p.getAddress().getHostAddress()</code> and
612 * <code>p.getPort()</code>. Each call to a security manager method
613 * could result in a SecurityException if the operation is not allowed.
614 *
615 * @param p the <code>DatagramPacket</code> to be sent.
616 *
617 * @exception IOException if an I/O error occurs.
618 * @exception SecurityException if a security manager exists and its
619 * <code>checkMulticast</code> or <code>checkConnect</code>
620 * method doesn't allow the send.
621 * @exception PortUnreachableException may be thrown if the socket is connected
622 * to a currently unreachable destination. Note, there is no
623 * guarantee that the exception will be thrown.
624 * @exception java.nio.channels.IllegalBlockingModeException
625 * if this socket has an associated channel,
626 * and the channel is in non-blocking mode.
627 * @exception IllegalArgumentException if the socket is connected,
628 * and connected address and packet address differ.
629 *
630 * @see java.net.DatagramPacket
631 * @see SecurityManager#checkMulticast(InetAddress)
632 * @see SecurityManager#checkConnect
633 * @revised 1.4
634 * @spec JSR-51
635 */
636 public void send(DatagramPacket p) throws IOException {
637 InetAddress packetAddress = null;
638 synchronized (p) {
639 if (isClosed())
640 throw new SocketException("Socket is closed");
641 checkAddress (p.getAddress(), "send");
642 if (connectState == ST_NOT_CONNECTED) {
643 // check the address is ok wiht the security manager on every send.
644 SecurityManager security = System.getSecurityManager();
645
646 // The reason you want to synchronize on datagram packet
647 // is because you dont want an applet to change the address
648 // while you are trying to send the packet for example
649 // after the security check but before the send.
650 if (security != null) {
651 if (p.getAddress().isMulticastAddress()) {
652 security.checkMulticast(p.getAddress());
653 } else {
654 security.checkConnect(p.getAddress().getHostAddress(),
655 p.getPort());
656 }
657 }
658 } else {
659 // we're connected
660 packetAddress = p.getAddress();
661 if (packetAddress == null) {
662 p.setAddress(connectedAddress);
663 p.setPort(connectedPort);
664 } else if ((!packetAddress.equals(connectedAddress)) ||
665 p.getPort() != connectedPort) {
666 throw new IllegalArgumentException("connected address " +
667 "and packet address" +
668 " differ");
669 }
670 }
671 // Check whether the socket is bound
672 if (!isBound())
673 bind(new InetSocketAddress(0));
674 // call the method to send
675 getImpl().send(p);
676 }
677 }
678
679 /**
680 * Receives a datagram packet from this socket. When this method
681 * returns, the <code>DatagramPacket</code>'s buffer is filled with
682 * the data received. The datagram packet also contains the sender's
683 * IP address, and the port number on the sender's machine.
684 * <p>
685 * This method blocks until a datagram is received. The
686 * <code>length</code> field of the datagram packet object contains
687 * the length of the received message. If the message is longer than
688 * the packet's length, the message is truncated.
689 * <p>
690 * If there is a security manager, a packet cannot be received if the
691 * security manager's <code>checkAccept</code> method
692 * does not allow it.
693 *
694 * @param p the <code>DatagramPacket</code> into which to place
695 * the incoming data.
696 * @exception IOException if an I/O error occurs.
697 * @exception SocketTimeoutException if setSoTimeout was previously called
698 * and the timeout has expired.
699 * @exception PortUnreachableException may be thrown if the socket is connected
700 * to a currently unreachable destination. Note, there is no guarantee that the
701 * exception will be thrown.
702 * @exception java.nio.channels.IllegalBlockingModeException
703 * if this socket has an associated channel,
704 * and the channel is in non-blocking mode.
705 * @see java.net.DatagramPacket
706 * @see java.net.DatagramSocket
707 * @revised 1.4
708 * @spec JSR-51
709 */
710 public synchronized void receive(DatagramPacket p) throws IOException {
711 synchronized (p) {
712 if (!isBound())
713 bind(new InetSocketAddress(0));
714 if (connectState == ST_NOT_CONNECTED) {
715 // check the address is ok with the security manager before every recv.
716 SecurityManager security = System.getSecurityManager();
717 if (security != null) {
718 while(true) {
719 String peekAd = null;
720 int peekPort = 0;
721 // peek at the packet to see who it is from.
722 if (!oldImpl) {
723 // We can use the new peekData() API
724 DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
725 peekPort = getImpl().peekData(peekPacket);
726 peekAd = peekPacket.getAddress().getHostAddress();
727 } else {
728 InetAddress adr = new InetAddress();
729 peekPort = getImpl().peek(adr);
730 peekAd = adr.getHostAddress();
731 }
732 try {
733 security.checkAccept(peekAd, peekPort);
734 // security check succeeded - so now break
735 // and recv the packet.
736 break;
737 } catch (SecurityException se) {
738 // Throw away the offending packet by consuming
739 // it in a tmp buffer.
740 DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
741 getImpl().receive(tmp);
742
743 // silently discard the offending packet
744 // and continue: unknown/malicious
745 // entities on nets should not make
746 // runtime throw security exception and
747 // disrupt the applet by sending random
748 // datagram packets.
749 continue;
750 }
751 } // end of while
752 }
753 }
754 if (connectState == ST_CONNECTED_NO_IMPL) {
755 // We have to do the filtering the old fashioned way since
756 // the native impl doesn't support connect or the connect
757 // via the impl failed.
758 boolean stop = false;
759 while (!stop) {
760 // peek at the packet to see who it is from.
761 InetAddress peekAddress = new InetAddress();
762 int peekPort = getImpl().peek(peekAddress);
763 if ((!connectedAddress.equals(peekAddress)) ||
764 (connectedPort != peekPort)) {
765 // throw the packet away and silently continue
766 DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
767 getImpl().receive(tmp);
768 } else {
769 stop = true;
770 }
771 }
772 }
773 // If the security check succeeds, or the datagram is
774 // connected then receive the packet
775 getImpl().receive(p);
776 }
777 }
778
779 /**
780 * Gets the local address to which the socket is bound.
781 *
782 * <p>If there is a security manager, its
783 * <code>checkConnect</code> method is first called
784 * with the host address and <code>-1</code>
785 * as its arguments to see if the operation is allowed.
786 *
787 * @see SecurityManager#checkConnect
788 * @return the local address to which the socket is bound,
789 * <code>null</code> if the socket is closed, or
790 * an <code>InetAddress</code> representing
791 * {@link InetAddress#isAnyLocalAddress wildcard}
792 * address if either the socket is not bound, or
793 * the security manager <code>checkConnect</code>
794 * method does not allow the operation
795 * @since 1.1
796 */
797 public InetAddress getLocalAddress() {
798 if (isClosed())
799 return null;
800 InetAddress in = null;
801 try {
802 in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
803 if (in.isAnyLocalAddress()) {
804 in = InetAddress.anyLocalAddress();
805 }
806 SecurityManager s = System.getSecurityManager();
807 if (s != null) {
808 s.checkConnect(in.getHostAddress(), -1);
809 }
810 } catch (Exception e) {
811 in = InetAddress.anyLocalAddress(); // "0.0.0.0"
812 }
813 return in;
814 }
815
816 /**
817 * Returns the port number on the local host to which this socket
818 * is bound.
819 *
820 * @return the port number on the local host to which this socket is bound,
821 <code>-1</code> if the socket is closed, or
822 <code>0</code> if it is not bound yet.
823 */
824 public int getLocalPort() {
825 if (isClosed())
826 return -1;
827 try {
828 return getImpl().getLocalPort();
829 } catch (Exception e) {
830 return 0;
831 }
832 }
833
834 /** Enable/disable SO_TIMEOUT with the specified timeout, in
835 * milliseconds. With this option set to a non-zero timeout,
836 * a call to receive() for this DatagramSocket
837 * will block for only this amount of time. If the timeout expires,
838 * a <B>java.net.SocketTimeoutException</B> is raised, though the
839 * DatagramSocket is still valid. The option <B>must</B> be enabled
840 * prior to entering the blocking operation to have effect. The
841 * timeout must be > 0.
842 * A timeout of zero is interpreted as an infinite timeout.
843 *
844 * @param timeout the specified timeout in milliseconds.
845 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
846 * @since JDK1.1
847 * @see #getSoTimeout()
848 */
849 public synchronized void setSoTimeout(int timeout) throws SocketException {
850 if (isClosed())
851 throw new SocketException("Socket is closed");
852 getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
853 }
854
855 /**
856 * Retrieve setting for SO_TIMEOUT. 0 returns implies that the
857 * option is disabled (i.e., timeout of infinity).
858 *
859 * @return the setting for SO_TIMEOUT
860 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
861 * @since JDK1.1
862 * @see #setSoTimeout(int)
863 */
864 public synchronized int getSoTimeout() throws SocketException {
865 if (isClosed())
866 throw new SocketException("Socket is closed");
867 if (getImpl() == null)
868 return 0;
869 Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
870 /* extra type safety */
871 if (o instanceof Integer) {
872 return ((Integer) o).intValue();
873 } else {
874 return 0;
875 }
876 }
877
878 /**
879 * Sets the SO_SNDBUF option to the specified value for this
880 * <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the
881 * network implementation as a hint to size the underlying
882 * network I/O buffers. The SO_SNDBUF setting may also be used
883 * by the network implementation to determine the maximum size
884 * of the packet that can be sent on this socket.
885 * <p>
886 * As SO_SNDBUF is a hint, applications that want to verify
887 * what size the buffer is should call {@link #getSendBufferSize()}.
888 * <p>
889 * Increasing the buffer size may allow multiple outgoing packets
890 * to be queued by the network implementation when the send rate
891 * is high.
892 * <p>
893 * Note: If {@link #send(DatagramPacket)} is used to send a
894 * <code>DatagramPacket</code> that is larger than the setting
895 * of SO_SNDBUF then it is implementation specific if the
896 * packet is sent or discarded.
897 *
898 * @param size the size to which to set the send buffer
899 * size. This value must be greater than 0.
900 *
901 * @exception SocketException if there is an error
902 * in the underlying protocol, such as an UDP error.
903 * @exception IllegalArgumentException if the value is 0 or is
904 * negative.
905 * @see #getSendBufferSize()
906 */
907 public synchronized void setSendBufferSize(int size)
908 throws SocketException{
909 if (!(size > 0)) {
910 throw new IllegalArgumentException("negative send size");
911 }
912 if (isClosed())
913 throw new SocketException("Socket is closed");
914 getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
915 }
916
917 /**
918 * Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that is the
919 * buffer size used by the platform for output on this <tt>DatagramSocket</tt>.
920 *
921 * @return the value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>
922 * @exception SocketException if there is an error in
923 * the underlying protocol, such as an UDP error.
924 * @see #setSendBufferSize
925 */
926 public synchronized int getSendBufferSize() throws SocketException {
927 if (isClosed())
928 throw new SocketException("Socket is closed");
929 int result = 0;
930 Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
931 if (o instanceof Integer) {
932 result = ((Integer)o).intValue();
933 }
934 return result;
935 }
936
937 /**
938 * Sets the SO_RCVBUF option to the specified value for this
939 * <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the
940 * the network implementation as a hint to size the underlying
941 * network I/O buffers. The SO_RCVBUF setting may also be used
942 * by the network implementation to determine the maximum size
943 * of the packet that can be received on this socket.
944 * <p>
945 * Because SO_RCVBUF is a hint, applications that want to
946 * verify what size the buffers were set to should call
947 * {@link #getReceiveBufferSize()}.
948 * <p>
949 * Increasing SO_RCVBUF may allow the network implementation
950 * to buffer multiple packets when packets arrive faster than
951 * are being received using {@link #receive(DatagramPacket)}.
952 * <p>
953 * Note: It is implementation specific if a packet larger
954 * than SO_RCVBUF can be received.
955 *
956 * @param size the size to which to set the receive buffer
957 * size. This value must be greater than 0.
958 *
959 * @exception SocketException if there is an error in
960 * the underlying protocol, such as an UDP error.
961 * @exception IllegalArgumentException if the value is 0 or is
962 * negative.
963 * @see #getReceiveBufferSize()
964 */
965 public synchronized void setReceiveBufferSize(int size)
966 throws SocketException{
967 if (size <= 0) {
968 throw new IllegalArgumentException("invalid receive size");
969 }
970 if (isClosed())
971 throw new SocketException("Socket is closed");
972 getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
973 }
974
975 /**
976 * Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that is the
977 * buffer size used by the platform for input on this <tt>DatagramSocket</tt>.
978 *
979 * @return the value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>
980 * @exception SocketException if there is an error in the underlying protocol, such as an UDP error.
981 * @see #setReceiveBufferSize(int)
982 */
983 public synchronized int getReceiveBufferSize()
984 throws SocketException{
985 if (isClosed())
986 throw new SocketException("Socket is closed");
987 int result = 0;
988 Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
989 if (o instanceof Integer) {
990 result = ((Integer)o).intValue();
991 }
992 return result;
993 }
994
995 /**
996 * Enable/disable the SO_REUSEADDR socket option.
997 * <p>
998 * For UDP sockets it may be necessary to bind more than one
999 * socket to the same socket address. This is typically for the
1000 * purpose of receiving multicast packets
1001 * (See {@link java.net.MulticastSocket}). The
1002 * <tt>SO_REUSEADDR</tt> socket option allows multiple
1003 * sockets to be bound to the same socket address if the
1004 * <tt>SO_REUSEADDR</tt> socket option is enabled prior
1005 * to binding the socket using {@link #bind(SocketAddress)}.
1006 * <p>
1007 * Note: This functionality is not supported by all existing platforms,
1008 * so it is implementation specific whether this option will be ignored
1009 * or not. However, if it is not supported then
1010 * {@link #getReuseAddress()} will always return <code>false</code>.
1011 * <p>
1012 * When a <tt>DatagramSocket</tt> is created the initial setting
1013 * of <tt>SO_REUSEADDR</tt> is disabled.
1014 * <p>
1015 * The behaviour when <tt>SO_REUSEADDR</tt> is enabled or
1016 * disabled after a socket is bound (See {@link #isBound()})
1017 * is not defined.
1018 *
1019 * @param on whether to enable or disable the
1020 * @exception SocketException if an error occurs enabling or
1021 * disabling the <tt>SO_RESUEADDR</tt> socket option,
1022 * or the socket is closed.
1023 * @since 1.4
1024 * @see #getReuseAddress()
1025 * @see #bind(SocketAddress)
1026 * @see #isBound()
1027 * @see #isClosed()
1028 */
1029 public synchronized void setReuseAddress(boolean on) throws SocketException {
1030 if (isClosed())
1031 throw new SocketException("Socket is closed");
1032 // Integer instead of Boolean for compatibility with older DatagramSocketImpl
1033 if (oldImpl)
1034 getImpl().setOption(SocketOptions.SO_REUSEADDR, new Integer(on?-1:0));
1035 else
1036 getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
1037 }
1038
1039 /**
1040 * Tests if SO_REUSEADDR is enabled.
1041 *
1042 * @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is enabled.
1043 * @exception SocketException if there is an error
1044 * in the underlying protocol, such as an UDP error.
1045 * @since 1.4
1046 * @see #setReuseAddress(boolean)
1047 */
1048 public synchronized boolean getReuseAddress() throws SocketException {
1049 if (isClosed())
1050 throw new SocketException("Socket is closed");
1051 Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1052 return ((Boolean)o).booleanValue();
1053 }
1054
1055 /**
1056 * Enable/disable SO_BROADCAST.
1057 *
1058 * <p> Some operating systems may require that the Java virtual machine be
1059 * started with implementation specific privileges to enable this option or
1060 * send broadcast datagrams.
1061 *
1062 * @param on
1063 * whether or not to have broadcast turned on.
1064 *
1065 * @throws SocketException
1066 * if there is an error in the underlying protocol, such as an UDP
1067 * error.
1068 *
1069 * @since 1.4
1070 * @see #getBroadcast()
1071 */
1072 public synchronized void setBroadcast(boolean on) throws SocketException {
1073 if (isClosed())
1074 throw new SocketException("Socket is closed");
1075 getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on));
1076 }
1077
1078 /**
1079 * Tests if SO_BROADCAST is enabled.
1080 * @return a <code>boolean</code> indicating whether or not SO_BROADCAST is enabled.
1081 * @exception SocketException if there is an error
1082 * in the underlying protocol, such as an UDP error.
1083 * @since 1.4
1084 * @see #setBroadcast(boolean)
1085 */
1086 public synchronized boolean getBroadcast() throws SocketException {
1087 if (isClosed())
1088 throw new SocketException("Socket is closed");
1089 return ((Boolean)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue();
1090 }
1091
1092 /**
1093 * Sets traffic class or type-of-service octet in the IP
1094 * datagram header for datagrams sent from this DatagramSocket.
1095 * As the underlying network implementation may ignore this
1096 * value applications should consider it a hint.
1097 *
1098 * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
1099 * 255</code> or an IllegalArgumentException will be thrown.
1100 * <p>Notes:
1101 * <p>For Internet Protocol v4 the value consists of an
1102 * <code>integer</code>, the least significant 8 bits of which
1103 * represent the value of the TOS octet in IP packets sent by
1104 * the socket.
1105 * RFC 1349 defines the TOS values as follows:
1106 * <p>
1107 * <UL>
1108 * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
1109 * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
1110 * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
1111 * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
1112 * </UL>
1113 * The last low order bit is always ignored as this
1114 * corresponds to the MBZ (must be zero) bit.
1115 * <p>
1116 * Setting bits in the precedence field may result in a
1117 * SocketException indicating that the operation is not
1118 * permitted.
1119 * <p>
1120 * for Internet Protocol v6 <code>tc</code> is the value that
1121 * would be placed into the sin6_flowinfo field of the IP header.
1122 *
1123 * @param tc an <code>int</code> value for the bitset.
1124 * @throws SocketException if there is an error setting the
1125 * traffic class or type-of-service
1126 * @since 1.4
1127 * @see #getTrafficClass
1128 */
1129 public synchronized void setTrafficClass(int tc) throws SocketException {
1130 if (tc < 0 || tc > 255)
1131 throw new IllegalArgumentException("tc is not in range 0 -- 255");
1132
1133 if (isClosed())
1134 throw new SocketException("Socket is closed");
1135 getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
1136 }
1137
1138 /**
1139 * Gets traffic class or type-of-service in the IP datagram
1140 * header for packets sent from this DatagramSocket.
1141 * <p>
1142 * As the underlying network implementation may ignore the
1143 * traffic class or type-of-service set using {@link #setTrafficClass(int)}
1144 * this method may return a different value than was previously
1145 * set using the {@link #setTrafficClass(int)} method on this
1146 * DatagramSocket.
1147 *
1148 * @return the traffic class or type-of-service already set
1149 * @throws SocketException if there is an error obtaining the
1150 * traffic class or type-of-service value.
1151 * @since 1.4
1152 * @see #setTrafficClass(int)
1153 */
1154 public synchronized int getTrafficClass() throws SocketException {
1155 if (isClosed())
1156 throw new SocketException("Socket is closed");
1157 return ((Integer)(getImpl().getOption(SocketOptions.IP_TOS))).intValue();
1158 }
1159
1160 /**
1161 * Closes this datagram socket.
1162 * <p>
1163 * Any thread currently blocked in {@link #receive} upon this socket
1164 * will throw a {@link SocketException}.
1165 *
1166 * <p> If this socket has an associated channel then the channel is closed
1167 * as well.
1168 *
1169 * @revised 1.4
1170 * @spec JSR-51
1171 */
1172 public void close() {
1173 synchronized(closeLock) {
1174 if (isClosed())
1175 return;
1176 impl.close();
1177 closed = true;
1178 }
1179 }
1180
1181 /**
1182 * Returns whether the socket is closed or not.
1183 *
1184 * @return true if the socket has been closed
1185 * @since 1.4
1186 */
1187 public boolean isClosed() {
1188 synchronized(closeLock) {
1189 return closed;
1190 }
1191 }
1192
1193 /**
1194 * Returns the unique {@link java.nio.channels.DatagramChannel} object
1195 * associated with this datagram socket, if any.
1196 *
1197 * <p> A datagram socket will have a channel if, and only if, the channel
1198 * itself was created via the {@link java.nio.channels.DatagramChannel#open
1199 * DatagramChannel.open} method.
1200 *
1201 * @return the datagram channel associated with this datagram socket,
1202 * or <tt>null</tt> if this socket was not created for a channel
1203 *
1204 * @since 1.4
1205 * @spec JSR-51
1206 */
1207 public DatagramChannel getChannel() {
1208 return null;
1209 }
1210
1211 /**
1212 * User defined factory for all datagram sockets.
1213 */
1214 static DatagramSocketImplFactory factory;
1215
1216 /**
1217 * Sets the datagram socket implementation factory for the
1218 * application. The factory can be specified only once.
1219 * <p>
1220 * When an application creates a new datagram socket, the socket
1221 * implementation factory's <code>createDatagramSocketImpl</code> method is
1222 * called to create the actual datagram socket implementation.
1223 * <p>
1224 * Passing <code>null</code> to the method is a no-op unless the factory
1225 * was already set.
1226 *
1227 * <p>If there is a security manager, this method first calls
1228 * the security manager's <code>checkSetFactory</code> method
1229 * to ensure the operation is allowed.
1230 * This could result in a SecurityException.
1231 *
1232 * @param fac the desired factory.
1233 * @exception IOException if an I/O error occurs when setting the
1234 * datagram socket factory.
1235 * @exception SocketException if the factory is already defined.
1236 * @exception SecurityException if a security manager exists and its
1237 * <code>checkSetFactory</code> method doesn't allow the
1238 operation.
1239 * @see
1240 java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
1241 * @see SecurityManager#checkSetFactory
1242 * @since 1.3
1243 */
1244 public static synchronized void
1245 setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
1246 throws IOException
1247 {
1248 if (factory != null) {
1249 throw new SocketException("factory already defined");
1250 }
1251 SecurityManager security = System.getSecurityManager();
1252 if (security != null) {
1253 security.checkSetFactory();
1254 }
1255 factory = fac;
1256 }
1257 }