1 /* DatagramSocket.java -- A class to model UDP sockets
2    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
3    Free Software Foundation, Inc.
4 
5 This file is part of GNU Classpath.
6 
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.
11 
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.
16 
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.
21 
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.
26 
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. */
38 
39 package java.net;
40 
41 import gnu.classpath.SystemProperties;
42 
43 import gnu.java.net.PlainDatagramSocketImpl;
44 import gnu.java.nio.DatagramChannelImpl;
45 
46 import java.io.IOException;
47 import java.nio.channels.DatagramChannel;
48 import java.nio.channels.IllegalBlockingModeException;
49 
50 
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.
55  */
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.
62  *
63  * @author Aaron M. Renn (arenn@urbanophile.com)
64  * @author Warren Levy (warrenl@cygnus.com)
65  * @date May 3, 1999.
66  */
67 public class DatagramSocket
68 {
69   /**
70    * This is the user DatagramSocketImplFactory for this class.  If this
71    * variable is null, a default factory is used.
72    */
73   private static DatagramSocketImplFactory factory;
74 
75   /**
76    * This is the implementation object used by this socket.
77    */
78   private DatagramSocketImpl impl;
79 
80   /**
81    * True if socket implementation was created.
82    */
83   private boolean implCreated;
84 
85   /**
86    * This is the address we are "connected" to
87    */
88   private InetAddress remoteAddress;
89 
90   /**
91    * This is the port we are "connected" to
92    */
93   private int remotePort = -1;
94 
95   /**
96    * True if socket is bound.
97    */
98   private boolean bound;
99 
100   /**
101    * Creates a <code>DatagramSocket</code> from a specified
102    * <code>DatagramSocketImpl</code> instance
103    *
104    * @param impl The <code>DatagramSocketImpl</code> the socket will be
105    * created from
106    *
107    * @since 1.4
108    */
DatagramSocket(DatagramSocketImpl impl)109   protected DatagramSocket(DatagramSocketImpl impl)
110   {
111     if (impl == null)
112       throw new NullPointerException("impl may not be null");
113 
114     this.impl = impl;
115     this.remoteAddress = null;
116     this.remotePort = -1;
117   }
118 
119   /**
120    * Initializes a new instance of <code>DatagramSocket</code> that binds to
121    * a random port and every address on the local machine.
122    *
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.
126    */
DatagramSocket()127   public DatagramSocket() throws SocketException
128   {
129     this(new InetSocketAddress(0));
130   }
131 
132   /**
133    * Initializes a new instance of <code>DatagramSocket</code> that binds to
134    * the specified port and every address on the local machine.
135    *
136    * @param port The local port number to bind to.
137    *
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.
141    */
DatagramSocket(int port)142   public DatagramSocket(int port) throws SocketException
143   {
144     this(new InetSocketAddress(port));
145   }
146 
147   /**
148    * Initializes a new instance of <code>DatagramSocket</code> that binds to
149    * the specified local port and address.
150    *
151    * @param port The local port number to bind to.
152    * @param addr The local address to bind to.
153    *
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.
157    */
DatagramSocket(int port, InetAddress addr)158   public DatagramSocket(int port, InetAddress addr) throws SocketException
159   {
160     this(new InetSocketAddress(addr, port));
161   }
162 
163   /**
164    * Initializes a new instance of <code>DatagramSocket</code> that binds to
165    * the specified local port and address.
166    *
167    * @param address The local address and port number to bind to.
168    *
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.
172    *
173    * @since 1.4
174    */
DatagramSocket(SocketAddress address)175   public DatagramSocket(SocketAddress address) throws SocketException
176   {
177     String propVal = SystemProperties.getProperty("impl.prefix");
178     if (propVal == null || propVal.equals(""))
179       {
180         if (factory != null)
181           impl = factory.createDatagramSocketImpl();
182         else
183           {
184             try
185               {
186                 impl = new PlainDatagramSocketImpl();
187               }
188             catch (IOException ioe)
189               {
190                 SocketException se = new SocketException();
191                 se.initCause(ioe);
192                 throw se;
193               }
194           }
195       }
196     else
197       try
198         {
199           impl =
200             (DatagramSocketImpl) Class.forName("java.net." + propVal
201                                                + "DatagramSocketImpl")
202                                       .newInstance();
203         }
204       catch (Exception e)
205         {
206           System.err.println("Could not instantiate class: java.net."
207                              + propVal + "DatagramSocketImpl");
208           try
209             {
210               impl = new PlainDatagramSocketImpl();
211             }
212           catch (IOException ioe)
213             {
214               SocketException se = new SocketException();
215               se.initCause(ioe);
216               throw se;
217             }
218         }
219 
220     if (address != null)
221       bind(address);
222   }
223 
224   // This needs to be accessible from java.net.MulticastSocket
getImpl()225   DatagramSocketImpl getImpl() throws SocketException
226   {
227     try
228       {
229         if (! implCreated)
230           {
231             impl.create();
232             implCreated = true;
233           }
234 
235         return impl;
236       }
237     catch (IOException e)
238       {
239         SocketException se = new SocketException();
240         se.initCause(e);
241         throw se;
242       }
243   }
244 
245   /**
246    * Closes this datagram socket.
247    */
close()248   public void close()
249   {
250     if (isClosed())
251       return;
252 
253     try
254       {
255         getImpl().close();
256       }
257     catch (SocketException e)
258       {
259         // Ignore this case, just close the socket in finally clause.
260       }
261     finally
262       {
263         remoteAddress = null;
264         remotePort = -1;
265         impl = null;
266       }
267 
268     try
269       {
270         if (getChannel() != null)
271           getChannel().close();
272       }
273     catch (IOException e)
274       {
275         // Do nothing.
276       }
277   }
278 
279   /**
280    * This method returns the remote address to which this socket is
281    * connected.  If this socket is not connected, then this method will
282    * return <code>null</code>.
283    *
284    * @return The remote address.
285    *
286    * @since 1.2
287    */
getInetAddress()288   public InetAddress getInetAddress()
289   {
290     return remoteAddress;
291   }
292 
293   /**
294    * This method returns the remote port to which this socket is
295    * connected.  If this socket is not connected, then this method will
296    * return -1.
297    *
298    * @return The remote port.
299    *
300    * @since 1.2
301    */
getPort()302   public int getPort()
303   {
304     return remotePort;
305   }
306 
307   /**
308    * Returns the local address this datagram socket is bound to.
309    *
310    * @return The local address is the socket is bound or null
311    *
312    * @since 1.1
313    */
getLocalAddress()314   public InetAddress getLocalAddress()
315   {
316     if (! isBound())
317       return null;
318 
319     InetAddress localAddr;
320 
321     try
322       {
323         localAddr =
324           (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
325 
326         SecurityManager s = System.getSecurityManager();
327         if (s != null)
328           s.checkConnect(localAddr.getHostAddress(), -1);
329       }
330     catch (SecurityException e)
331       {
332         localAddr = InetAddress.ANY_IF;
333       }
334     catch (SocketException e)
335       {
336         // This cannot happen as we are bound.
337         return null;
338       }
339 
340     return localAddr;
341   }
342 
343   /**
344    * Returns the local port this socket is bound to.
345    *
346    * @return The local port number.
347    */
getLocalPort()348   public int getLocalPort()
349   {
350     if (isClosed())
351       return -1;
352 
353     try
354       {
355         return getImpl().getLocalPort();
356       }
357     catch (SocketException e)
358       {
359         // This cannot happen as we are bound.
360         return 0;
361       }
362   }
363 
364   /**
365    * Returns the value of the socket's SO_TIMEOUT setting.  If this method
366    * returns 0 then SO_TIMEOUT is disabled.
367    *
368    * @return The current timeout in milliseconds.
369    *
370    * @exception SocketException If an error occurs.
371    *
372    * @since 1.1
373    */
getSoTimeout()374   public synchronized int getSoTimeout() throws SocketException
375   {
376     if (isClosed())
377       throw new SocketException("socket is closed");
378 
379     Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT);
380 
381     if (buf instanceof Integer)
382       return ((Integer) buf).intValue();
383 
384     throw new SocketException("unexpected type");
385   }
386 
387   /**
388    * Sets the value of the socket's SO_TIMEOUT value.  A value of 0 will
389    * disable SO_TIMEOUT.  Any other value is the number of milliseconds
390    * a socket read/write will block before timing out.
391    *
392    * @param timeout The new SO_TIMEOUT value in milliseconds.
393    *
394    * @exception SocketException If an error occurs.
395    *
396    * @since 1.1
397    */
setSoTimeout(int timeout)398   public synchronized void setSoTimeout(int timeout) throws SocketException
399   {
400     if (isClosed())
401       throw new SocketException("socket is closed");
402 
403     if (timeout < 0)
404       throw new IllegalArgumentException("Invalid timeout: " + timeout);
405 
406     getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
407   }
408 
409   /**
410    * This method returns the value of the system level socket option
411    * SO_SNDBUF, which is used by the operating system to tune buffer
412    * sizes for data transfers.
413    *
414    * @return The send buffer size.
415    *
416    * @exception SocketException If an error occurs.
417    *
418    * @since 1.2
419    */
getSendBufferSize()420   public int getSendBufferSize() throws SocketException
421   {
422     if (isClosed())
423       throw new SocketException("socket is closed");
424 
425     Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
426 
427     if (buf instanceof Integer)
428       return ((Integer) buf).intValue();
429 
430     throw new SocketException("unexpected type");
431   }
432 
433   /**
434    * This method sets the value for the system level socket option
435    * SO_SNDBUF to the specified value.  Note that valid values for this
436    * option are specific to a given operating system.
437    *
438    * @param size The new send buffer size.
439    *
440    * @exception SocketException If an error occurs.
441    * @exception IllegalArgumentException If size is 0 or negative.
442    *
443    * @since 1.2
444    */
setSendBufferSize(int size)445   public void setSendBufferSize(int size) throws SocketException
446   {
447     if (isClosed())
448       throw new SocketException("socket is closed");
449 
450     if (size < 0)
451       throw new IllegalArgumentException("Buffer size is less than 0");
452 
453     getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
454   }
455 
456   /**
457    * This method returns the value of the system level socket option
458    * SO_RCVBUF, which is used by the operating system to tune buffer
459    * sizes for data transfers.
460    *
461    * @return The receive buffer size.
462    *
463    * @exception SocketException If an error occurs.
464    *
465    * @since 1.2
466    */
getReceiveBufferSize()467   public int getReceiveBufferSize() throws SocketException
468   {
469     if (isClosed())
470       throw new SocketException("socket is closed");
471 
472     Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
473 
474     if (buf instanceof Integer)
475       return ((Integer) buf).intValue();
476 
477     throw new SocketException("unexpected type");
478   }
479 
480   /**
481    * This method sets the value for the system level socket option
482    * SO_RCVBUF to the specified value.  Note that valid values for this
483    * option are specific to a given operating system.
484    *
485    * @param size The new receive buffer size.
486    *
487    * @exception SocketException If an error occurs.
488    * @exception IllegalArgumentException If size is 0 or negative.
489    *
490    * @since 1.2
491    */
setReceiveBufferSize(int size)492   public void setReceiveBufferSize(int size) throws SocketException
493   {
494     if (isClosed())
495       throw new SocketException("socket is closed");
496 
497     if (size < 0)
498       throw new IllegalArgumentException("Buffer size is less than 0");
499 
500     getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
501   }
502 
503   /**
504    * This method connects this socket to the specified address and port.
505    * When a datagram socket is connected, it will only send or receive
506    * packets to and from the host to which it is connected. A multicast
507    * socket that is connected may only send and not receive packets.
508    *
509    * @param address The address to connect this socket to.
510    * @param port The port to connect this socket to.
511    *
512    * @exception IllegalArgumentException If address or port are invalid.
513    * @exception SecurityException If the caller is not allowed to send
514    * datagrams to or receive from this address and port.
515    *
516    * @since 1.2
517    */
connect(InetAddress address, int port)518   public void connect(InetAddress address, int port)
519   {
520     if (address == null)
521       throw new IllegalArgumentException("Connect address may not be null");
522 
523     if ((port < 1) || (port > 65535))
524       throw new IllegalArgumentException("Port number is illegal: " + port);
525 
526     SecurityManager sm = System.getSecurityManager();
527     if (sm != null)
528       {
529         if (address.isMulticastAddress())
530           sm.checkMulticast(address);
531         else
532           {
533             sm.checkConnect(address.getHostAddress(), port);
534             sm.checkAccept(address.getHostAddress(), port);
535           }
536       }
537 
538     if (!isBound())
539       {
540         try
541           {
542             bind(new InetSocketAddress(0));
543           }
544         catch (SocketException e)
545           {
546             throw new Error("Binding socket failed.", e);
547           }
548       }
549 
550     try
551       {
552         getImpl().connect(address, port);
553         remoteAddress = address;
554         remotePort = port;
555       }
556     catch (SocketException e)
557       {
558         // This means simply not connected or connect not implemented.
559       }
560   }
561 
562   /**
563    * This method disconnects this socket from the address/port it was
564    * connected to.  If the socket was not connected in the first place,
565    * this method does nothing.
566    *
567    * @since 1.2
568    */
disconnect()569   public void disconnect()
570   {
571     if (! isConnected())
572       return;
573 
574     try
575       {
576         getImpl().disconnect();
577       }
578     catch (SocketException e)
579       {
580         // This cannot happen as we are connected.
581       }
582     finally
583       {
584         remoteAddress = null;
585         remotePort = -1;
586       }
587   }
588 
589   /**
590    * Reads a datagram packet from the socket.  Note that this method
591    * will block until a packet is received from the network.  On return,
592    * the passed in <code>DatagramPacket</code> is populated with the data
593    * received and all the other information about the packet.
594    *
595    * @param p A <code>DatagramPacket</code> for storing the data
596    *
597    * @exception IOException If an error occurs.
598    * @exception SocketTimeoutException If setSoTimeout was previously called
599    * and the timeout has expired.
600    * @exception PortUnreachableException If the socket is connected to a
601    * currently unreachable destination. Note, there is no guarantee that the
602    * exception will be thrown.
603    * @exception IllegalBlockingModeException If this socket has an associated
604    * channel, and the channel is in non-blocking mode.
605    * @exception SecurityException If a security manager exists and its
606    * checkAccept method doesn't allow the receive.
607    */
receive(DatagramPacket p)608   public synchronized void receive(DatagramPacket p) throws IOException
609   {
610     if (isClosed())
611       throw new SocketException("socket is closed");
612 
613     if (remoteAddress != null && remoteAddress.isMulticastAddress())
614       throw new IOException
615         ("Socket connected to a multicast address my not receive");
616 
617     if (getChannel() != null && ! getChannel().isBlocking()
618         && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
619       throw new IllegalBlockingModeException();
620 
621     DatagramPacket p2 = new DatagramPacket(p.getData(), p.getOffset(), p.maxlen);
622     getImpl().receive(p2);
623     p.length = p2.length;
624     if (p2.getAddress() != null)
625       p.setAddress(p2.getAddress());
626     if (p2.getPort() != -1)
627       p.setPort(p2.getPort());
628 
629     SecurityManager s = System.getSecurityManager();
630     if (s != null && isConnected())
631       s.checkAccept(p.getAddress().getHostAddress(), p.getPort());
632   }
633 
634   /**
635    * Sends the specified packet.  The host and port to which the packet
636    * are to be sent should be set inside the packet.
637    *
638    * @param p The datagram packet to send.
639    *
640    * @exception IOException If an error occurs.
641    * @exception SecurityException If a security manager exists and its
642    * checkMulticast or checkConnect method doesn't allow the send.
643    * @exception PortUnreachableException If the socket is connected to a
644    * currently unreachable destination. Note, there is no guarantee that the
645    * exception will be thrown.
646    * @exception IllegalBlockingModeException If this socket has an associated
647    * channel, and the channel is in non-blocking mode.
648    */
send(DatagramPacket p)649   public void send(DatagramPacket p) throws IOException
650   {
651     if (isClosed())
652       throw new SocketException("socket is closed");
653 
654     // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
655     SecurityManager s = System.getSecurityManager();
656     if (s != null && ! isConnected())
657       {
658         InetAddress addr = p.getAddress();
659         if (addr.isMulticastAddress())
660           s.checkMulticast(addr);
661         else
662           s.checkConnect(addr.getHostAddress(), p.getPort());
663       }
664 
665     if (isConnected())
666       {
667         if (p.getAddress() != null
668             && (remoteAddress != p.getAddress() || remotePort != p.getPort()))
669           throw new IllegalArgumentException
670             ("DatagramPacket address does not match remote address");
671       }
672 
673     // FIXME: if this is a subclass of MulticastSocket,
674     // use getTimeToLive for TTL val.
675     if (getChannel() != null && ! getChannel().isBlocking()
676         && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
677       throw new IllegalBlockingModeException();
678 
679     getImpl().send(p);
680   }
681 
682   /**
683    * Binds the socket to the given socket address.
684    *
685    * @param address The socket address to bind to.
686    *
687    * @exception SocketException If an error occurs.
688    * @exception SecurityException If a security manager exists and
689    * its checkListen method doesn't allow the operation.
690    * @exception IllegalArgumentException If address type is not supported.
691    *
692    * @since 1.4
693    */
bind(SocketAddress address)694   public void bind(SocketAddress address) throws SocketException
695   {
696     if (isClosed())
697       throw new SocketException("socket is closed");
698 
699     if (address == null)
700       address = new InetSocketAddress(InetAddress.ANY_IF, 0);
701 
702     if (! (address instanceof InetSocketAddress))
703       throw new IllegalArgumentException("unsupported address type");
704 
705     InetAddress addr = ((InetSocketAddress) address).getAddress();
706     int port = ((InetSocketAddress) address).getPort();
707 
708     if (port < 0 || port > 65535)
709       throw new IllegalArgumentException("Invalid port: " + port);
710 
711     SecurityManager s = System.getSecurityManager();
712     if (s != null)
713       s.checkListen(port);
714 
715     if (addr == null)
716       addr = InetAddress.ANY_IF;
717 
718     try
719       {
720         getImpl().bind(port, addr);
721         bound = true;
722       }
723     catch (SocketException exception)
724       {
725         getImpl().close();
726         throw exception;
727       }
728     catch (RuntimeException exception)
729       {
730         getImpl().close();
731         throw exception;
732       }
733     catch (Error error)
734       {
735         getImpl().close();
736         throw error;
737       }
738   }
739 
740   /**
741    * Checks if the datagram socket is closed.
742    *
743    * @return True if socket is closed, false otherwise.
744    *
745    * @since 1.4
746    */
isClosed()747   public boolean isClosed()
748   {
749     return impl == null;
750   }
751 
752   /**
753    * Returns the datagram channel assoziated with this datagram socket.
754    *
755    * @return The associated <code>DatagramChannel</code> object or null
756    *
757    * @since 1.4
758    */
getChannel()759   public DatagramChannel getChannel()
760   {
761     return null;
762   }
763 
764   /**
765    * Connects the datagram socket to a specified socket address.
766    *
767    * @param address The socket address to connect to.
768    *
769    * @exception SocketException If an error occurs.
770    * @exception IllegalArgumentException If address type is not supported.
771    *
772    * @since 1.4
773    */
connect(SocketAddress address)774   public void connect(SocketAddress address) throws SocketException
775   {
776     if (isClosed())
777       throw new SocketException("socket is closed");
778 
779     if (! (address instanceof InetSocketAddress))
780       throw new IllegalArgumentException("unsupported address type");
781 
782     InetSocketAddress tmp = (InetSocketAddress) address;
783     connect(tmp.getAddress(), tmp.getPort());
784   }
785 
786   /**
787    * Returns the binding state of the socket.
788    *
789    * @return True if socket bound, false otherwise.
790    *
791    * @since 1.4
792    */
isBound()793   public boolean isBound()
794   {
795     return bound;
796   }
797 
798   /**
799    * Returns the connection state of the socket.
800    *
801    * @return True if socket is connected, false otherwise.
802    *
803    * @since 1.4
804    */
isConnected()805   public boolean isConnected()
806   {
807     return remoteAddress != null;
808   }
809 
810   /**
811    * Returns the SocketAddress of the host this socket is conneted to
812    * or null if this socket is not connected.
813    *
814    * @return The socket address of the remote host if connected or null
815    *
816    * @since 1.4
817    */
getRemoteSocketAddress()818   public SocketAddress getRemoteSocketAddress()
819   {
820     if (! isConnected())
821       return null;
822 
823     return new InetSocketAddress(remoteAddress, remotePort);
824   }
825 
826   /**
827    * Returns the local SocketAddress this socket is bound to.
828    *
829    * @return The local SocketAddress or null if the socket is not bound.
830    *
831    * @since 1.4
832    */
getLocalSocketAddress()833   public SocketAddress getLocalSocketAddress()
834   {
835     if (! isBound())
836       return null;
837 
838     return new InetSocketAddress(getLocalAddress(), getLocalPort());
839   }
840 
841   /**
842    * Enables/Disables SO_REUSEADDR.
843    *
844    * @param on Whether or not to have SO_REUSEADDR turned on.
845    *
846    * @exception SocketException If an error occurs.
847    *
848    * @since 1.4
849    */
setReuseAddress(boolean on)850   public void setReuseAddress(boolean on) throws SocketException
851   {
852     if (isClosed())
853       throw new SocketException("socket is closed");
854 
855     getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
856   }
857 
858   /**
859    * Checks if SO_REUSEADDR is enabled.
860    *
861    * @return True if SO_REUSEADDR is set on the socket, false otherwise.
862    *
863    * @exception SocketException If an error occurs.
864    *
865    * @since 1.4
866    */
getReuseAddress()867   public boolean getReuseAddress() throws SocketException
868   {
869     if (isClosed())
870       throw new SocketException("socket is closed");
871 
872     Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR);
873 
874     if (buf instanceof Boolean)
875       return ((Boolean) buf).booleanValue();
876 
877     throw new SocketException("unexpected type");
878   }
879 
880   /**
881    * Enables/Disables SO_BROADCAST
882    *
883    * @param enable True if SO_BROADCAST should be enabled, false otherwise.
884    *
885    * @exception SocketException If an error occurs
886    *
887    * @since 1.4
888    */
setBroadcast(boolean enable)889   public void setBroadcast(boolean enable) throws SocketException
890   {
891     if (isClosed())
892       throw new SocketException("socket is closed");
893 
894     getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable));
895   }
896 
897   /**
898    * Checks if SO_BROADCAST is enabled
899    *
900    * @return Whether SO_BROADCAST is set
901    *
902    * @exception SocketException If an error occurs
903    *
904    * @since 1.4
905    */
getBroadcast()906   public boolean getBroadcast() throws SocketException
907   {
908     if (isClosed())
909       throw new SocketException("socket is closed");
910 
911     Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
912 
913     if (buf instanceof Boolean)
914       return ((Boolean) buf).booleanValue();
915 
916     throw new SocketException("unexpected type");
917   }
918 
919   /**
920    * Sets the traffic class value
921    *
922    * @param tc The traffic class
923    *
924    * @exception SocketException If an error occurs
925    * @exception IllegalArgumentException If tc value is illegal
926    *
927    * @see DatagramSocket#getTrafficClass()
928    *
929    * @since 1.4
930    */
setTrafficClass(int tc)931   public void setTrafficClass(int tc) throws SocketException
932   {
933     if (isClosed())
934       throw new SocketException("socket is closed");
935 
936     if (tc < 0 || tc > 255)
937       throw new IllegalArgumentException();
938 
939     getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc));
940   }
941 
942   /**
943    * Returns the current traffic class
944    *
945    * @return The current traffic class.
946    *
947    * @see DatagramSocket#setTrafficClass(int tc)
948    *
949    * @exception SocketException If an error occurs
950    *
951    * @since 1.4
952    */
getTrafficClass()953   public int getTrafficClass() throws SocketException
954   {
955     if (isClosed())
956       throw new SocketException("socket is closed");
957 
958     Object buf = getImpl().getOption(SocketOptions.IP_TOS);
959 
960     if (buf instanceof Integer)
961       return ((Integer) buf).intValue();
962 
963     throw new SocketException("unexpected type");
964   }
965 
966   /**
967    * Sets the datagram socket implementation factory for the application
968    *
969    * @param fac The factory to set
970    *
971    * @exception IOException If an error occurs
972    * @exception SocketException If the factory is already defined
973    * @exception SecurityException If a security manager exists and its
974    * checkSetFactory method doesn't allow the operation
975    */
setDatagramSocketImplFactory(DatagramSocketImplFactory fac)976   public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
977     throws IOException
978   {
979     if (factory != null)
980       throw new SocketException("DatagramSocketImplFactory already defined");
981 
982     SecurityManager sm = System.getSecurityManager();
983     if (sm != null)
984       sm.checkSetFactory();
985 
986     factory = fac;
987   }
988 }
989