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