001/* ServerSocket.java -- Class for implementing server side sockets
002   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006
003   Free Software Foundation, Inc.
004
005This file is part of GNU Classpath.
006
007GNU Classpath is free software; you can redistribute it and/or modify
008it under the terms of the GNU General Public License as published by
009the Free Software Foundation; either version 2, or (at your option)
010any later version.
011
012GNU Classpath is distributed in the hope that it will be useful, but
013WITHOUT ANY WARRANTY; without even the implied warranty of
014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015General Public License for more details.
016
017You should have received a copy of the GNU General Public License
018along with GNU Classpath; see the file COPYING.  If not, write to the
019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02002110-1301 USA.
021
022Linking this library statically or dynamically with other modules is
023making a combined work based on this library.  Thus, the terms and
024conditions of the GNU General Public License cover the whole
025combination.
026
027As a special exception, the copyright holders of this library give you
028permission to link this library with independent modules to produce an
029executable, regardless of the license terms of these independent
030modules, and to copy and distribute the resulting executable under
031terms of your choice, provided that you also meet, for each linked
032independent module, the terms and conditions of the license of that
033module.  An independent module is a module which is not derived from
034or based on this library.  If you modify this library, you may extend
035this exception to your version of the library, but you are not
036obligated to do so.  If you do not wish to do so, delete this
037exception statement from your version. */
038
039package java.net;
040
041import gnu.java.net.PlainSocketImpl;
042
043import java.io.IOException;
044import java.nio.channels.IllegalBlockingModeException;
045import java.nio.channels.ServerSocketChannel;
046
047
048/* Written using on-line Java Platform 1.2 API Specification.
049 * Status:  I believe all methods are implemented.
050 */
051
052/**
053 * This class models server side sockets.  The basic model is that the
054 * server socket is created and bound to some well known port.  It then
055 * listens for and accepts connections.  At that point the client and
056 * server sockets are ready to communicate with one another utilizing
057 * whatever application layer protocol they desire.
058 *
059 * As with the <code>Socket</code> class, most instance methods of this class
060 * simply redirect their calls to an implementation class.
061 *
062 * @author Aaron M. Renn (arenn@urbanophile.com)
063 * @author Per Bothner (bothner@cygnus.com)
064 */
065public class ServerSocket
066{
067  /**
068   * This is the user defined SocketImplFactory, if one is supplied
069   */
070  private static SocketImplFactory factory;
071
072  /**
073   * This is the SocketImp object to which most instance methods in this
074   * class are redirected
075   */
076  private SocketImpl impl;
077
078  /**
079   * We need to retain the local address even after the socket is closed.
080   */
081  private InetSocketAddress local;
082  private int port;
083
084  /*
085   * This constructor is only used by java.nio.
086   */
087
088  ServerSocket(PlainSocketImpl impl) throws IOException
089  {
090    if (impl == null)
091      throw new NullPointerException("impl may not be null");
092
093    this.impl = impl;
094    this.impl.create(true);
095    setReuseAddress(true);
096  }
097
098  /*
099   * This method is only used by java.nio.
100   */
101
102  SocketImpl getImpl()
103  {
104    return impl;
105  }
106
107  /**
108   * Constructor that simply sets the implementation.
109   *
110   * @exception IOException If an error occurs
111   *
112   * @specnote This constructor is public since JDK 1.4
113   */
114  public ServerSocket() throws IOException
115  {
116    if (factory != null)
117      impl = factory.createSocketImpl();
118    else
119      impl = new PlainSocketImpl();
120
121    impl.create(true);
122  }
123
124  /**
125   * Creates a server socket and binds it to the specified port.  If the
126   * port number is 0, a random free port will be chosen.  The pending
127   * connection queue on this socket will be set to 50.
128   *
129   * @param port The port number to bind to
130   *
131   * @exception IOException If an error occurs
132   * @exception SecurityException If a security manager exists and its
133   * checkListen method doesn't allow the operation
134   */
135  public ServerSocket(int port) throws IOException
136  {
137    this(port, 50);
138  }
139
140  /**
141   * Creates a server socket and binds it to the specified port.  If the
142   * port number is 0, a random free port will be chosen.  The pending
143   * connection queue on this socket will be set to the value passed as
144   * arg2.
145   *
146   * @param port The port number to bind to
147   * @param backlog The length of the pending connection queue
148   *
149   * @exception IOException If an error occurs
150   * @exception SecurityException If a security manager exists and its
151   * checkListen method doesn't allow the operation
152   */
153  public ServerSocket(int port, int backlog) throws IOException
154  {
155    this(port, backlog, null);
156  }
157
158  /**
159   * Creates a server socket and binds it to the specified port.  If the
160   * port number is 0, a random free port will be chosen.  The pending
161   * connection queue on this socket will be set to the value passed as
162   * backlog.  The third argument specifies a particular local address to
163   * bind t or null to bind to all local address.
164   *
165   * @param port The port number to bind to
166   * @param backlog The length of the pending connection queue
167   * @param bindAddr The address to bind to, or null to bind to all addresses
168   *
169   * @exception IOException If an error occurs
170   * @exception SecurityException If a security manager exists and its
171   * checkListen method doesn't allow the operation
172   *
173   * @since 1.1
174   */
175  public ServerSocket(int port, int backlog, InetAddress bindAddr)
176    throws IOException
177  {
178    this();
179
180    // bind/listen socket
181    bind(new InetSocketAddress(bindAddr, port), backlog);
182  }
183
184  /**
185   * Binds the server socket to a specified socket address
186   *
187   * @param endpoint The socket address to bind to
188   *
189   * @exception IOException If an error occurs
190   * @exception IllegalArgumentException If address type is not supported
191   * @exception SecurityException If a security manager exists and its
192   * checkListen method doesn't allow the operation
193   *
194   * @since 1.4
195   */
196  public void bind(SocketAddress endpoint) throws IOException
197  {
198    bind(endpoint, 50);
199  }
200
201  /**
202   * Binds the server socket to a specified socket address
203   *
204   * @param endpoint The socket address to bind to
205   * @param backlog The length of the pending connection queue
206   *
207   * @exception IOException If an error occurs
208   * @exception IllegalArgumentException If address type is not supported
209   * @exception SecurityException If a security manager exists and its
210   * checkListen method doesn't allow the operation
211   *
212   * @since 1.4
213   */
214  public void bind(SocketAddress endpoint, int backlog)
215    throws IOException
216  {
217    if (isClosed())
218      throw new SocketException("ServerSocket is closed");
219
220    if (isBound())
221      throw new SocketException("Already bound");
222
223    InetAddress addr;
224    int port;
225
226    if (endpoint == null)
227      {
228        addr = InetAddress.ANY_IF;
229        port = 0;
230      }
231    else if (! (endpoint instanceof InetSocketAddress))
232      {
233        throw new IllegalArgumentException("Address type not supported");
234      }
235    else
236      {
237        InetSocketAddress tmp = (InetSocketAddress) endpoint;
238        if (tmp.isUnresolved())
239          throw new SocketException("Unresolved address");
240        addr = tmp.getAddress();
241        port = tmp.getPort();
242      }
243
244    SecurityManager s = System.getSecurityManager();
245    if (s != null)
246      s.checkListen(port);
247
248    try
249      {
250        impl.bind(addr, port);
251        impl.listen(backlog);
252        this.port = port;
253        local = new InetSocketAddress(
254            (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR),
255            impl.getLocalPort());
256      }
257    finally
258      {
259        try
260          {
261            if (local == null)
262              close();
263          }
264        catch (IOException _)
265          {
266          }
267      }
268  }
269
270  /**
271   * This method returns the local address to which this socket is bound
272   *
273   * @return The socket's local address
274   */
275  public InetAddress getInetAddress()
276  {
277    if (local == null)
278      return null;
279
280    return local.getAddress();
281  }
282
283  /**
284   * This method returns the local port number to which this socket is bound
285   *
286   * @return The socket's port number
287   */
288  public int getLocalPort()
289  {
290    if (local == null)
291      return -1;
292
293    return local.getPort();
294  }
295
296  /**
297   * Returns the local socket address
298   *
299   * @return the local socket address, null if not bound
300   *
301   * @since 1.4
302   */
303  public SocketAddress getLocalSocketAddress()
304  {
305    return local;
306  }
307
308  /**
309   * Accepts a new connection and returns a connected <code>Socket</code>
310   * instance representing that connection.  This method will block until a
311   * connection is available.
312   *
313   * @return socket object for the just accepted connection
314   *
315   * @exception IOException If an error occurs
316   * @exception SecurityException If a security manager exists and its
317   * checkListen method doesn't allow the operation
318   * @exception IllegalBlockingModeException If this socket has an associated
319   * channel, and the channel is in non-blocking mode
320   * @exception SocketTimeoutException If a timeout was previously set with
321   * setSoTimeout and the timeout has been reached
322   */
323  public Socket accept() throws IOException
324  {
325    Socket socket = new Socket();
326
327    try
328      {
329        implAccept(socket);
330      }
331    catch (IOException e)
332      {
333        try
334          {
335            socket.close();
336          }
337        catch (IOException e2)
338          {
339            // Ignore.
340          }
341
342        throw e;
343      }
344    catch (SecurityException e)
345      {
346        try
347          {
348            socket.close();
349          }
350        catch (IOException e2)
351          {
352            // Ignore.
353          }
354
355        throw e;
356      }
357
358    return socket;
359  }
360
361  /**
362   * This protected method is used to help subclasses override
363   * <code>ServerSocket.accept()</code>.  The passed in socket will be
364   * connected when this method returns.
365   *
366   * @param socket The socket that is used for the accepted connection
367   *
368   * @exception IOException If an error occurs
369   * @exception IllegalBlockingModeException If this socket has an associated
370   * channel, and the channel is in non-blocking mode
371   *
372   * @since 1.1
373   */
374  protected final void implAccept(Socket socket) throws IOException
375  {
376    if (isClosed())
377      throw new SocketException("ServerSocket is closed");
378
379    // The Sun spec says that if we have an associated channel and
380    // it is in non-blocking mode, we throw an IllegalBlockingModeException.
381    // However, in our implementation if the channel itself initiated this
382    // operation, then we must honor it regardless of its blocking mode.
383    if (getChannel() != null && ! getChannel().isBlocking()
384        && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
385      throw new IllegalBlockingModeException();
386
387    impl.accept(socket.impl);
388    socket.bound = true;
389    socket.implCreated = true;
390
391    SecurityManager sm = System.getSecurityManager();
392    if (sm != null)
393      sm.checkAccept(socket.getInetAddress().getHostAddress(),
394                     socket.getPort());
395  }
396
397  /**
398   * Closes this socket and stops listening for connections
399   *
400   * @exception IOException If an error occurs
401   */
402  public void close() throws IOException
403  {
404    if (impl != null)
405      {
406        impl.close();
407        impl = null;
408      }
409  }
410
411  /**
412   * Returns the unique <code>ServerSocketChannel</code> object
413   * associated with this socket, if any.
414   *
415   * <p>The socket only has a <code>ServerSocketChannel</code> if its created
416   * by <code>ServerSocketChannel.open()</code>.</p>
417   *
418   * @return the associated socket channel, null if none exists
419   *
420   * @since 1.4
421   */
422  public ServerSocketChannel getChannel()
423  {
424    return null;
425  }
426
427  /**
428   * Returns true when the socket is bound, otherwise false
429   *
430   * @return true if socket is bound, false otherwise
431   *
432   * @since 1.4
433   */
434  public boolean isBound()
435  {
436    return local != null;
437  }
438
439  /**
440   * Returns true if the socket is closed, otherwise false
441   *
442   * @return true if socket is closed, false otherwise
443   *
444   * @since 1.4
445   */
446  public boolean isClosed()
447  {
448    ServerSocketChannel channel = getChannel();
449    return impl == null || (channel != null && ! channel.isOpen());
450  }
451
452  /**
453   * Sets the value of SO_TIMEOUT.  A value of 0 implies that SO_TIMEOUT is
454   * disabled (ie, operations never time out).  This is the number of
455   * milliseconds a socket operation can block before an
456   * InterruptedIOException is thrown.
457   *
458   * @param timeout The new SO_TIMEOUT value
459   *
460   * @exception SocketException If an error occurs
461   *
462   * @since 1.1
463   */
464  public void setSoTimeout(int timeout) throws SocketException
465  {
466    if (isClosed())
467      throw new SocketException("ServerSocket is closed");
468
469    if (timeout < 0)
470      throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
471
472    impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
473  }
474
475  /**
476   * Retrieves the current value of the SO_TIMEOUT setting.  A value of 0
477   * implies that SO_TIMEOUT is disabled (ie, operations never time out).
478   * This is the number of milliseconds a socket operation can block before
479   * an InterruptedIOException is thrown.
480   *
481   * @return The value of SO_TIMEOUT
482   *
483   * @exception IOException If an error occurs
484   *
485   * @since 1.1
486   */
487  public int getSoTimeout() throws IOException
488  {
489    if (isClosed())
490      throw new SocketException("ServerSocket is closed");
491
492    Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
493
494    if (! (timeout instanceof Integer))
495      throw new IOException("Internal Error");
496
497    return ((Integer) timeout).intValue();
498  }
499
500  /**
501   * Enables/Disables the SO_REUSEADDR option
502   *
503   * @param on true if SO_REUSEADDR should be enabled, false otherwise
504   *
505   * @exception SocketException If an error occurs
506   *
507   * @since 1.4
508   */
509  public void setReuseAddress(boolean on) throws SocketException
510  {
511    if (isClosed())
512      throw new SocketException("ServerSocket is closed");
513
514    impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
515  }
516
517  /**
518   * Checks if the SO_REUSEADDR option is enabled
519   *
520   * @return true if SO_REUSEADDR is set, false otherwise
521   *
522   * @exception SocketException If an error occurs
523   *
524   * @since 1.4
525   */
526  public boolean getReuseAddress() throws SocketException
527  {
528    if (isClosed())
529      throw new SocketException("ServerSocket is closed");
530
531    Object reuseaddr = impl.getOption(SocketOptions.SO_REUSEADDR);
532
533    if (! (reuseaddr instanceof Boolean))
534      throw new SocketException("Internal Error");
535
536    return ((Boolean) reuseaddr).booleanValue();
537  }
538
539  /**
540   * This method sets the value for the system level socket option
541   * SO_RCVBUF to the specified value.  Note that valid values for this
542   * option are specific to a given operating system.
543   *
544   * @param size The new receive buffer size.
545   *
546   * @exception SocketException If an error occurs or Socket is not connected
547   * @exception IllegalArgumentException If size is 0 or negative
548   *
549   * @since 1.4
550   */
551  public void setReceiveBufferSize(int size) throws SocketException
552  {
553    if (isClosed())
554      throw new SocketException("ServerSocket is closed");
555
556    if (size <= 0)
557      throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
558
559    impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
560  }
561
562  /**
563   * This method returns the value of the system level socket option
564   * SO_RCVBUF, which is used by the operating system to tune buffer
565   * sizes for data transfers.
566   *
567   * @return The receive buffer size.
568   *
569   * @exception SocketException If an error occurs or Socket is not connected
570   *
571   * @since 1.4
572   */
573  public int getReceiveBufferSize() throws SocketException
574  {
575    if (isClosed())
576      throw new SocketException("ServerSocket is closed");
577
578    Object buf = impl.getOption(SocketOptions.SO_RCVBUF);
579
580    if (! (buf instanceof Integer))
581      throw new SocketException("Internal Error: Unexpected type");
582
583    return ((Integer) buf).intValue();
584  }
585
586  /**
587   * Returns the value of this socket as a <code>String</code>.
588   *
589   * @return This socket represented as a <code>String</code>.
590   */
591  public String toString()
592  {
593    if (! isBound())
594      return "ServerSocket[unbound]";
595
596    return ("ServerSocket[addr=" + getInetAddress() + ",port="
597           + port + ",localport=" + getLocalPort() + "]");
598  }
599
600  /**
601   * Sets the <code>SocketImplFactory</code> for all
602   * <code>ServerSocket</code>'s.  This may only be done
603   * once per virtual machine.  Subsequent attempts will generate an
604   * exception.  Note that a <code>SecurityManager</code> check is made prior
605   * to setting the factory.  If insufficient privileges exist to set the
606   * factory, an exception will be thrown
607   *
608   * @param fac the factory to set
609   *
610   * @exception SecurityException If this operation is not allowed by the
611   * <code>SecurityManager</code>.
612   * @exception SocketException If the factory object is already defined
613   * @exception IOException If any other error occurs
614   */
615  public static synchronized void setSocketFactory(SocketImplFactory fac)
616    throws IOException
617  {
618    if (factory != null)
619      throw new SocketException("SocketFactory already defined");
620
621    SecurityManager sm = System.getSecurityManager();
622    if (sm != null)
623      sm.checkSetFactory();
624
625    factory = fac;
626  }
627}