2002-09-25 Michael Koch <konqueror@gmx.de>
[platform/upstream/gcc.git] / libjava / java / net / ServerSocket.java
1 /* ServerSocket.java -- Class for implementing server side sockets
2    Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10  
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.
15
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.
20
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.
25
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. */
37
38 package java.net;
39
40 import java.io.IOException;
41 import java.nio.channels.IllegalBlockingModeException;
42 import java.nio.channels.ServerSocketChannel;
43
44 /* Written using on-line Java Platform 1.2 API Specification.
45  * Status:  I believe all methods are implemented.
46  */
47
48 /**
49  * This class models server side sockets.  The basic model is that the
50  * server socket is created and bound to some well known port.  It then
51  * listens for and accepts connections.  At that point the client and
52  * server sockets are ready to communicate with one another utilizing
53  * whatever application layer protocol they desire.
54  *
55  * As with the <code>Socket</code> class, most instance methods of this class 
56  * simply redirect their calls to an implementation class.
57  *
58  * @author Aaron M. Renn (arenn@urbanophile.com)
59  * @author Per Bothner (bothner@cygnus.com)
60  */
61 public class ServerSocket
62 {
63
64   // Class Variables
65
66   /**
67    * This is the user defined SocketImplFactory, if one is supplied
68    */
69   private static SocketImplFactory factory;
70
71   // Instance Variables
72
73   /**
74    * This is the SocketImp object to which most instance methods in this
75    * class are redirected
76    */
77   private SocketImpl impl;
78
79   /**
80    * ServerSocketChannel of this ServerSocket. This channel only exists
81    * when the socket is created by ServerSocketChannel.open().
82    */
83   private ServerSocketChannel ch;
84
85   /**
86    * Constructor that simply sets the implementation.
87    * 
88    * @exception IOException If an error occurs
89    *
90    * @specnote This constructor is public since JDK 1.4
91    */
92   public ServerSocket() throws IOException
93   {
94     if (factory != null)
95       impl = factory.createSocketImpl();
96     else
97       impl = new PlainSocketImpl();
98   }
99
100   /**
101    * Creates a server socket and binds it to the specified port.  If the
102    * port number is 0, a random free port will be chosen.  The pending
103    * connection queue on this socket will be set to 50.
104    *
105    * @param port The port number to bind to
106    * 
107    * @exception IOException If an error occurs
108    * @exception SecurityException If a security manager exists and its
109    * checkListen method doesn't allow the operation
110    */
111   public ServerSocket (int port)
112     throws IOException
113   {
114     this(port, 50);
115   }
116
117   /**
118    * Creates a server socket and binds it to the specified port.  If the
119    * port number is 0, a random free port will be chosen.  The pending
120    * connection queue on this socket will be set to the value passed as
121    * arg2.
122    *
123    * @param port The port number to bind to
124    * @param backlog The length of the pending connection queue
125    *
126    * @exception IOException If an error occurs
127    * @exception SecurityException If a security manager exists and its
128    * checkListen method doesn't allow the operation
129    */
130   public ServerSocket (int port, int backlog)
131     throws IOException
132   {
133     this(port, backlog, null);
134   }
135
136   /**
137    * Creates a server socket and binds it to the specified port.  If the
138    * port number is 0, a random free port will be chosen.  The pending
139    * connection queue on this socket will be set to the value passed as
140    * backlog.  The third argument specifies a particular local address to
141    * bind t or null to bind to all local address.
142    *
143    * @param port The port number to bind to
144    * @param backlog The length of the pending connection queue
145    * @param bindAddr The address to bind to, or null to bind to all addresses
146    *
147    * @exception IOException If an error occurs
148    * @exception SecurityException If a security manager exists and its
149    * checkListen method doesn't allow the operation
150    *
151    * @since 1.1
152    */
153   public ServerSocket (int port, int backlog, InetAddress bindAddr)
154     throws IOException
155   {
156     this();
157     if (impl == null)
158       throw new IOException("Cannot initialize Socket implementation");
159
160     SecurityManager s = System.getSecurityManager();
161     if (s != null)
162       s.checkListen(port);
163
164     if (bindAddr == null)
165       bindAddr = InetAddress.ANY_IF;
166
167     impl.create(true);
168     impl.bind(bindAddr, port);
169     impl.listen(backlog);
170   }
171
172   /**
173    * Binds the server socket to a specified socket address
174    *
175    * @param endpoint The socket address to bind to
176    *
177    * @exception IOException If an error occurs
178    * @exception IllegalArgumentException If address type is not supported
179    * @exception SecurityException If a security manager exists and its
180    * checkListen method doesn't allow the operation
181    * 
182    * @since 1.4
183    */
184   public void bind (SocketAddress endpoint)
185     throws IOException
186   {
187     if (impl == null)
188       throw new IOException ("Cannot initialize Socket implementation");
189
190     if (! (endpoint instanceof InetSocketAddress))
191       throw new IllegalArgumentException ("Address type not supported");
192
193     InetSocketAddress tmp = (InetSocketAddress) endpoint;
194     
195     SecurityManager s = System.getSecurityManager ();
196     if (s != null)
197       s.checkListen (tmp.getPort ());
198
199     impl.bind (tmp.getAddress (), tmp.getPort ());
200   }
201  
202   /**
203    * Binds the server socket to a specified socket address
204    *
205    * @param endpoint The socket address to bind to
206    * @param backlog The length of the pending connection queue
207    * 
208    * @exception IOException If an error occurs
209    * @exception IllegalArgumentException If address type is not supported
210    * @exception SecurityException If a security manager exists and its
211    * checkListen method doesn't allow the operation
212    *
213    * @since 1.4
214    */
215   public void bind (SocketAddress endpoint, int backlog) throws IOException
216   {
217     if (impl == null)
218       throw new IOException ("Cannot initialize Socket implementation");
219
220     if (! (endpoint instanceof InetSocketAddress))
221       throw new IllegalArgumentException ("Address type not supported");
222
223     InetSocketAddress tmp = (InetSocketAddress) endpoint;
224     
225     SecurityManager s = System.getSecurityManager ();
226     if (s != null)
227       s.checkListen (tmp.getPort ());
228
229     impl.bind (tmp.getAddress (), tmp.getPort ());
230     impl.listen(backlog);
231   }
232   
233   /**
234    * This method returns the local address to which this socket is bound
235    *
236    * @return The socket's local address
237    */
238   public InetAddress getInetAddress()
239   {
240     try
241       {
242         return (InetAddress) impl.getOption (SocketOptions.SO_BINDADDR);
243       }
244     catch (SocketException e)
245       {
246         return null;
247       }
248   }
249
250   /**
251    * This method returns the local port number to which this socket is bound
252    *
253    * @return The socket's port number
254    */
255   public int getLocalPort()
256   {
257     return impl.getLocalPort();
258   }
259
260   /**
261    * Returns the local socket address
262    *
263    * @since 1.4
264    */
265   public SocketAddress getLocalSocketAddress()
266   {
267     InetAddress addr = getInetAddress();
268
269     if (addr != null)
270       return new InetSocketAddress (getInetAddress(), getLocalPort());
271
272     return null;
273   }
274
275   /**
276    * Accepts a new connection and returns a connected <code>Socket</code> 
277    * instance representing that connection.  This method will block until a 
278    * connection is available.
279    *
280    * @exception IOException If an error occurs
281    * @exception SecurityException If a security manager exists and its
282    * checkListen method doesn't allow the operation
283    * @exception IllegalBlockingModeException If this socket has an associated
284    * channel, and the channel is in non-blocking mode
285    * @exception SocketTimeoutException If a timeout was previously set with
286    * setSoTimeout and the timeout has been reached
287    */
288   public Socket accept () throws IOException
289   {
290     Socket s = new Socket();
291     implAccept (s);
292
293     return s;
294   }
295
296   /**
297    * This protected method is used to help subclasses override 
298    * <code>ServerSocket.accept()</code>.  The passed in socket will be
299    * connected when this method returns.
300    *
301    * @param socket The socket that is used for the accepted connection
302    *
303    * @exception IOException If an error occurs
304    * @exception IllegalBlockingModeException If this socket has an associated
305    * channel, and the channel is in non-blocking mode
306    *
307    * @since 1.1
308    */
309   protected final void implAccept (Socket s)
310     throws IOException
311   {
312     if (ch != null && !ch.isBlocking())
313       throw new IllegalBlockingModeException();
314             
315     impl.accept(s.impl);
316   }
317
318   /**
319    * Closes this socket and stops listening for connections
320    *
321    * @exception IOException If an error occurs
322    */
323   public void close () throws IOException
324   {
325     impl.close();
326   }
327
328   /**
329    * Returns the unique ServerSocketChannel object
330    * associated with this socket, if any.
331    *
332    * The socket only has a ServerSocketChannel if its created
333    * by ServerSocketChannel.open.
334    * 
335    * @since 1.4
336    */
337   public ServerSocketChannel getChannel()
338   {
339     return ch;
340   }
341
342   /**
343    * Returns true then the socket is bound, otherwise false
344    * 
345    * @since 1.4
346    */
347   public boolean isBound()
348   {
349     try
350       {
351         Object bindaddr = impl.getOption (SocketOptions.SO_BINDADDR);
352       }
353     catch (SocketException e)
354       {
355         return false;
356       }
357     
358     return true;
359   }
360
361   /**
362    * Sets the value of SO_TIMEOUT.  A value of 0 implies that SO_TIMEOUT is
363    * disabled (ie, operations never time out).  This is the number of 
364    * milliseconds a socket operation can block before an
365    * InterruptedIOException is thrown.
366    *
367    * @param timeout The new SO_TIMEOUT value
368    *
369    * @exception SocketException If an error occurs
370    *
371    * @since 1.1
372    */
373   public void setSoTimeout (int timeout) throws SocketException
374   {
375     if (timeout < 0)
376       throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
377
378     impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
379   }
380
381   /**
382    * Retrieves the current value of the SO_TIMEOUT setting.  A value of 0
383    * implies that SO_TIMEOUT is disabled (ie, operations never time out).
384    * This is the number of milliseconds a socket operation can block before
385    * an InterruptedIOException is thrown.
386    *
387    * @return The value of SO_TIMEOUT
388    *
389    * @exception IOException If an error occurs
390    *
391    * @since 1.1
392    */
393   public int getSoTimeout () throws IOException
394   {
395     Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
396
397     if (!(timeout instanceof Integer))
398       throw new IOException("Internal Error");
399
400     return ((Integer)timeout).intValue();
401   }
402
403   /**
404    * Enables/Disables the SO_REUSEADDR option
405    * 
406    * @exception SocketException If an error occurs
407    * 
408    * @since 1.4
409    */
410   public void setReuseAddress (boolean on)
411     throws SocketException
412   {
413     if (impl == null)
414       throw new SocketException ("Cannot initialize Socket implementation");
415
416     impl.setOption (SocketOptions.SO_REUSEADDR, new Boolean (on));
417   }
418
419   /**
420    * Checks if the SO_REUSEADDR option is enabled
421    * 
422    * @exception SocketException If an error occurs
423    * 
424    * @since 1.4
425    */
426   public boolean getReuseAddress()
427     throws SocketException
428   {
429     if (impl == null)
430       throw new SocketException ("Cannot initialize Socket implementation");
431
432     Object reuseaddr = impl.getOption (SocketOptions.SO_REUSEADDR);
433
434     if (!(reuseaddr instanceof Boolean))
435       throw new SocketException ("Internal Error");
436     
437     return ((Boolean) reuseaddr).booleanValue ();
438   }
439
440   /**
441    * This method sets the value for the system level socket option
442    * SO_RCVBUF to the specified value.  Note that valid values for this
443    * option are specific to a given operating system.
444    * 
445    * @param size The new receive buffer size.
446    * 
447    * @exception SocketException If an error occurs or Socket is not connected
448    * @exception IllegalArgumentException If size is 0 or negative
449    *
450    * @since 1.4
451    */
452   public void setReceiveBufferSize (int size)
453     throws SocketException
454   {
455     if (impl == null)
456       throw new SocketException ("Not connected");
457
458     if (size <= 0)
459       throw new IllegalArgumentException ("SO_RCVBUF value must be > 0");
460
461     impl.setOption (SocketOptions.SO_RCVBUF, new Integer (size));
462   }
463
464   /**
465    * This method returns the value of the system level socket option
466    * SO_RCVBUF, which is used by the operating system to tune buffer
467    * sizes for data transfers.
468    * 
469    * @return The receive buffer size.
470    *             
471    * @exception SocketException If an error occurs or Socket is not connected
472    * 
473    * @since 1.4
474    */
475   public int getReceiveBufferSize ()
476     throws SocketException
477   {
478     if (impl == null)
479       throw new SocketException ("Not connected");
480
481     Object buf = impl.getOption (SocketOptions.SO_RCVBUF);
482
483     if (!(buf instanceof Integer))
484       throw new SocketException ("Internal Error: Unexpected type");
485     
486     return ((Integer) buf).intValue ();
487   }
488
489   /**
490    * Returns the value of this socket as a <code>String</code>. 
491    *
492    * @return This socket represented as a <code>String</code>.
493    */
494   public String toString ()
495   {
496     return "ServerSocket" + impl.toString();
497   }
498
499   // Class methods
500
501   /**
502    * Sets the <code>SocketImplFactory</code> for all 
503    * <code>ServerSocket</code>'s.  This may only be done
504    * once per virtual machine.  Subsequent attempts will generate an
505    * exception.  Note that a <code>SecurityManager</code> check is made prior
506    * to setting the factory.  If insufficient privileges exist to set the
507    * factory, an exception will be thrown
508    *
509    * @exception SecurityException If this operation is not allowed by the
510    * <code>SecurityManager</code>.
511    * @exception SocketException If the factory object is already defined
512    * @exception IOException If any other error occurs
513    */
514   public static synchronized void setSocketFactory (SocketImplFactory fac)
515     throws IOException
516   {
517     factory = fac;
518   }
519 }