Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / java / net / DatagramSocket.java
blobd8837c006b5d82c281bd64f5cafa078b3682a5a0
1 /* DatagramSocket.java -- A class to model UDP sockets
2 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
39 package java.net;
41 import gnu.classpath.SystemProperties;
43 import gnu.java.net.PlainDatagramSocketImpl;
44 import gnu.java.nio.DatagramChannelImpl;
46 import java.io.IOException;
47 import java.nio.channels.DatagramChannel;
48 import java.nio.channels.IllegalBlockingModeException;
51 /**
52 * Written using on-line Java Platform 1.2 API Specification, as well
53 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
54 * Status: Believed complete and correct.
56 /**
57 * This class models a connectionless datagram socket that sends
58 * individual packets of data across the network. In the TCP/IP world,
59 * this means UDP. Datagram packets do not have guaranteed delivery,
60 * or any guarantee about the order the data will be received on the
61 * remote host.
63 * @author Aaron M. Renn (arenn@urbanophile.com)
64 * @author Warren Levy (warrenl@cygnus.com)
65 * @date May 3, 1999.
67 public class DatagramSocket
69 /**
70 * This is the user DatagramSocketImplFactory for this class. If this
71 * variable is null, a default factory is used.
73 private static DatagramSocketImplFactory factory;
75 /**
76 * This is the implementation object used by this socket.
78 private DatagramSocketImpl impl;
80 /**
81 * True if socket implementation was created.
83 private boolean implCreated;
85 /**
86 * This is the address we are "connected" to
88 private InetAddress remoteAddress;
90 /**
91 * This is the port we are "connected" to
93 private int remotePort = -1;
95 /**
96 * True if socket is bound.
98 private boolean bound;
101 * Creates a <code>DatagramSocket</code> from a specified
102 * <code>DatagramSocketImpl</code> instance
104 * @param impl The <code>DatagramSocketImpl</code> the socket will be
105 * created from
107 * @since 1.4
109 protected DatagramSocket(DatagramSocketImpl impl)
111 if (impl == null)
112 throw new NullPointerException("impl may not be null");
114 this.impl = impl;
115 this.remoteAddress = null;
116 this.remotePort = -1;
120 * Initializes a new instance of <code>DatagramSocket</code> that binds to
121 * a random port and every address on the local machine.
123 * @exception SocketException If an error occurs.
124 * @exception SecurityException If a security manager exists and
125 * its <code>checkListen</code> method doesn't allow the operation.
127 public DatagramSocket() throws SocketException
129 this(new InetSocketAddress(0));
133 * Initializes a new instance of <code>DatagramSocket</code> that binds to
134 * the specified port and every address on the local machine.
136 * @param port The local port number to bind to.
138 * @exception SecurityException If a security manager exists and its
139 * <code>checkListen</code> method doesn't allow the operation.
140 * @exception SocketException If an error occurs.
142 public DatagramSocket(int port) throws SocketException
144 this(new InetSocketAddress(port));
148 * Initializes a new instance of <code>DatagramSocket</code> that binds to
149 * the specified local port and address.
151 * @param port The local port number to bind to.
152 * @param addr The local address to bind to.
154 * @exception SecurityException If a security manager exists and its
155 * checkListen method doesn't allow the operation.
156 * @exception SocketException If an error occurs.
158 public DatagramSocket(int port, InetAddress addr) throws SocketException
160 this(new InetSocketAddress(addr, port));
164 * Initializes a new instance of <code>DatagramSocket</code> that binds to
165 * the specified local port and address.
167 * @param address The local address and port number to bind to.
169 * @exception SecurityException If a security manager exists and its
170 * <code>checkListen</code> method doesn't allow the operation.
171 * @exception SocketException If an error occurs.
173 * @since 1.4
175 public DatagramSocket(SocketAddress address) throws SocketException
177 String propVal = SystemProperties.getProperty("impl.prefix");
178 if (propVal == null || propVal.equals(""))
180 if (factory != null)
181 impl = factory.createDatagramSocketImpl();
182 else
183 impl = new PlainDatagramSocketImpl();
185 else
188 impl =
189 (DatagramSocketImpl) Class.forName("java.net." + propVal
190 + "DatagramSocketImpl")
191 .newInstance();
193 catch (Exception e)
195 System.err.println("Could not instantiate class: java.net."
196 + propVal + "DatagramSocketImpl");
197 impl = new PlainDatagramSocketImpl();
200 if (address != null)
201 bind(address);
204 // This needs to be accessible from java.net.MulticastSocket
205 DatagramSocketImpl getImpl() throws SocketException
209 if (! implCreated)
211 impl.create();
212 implCreated = true;
215 return impl;
217 catch (IOException e)
219 SocketException se = new SocketException();
220 se.initCause(e);
221 throw se;
226 * Closes this datagram socket.
228 public void close()
230 if (isClosed())
231 return;
235 getImpl().close();
237 catch (SocketException e)
239 // Ignore this case, just close the socket in finally clause.
241 finally
243 remoteAddress = null;
244 remotePort = -1;
245 impl = null;
250 if (getChannel() != null)
251 getChannel().close();
253 catch (IOException e)
255 // Do nothing.
260 * This method returns the remote address to which this socket is
261 * connected. If this socket is not connected, then this method will
262 * return <code>null</code>.
264 * @return The remote address.
266 * @since 1.2
268 public InetAddress getInetAddress()
270 return remoteAddress;
274 * This method returns the remote port to which this socket is
275 * connected. If this socket is not connected, then this method will
276 * return -1.
278 * @return The remote port.
280 * @since 1.2
282 public int getPort()
284 return remotePort;
288 * Returns the local address this datagram socket is bound to.
290 * @return The local address is the socket is bound or null
292 * @since 1.1
294 public InetAddress getLocalAddress()
296 if (! isBound())
297 return null;
299 InetAddress localAddr;
303 localAddr =
304 (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
306 SecurityManager s = System.getSecurityManager();
307 if (s != null)
308 s.checkConnect(localAddr.getHostName(), -1);
310 catch (SecurityException e)
312 localAddr = InetAddress.ANY_IF;
314 catch (SocketException e)
316 // This cannot happen as we are bound.
317 return null;
320 return localAddr;
324 * Returns the local port this socket is bound to.
326 * @return The local port number.
328 public int getLocalPort()
330 if (isClosed())
331 return -1;
335 return getImpl().getLocalPort();
337 catch (SocketException e)
339 // This cannot happen as we are bound.
340 return 0;
345 * Returns the value of the socket's SO_TIMEOUT setting. If this method
346 * returns 0 then SO_TIMEOUT is disabled.
348 * @return The current timeout in milliseconds.
350 * @exception SocketException If an error occurs.
352 * @since 1.1
354 public synchronized int getSoTimeout() throws SocketException
356 if (isClosed())
357 throw new SocketException("socket is closed");
359 Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT);
361 if (buf instanceof Integer)
362 return ((Integer) buf).intValue();
364 throw new SocketException("unexpected type");
368 * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will
369 * disable SO_TIMEOUT. Any other value is the number of milliseconds
370 * a socket read/write will block before timing out.
372 * @param timeout The new SO_TIMEOUT value in milliseconds.
374 * @exception SocketException If an error occurs.
376 * @since 1.1
378 public synchronized void setSoTimeout(int timeout) throws SocketException
380 if (isClosed())
381 throw new SocketException("socket is closed");
383 if (timeout < 0)
384 throw new IllegalArgumentException("Invalid timeout: " + timeout);
386 getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
390 * This method returns the value of the system level socket option
391 * SO_SNDBUF, which is used by the operating system to tune buffer
392 * sizes for data transfers.
394 * @return The send buffer size.
396 * @exception SocketException If an error occurs.
398 * @since 1.2
400 public int getSendBufferSize() throws SocketException
402 if (isClosed())
403 throw new SocketException("socket is closed");
405 Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
407 if (buf instanceof Integer)
408 return ((Integer) buf).intValue();
410 throw new SocketException("unexpected type");
414 * This method sets the value for the system level socket option
415 * SO_SNDBUF to the specified value. Note that valid values for this
416 * option are specific to a given operating system.
418 * @param size The new send buffer size.
420 * @exception SocketException If an error occurs.
421 * @exception IllegalArgumentException If size is 0 or negative.
423 * @since 1.2
425 public void setSendBufferSize(int size) throws SocketException
427 if (isClosed())
428 throw new SocketException("socket is closed");
430 if (size < 0)
431 throw new IllegalArgumentException("Buffer size is less than 0");
433 getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
437 * This method returns the value of the system level socket option
438 * SO_RCVBUF, which is used by the operating system to tune buffer
439 * sizes for data transfers.
441 * @return The receive buffer size.
443 * @exception SocketException If an error occurs.
445 * @since 1.2
447 public int getReceiveBufferSize() throws SocketException
449 if (isClosed())
450 throw new SocketException("socket is closed");
452 Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
454 if (buf instanceof Integer)
455 return ((Integer) buf).intValue();
457 throw new SocketException("unexpected type");
461 * This method sets the value for the system level socket option
462 * SO_RCVBUF to the specified value. Note that valid values for this
463 * option are specific to a given operating system.
465 * @param size The new receive buffer size.
467 * @exception SocketException If an error occurs.
468 * @exception IllegalArgumentException If size is 0 or negative.
470 * @since 1.2
472 public void setReceiveBufferSize(int size) throws SocketException
474 if (isClosed())
475 throw new SocketException("socket is closed");
477 if (size < 0)
478 throw new IllegalArgumentException("Buffer size is less than 0");
480 getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
484 * This method connects this socket to the specified address and port.
485 * When a datagram socket is connected, it will only send or receive
486 * packets to and from the host to which it is connected. A multicast
487 * socket that is connected may only send and not receive packets.
489 * @param address The address to connect this socket to.
490 * @param port The port to connect this socket to.
492 * @exception IllegalArgumentException If address or port are invalid.
493 * @exception SecurityException If the caller is not allowed to send
494 * datagrams to or receive from this address and port.
496 * @since 1.2
498 public void connect(InetAddress address, int port)
500 if (address == null)
501 throw new IllegalArgumentException("Connect address may not be null");
503 if ((port < 1) || (port > 65535))
504 throw new IllegalArgumentException("Port number is illegal: " + port);
506 SecurityManager sm = System.getSecurityManager();
507 if (sm != null)
508 sm.checkConnect(address.getHostName(), port);
512 getImpl().connect(address, port);
513 remoteAddress = address;
514 remotePort = port;
516 catch (SocketException e)
518 // This means simply not connected or connect not implemented.
523 * This method disconnects this socket from the address/port it was
524 * connected to. If the socket was not connected in the first place,
525 * this method does nothing.
527 * @since 1.2
529 public void disconnect()
531 if (! isConnected())
532 return;
536 getImpl().disconnect();
538 catch (SocketException e)
540 // This cannot happen as we are connected.
542 finally
544 remoteAddress = null;
545 remotePort = -1;
550 * Reads a datagram packet from the socket. Note that this method
551 * will block until a packet is received from the network. On return,
552 * the passed in <code>DatagramPacket</code> is populated with the data
553 * received and all the other information about the packet.
555 * @param p A <code>DatagramPacket</code> for storing the data
557 * @exception IOException If an error occurs.
558 * @exception SocketTimeoutException If setSoTimeout was previously called
559 * and the timeout has expired.
560 * @exception PortUnreachableException If the socket is connected to a
561 * currently unreachable destination. Note, there is no guarantee that the
562 * exception will be thrown.
563 * @exception IllegalBlockingModeException If this socket has an associated
564 * channel, and the channel is in non-blocking mode.
565 * @exception SecurityException If a security manager exists and its
566 * checkAccept method doesn't allow the receive.
568 public synchronized void receive(DatagramPacket p) throws IOException
570 if (isClosed())
571 throw new SocketException("socket is closed");
573 if (remoteAddress != null && remoteAddress.isMulticastAddress())
574 throw new IOException
575 ("Socket connected to a multicast address my not receive");
577 if (getChannel() != null && ! getChannel().isBlocking()
578 && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
579 throw new IllegalBlockingModeException();
581 getImpl().receive(p);
583 SecurityManager s = System.getSecurityManager();
584 if (s != null && isConnected())
585 s.checkAccept(p.getAddress().getHostName(), p.getPort());
589 * Sends the specified packet. The host and port to which the packet
590 * are to be sent should be set inside the packet.
592 * @param p The datagram packet to send.
594 * @exception IOException If an error occurs.
595 * @exception SecurityException If a security manager exists and its
596 * checkMulticast or checkConnect method doesn't allow the send.
597 * @exception PortUnreachableException If the socket is connected to a
598 * currently unreachable destination. Note, there is no guarantee that the
599 * exception will be thrown.
600 * @exception IllegalBlockingModeException If this socket has an associated
601 * channel, and the channel is in non-blocking mode.
603 public void send(DatagramPacket p) throws IOException
605 if (isClosed())
606 throw new SocketException("socket is closed");
608 // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
609 SecurityManager s = System.getSecurityManager();
610 if (s != null && ! isConnected())
612 InetAddress addr = p.getAddress();
613 if (addr.isMulticastAddress())
614 s.checkMulticast(addr);
615 else
616 s.checkConnect(addr.getHostAddress(), p.getPort());
619 if (isConnected())
621 if (p.getAddress() != null
622 && (remoteAddress != p.getAddress() || remotePort != p.getPort()))
623 throw new IllegalArgumentException
624 ("DatagramPacket address does not match remote address");
627 // FIXME: if this is a subclass of MulticastSocket,
628 // use getTimeToLive for TTL val.
629 if (getChannel() != null && ! getChannel().isBlocking()
630 && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
631 throw new IllegalBlockingModeException();
633 getImpl().send(p);
637 * Binds the socket to the given socket address.
639 * @param address The socket address to bind to.
641 * @exception SocketException If an error occurs.
642 * @exception SecurityException If a security manager exists and
643 * its checkListen method doesn't allow the operation.
644 * @exception IllegalArgumentException If address type is not supported.
646 * @since 1.4
648 public void bind(SocketAddress address) throws SocketException
650 if (isClosed())
651 throw new SocketException("socket is closed");
653 if (! (address instanceof InetSocketAddress))
654 throw new IllegalArgumentException("unsupported address type");
656 InetAddress addr = ((InetSocketAddress) address).getAddress();
657 int port = ((InetSocketAddress) address).getPort();
659 if (port < 0 || port > 65535)
660 throw new IllegalArgumentException("Invalid port: " + port);
662 SecurityManager s = System.getSecurityManager();
663 if (s != null)
664 s.checkListen(port);
666 if (addr == null)
667 addr = InetAddress.ANY_IF;
671 getImpl().bind(port, addr);
672 bound = true;
674 catch (SocketException exception)
676 getImpl().close();
677 throw exception;
679 catch (RuntimeException exception)
681 getImpl().close();
682 throw exception;
684 catch (Error error)
686 getImpl().close();
687 throw error;
692 * Checks if the datagram socket is closed.
694 * @return True if socket is closed, false otherwise.
696 * @since 1.4
698 public boolean isClosed()
700 return impl == null;
704 * Returns the datagram channel assoziated with this datagram socket.
706 * @return The associated <code>DatagramChannel</code> object or null
708 * @since 1.4
710 public DatagramChannel getChannel()
712 return null;
716 * Connects the datagram socket to a specified socket address.
718 * @param address The socket address to connect to.
720 * @exception SocketException If an error occurs.
721 * @exception IllegalArgumentException If address type is not supported.
723 * @since 1.4
725 public void connect(SocketAddress address) throws SocketException
727 if (isClosed())
728 throw new SocketException("socket is closed");
730 if (! (address instanceof InetSocketAddress))
731 throw new IllegalArgumentException("unsupported address type");
733 InetSocketAddress tmp = (InetSocketAddress) address;
734 connect(tmp.getAddress(), tmp.getPort());
738 * Returns the binding state of the socket.
740 * @return True if socket bound, false otherwise.
742 * @since 1.4
744 public boolean isBound()
746 return bound;
750 * Returns the connection state of the socket.
752 * @return True if socket is connected, false otherwise.
754 * @since 1.4
756 public boolean isConnected()
758 return remoteAddress != null;
762 * Returns the SocketAddress of the host this socket is conneted to
763 * or null if this socket is not connected.
765 * @return The socket address of the remote host if connected or null
767 * @since 1.4
769 public SocketAddress getRemoteSocketAddress()
771 if (! isConnected())
772 return null;
774 return new InetSocketAddress(remoteAddress, remotePort);
778 * Returns the local SocketAddress this socket is bound to.
780 * @return The local SocketAddress or null if the socket is not bound.
782 * @since 1.4
784 public SocketAddress getLocalSocketAddress()
786 if (! isBound())
787 return null;
789 return new InetSocketAddress(getLocalAddress(), getLocalPort());
793 * Enables/Disables SO_REUSEADDR.
795 * @param on Whether or not to have SO_REUSEADDR turned on.
797 * @exception SocketException If an error occurs.
799 * @since 1.4
801 public void setReuseAddress(boolean on) throws SocketException
803 if (isClosed())
804 throw new SocketException("socket is closed");
806 getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
810 * Checks if SO_REUSEADDR is enabled.
812 * @return True if SO_REUSEADDR is set on the socket, false otherwise.
814 * @exception SocketException If an error occurs.
816 * @since 1.4
818 public boolean getReuseAddress() throws SocketException
820 if (isClosed())
821 throw new SocketException("socket is closed");
823 Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR);
825 if (buf instanceof Boolean)
826 return ((Boolean) buf).booleanValue();
828 throw new SocketException("unexpected type");
832 * Enables/Disables SO_BROADCAST
834 * @param enable True if SO_BROADCAST should be enabled, false otherwise.
836 * @exception SocketException If an error occurs
838 * @since 1.4
840 public void setBroadcast(boolean enable) throws SocketException
842 if (isClosed())
843 throw new SocketException("socket is closed");
845 getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable));
849 * Checks if SO_BROADCAST is enabled
851 * @return Whether SO_BROADCAST is set
853 * @exception SocketException If an error occurs
855 * @since 1.4
857 public boolean getBroadcast() throws SocketException
859 if (isClosed())
860 throw new SocketException("socket is closed");
862 Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
864 if (buf instanceof Boolean)
865 return ((Boolean) buf).booleanValue();
867 throw new SocketException("unexpected type");
871 * Sets the traffic class value
873 * @param tc The traffic class
875 * @exception SocketException If an error occurs
876 * @exception IllegalArgumentException If tc value is illegal
878 * @see DatagramSocket#getTrafficClass()
880 * @since 1.4
882 public void setTrafficClass(int tc) throws SocketException
884 if (isClosed())
885 throw new SocketException("socket is closed");
887 if (tc < 0 || tc > 255)
888 throw new IllegalArgumentException();
890 getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
894 * Returns the current traffic class
896 * @return The current traffic class.
898 * @see DatagramSocket#setTrafficClass(int tc)
900 * @exception SocketException If an error occurs
902 * @since 1.4
904 public int getTrafficClass() throws SocketException
906 if (isClosed())
907 throw new SocketException("socket is closed");
909 Object buf = getImpl().getOption(SocketOptions.IP_TOS);
911 if (buf instanceof Integer)
912 return ((Integer) buf).intValue();
914 throw new SocketException("unexpected type");
918 * Sets the datagram socket implementation factory for the application
920 * @param fac The factory to set
922 * @exception IOException If an error occurs
923 * @exception SocketException If the factory is already defined
924 * @exception SecurityException If a security manager exists and its
925 * checkSetFactory method doesn't allow the operation
927 public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
928 throws IOException
930 if (factory != null)
931 throw new SocketException("DatagramSocketImplFactory already defined");
933 SecurityManager sm = System.getSecurityManager();
934 if (sm != null)
935 sm.checkSetFactory();
937 factory = fac;