OSDN Git Service

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