2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / net / DatagramSocket.java
blobc9c0f5d0f03ddd33d7ee0e0196872d04c7098cbc
1 /* DatagramSocket.java -- A class to model UDP sockets
2 Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.net;
41 import gnu.java.net.PlainDatagramSocketImpl;
42 import java.io.IOException;
43 import java.nio.channels.DatagramChannel;
44 import java.nio.channels.IllegalBlockingModeException;
46 /**
47 * Written using on-line Java Platform 1.2 API Specification, as well
48 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
49 * Status: Believed complete and correct.
52 /**
53 * This class models a connectionless datagram socket that sends
54 * individual packets of data across the network. In the TCP/IP world,
55 * this means UDP. Datagram packets do not have guaranteed delivery,
56 * or any guarantee about the order the data will be received on the
57 * remote host.
59 * @author Aaron M. Renn (arenn@urbanophile.com)
60 * @author Warren Levy (warrenl@cygnus.com)
61 * @date May 3, 1999.
64 public class DatagramSocket
66 /**
67 * This is the user DatagramSocketImplFactory for this class. If this
68 * variable is null, a default factory is used.
70 private static DatagramSocketImplFactory factory;
72 /**
73 * This is the implementation object used by this socket.
75 private DatagramSocketImpl impl;
77 /**
78 * True if socket implementation was created.
80 private boolean implCreated;
82 /**
83 * This is the address we are "connected" to
85 private InetAddress remoteAddress;
87 /**
88 * This is the port we are "connected" to
90 private int remotePort = -1;
92 /**
93 * True if socket is bound.
95 private boolean bound;
97 /**
98 * Creates a <code>DatagramSocket</code> from a specified
99 * <code>DatagramSocketImpl</code> instance
101 * @param impl The <code>DatagramSocketImpl</code> the socket will be
102 * created from
104 * @since 1.4
106 protected DatagramSocket (DatagramSocketImpl impl)
108 if (impl == null)
109 throw new NullPointerException("impl may not be null");
111 this.impl = impl;
112 this.remoteAddress = null;
113 this.remotePort = -1;
117 * Initializes a new instance of <code>DatagramSocket</code> that binds to
118 * a random port and every address on the local machine.
120 * @exception SocketException If an error occurs.
121 * @exception SecurityException If a security manager exists and
122 * its <code>checkListen</code> method doesn't allow the operation.
124 public DatagramSocket() throws SocketException
126 this(new InetSocketAddress(0));
130 * Initializes a new instance of <code>DatagramSocket</code> that binds to
131 * the specified port and every address on the local machine.
133 * @param port The local port number to bind to.
135 * @exception SecurityException If a security manager exists and its
136 * <code>checkListen</code> method doesn't allow the operation.
137 * @exception SocketException If an error occurs.
139 public DatagramSocket(int port) throws SocketException
141 this(new InetSocketAddress(port));
145 * Initializes a new instance of <code>DatagramSocket</code> that binds to
146 * the specified local port and address.
148 * @param port The local port number to bind to.
149 * @param addr The local address to bind to.
151 * @exception SecurityException If a security manager exists and its
152 * checkListen method doesn't allow the operation.
153 * @exception SocketException If an error occurs.
155 public DatagramSocket(int port, InetAddress addr) throws SocketException
157 this(new InetSocketAddress(addr, port));
161 * Initializes a new instance of <code>DatagramSocket</code> that binds to
162 * the specified local port and address.
164 * @param address The local address and port number to bind to.
166 * @exception SecurityException If a security manager exists and its
167 * <code>checkListen</code> method doesn't allow the operation.
168 * @exception SocketException If an error occurs.
170 * @since 1.4
172 public DatagramSocket (SocketAddress address) throws SocketException
174 String propVal = System.getProperty("impl.prefix");
175 if (propVal == null || propVal.equals(""))
176 impl = new PlainDatagramSocketImpl();
177 else
180 impl = (DatagramSocketImpl) Class.forName
181 ("java.net." + propVal + "DatagramSocketImpl").newInstance();
183 catch (Exception e)
185 System.err.println("Could not instantiate class: java.net." +
186 propVal + "DatagramSocketImpl");
187 impl = new PlainDatagramSocketImpl();
190 if (address != null)
191 bind(address);
194 // This needs to be accessible from java.net.MulticastSocket
195 DatagramSocketImpl getImpl()
196 throws SocketException
200 if (!implCreated)
202 impl.create();
203 implCreated = true;
206 return impl;
208 catch (IOException e)
210 throw new SocketException(e.getMessage());
215 * Closes this datagram socket.
217 public void close()
219 if (isClosed())
220 return;
224 getImpl().close();
226 catch (SocketException e)
228 // Ignore this case, just close the socket in finally clause.
230 finally
232 remoteAddress = null;
233 remotePort = -1;
234 impl = null;
239 if (getChannel() != null)
240 getChannel().close();
242 catch (IOException e)
244 // Do nothing.
249 * This method returns the remote address to which this socket is
250 * connected. If this socket is not connected, then this method will
251 * return <code>null</code>.
253 * @return The remote address.
255 * @since 1.2
257 public InetAddress getInetAddress()
259 return remoteAddress;
263 * This method returns the remote port to which this socket is
264 * connected. If this socket is not connected, then this method will
265 * return -1.
267 * @return The remote port.
269 * @since 1.2
271 public int getPort()
273 return remotePort;
277 * Returns the local address this datagram socket is bound to.
279 * @return The local address is the socket is bound or null
281 * @since 1.1
283 public InetAddress getLocalAddress()
285 if (isClosed())
286 return null;
288 InetAddress localAddr;
292 localAddr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
294 SecurityManager s = System.getSecurityManager();
295 if (s != null)
296 s.checkConnect (localAddr.getHostName(), -1);
298 catch (SecurityException e)
300 localAddr = InetAddress.ANY_IF;
302 catch (SocketException e)
304 // This cannot happen as we are bound.
305 return null;
308 return localAddr;
312 * Returns the local port this socket is bound to.
314 * @return The local port number.
316 public int getLocalPort()
318 if (isClosed())
319 return -1;
323 return getImpl().getLocalPort();
325 catch (SocketException e)
327 // This cannot happen as we are bound.
328 return 0;
333 * Returns the value of the socket's SO_TIMEOUT setting. If this method
334 * returns 0 then SO_TIMEOUT is disabled.
336 * @return The current timeout in milliseconds.
338 * @exception SocketException If an error occurs.
340 * @since 1.1
342 public synchronized int getSoTimeout() throws SocketException
344 if (isClosed())
345 throw new SocketException("socket is closed");
347 Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT);
349 if (buf instanceof Integer)
350 return ((Integer) buf).intValue();
352 throw new SocketException("unexpected type");
356 * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will
357 * disable SO_TIMEOUT. Any other value is the number of milliseconds
358 * a socket read/write will block before timing out.
360 * @param timeout The new SO_TIMEOUT value in milliseconds.
362 * @exception SocketException If an error occurs.
364 * @since 1.1
366 public synchronized void setSoTimeout(int timeout) throws SocketException
368 if (isClosed())
369 throw new SocketException("socket is closed");
371 if (timeout < 0)
372 throw new IllegalArgumentException("Invalid timeout: " + timeout);
374 getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
378 * This method returns the value of the system level socket option
379 * SO_SNDBUF, which is used by the operating system to tune buffer
380 * sizes for data transfers.
382 * @return The send buffer size.
384 * @exception SocketException If an error occurs.
386 * @since 1.2
388 public int getSendBufferSize() throws SocketException
390 if (isClosed())
391 throw new SocketException("socket is closed");
393 Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
395 if (buf instanceof Integer)
396 return ((Integer) buf).intValue();
398 throw new SocketException("unexpected type");
402 * This method sets the value for the system level socket option
403 * SO_SNDBUF to the specified value. Note that valid values for this
404 * option are specific to a given operating system.
406 * @param size The new send buffer size.
408 * @exception SocketException If an error occurs.
409 * @exception IllegalArgumentException If size is 0 or negative.
411 * @since 1.2
413 public void setSendBufferSize(int size) throws SocketException
415 if (isClosed())
416 throw new SocketException("socket is closed");
418 if (size < 0)
419 throw new IllegalArgumentException("Buffer size is less than 0");
421 getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
425 * This method returns the value of the system level socket option
426 * SO_RCVBUF, which is used by the operating system to tune buffer
427 * sizes for data transfers.
429 * @return The receive buffer size.
431 * @exception SocketException If an error occurs.
433 * @since 1.2
435 public int getReceiveBufferSize() throws SocketException
437 if (isClosed())
438 throw new SocketException("socket is closed");
440 Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
442 if (buf instanceof Integer)
443 return ((Integer) buf).intValue();
445 throw new SocketException("unexpected type");
449 * This method sets the value for the system level socket option
450 * SO_RCVBUF to the specified value. Note that valid values for this
451 * option are specific to a given operating system.
453 * @param size The new receive buffer size.
455 * @exception SocketException If an error occurs.
456 * @exception IllegalArgumentException If size is 0 or negative.
458 * @since 1.2
460 public void setReceiveBufferSize(int size) throws SocketException
462 if (isClosed())
463 throw new SocketException("socket is closed");
465 if (size < 0)
466 throw new IllegalArgumentException("Buffer size is less than 0");
468 getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
472 * This method connects this socket to the specified address and port.
473 * When a datagram socket is connected, it will only send or receive
474 * packets to and from the host to which it is connected. A multicast
475 * socket that is connected may only send and not receive packets.
477 * @param address The address to connect this socket to.
478 * @param port The port to connect this socket to.
480 * @exception SocketException If an error occurs.
481 * @exception IllegalArgumentException If address or port are invalid.
482 * @exception SecurityException If the caller is not allowed to send
483 * datagrams to or receive from this address and port.
485 * @since 1.2
487 public void connect(InetAddress address, int port)
489 if (address == null)
490 throw new IllegalArgumentException ("Connect address may not be null");
492 if ((port < 1) || (port > 65535))
493 throw new IllegalArgumentException ("Port number is illegal: " + port);
495 SecurityManager sm = System.getSecurityManager();
496 if (sm != null)
497 sm.checkConnect(address.getHostName(), port);
501 getImpl().connect (address, port);
502 remoteAddress = address;
503 remotePort = port;
505 catch (SocketException e)
507 // This means simply not connected or connect not implemented.
512 * This method disconnects this socket from the address/port it was
513 * connected to. If the socket was not connected in the first place,
514 * this method does nothing.
516 * @since 1.2
518 public void disconnect()
520 if (!isConnected())
521 return;
525 getImpl().disconnect();
527 catch (SocketException e)
529 // This cannot happen as we are connected.
531 finally
533 remoteAddress = null;
534 remotePort = -1;
539 * Reads a datagram packet from the socket. Note that this method
540 * will block until a packet is received from the network. On return,
541 * the passed in <code>DatagramPacket</code> is populated with the data
542 * received and all the other information about the packet.
544 * @param p A <code>DatagramPacket</code> for storing the data
546 * @exception IOException If an error occurs.
547 * @exception SocketTimeoutException If setSoTimeout was previously called
548 * and the timeout has expired.
549 * @exception PortUnreachableException If the socket is connected to a
550 * currently unreachable destination. Note, there is no guarantee that the
551 * exception will be thrown.
552 * @exception IllegalBlockingModeException If this socket has an associated
553 * channel, and the channel is in non-blocking mode.
554 * @exception SecurityException If a security manager exists and its
555 * checkAccept ethod doesn't allow the receive.
557 public synchronized void receive(DatagramPacket p) throws IOException
559 if (isClosed())
560 throw new SocketException("socket is closed");
562 if (remoteAddress != null
563 && remoteAddress.isMulticastAddress())
564 throw new IOException
565 ("Socket connected to a multicast address my not receive");
567 if (getChannel() != null
568 && !getChannel().isBlocking ())
569 throw new IllegalBlockingModeException ();
571 getImpl().receive(p);
573 SecurityManager s = System.getSecurityManager();
574 if (s != null && isConnected ())
575 s.checkAccept (p.getAddress().getHostName (), p.getPort ());
579 * Sends the specified packet. The host and port to which the packet
580 * are to be sent should be set inside the packet.
582 * @param p The datagram packet to send.
584 * @exception IOException If an error occurs.
585 * @exception SecurityException If a security manager exists and its
586 * checkMulticast or checkConnect method doesn't allow the send.
587 * @exception PortUnreachableException If the socket is connected to a
588 * currently unreachable destination. Note, there is no guarantee that the
589 * exception will be thrown.
590 * @exception IllegalBlockingModeException If this socket has an associated
591 * channel, and the channel is in non-blocking mode.
593 public void send(DatagramPacket p) throws IOException
595 if (isClosed())
596 throw new SocketException("socket is closed");
598 // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
599 SecurityManager s = System.getSecurityManager();
600 if (s != null && !isConnected ())
602 InetAddress addr = p.getAddress();
603 if (addr.isMulticastAddress())
604 s.checkMulticast(addr);
605 else
606 s.checkConnect(addr.getHostAddress(), p.getPort());
609 if (isConnected ())
611 if (p.getAddress () != null && (remoteAddress != p.getAddress () ||
612 remotePort != p.getPort ()))
613 throw new IllegalArgumentException (
614 "DatagramPacket address does not match remote address" );
617 // FIXME: if this is a subclass of MulticastSocket,
618 // use getTimeToLive for TTL val.
620 if (getChannel() != null
621 && !getChannel().isBlocking ())
622 throw new IllegalBlockingModeException ();
624 getImpl().send(p);
628 * Binds the socket to the given socket address.
630 * @param address The socket address to bind to.
632 * @exception SocketException If an error occurs.
633 * @exception SecurityException If a security manager exists and
634 * its checkListen method doesn't allow the operation.
635 * @exception IllegalArgumentException If address type is not supported.
637 * @since 1.4
639 public void bind (SocketAddress address)
640 throws SocketException
642 if (isClosed())
643 throw new SocketException("socket is closed");
645 if (! (address instanceof InetSocketAddress))
646 throw new IllegalArgumentException("unsupported address type");
648 InetAddress addr = ((InetSocketAddress) address).getAddress();
649 int port = ((InetSocketAddress) address).getPort();
651 if (port < 0 || port > 65535)
652 throw new IllegalArgumentException("Invalid port: " + port);
654 SecurityManager s = System.getSecurityManager ();
655 if (s != null)
656 s.checkListen(port);
658 if (addr == null)
659 addr = InetAddress.ANY_IF;
663 getImpl().bind(port, addr);
664 bound = true;
666 catch (SocketException exception)
668 getImpl().close();
669 throw exception;
671 catch (RuntimeException exception)
673 getImpl().close();
674 throw exception;
676 catch (Error error)
678 getImpl().close();
679 throw error;
684 * Checks if the datagram socket is closed.
686 * @return True if socket is closed, false otherwise.
688 * @since 1.4
690 public boolean isClosed()
692 return impl == null;
696 * Returns the datagram channel assoziated with this datagram socket.
698 * @return The associated <code>DatagramChannel</code> object or null
700 * @since 1.4
702 public DatagramChannel getChannel()
704 return null;
708 * Connects the datagram socket to a specified socket address.
710 * @param address The socket address to connect to.
712 * @exception SocketException If an error occurs.
713 * @exception IllegalArgumentException If address type is not supported.
715 * @since 1.4
717 public void connect (SocketAddress address) throws SocketException
719 if (isClosed())
720 throw new SocketException("socket is closed");
722 if ( !(address instanceof InetSocketAddress) )
723 throw new IllegalArgumentException("unsupported address type");
725 InetSocketAddress tmp = (InetSocketAddress) address;
726 connect(tmp.getAddress(), tmp.getPort());
730 * Returns the binding state of the socket.
732 * @return True if socket bound, false otherwise.
734 * @since 1.4
736 public boolean isBound()
738 return bound;
742 * Returns the connection state of the socket.
744 * @return True if socket is connected, false otherwise.
746 * @since 1.4
748 public boolean isConnected()
750 return remoteAddress != null;
754 * Returns the SocketAddress of the host this socket is conneted to
755 * or null if this socket is not connected.
757 * @return The socket address of the remote host if connected or null
759 * @since 1.4
761 public SocketAddress getRemoteSocketAddress()
763 if (!isConnected ())
764 return null;
766 return new InetSocketAddress (remoteAddress, remotePort);
770 * Returns the local SocketAddress this socket is bound to.
772 * @return The local SocketAddress or null if the socket is not bound.
774 * @since 1.4
776 public SocketAddress getLocalSocketAddress()
778 if (!isBound())
779 return null;
781 return new InetSocketAddress (getLocalAddress(), getLocalPort());
785 * Enables/Disables SO_REUSEADDR.
787 * @param on Whether or not to have SO_REUSEADDR turned on.
789 * @exception SocketException If an error occurs.
791 * @since 1.4
793 public void setReuseAddress(boolean on) throws SocketException
795 if (isClosed())
796 throw new SocketException("socket is closed");
798 getImpl().setOption (SocketOptions.SO_REUSEADDR, new Boolean (on));
802 * Checks if SO_REUSEADDR is enabled.
804 * @return True if SO_REUSEADDR is set on the socket, false otherwise.
806 * @exception SocketException If an error occurs.
808 * @since 1.4
810 public boolean getReuseAddress() throws SocketException
812 if (isClosed())
813 throw new SocketException("socket is closed");
815 Object buf = getImpl().getOption (SocketOptions.SO_REUSEADDR);
817 if (buf instanceof Boolean)
818 return ((Boolean) buf).booleanValue();
820 throw new SocketException("unexpected type");
824 * Enables/Disables SO_BROADCAST
826 * @param enable True if SO_BROADCAST should be enabled, false otherwise.
828 * @exception SocketException If an error occurs
830 * @since 1.4
832 public void setBroadcast(boolean enable) throws SocketException
834 if (isClosed())
835 throw new SocketException("socket is closed");
837 getImpl().setOption(SocketOptions.SO_BROADCAST, new Boolean(enable));
841 * Checks if SO_BROADCAST is enabled
843 * @return Whether SO_BROADCAST is set
845 * @exception SocketException If an error occurs
847 * @since 1.4
849 public boolean getBroadcast() throws SocketException
851 if (isClosed())
852 throw new SocketException("socket is closed");
854 Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
856 if (buf instanceof Boolean)
857 return ((Boolean) buf).booleanValue();
859 throw new SocketException("unexpected type");
863 * Sets the traffic class value
865 * @param tc The traffic class
867 * @exception SocketException If an error occurs
868 * @exception IllegalArgumentException If tc value is illegal
870 * @see DatagramSocket#getTrafficClass()
872 * @since 1.4
874 public void setTrafficClass(int tc)
875 throws SocketException
877 if (isClosed())
878 throw new SocketException("socket is closed");
880 if (tc < 0 || tc > 255)
881 throw new IllegalArgumentException();
883 getImpl().setOption (SocketOptions.IP_TOS, new Integer (tc));
887 * Returns the current traffic class
889 * @return The current traffic class.
891 * @see DatagramSocket#setTrafficClass(int tc)
893 * @exception SocketException If an error occurs
895 * @since 1.4
897 public int getTrafficClass() throws SocketException
899 if (isClosed())
900 throw new SocketException("socket is closed");
902 Object buf = getImpl().getOption(SocketOptions.IP_TOS);
904 if (buf instanceof Integer)
905 return ((Integer) buf).intValue();
907 throw new SocketException("unexpected type");
911 * Sets the datagram socket implementation factory for the application
913 * @param fac The factory to set
915 * @exception IOException If an error occurs
916 * @exception SocketException If the factory is already defined
917 * @exception SecurityException If a security manager exists and its
918 * checkSetFactory method doesn't allow the operation
920 public static void setDatagramSocketImplFactory
921 (DatagramSocketImplFactory fac) throws IOException
923 if (factory != null)
924 throw new SocketException ("DatagramSocketImplFactory already defined");
926 SecurityManager sm = System.getSecurityManager();
927 if (sm != null)
928 sm.checkSetFactory();
930 factory = fac;