| /* DatagramSocket.java -- A class to model UDP sockets |
| Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004 |
| Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package java.net; |
| |
| import gnu.java.net.PlainDatagramSocketImpl; |
| import gnu.java.nio.DatagramChannelImpl; |
| |
| import java.io.IOException; |
| import java.nio.channels.DatagramChannel; |
| import java.nio.channels.IllegalBlockingModeException; |
| |
| |
| /** |
| * Written using on-line Java Platform 1.2 API Specification, as well |
| * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). |
| * Status: Believed complete and correct. |
| */ |
| /** |
| * This class models a connectionless datagram socket that sends |
| * individual packets of data across the network. In the TCP/IP world, |
| * this means UDP. Datagram packets do not have guaranteed delivery, |
| * or any guarantee about the order the data will be received on the |
| * remote host. |
| * |
| * @author Aaron M. Renn (arenn@urbanophile.com) |
| * @author Warren Levy (warrenl@cygnus.com) |
| * @date May 3, 1999. |
| */ |
| public class DatagramSocket |
| { |
| /** |
| * This is the user DatagramSocketImplFactory for this class. If this |
| * variable is null, a default factory is used. |
| */ |
| private static DatagramSocketImplFactory factory; |
| |
| /** |
| * This is the implementation object used by this socket. |
| */ |
| private DatagramSocketImpl impl; |
| |
| /** |
| * True if socket implementation was created. |
| */ |
| private boolean implCreated; |
| |
| /** |
| * This is the address we are "connected" to |
| */ |
| private InetAddress remoteAddress; |
| |
| /** |
| * This is the port we are "connected" to |
| */ |
| private int remotePort = -1; |
| |
| /** |
| * True if socket is bound. |
| */ |
| private boolean bound; |
| |
| /** |
| * Creates a <code>DatagramSocket</code> from a specified |
| * <code>DatagramSocketImpl</code> instance |
| * |
| * @param impl The <code>DatagramSocketImpl</code> the socket will be |
| * created from |
| * |
| * @since 1.4 |
| */ |
| protected DatagramSocket(DatagramSocketImpl impl) |
| { |
| if (impl == null) |
| throw new NullPointerException("impl may not be null"); |
| |
| this.impl = impl; |
| this.remoteAddress = null; |
| this.remotePort = -1; |
| } |
| |
| /** |
| * Initializes a new instance of <code>DatagramSocket</code> that binds to |
| * a random port and every address on the local machine. |
| * |
| * @exception SocketException If an error occurs. |
| * @exception SecurityException If a security manager exists and |
| * its <code>checkListen</code> method doesn't allow the operation. |
| */ |
| public DatagramSocket() throws SocketException |
| { |
| this(new InetSocketAddress(0)); |
| } |
| |
| /** |
| * Initializes a new instance of <code>DatagramSocket</code> that binds to |
| * the specified port and every address on the local machine. |
| * |
| * @param port The local port number to bind to. |
| * |
| * @exception SecurityException If a security manager exists and its |
| * <code>checkListen</code> method doesn't allow the operation. |
| * @exception SocketException If an error occurs. |
| */ |
| public DatagramSocket(int port) throws SocketException |
| { |
| this(new InetSocketAddress(port)); |
| } |
| |
| /** |
| * Initializes a new instance of <code>DatagramSocket</code> that binds to |
| * the specified local port and address. |
| * |
| * @param port The local port number to bind to. |
| * @param addr The local address to bind to. |
| * |
| * @exception SecurityException If a security manager exists and its |
| * checkListen method doesn't allow the operation. |
| * @exception SocketException If an error occurs. |
| */ |
| public DatagramSocket(int port, InetAddress addr) throws SocketException |
| { |
| this(new InetSocketAddress(addr, port)); |
| } |
| |
| /** |
| * Initializes a new instance of <code>DatagramSocket</code> that binds to |
| * the specified local port and address. |
| * |
| * @param address The local address and port number to bind to. |
| * |
| * @exception SecurityException If a security manager exists and its |
| * <code>checkListen</code> method doesn't allow the operation. |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.4 |
| */ |
| public DatagramSocket(SocketAddress address) throws SocketException |
| { |
| String propVal = System.getProperty("impl.prefix"); |
| if (propVal == null || propVal.equals("")) |
| impl = new PlainDatagramSocketImpl(); |
| else |
| try |
| { |
| impl = |
| (DatagramSocketImpl) Class.forName("java.net." + propVal |
| + "DatagramSocketImpl") |
| .newInstance(); |
| } |
| catch (Exception e) |
| { |
| System.err.println("Could not instantiate class: java.net." |
| + propVal + "DatagramSocketImpl"); |
| impl = new PlainDatagramSocketImpl(); |
| } |
| |
| if (address != null) |
| bind(address); |
| } |
| |
| // This needs to be accessible from java.net.MulticastSocket |
| DatagramSocketImpl getImpl() throws SocketException |
| { |
| try |
| { |
| if (! implCreated) |
| { |
| impl.create(); |
| implCreated = true; |
| } |
| |
| return impl; |
| } |
| catch (IOException e) |
| { |
| throw new SocketException(e.getMessage()); |
| } |
| } |
| |
| /** |
| * Closes this datagram socket. |
| */ |
| public void close() |
| { |
| if (isClosed()) |
| return; |
| |
| try |
| { |
| getImpl().close(); |
| } |
| catch (SocketException e) |
| { |
| // Ignore this case, just close the socket in finally clause. |
| } |
| finally |
| { |
| remoteAddress = null; |
| remotePort = -1; |
| impl = null; |
| } |
| |
| try |
| { |
| if (getChannel() != null) |
| getChannel().close(); |
| } |
| catch (IOException e) |
| { |
| // Do nothing. |
| } |
| } |
| |
| /** |
| * This method returns the remote address to which this socket is |
| * connected. If this socket is not connected, then this method will |
| * return <code>null</code>. |
| * |
| * @return The remote address. |
| * |
| * @since 1.2 |
| */ |
| public InetAddress getInetAddress() |
| { |
| return remoteAddress; |
| } |
| |
| /** |
| * This method returns the remote port to which this socket is |
| * connected. If this socket is not connected, then this method will |
| * return -1. |
| * |
| * @return The remote port. |
| * |
| * @since 1.2 |
| */ |
| public int getPort() |
| { |
| return remotePort; |
| } |
| |
| /** |
| * Returns the local address this datagram socket is bound to. |
| * |
| * @return The local address is the socket is bound or null |
| * |
| * @since 1.1 |
| */ |
| public InetAddress getLocalAddress() |
| { |
| if (! isBound()) |
| return null; |
| |
| InetAddress localAddr; |
| |
| try |
| { |
| localAddr = |
| (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); |
| |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| s.checkConnect(localAddr.getHostName(), -1); |
| } |
| catch (SecurityException e) |
| { |
| localAddr = InetAddress.ANY_IF; |
| } |
| catch (SocketException e) |
| { |
| // This cannot happen as we are bound. |
| return null; |
| } |
| |
| return localAddr; |
| } |
| |
| /** |
| * Returns the local port this socket is bound to. |
| * |
| * @return The local port number. |
| */ |
| public int getLocalPort() |
| { |
| if (isClosed()) |
| return -1; |
| |
| try |
| { |
| return getImpl().getLocalPort(); |
| } |
| catch (SocketException e) |
| { |
| // This cannot happen as we are bound. |
| return 0; |
| } |
| } |
| |
| /** |
| * Returns the value of the socket's SO_TIMEOUT setting. If this method |
| * returns 0 then SO_TIMEOUT is disabled. |
| * |
| * @return The current timeout in milliseconds. |
| * |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.1 |
| */ |
| public synchronized int getSoTimeout() throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT); |
| |
| if (buf instanceof Integer) |
| return ((Integer) buf).intValue(); |
| |
| throw new SocketException("unexpected type"); |
| } |
| |
| /** |
| * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will |
| * disable SO_TIMEOUT. Any other value is the number of milliseconds |
| * a socket read/write will block before timing out. |
| * |
| * @param timeout The new SO_TIMEOUT value in milliseconds. |
| * |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.1 |
| */ |
| public synchronized void setSoTimeout(int timeout) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (timeout < 0) |
| throw new IllegalArgumentException("Invalid timeout: " + timeout); |
| |
| getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); |
| } |
| |
| /** |
| * This method returns the value of the system level socket option |
| * SO_SNDBUF, which is used by the operating system to tune buffer |
| * sizes for data transfers. |
| * |
| * @return The send buffer size. |
| * |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.2 |
| */ |
| public int getSendBufferSize() throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF); |
| |
| if (buf instanceof Integer) |
| return ((Integer) buf).intValue(); |
| |
| throw new SocketException("unexpected type"); |
| } |
| |
| /** |
| * This method sets the value for the system level socket option |
| * SO_SNDBUF to the specified value. Note that valid values for this |
| * option are specific to a given operating system. |
| * |
| * @param size The new send buffer size. |
| * |
| * @exception SocketException If an error occurs. |
| * @exception IllegalArgumentException If size is 0 or negative. |
| * |
| * @since 1.2 |
| */ |
| public void setSendBufferSize(int size) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (size < 0) |
| throw new IllegalArgumentException("Buffer size is less than 0"); |
| |
| getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size)); |
| } |
| |
| /** |
| * This method returns the value of the system level socket option |
| * SO_RCVBUF, which is used by the operating system to tune buffer |
| * sizes for data transfers. |
| * |
| * @return The receive buffer size. |
| * |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.2 |
| */ |
| public int getReceiveBufferSize() throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF); |
| |
| if (buf instanceof Integer) |
| return ((Integer) buf).intValue(); |
| |
| throw new SocketException("unexpected type"); |
| } |
| |
| /** |
| * This method sets the value for the system level socket option |
| * SO_RCVBUF to the specified value. Note that valid values for this |
| * option are specific to a given operating system. |
| * |
| * @param size The new receive buffer size. |
| * |
| * @exception SocketException If an error occurs. |
| * @exception IllegalArgumentException If size is 0 or negative. |
| * |
| * @since 1.2 |
| */ |
| public void setReceiveBufferSize(int size) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (size < 0) |
| throw new IllegalArgumentException("Buffer size is less than 0"); |
| |
| getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size)); |
| } |
| |
| /** |
| * This method connects this socket to the specified address and port. |
| * When a datagram socket is connected, it will only send or receive |
| * packets to and from the host to which it is connected. A multicast |
| * socket that is connected may only send and not receive packets. |
| * |
| * @param address The address to connect this socket to. |
| * @param port The port to connect this socket to. |
| * |
| * @exception SocketException If an error occurs. |
| * @exception IllegalArgumentException If address or port are invalid. |
| * @exception SecurityException If the caller is not allowed to send |
| * datagrams to or receive from this address and port. |
| * |
| * @since 1.2 |
| */ |
| public void connect(InetAddress address, int port) |
| { |
| if (address == null) |
| throw new IllegalArgumentException("Connect address may not be null"); |
| |
| if ((port < 1) || (port > 65535)) |
| throw new IllegalArgumentException("Port number is illegal: " + port); |
| |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) |
| sm.checkConnect(address.getHostName(), port); |
| |
| try |
| { |
| getImpl().connect(address, port); |
| remoteAddress = address; |
| remotePort = port; |
| } |
| catch (SocketException e) |
| { |
| // This means simply not connected or connect not implemented. |
| } |
| } |
| |
| /** |
| * This method disconnects this socket from the address/port it was |
| * connected to. If the socket was not connected in the first place, |
| * this method does nothing. |
| * |
| * @since 1.2 |
| */ |
| public void disconnect() |
| { |
| if (! isConnected()) |
| return; |
| |
| try |
| { |
| getImpl().disconnect(); |
| } |
| catch (SocketException e) |
| { |
| // This cannot happen as we are connected. |
| } |
| finally |
| { |
| remoteAddress = null; |
| remotePort = -1; |
| } |
| } |
| |
| /** |
| * Reads a datagram packet from the socket. Note that this method |
| * will block until a packet is received from the network. On return, |
| * the passed in <code>DatagramPacket</code> is populated with the data |
| * received and all the other information about the packet. |
| * |
| * @param p A <code>DatagramPacket</code> for storing the data |
| * |
| * @exception IOException If an error occurs. |
| * @exception SocketTimeoutException If setSoTimeout was previously called |
| * and the timeout has expired. |
| * @exception PortUnreachableException If the socket is connected to a |
| * currently unreachable destination. Note, there is no guarantee that the |
| * exception will be thrown. |
| * @exception IllegalBlockingModeException If this socket has an associated |
| * channel, and the channel is in non-blocking mode. |
| * @exception SecurityException If a security manager exists and its |
| * checkAccept method doesn't allow the receive. |
| */ |
| public synchronized void receive(DatagramPacket p) throws IOException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (remoteAddress != null && remoteAddress.isMulticastAddress()) |
| throw new IOException |
| ("Socket connected to a multicast address my not receive"); |
| |
| if (getChannel() != null && ! getChannel().isBlocking() |
| && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) |
| throw new IllegalBlockingModeException(); |
| |
| getImpl().receive(p); |
| |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null && isConnected()) |
| s.checkAccept(p.getAddress().getHostName(), p.getPort()); |
| } |
| |
| /** |
| * Sends the specified packet. The host and port to which the packet |
| * are to be sent should be set inside the packet. |
| * |
| * @param p The datagram packet to send. |
| * |
| * @exception IOException If an error occurs. |
| * @exception SecurityException If a security manager exists and its |
| * checkMulticast or checkConnect method doesn't allow the send. |
| * @exception PortUnreachableException If the socket is connected to a |
| * currently unreachable destination. Note, there is no guarantee that the |
| * exception will be thrown. |
| * @exception IllegalBlockingModeException If this socket has an associated |
| * channel, and the channel is in non-blocking mode. |
| */ |
| public void send(DatagramPacket p) throws IOException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api. |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null && ! isConnected()) |
| { |
| InetAddress addr = p.getAddress(); |
| if (addr.isMulticastAddress()) |
| s.checkMulticast(addr); |
| else |
| s.checkConnect(addr.getHostAddress(), p.getPort()); |
| } |
| |
| if (isConnected()) |
| { |
| if (p.getAddress() != null |
| && (remoteAddress != p.getAddress() || remotePort != p.getPort())) |
| throw new IllegalArgumentException |
| ("DatagramPacket address does not match remote address"); |
| } |
| |
| // FIXME: if this is a subclass of MulticastSocket, |
| // use getTimeToLive for TTL val. |
| if (getChannel() != null && ! getChannel().isBlocking() |
| && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) |
| throw new IllegalBlockingModeException(); |
| |
| getImpl().send(p); |
| } |
| |
| /** |
| * Binds the socket to the given socket address. |
| * |
| * @param address The socket address to bind to. |
| * |
| * @exception SocketException If an error occurs. |
| * @exception SecurityException If a security manager exists and |
| * its checkListen method doesn't allow the operation. |
| * @exception IllegalArgumentException If address type is not supported. |
| * |
| * @since 1.4 |
| */ |
| public void bind(SocketAddress address) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (! (address instanceof InetSocketAddress)) |
| throw new IllegalArgumentException("unsupported address type"); |
| |
| InetAddress addr = ((InetSocketAddress) address).getAddress(); |
| int port = ((InetSocketAddress) address).getPort(); |
| |
| if (port < 0 || port > 65535) |
| throw new IllegalArgumentException("Invalid port: " + port); |
| |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| s.checkListen(port); |
| |
| if (addr == null) |
| addr = InetAddress.ANY_IF; |
| |
| try |
| { |
| getImpl().bind(port, addr); |
| bound = true; |
| } |
| catch (SocketException exception) |
| { |
| getImpl().close(); |
| throw exception; |
| } |
| catch (RuntimeException exception) |
| { |
| getImpl().close(); |
| throw exception; |
| } |
| catch (Error error) |
| { |
| getImpl().close(); |
| throw error; |
| } |
| } |
| |
| /** |
| * Checks if the datagram socket is closed. |
| * |
| * @return True if socket is closed, false otherwise. |
| * |
| * @since 1.4 |
| */ |
| public boolean isClosed() |
| { |
| return impl == null; |
| } |
| |
| /** |
| * Returns the datagram channel assoziated with this datagram socket. |
| * |
| * @return The associated <code>DatagramChannel</code> object or null |
| * |
| * @since 1.4 |
| */ |
| public DatagramChannel getChannel() |
| { |
| return null; |
| } |
| |
| /** |
| * Connects the datagram socket to a specified socket address. |
| * |
| * @param address The socket address to connect to. |
| * |
| * @exception SocketException If an error occurs. |
| * @exception IllegalArgumentException If address type is not supported. |
| * |
| * @since 1.4 |
| */ |
| public void connect(SocketAddress address) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (! (address instanceof InetSocketAddress)) |
| throw new IllegalArgumentException("unsupported address type"); |
| |
| InetSocketAddress tmp = (InetSocketAddress) address; |
| connect(tmp.getAddress(), tmp.getPort()); |
| } |
| |
| /** |
| * Returns the binding state of the socket. |
| * |
| * @return True if socket bound, false otherwise. |
| * |
| * @since 1.4 |
| */ |
| public boolean isBound() |
| { |
| return bound; |
| } |
| |
| /** |
| * Returns the connection state of the socket. |
| * |
| * @return True if socket is connected, false otherwise. |
| * |
| * @since 1.4 |
| */ |
| public boolean isConnected() |
| { |
| return remoteAddress != null; |
| } |
| |
| /** |
| * Returns the SocketAddress of the host this socket is conneted to |
| * or null if this socket is not connected. |
| * |
| * @return The socket address of the remote host if connected or null |
| * |
| * @since 1.4 |
| */ |
| public SocketAddress getRemoteSocketAddress() |
| { |
| if (! isConnected()) |
| return null; |
| |
| return new InetSocketAddress(remoteAddress, remotePort); |
| } |
| |
| /** |
| * Returns the local SocketAddress this socket is bound to. |
| * |
| * @return The local SocketAddress or null if the socket is not bound. |
| * |
| * @since 1.4 |
| */ |
| public SocketAddress getLocalSocketAddress() |
| { |
| if (! isBound()) |
| return null; |
| |
| return new InetSocketAddress(getLocalAddress(), getLocalPort()); |
| } |
| |
| /** |
| * Enables/Disables SO_REUSEADDR. |
| * |
| * @param on Whether or not to have SO_REUSEADDR turned on. |
| * |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.4 |
| */ |
| public void setReuseAddress(boolean on) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); |
| } |
| |
| /** |
| * Checks if SO_REUSEADDR is enabled. |
| * |
| * @return True if SO_REUSEADDR is set on the socket, false otherwise. |
| * |
| * @exception SocketException If an error occurs. |
| * |
| * @since 1.4 |
| */ |
| public boolean getReuseAddress() throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR); |
| |
| if (buf instanceof Boolean) |
| return ((Boolean) buf).booleanValue(); |
| |
| throw new SocketException("unexpected type"); |
| } |
| |
| /** |
| * Enables/Disables SO_BROADCAST |
| * |
| * @param enable True if SO_BROADCAST should be enabled, false otherwise. |
| * |
| * @exception SocketException If an error occurs |
| * |
| * @since 1.4 |
| */ |
| public void setBroadcast(boolean enable) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable)); |
| } |
| |
| /** |
| * Checks if SO_BROADCAST is enabled |
| * |
| * @return Whether SO_BROADCAST is set |
| * |
| * @exception SocketException If an error occurs |
| * |
| * @since 1.4 |
| */ |
| public boolean getBroadcast() throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST); |
| |
| if (buf instanceof Boolean) |
| return ((Boolean) buf).booleanValue(); |
| |
| throw new SocketException("unexpected type"); |
| } |
| |
| /** |
| * Sets the traffic class value |
| * |
| * @param tc The traffic class |
| * |
| * @exception SocketException If an error occurs |
| * @exception IllegalArgumentException If tc value is illegal |
| * |
| * @see DatagramSocket#getTrafficClass() |
| * |
| * @since 1.4 |
| */ |
| public void setTrafficClass(int tc) throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| if (tc < 0 || tc > 255) |
| throw new IllegalArgumentException(); |
| |
| getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); |
| } |
| |
| /** |
| * Returns the current traffic class |
| * |
| * @return The current traffic class. |
| * |
| * @see DatagramSocket#setTrafficClass(int tc) |
| * |
| * @exception SocketException If an error occurs |
| * |
| * @since 1.4 |
| */ |
| public int getTrafficClass() throws SocketException |
| { |
| if (isClosed()) |
| throw new SocketException("socket is closed"); |
| |
| Object buf = getImpl().getOption(SocketOptions.IP_TOS); |
| |
| if (buf instanceof Integer) |
| return ((Integer) buf).intValue(); |
| |
| throw new SocketException("unexpected type"); |
| } |
| |
| /** |
| * Sets the datagram socket implementation factory for the application |
| * |
| * @param fac The factory to set |
| * |
| * @exception IOException If an error occurs |
| * @exception SocketException If the factory is already defined |
| * @exception SecurityException If a security manager exists and its |
| * checkSetFactory method doesn't allow the operation |
| */ |
| public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) |
| throws IOException |
| { |
| if (factory != null) |
| throw new SocketException("DatagramSocketImplFactory already defined"); |
| |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) |
| sm.checkSetFactory(); |
| |
| factory = fac; |
| } |
| } |