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