0001 /*
0002 * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.net;
0027
0028 import java.io.FileDescriptor;
0029 import java.io.IOException;
0030 import java.io.InterruptedIOException;
0031 import java.nio.channels.DatagramChannel;
0032 import java.security.AccessController;
0033 import java.security.PrivilegedExceptionAction;
0034
0035 /**
0036 * This class represents a socket for sending and receiving datagram packets.
0037 *
0038 * <p>A datagram socket is the sending or receiving point for a packet
0039 * delivery service. Each packet sent or received on a datagram socket
0040 * is individually addressed and routed. Multiple packets sent from
0041 * one machine to another may be routed differently, and may arrive in
0042 * any order.
0043 *
0044 * <p>UDP broadcasts sends are always enabled on a DatagramSocket.
0045 * In order to receive broadcast packets a DatagramSocket
0046 * should be bound to the wildcard address. In some
0047 * implementations, broadcast packets may also be received when
0048 * a DatagramSocket is bound to a more specific address.
0049 * <p>
0050 * Example:
0051 * <code>
0052 * DatagramSocket s = new DatagramSocket(null);
0053 * s.bind(new InetSocketAddress(8888));
0054 * </code>
0055 * Which is equivalent to:
0056 * <code>
0057 * DatagramSocket s = new DatagramSocket(8888);
0058 * </code>
0059 * Both cases will create a DatagramSocket able to receive broadcasts on
0060 * UDP port 8888.
0061 *
0062 * @author Pavani Diwanji
0063 * @version 1.111, 06/11/07
0064 * @see java.net.DatagramPacket
0065 * @see java.nio.channels.DatagramChannel
0066 * @since JDK1.0
0067 */
0068 public class DatagramSocket implements java.io.Closeable {
0069 /**
0070 * Various states of this socket.
0071 */
0072 private boolean created = false;
0073 private boolean bound = false;
0074 private boolean closed = false;
0075 private Object closeLock = new Object();
0076
0077 /*
0078 * The implementation of this DatagramSocket.
0079 */
0080 DatagramSocketImpl impl;
0081
0082 /**
0083 * Are we using an older DatagramSocketImpl?
0084 */
0085 boolean oldImpl = false;
0086
0087 /*
0088 * Connection state:
0089 * ST_NOT_CONNECTED = socket not connected
0090 * ST_CONNECTED = socket connected
0091 * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
0092 */
0093 static final int ST_NOT_CONNECTED = 0;
0094 static final int ST_CONNECTED = 1;
0095 static final int ST_CONNECTED_NO_IMPL = 2;
0096
0097 int connectState = ST_NOT_CONNECTED;
0098
0099 /*
0100 * Connected address & port
0101 */
0102 InetAddress connectedAddress = null;
0103 int connectedPort = -1;
0104
0105 /**
0106 * Connects this socket to a remote socket address (IP address + port number).
0107 * Binds socket if not already bound.
0108 * <p>
0109 * @param addr The remote address.
0110 * @param port The remote port
0111 * @throws SocketException if binding the socket fails.
0112 */
0113 private synchronized void connectInternal(InetAddress address,
0114 int port) throws SocketException {
0115 if (port < 0 || port > 0xFFFF) {
0116 throw new IllegalArgumentException("connect: " + port);
0117 }
0118 if (address == null) {
0119 throw new IllegalArgumentException("connect: null address");
0120 }
0121 if (isClosed())
0122 return;
0123 SecurityManager security = System.getSecurityManager();
0124 if (security != null) {
0125 if (address.isMulticastAddress()) {
0126 security.checkMulticast(address);
0127 } else {
0128 security.checkConnect(address.getHostAddress(), port);
0129 security.checkAccept(address.getHostAddress(), port);
0130 }
0131 }
0132
0133 if (!isBound())
0134 bind(new InetSocketAddress(0));
0135
0136 // old impls do not support connect/disconnect
0137 if (oldImpl) {
0138 connectState = ST_CONNECTED_NO_IMPL;
0139 } else {
0140 try {
0141 getImpl().connect(address, port);
0142
0143 // socket is now connected by the impl
0144 connectState = ST_CONNECTED;
0145 } catch (SocketException se) {
0146
0147 // connection will be emulated by DatagramSocket
0148 connectState = ST_CONNECTED_NO_IMPL;
0149 }
0150 }
0151
0152 connectedAddress = address;
0153 connectedPort = port;
0154 }
0155
0156 /**
0157 * Constructs a datagram socket and binds it to any available port
0158 * on the local host machine. The socket will be bound to the
0159 * {@link InetAddress#isAnyLocalAddress wildcard} address,
0160 * an IP address chosen by the kernel.
0161 *
0162 * <p>If there is a security manager,
0163 * its <code>checkListen</code> method is first called
0164 * with 0 as its argument to ensure the operation is allowed.
0165 * This could result in a SecurityException.
0166 *
0167 * @exception SocketException if the socket could not be opened,
0168 * or the socket could not bind to the specified local port.
0169 * @exception SecurityException if a security manager exists and its
0170 * <code>checkListen</code> method doesn't allow the operation.
0171 *
0172 * @see SecurityManager#checkListen
0173 */
0174 public DatagramSocket() throws SocketException {
0175 // create a datagram socket.
0176 createImpl();
0177 try {
0178 bind(new InetSocketAddress(0));
0179 } catch (SocketException se) {
0180 throw se;
0181 } catch (IOException e) {
0182 throw new SocketException(e.getMessage());
0183 }
0184 }
0185
0186 /**
0187 * Creates an unbound datagram socket with the specified
0188 * DatagramSocketImpl.
0189 *
0190 * @param impl an instance of a <B>DatagramSocketImpl</B>
0191 * the subclass wishes to use on the DatagramSocket.
0192 * @since 1.4
0193 */
0194 protected DatagramSocket(DatagramSocketImpl impl) {
0195 if (impl == null)
0196 throw new NullPointerException();
0197 this .impl = impl;
0198 checkOldImpl();
0199 }
0200
0201 /**
0202 * Creates a datagram socket, bound to the specified local
0203 * socket address.
0204 * <p>
0205 * If, if the address is <code>null</code>, creates an unbound socket.
0206 * <p>
0207 * <p>If there is a security manager,
0208 * its <code>checkListen</code> method is first called
0209 * with the port from the socket address
0210 * as its argument to ensure the operation is allowed.
0211 * This could result in a SecurityException.
0212 *
0213 * @param bindaddr local socket address to bind, or <code>null</code>
0214 * for an unbound socket.
0215 *
0216 * @exception SocketException if the socket could not be opened,
0217 * or the socket could not bind to the specified local port.
0218 * @exception SecurityException if a security manager exists and its
0219 * <code>checkListen</code> method doesn't allow the operation.
0220 *
0221 * @see SecurityManager#checkListen
0222 * @since 1.4
0223 */
0224 public DatagramSocket(SocketAddress bindaddr)
0225 throws SocketException {
0226 // create a datagram socket.
0227 createImpl();
0228 if (bindaddr != null) {
0229 bind(bindaddr);
0230 }
0231 }
0232
0233 /**
0234 * Constructs a datagram socket and binds it to the specified port
0235 * on the local host machine. The socket will be bound to the
0236 * {@link InetAddress#isAnyLocalAddress wildcard} address,
0237 * an IP address chosen by the kernel.
0238 *
0239 * <p>If there is a security manager,
0240 * its <code>checkListen</code> method is first called
0241 * with the <code>port</code> argument
0242 * as its argument to ensure the operation is allowed.
0243 * This could result in a SecurityException.
0244 *
0245 * @param port port to use.
0246 * @exception SocketException if the socket could not be opened,
0247 * or the socket could not bind to the specified local port.
0248 * @exception SecurityException if a security manager exists and its
0249 * <code>checkListen</code> method doesn't allow the operation.
0250 *
0251 * @see SecurityManager#checkListen
0252 */
0253 public DatagramSocket(int port) throws SocketException {
0254 this (port, null);
0255 }
0256
0257 /**
0258 * Creates a datagram socket, bound to the specified local
0259 * address. The local port must be between 0 and 65535 inclusive.
0260 * If the IP address is 0.0.0.0, the socket will be bound to the
0261 * {@link InetAddress#isAnyLocalAddress wildcard} address,
0262 * an IP address chosen by the kernel.
0263 *
0264 * <p>If there is a security manager,
0265 * its <code>checkListen</code> method is first called
0266 * with the <code>port</code> argument
0267 * as its argument to ensure the operation is allowed.
0268 * This could result in a SecurityException.
0269 *
0270 * @param port local port to use
0271 * @param laddr local address to bind
0272 *
0273 * @exception SocketException if the socket could not be opened,
0274 * or the socket could not bind to the specified local port.
0275 * @exception SecurityException if a security manager exists and its
0276 * <code>checkListen</code> method doesn't allow the operation.
0277 *
0278 * @see SecurityManager#checkListen
0279 * @since JDK1.1
0280 */
0281 public DatagramSocket(int port, InetAddress laddr)
0282 throws SocketException {
0283 this (new InetSocketAddress(laddr, port));
0284 }
0285
0286 private void checkOldImpl() {
0287 if (impl == null)
0288 return;
0289 // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
0290 // getDeclaredMethod, therefore we need permission to access the member
0291 try {
0292 AccessController
0293 .doPrivileged(new PrivilegedExceptionAction() {
0294 public Object run()
0295 throws NoSuchMethodException {
0296 Class[] cl = new Class[1];
0297 cl[0] = DatagramPacket.class;
0298 impl.getClass().getDeclaredMethod(
0299 "peekData", cl);
0300 return null;
0301 }
0302 });
0303 } catch (java.security.PrivilegedActionException e) {
0304 oldImpl = true;
0305 }
0306 }
0307
0308 static Class implClass = null;
0309
0310 void createImpl() throws SocketException {
0311 if (impl == null) {
0312 if (factory != null) {
0313 impl = factory.createDatagramSocketImpl();
0314 checkOldImpl();
0315 } else {
0316 boolean isMulticast = (this instanceof MulticastSocket) ? true
0317 : false;
0318 impl = DefaultDatagramSocketImplFactory
0319 .createDatagramSocketImpl(isMulticast);
0320
0321 checkOldImpl();
0322 }
0323 }
0324 // creates a udp socket
0325 impl.create();
0326 created = true;
0327 }
0328
0329 /**
0330 * Get the <code>DatagramSocketImpl</code> attached to this socket,
0331 * creating it if necessary.
0332 *
0333 * @return the <code>DatagramSocketImpl</code> attached to that
0334 * DatagramSocket
0335 * @throws SocketException if creation fails.
0336 * @since 1.4
0337 */
0338 DatagramSocketImpl getImpl() throws SocketException {
0339 if (!created)
0340 createImpl();
0341 return impl;
0342 }
0343
0344 /**
0345 * Binds this DatagramSocket to a specific address & port.
0346 * <p>
0347 * If the address is <code>null</code>, then the system will pick up
0348 * an ephemeral port and a valid local address to bind the socket.
0349 *<p>
0350 * @param addr The address & port to bind to.
0351 * @throws SocketException if any error happens during the bind, or if the
0352 * socket is already bound.
0353 * @throws SecurityException if a security manager exists and its
0354 * <code>checkListen</code> method doesn't allow the operation.
0355 * @throws IllegalArgumentException if addr is a SocketAddress subclass
0356 * not supported by this socket.
0357 * @since 1.4
0358 */
0359 public synchronized void bind(SocketAddress addr)
0360 throws SocketException {
0361 if (isClosed())
0362 throw new SocketException("Socket is closed");
0363 if (isBound())
0364 throw new SocketException("already bound");
0365 if (addr == null)
0366 addr = new InetSocketAddress(0);
0367 if (!(addr instanceof InetSocketAddress))
0368 throw new IllegalArgumentException(
0369 "Unsupported address type!");
0370 InetSocketAddress epoint = (InetSocketAddress) addr;
0371 if (epoint.isUnresolved())
0372 throw new SocketException("Unresolved address");
0373 SecurityManager sec = System.getSecurityManager();
0374 if (sec != null) {
0375 sec.checkListen(epoint.getPort());
0376 }
0377 try {
0378 getImpl().bind(epoint.getPort(), epoint.getAddress());
0379 } catch (SocketException e) {
0380 getImpl().close();
0381 throw e;
0382 }
0383 bound = true;
0384 }
0385
0386 /**
0387 * Connects the socket to a remote address for this socket. When a
0388 * socket is connected to a remote address, packets may only be
0389 * sent to or received from that address. By default a datagram
0390 * socket is not connected.
0391 *
0392 * <p>If the remote destination to which the socket is connected does not
0393 * exist, or is otherwise unreachable, and if an ICMP destination unreachable
0394 * packet has been received for that address, then a subsequent call to
0395 * send or receive may throw a PortUnreachableException. Note, there is no
0396 * guarantee that the exception will be thrown.
0397 *
0398 * <p>A caller's permission to send and receive datagrams to a
0399 * given host and port are checked at connect time. When a socket
0400 * is connected, receive and send <b>will not
0401 * perform any security checks</b> on incoming and outgoing
0402 * packets, other than matching the packet's and the socket's
0403 * address and port. On a send operation, if the packet's address
0404 * is set and the packet's address and the socket's address do not
0405 * match, an IllegalArgumentException will be thrown. A socket
0406 * connected to a multicast address may only be used to send packets.
0407 *
0408 * @param address the remote address for the socket
0409 *
0410 * @param port the remote port for the socket.
0411 *
0412 * @exception IllegalArgumentException if the address is null,
0413 * or the port is out of range.
0414 *
0415 * @exception SecurityException if the caller is not allowed to
0416 * send datagrams to and receive datagrams from the address and port.
0417 *
0418 * @see #disconnect
0419 * @see #send
0420 * @see #receive
0421 */
0422 public void connect(InetAddress address, int port) {
0423 try {
0424 connectInternal(address, port);
0425 } catch (SocketException se) {
0426 throw new Error("connect failed", se);
0427 }
0428 }
0429
0430 /**
0431 * Connects this socket to a remote socket address (IP address + port number).
0432 * <p>
0433 * @param addr The remote address.
0434 * @throws SocketException if the connect fails
0435 * @throws IllegalArgumentException if addr is null or addr is a SocketAddress
0436 * subclass not supported by this socket
0437 * @since 1.4
0438 * @see #connect
0439 */
0440 public void connect(SocketAddress addr) throws SocketException {
0441 if (addr == null)
0442 throw new IllegalArgumentException("Address can't be null");
0443 if (!(addr instanceof InetSocketAddress))
0444 throw new IllegalArgumentException(
0445 "Unsupported address type");
0446 InetSocketAddress epoint = (InetSocketAddress) addr;
0447 if (epoint.isUnresolved())
0448 throw new SocketException("Unresolved address");
0449 connectInternal(epoint.getAddress(), epoint.getPort());
0450 }
0451
0452 /**
0453 * Disconnects the socket. If the socket is closed or not connected,
0454 * then this method has no effect.
0455 *
0456 * @see #connect
0457 */
0458 public void disconnect() {
0459 synchronized (this ) {
0460 if (isClosed())
0461 return;
0462 if (connectState == ST_CONNECTED) {
0463 impl.disconnect();
0464 }
0465 connectedAddress = null;
0466 connectedPort = -1;
0467 connectState = ST_NOT_CONNECTED;
0468 }
0469 }
0470
0471 /**
0472 * Returns the binding state of the socket.
0473 * <p>
0474 * If the socket was bound prior to being {@link #close closed},
0475 * then this method will continue to return <code>true</code>
0476 * after the socket is closed.
0477 *
0478 * @return true if the socket successfully bound to an address
0479 * @since 1.4
0480 */
0481 public boolean isBound() {
0482 return bound;
0483 }
0484
0485 /**
0486 * Returns the connection state of the socket.
0487 * <p>
0488 * If the socket was connected prior to being {@link #close closed},
0489 * then this method will continue to return <code>true</code>
0490 * after the socket is closed.
0491 *
0492 * @return true if the socket successfully connected to a server
0493 * @since 1.4
0494 */
0495 public boolean isConnected() {
0496 return connectState != ST_NOT_CONNECTED;
0497 }
0498
0499 /**
0500 * Returns the address to which this socket is connected. Returns
0501 * <code>null</code> if the socket is not connected.
0502 * <p>
0503 * If the socket was connected prior to being {@link #close closed},
0504 * then this method will continue to return the connected address
0505 * after the socket is closed.
0506 *
0507 * @return the address to which this socket is connected.
0508 */
0509 public InetAddress getInetAddress() {
0510 return connectedAddress;
0511 }
0512
0513 /**
0514 * Returns the port number to which this socket is connected.
0515 * Returns <code>-1</code> if the socket is not connected.
0516 * <p>
0517 * If the socket was connected prior to being {@link #close closed},
0518 * then this method will continue to return the connected port number
0519 * after the socket is closed.
0520 *
0521 * @return the port number to which this socket is connected.
0522 */
0523 public int getPort() {
0524 return connectedPort;
0525 }
0526
0527 /**
0528 * Returns the address of the endpoint this socket is connected to, or
0529 * <code>null</code> if it is unconnected.
0530 * <p>
0531 * If the socket was connected prior to being {@link #close closed},
0532 * then this method will continue to return the connected address
0533 * after the socket is closed.
0534 *
0535 * @return a <code>SocketAddress</code> representing the remote
0536 * endpoint of this socket, or <code>null</code> if it is
0537 * not connected yet.
0538 * @see #getInetAddress()
0539 * @see #getPort()
0540 * @see #connect(SocketAddress)
0541 * @since 1.4
0542 */
0543 public SocketAddress getRemoteSocketAddress() {
0544 if (!isConnected())
0545 return null;
0546 return new InetSocketAddress(getInetAddress(), getPort());
0547 }
0548
0549 /**
0550 * Returns the address of the endpoint this socket is bound to.
0551 *
0552 * @return a <code>SocketAddress</code> representing the local endpoint of this
0553 * socket, or <code>null</code> if it is closed or not bound yet.
0554 * @see #getLocalAddress()
0555 * @see #getLocalPort()
0556 * @see #bind(SocketAddress)
0557 * @since 1.4
0558 */
0559
0560 public SocketAddress getLocalSocketAddress() {
0561 if (isClosed())
0562 return null;
0563 if (!isBound())
0564 return null;
0565 return new InetSocketAddress(getLocalAddress(), getLocalPort());
0566 }
0567
0568 /**
0569 * Sends a datagram packet from this socket. The
0570 * <code>DatagramPacket</code> includes information indicating the
0571 * data to be sent, its length, the IP address of the remote host,
0572 * and the port number on the remote host.
0573 *
0574 * <p>If there is a security manager, and the socket is not currently
0575 * connected to a remote address, this method first performs some
0576 * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
0577 * is true, this method calls the
0578 * security manager's <code>checkMulticast</code> method
0579 * with <code>p.getAddress()</code> as its argument.
0580 * If the evaluation of that expression is false,
0581 * this method instead calls the security manager's
0582 * <code>checkConnect</code> method with arguments
0583 * <code>p.getAddress().getHostAddress()</code> and
0584 * <code>p.getPort()</code>. Each call to a security manager method
0585 * could result in a SecurityException if the operation is not allowed.
0586 *
0587 * @param p the <code>DatagramPacket</code> to be sent.
0588 *
0589 * @exception IOException if an I/O error occurs.
0590 * @exception SecurityException if a security manager exists and its
0591 * <code>checkMulticast</code> or <code>checkConnect</code>
0592 * method doesn't allow the send.
0593 * @exception PortUnreachableException may be thrown if the socket is connected
0594 * to a currently unreachable destination. Note, there is no
0595 * guarantee that the exception will be thrown.
0596 * @exception java.nio.channels.IllegalBlockingModeException
0597 * if this socket has an associated channel,
0598 * and the channel is in non-blocking mode.
0599 * @exception IllegalArgumentException if the socket is connected,
0600 * and connected address and packet address differ.
0601 *
0602 * @see java.net.DatagramPacket
0603 * @see SecurityManager#checkMulticast(InetAddress)
0604 * @see SecurityManager#checkConnect
0605 * @revised 1.4
0606 * @spec JSR-51
0607 */
0608 public void send(DatagramPacket p) throws IOException {
0609 InetAddress packetAddress = null;
0610 synchronized (p) {
0611 if (isClosed())
0612 throw new SocketException("Socket is closed");
0613 if (connectState == ST_NOT_CONNECTED) {
0614 // check the address is ok wiht the security manager on every send.
0615 SecurityManager security = System.getSecurityManager();
0616
0617 // The reason you want to synchronize on datagram packet
0618 // is because you dont want an applet to change the address
0619 // while you are trying to send the packet for example
0620 // after the security check but before the send.
0621 if (security != null) {
0622 if (p.getAddress().isMulticastAddress()) {
0623 security.checkMulticast(p.getAddress());
0624 } else {
0625 security.checkConnect(p.getAddress()
0626 .getHostAddress(), p.getPort());
0627 }
0628 }
0629 } else {
0630 // we're connected
0631 packetAddress = p.getAddress();
0632 if (packetAddress == null) {
0633 p.setAddress(connectedAddress);
0634 p.setPort(connectedPort);
0635 } else if ((!packetAddress.equals(connectedAddress))
0636 || p.getPort() != connectedPort) {
0637 throw new IllegalArgumentException(
0638 "connected address " + "and packet address"
0639 + " differ");
0640 }
0641 }
0642 // Check whether the socket is bound
0643 if (!isBound())
0644 bind(new InetSocketAddress(0));
0645 // call the method to send
0646 getImpl().send(p);
0647 }
0648 }
0649
0650 /**
0651 * Receives a datagram packet from this socket. When this method
0652 * returns, the <code>DatagramPacket</code>'s buffer is filled with
0653 * the data received. The datagram packet also contains the sender's
0654 * IP address, and the port number on the sender's machine.
0655 * <p>
0656 * This method blocks until a datagram is received. The
0657 * <code>length</code> field of the datagram packet object contains
0658 * the length of the received message. If the message is longer than
0659 * the packet's length, the message is truncated.
0660 * <p>
0661 * If there is a security manager, a packet cannot be received if the
0662 * security manager's <code>checkAccept</code> method
0663 * does not allow it.
0664 *
0665 * @param p the <code>DatagramPacket</code> into which to place
0666 * the incoming data.
0667 * @exception IOException if an I/O error occurs.
0668 * @exception SocketTimeoutException if setSoTimeout was previously called
0669 * and the timeout has expired.
0670 * @exception PortUnreachableException may be thrown if the socket is connected
0671 * to a currently unreachable destination. Note, there is no guarantee that the
0672 * exception will be thrown.
0673 * @exception java.nio.channels.IllegalBlockingModeException
0674 * if this socket has an associated channel,
0675 * and the channel is in non-blocking mode.
0676 * @see java.net.DatagramPacket
0677 * @see java.net.DatagramSocket
0678 * @revised 1.4
0679 * @spec JSR-51
0680 */
0681 public synchronized void receive(DatagramPacket p)
0682 throws IOException {
0683 synchronized (p) {
0684 if (!isBound())
0685 bind(new InetSocketAddress(0));
0686 if (connectState == ST_NOT_CONNECTED) {
0687 // check the address is ok with the security manager before every recv.
0688 SecurityManager security = System.getSecurityManager();
0689 if (security != null) {
0690 while (true) {
0691 String peekAd = null;
0692 int peekPort = 0;
0693 // peek at the packet to see who it is from.
0694 if (!oldImpl) {
0695 // We can use the new peekData() API
0696 DatagramPacket peekPacket = new DatagramPacket(
0697 new byte[1], 1);
0698 peekPort = getImpl().peekData(peekPacket);
0699 peekAd = peekPacket.getAddress()
0700 .getHostAddress();
0701 } else {
0702 InetAddress adr = new InetAddress();
0703 peekPort = getImpl().peek(adr);
0704 peekAd = adr.getHostAddress();
0705 }
0706 try {
0707 security.checkAccept(peekAd, peekPort);
0708 // security check succeeded - so now break
0709 // and recv the packet.
0710 break;
0711 } catch (SecurityException se) {
0712 // Throw away the offending packet by consuming
0713 // it in a tmp buffer.
0714 DatagramPacket tmp = new DatagramPacket(
0715 new byte[1], 1);
0716 getImpl().receive(tmp);
0717
0718 // silently discard the offending packet
0719 // and continue: unknown/malicious
0720 // entities on nets should not make
0721 // runtime throw security exception and
0722 // disrupt the applet by sending random
0723 // datagram packets.
0724 continue;
0725 }
0726 } // end of while
0727 }
0728 }
0729 if (connectState == ST_CONNECTED_NO_IMPL) {
0730 // We have to do the filtering the old fashioned way since
0731 // the native impl doesn't support connect or the connect
0732 // via the impl failed.
0733 boolean stop = false;
0734 while (!stop) {
0735 // peek at the packet to see who it is from.
0736 InetAddress peekAddress = new InetAddress();
0737 int peekPort = getImpl().peek(peekAddress);
0738 if ((!connectedAddress.equals(peekAddress))
0739 || (connectedPort != peekPort)) {
0740 // throw the packet away and silently continue
0741 DatagramPacket tmp = new DatagramPacket(
0742 new byte[1], 1);
0743 getImpl().receive(tmp);
0744 } else {
0745 stop = true;
0746 }
0747 }
0748 }
0749 // If the security check succeeds, or the datagram is
0750 // connected then receive the packet
0751 getImpl().receive(p);
0752 }
0753 }
0754
0755 /**
0756 * Gets the local address to which the socket is bound.
0757 *
0758 * <p>If there is a security manager, its
0759 * <code>checkConnect</code> method is first called
0760 * with the host address and <code>-1</code>
0761 * as its arguments to see if the operation is allowed.
0762 *
0763 * @see SecurityManager#checkConnect
0764 * @return the local address to which the socket is bound,
0765 * <code>null</code> if the socket is closed, or
0766 * an <code>InetAddress</code> representing
0767 * {@link InetAddress#isAnyLocalAddress wildcard}
0768 * address if either the socket is not bound, or
0769 * the security manager <code>checkConnect</code>
0770 * method does not allow the operation
0771 * @since 1.1
0772 */
0773 public InetAddress getLocalAddress() {
0774 if (isClosed())
0775 return null;
0776 InetAddress in = null;
0777 try {
0778 in = (InetAddress) getImpl().getOption(
0779 SocketOptions.SO_BINDADDR);
0780 if (in.isAnyLocalAddress()) {
0781 in = InetAddress.anyLocalAddress();
0782 }
0783 SecurityManager s = System.getSecurityManager();
0784 if (s != null) {
0785 s.checkConnect(in.getHostAddress(), -1);
0786 }
0787 } catch (Exception e) {
0788 in = InetAddress.anyLocalAddress(); // "0.0.0.0"
0789 }
0790 return in;
0791 }
0792
0793 /**
0794 * Returns the port number on the local host to which this socket
0795 * is bound.
0796 *
0797 * @return the port number on the local host to which this socket is bound,
0798 <code>-1</code> if the socket is closed, or
0799 <code>0</code> if it is not bound yet.
0800 */
0801 public int getLocalPort() {
0802 if (isClosed())
0803 return -1;
0804 try {
0805 return getImpl().getLocalPort();
0806 } catch (Exception e) {
0807 return 0;
0808 }
0809 }
0810
0811 /** Enable/disable SO_TIMEOUT with the specified timeout, in
0812 * milliseconds. With this option set to a non-zero timeout,
0813 * a call to receive() for this DatagramSocket
0814 * will block for only this amount of time. If the timeout expires,
0815 * a <B>java.net.SocketTimeoutException</B> is raised, though the
0816 * DatagramSocket is still valid. The option <B>must</B> be enabled
0817 * prior to entering the blocking operation to have effect. The
0818 * timeout must be > 0.
0819 * A timeout of zero is interpreted as an infinite timeout.
0820 *
0821 * @param timeout the specified timeout in milliseconds.
0822 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
0823 * @since JDK1.1
0824 * @see #getSoTimeout()
0825 */
0826 public synchronized void setSoTimeout(int timeout)
0827 throws SocketException {
0828 if (isClosed())
0829 throw new SocketException("Socket is closed");
0830 getImpl().setOption(SocketOptions.SO_TIMEOUT,
0831 new Integer(timeout));
0832 }
0833
0834 /**
0835 * Retrieve setting for SO_TIMEOUT. 0 returns implies that the
0836 * option is disabled (i.e., timeout of infinity).
0837 *
0838 * @return the setting for SO_TIMEOUT
0839 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
0840 * @since JDK1.1
0841 * @see #setSoTimeout(int)
0842 */
0843 public synchronized int getSoTimeout() throws SocketException {
0844 if (isClosed())
0845 throw new SocketException("Socket is closed");
0846 if (getImpl() == null)
0847 return 0;
0848 Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
0849 /* extra type safety */
0850 if (o instanceof Integer) {
0851 return ((Integer) o).intValue();
0852 } else {
0853 return 0;
0854 }
0855 }
0856
0857 /**
0858 * Sets the SO_SNDBUF option to the specified value for this
0859 * <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the
0860 * network implementation as a hint to size the underlying
0861 * network I/O buffers. The SO_SNDBUF setting may also be used
0862 * by the network implementation to determine the maximum size
0863 * of the packet that can be sent on this socket.
0864 * <p>
0865 * As SO_SNDBUF is a hint, applications that want to verify
0866 * what size the buffer is should call {@link #getSendBufferSize()}.
0867 * <p>
0868 * Increasing the buffer size may allow multiple outgoing packets
0869 * to be queued by the network implementation when the send rate
0870 * is high.
0871 * <p>
0872 * Note: If {@link #send(DatagramPacket)} is used to send a
0873 * <code>DatagramPacket</code> that is larger than the setting
0874 * of SO_SNDBUF then it is implementation specific if the
0875 * packet is sent or discarded.
0876 *
0877 * @param size the size to which to set the send buffer
0878 * size. This value must be greater than 0.
0879 *
0880 * @exception SocketException if there is an error
0881 * in the underlying protocol, such as an UDP error.
0882 * @exception IllegalArgumentException if the value is 0 or is
0883 * negative.
0884 * @see #getSendBufferSize()
0885 */
0886 public synchronized void setSendBufferSize(int size)
0887 throws SocketException {
0888 if (!(size > 0)) {
0889 throw new IllegalArgumentException("negative send size");
0890 }
0891 if (isClosed())
0892 throw new SocketException("Socket is closed");
0893 getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
0894 }
0895
0896 /**
0897 * Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that is the
0898 * buffer size used by the platform for output on this <tt>DatagramSocket</tt>.
0899 *
0900 * @return the value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>
0901 * @exception SocketException if there is an error in
0902 * the underlying protocol, such as an UDP error.
0903 * @see #setSendBufferSize
0904 */
0905 public synchronized int getSendBufferSize() throws SocketException {
0906 if (isClosed())
0907 throw new SocketException("Socket is closed");
0908 int result = 0;
0909 Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
0910 if (o instanceof Integer) {
0911 result = ((Integer) o).intValue();
0912 }
0913 return result;
0914 }
0915
0916 /**
0917 * Sets the SO_RCVBUF option to the specified value for this
0918 * <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the
0919 * the network implementation as a hint to size the underlying
0920 * network I/O buffers. The SO_RCVBUF setting may also be used
0921 * by the network implementation to determine the maximum size
0922 * of the packet that can be received on this socket.
0923 * <p>
0924 * Because SO_RCVBUF is a hint, applications that want to
0925 * verify what size the buffers were set to should call
0926 * {@link #getReceiveBufferSize()}.
0927 * <p>
0928 * Increasing SO_RCVBUF may allow the network implementation
0929 * to buffer multiple packets when packets arrive faster than
0930 * are being received using {@link #receive(DatagramPacket)}.
0931 * <p>
0932 * Note: It is implementation specific if a packet larger
0933 * than SO_RCVBUF can be received.
0934 *
0935 * @param size the size to which to set the receive buffer
0936 * size. This value must be greater than 0.
0937 *
0938 * @exception SocketException if there is an error in
0939 * the underlying protocol, such as an UDP error.
0940 * @exception IllegalArgumentException if the value is 0 or is
0941 * negative.
0942 * @see #getReceiveBufferSize()
0943 */
0944 public synchronized void setReceiveBufferSize(int size)
0945 throws SocketException {
0946 if (size <= 0) {
0947 throw new IllegalArgumentException("invalid receive size");
0948 }
0949 if (isClosed())
0950 throw new SocketException("Socket is closed");
0951 getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
0952 }
0953
0954 /**
0955 * Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that is the
0956 * buffer size used by the platform for input on this <tt>DatagramSocket</tt>.
0957 *
0958 * @return the value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>
0959 * @exception SocketException if there is an error in the underlying protocol, such as an UDP error.
0960 * @see #setReceiveBufferSize(int)
0961 */
0962 public synchronized int getReceiveBufferSize()
0963 throws SocketException {
0964 if (isClosed())
0965 throw new SocketException("Socket is closed");
0966 int result = 0;
0967 Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
0968 if (o instanceof Integer) {
0969 result = ((Integer) o).intValue();
0970 }
0971 return result;
0972 }
0973
0974 /**
0975 * Enable/disable the SO_REUSEADDR socket option.
0976 * <p>
0977 * For UDP sockets it may be necessary to bind more than one
0978 * socket to the same socket address. This is typically for the
0979 * purpose of receiving multicast packets
0980 * (See {@link java.net.MulticastSocket}). The
0981 * <tt>SO_REUSEADDR</tt> socket option allows multiple
0982 * sockets to be bound to the same socket address if the
0983 * <tt>SO_REUSEADDR</tt> socket option is enabled prior
0984 * to binding the socket using {@link #bind(SocketAddress)}.
0985 * <p>
0986 * Note: This functionality is not supported by all existing platforms,
0987 * so it is implementation specific whether this option will be ignored
0988 * or not. However, if it is not supported then
0989 * {@link #getReuseAddress()} will always return <code>false</code>.
0990 * <p>
0991 * When a <tt>DatagramSocket</tt> is created the initial setting
0992 * of <tt>SO_REUSEADDR</tt> is disabled.
0993 * <p>
0994 * The behaviour when <tt>SO_REUSEADDR</tt> is enabled or
0995 * disabled after a socket is bound (See {@link #isBound()})
0996 * is not defined.
0997 *
0998 * @param on whether to enable or disable the
0999 * @exception SocketException if an error occurs enabling or
1000 * disabling the <tt>SO_RESUEADDR</tt> socket option,
1001 * or the socket is closed.
1002 * @since 1.4
1003 * @see #getReuseAddress()
1004 * @see #bind(SocketAddress)
1005 * @see #isBound()
1006 * @see #isClosed()
1007 */
1008 public synchronized void setReuseAddress(boolean on)
1009 throws SocketException {
1010 if (isClosed())
1011 throw new SocketException("Socket is closed");
1012 // Integer instead of Boolean for compatibility with older DatagramSocketImpl
1013 if (oldImpl)
1014 getImpl().setOption(SocketOptions.SO_REUSEADDR,
1015 new Integer(on ? -1 : 0));
1016 else
1017 getImpl().setOption(SocketOptions.SO_REUSEADDR,
1018 Boolean.valueOf(on));
1019 }
1020
1021 /**
1022 * Tests if SO_REUSEADDR is enabled.
1023 *
1024 * @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is enabled.
1025 * @exception SocketException if there is an error
1026 * in the underlying protocol, such as an UDP error.
1027 * @since 1.4
1028 * @see #setReuseAddress(boolean)
1029 */
1030 public synchronized boolean getReuseAddress()
1031 throws SocketException {
1032 if (isClosed())
1033 throw new SocketException("Socket is closed");
1034 Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1035 return ((Boolean) o).booleanValue();
1036 }
1037
1038 /**
1039 * Enable/disable SO_BROADCAST.
1040 * @param on whether or not to have broadcast turned on.
1041 * @exception SocketException if there is an error
1042 * in the underlying protocol, such as an UDP error.
1043 * @since 1.4
1044 * @see #getBroadcast()
1045 */
1046 public synchronized void setBroadcast(boolean on)
1047 throws SocketException {
1048 if (isClosed())
1049 throw new SocketException("Socket is closed");
1050 getImpl().setOption(SocketOptions.SO_BROADCAST,
1051 Boolean.valueOf(on));
1052 }
1053
1054 /**
1055 * Tests if SO_BROADCAST is enabled.
1056 * @return a <code>boolean</code> indicating whether or not SO_BROADCAST is enabled.
1057 * @exception SocketException if there is an error
1058 * in the underlying protocol, such as an UDP error.
1059 * @since 1.4
1060 * @see #setBroadcast(boolean)
1061 */
1062 public synchronized boolean getBroadcast() throws SocketException {
1063 if (isClosed())
1064 throw new SocketException("Socket is closed");
1065 return ((Boolean) (getImpl()
1066 .getOption(SocketOptions.SO_BROADCAST))).booleanValue();
1067 }
1068
1069 /**
1070 * Sets traffic class or type-of-service octet in the IP
1071 * datagram header for datagrams sent from this DatagramSocket.
1072 * As the underlying network implementation may ignore this
1073 * value applications should consider it a hint.
1074 *
1075 * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
1076 * 255</code> or an IllegalArgumentException will be thrown.
1077 * <p>Notes:
1078 * <p>For Internet Protocol v4 the value consists of an
1079 * <code>integer</code>, the least significant 8 bits of which
1080 * represent the value of the TOS octet in IP packets sent by
1081 * the socket.
1082 * RFC 1349 defines the TOS values as follows:
1083 * <p>
1084 * <UL>
1085 * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
1086 * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
1087 * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
1088 * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
1089 * </UL>
1090 * The last low order bit is always ignored as this
1091 * corresponds to the MBZ (must be zero) bit.
1092 * <p>
1093 * Setting bits in the precedence field may result in a
1094 * SocketException indicating that the operation is not
1095 * permitted.
1096 * <p>
1097 * for Internet Protocol v6 <code>tc</code> is the value that
1098 * would be placed into the sin6_flowinfo field of the IP header.
1099 *
1100 * @param tc an <code>int</code> value for the bitset.
1101 * @throws SocketException if there is an error setting the
1102 * traffic class or type-of-service
1103 * @since 1.4
1104 * @see #getTrafficClass
1105 */
1106 public synchronized void setTrafficClass(int tc)
1107 throws SocketException {
1108 if (tc < 0 || tc > 255)
1109 throw new IllegalArgumentException(
1110 "tc is not in range 0 -- 255");
1111
1112 if (isClosed())
1113 throw new SocketException("Socket is closed");
1114 getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
1115 }
1116
1117 /**
1118 * Gets traffic class or type-of-service in the IP datagram
1119 * header for packets sent from this DatagramSocket.
1120 * <p>
1121 * As the underlying network implementation may ignore the
1122 * traffic class or type-of-service set using {@link #setTrafficClass(int)}
1123 * this method may return a different value than was previously
1124 * set using the {@link #setTrafficClass(int)} method on this
1125 * DatagramSocket.
1126 *
1127 * @return the traffic class or type-of-service already set
1128 * @throws SocketException if there is an error obtaining the
1129 * traffic class or type-of-service value.
1130 * @since 1.4
1131 * @see #setTrafficClass(int)
1132 */
1133 public synchronized int getTrafficClass() throws SocketException {
1134 if (isClosed())
1135 throw new SocketException("Socket is closed");
1136 return ((Integer) (getImpl().getOption(SocketOptions.IP_TOS)))
1137 .intValue();
1138 }
1139
1140 /**
1141 * Closes this datagram socket.
1142 * <p>
1143 * Any thread currently blocked in {@link #receive} upon this socket
1144 * will throw a {@link SocketException}.
1145 *
1146 * <p> If this socket has an associated channel then the channel is closed
1147 * as well.
1148 *
1149 * @revised 1.4
1150 * @spec JSR-51
1151 */
1152 public void close() {
1153 synchronized (closeLock) {
1154 if (isClosed())
1155 return;
1156 impl.close();
1157 closed = true;
1158 }
1159 }
1160
1161 /**
1162 * Returns whether the socket is closed or not.
1163 *
1164 * @return true if the socket has been closed
1165 * @since 1.4
1166 */
1167 public boolean isClosed() {
1168 synchronized (closeLock) {
1169 return closed;
1170 }
1171 }
1172
1173 /**
1174 * Returns the unique {@link java.nio.channels.DatagramChannel} object
1175 * associated with this datagram socket, if any.
1176 *
1177 * <p> A datagram socket will have a channel if, and only if, the channel
1178 * itself was created via the {@link java.nio.channels.DatagramChannel#open
1179 * DatagramChannel.open} method.
1180 *
1181 * @return the datagram channel associated with this datagram socket,
1182 * or <tt>null</tt> if this socket was not created for a channel
1183 *
1184 * @since 1.4
1185 * @spec JSR-51
1186 */
1187 public DatagramChannel getChannel() {
1188 return null;
1189 }
1190
1191 /**
1192 * User defined factory for all datagram sockets.
1193 */
1194 static DatagramSocketImplFactory factory;
1195
1196 /**
1197 * Sets the datagram socket implementation factory for the
1198 * application. The factory can be specified only once.
1199 * <p>
1200 * When an application creates a new datagram socket, the socket
1201 * implementation factory's <code>createDatagramSocketImpl</code> method is
1202 * called to create the actual datagram socket implementation.
1203 * <p>
1204 * Passing <code>null</code> to the method is a no-op unless the factory
1205 * was already set.
1206 *
1207 * <p>If there is a security manager, this method first calls
1208 * the security manager's <code>checkSetFactory</code> method
1209 * to ensure the operation is allowed.
1210 * This could result in a SecurityException.
1211 *
1212 * @param fac the desired factory.
1213 * @exception IOException if an I/O error occurs when setting the
1214 * datagram socket factory.
1215 * @exception SocketException if the factory is already defined.
1216 * @exception SecurityException if a security manager exists and its
1217 * <code>checkSetFactory</code> method doesn't allow the
1218 operation.
1219 * @see
1220 java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
1221 * @see SecurityManager#checkSetFactory
1222 * @since 1.3
1223 */
1224 public static synchronized void setDatagramSocketImplFactory(
1225 DatagramSocketImplFactory fac) throws IOException {
1226 if (factory != null) {
1227 throw new SocketException("factory already defined");
1228 }
1229 SecurityManager security = System.getSecurityManager();
1230 if (security != null) {
1231 security.checkSetFactory();
1232 }
1233 factory = fac;
1234 }
1235 }
|