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
005 This file is part of GNU Classpath.
006
007 GNU Classpath is free software; you can redistribute it and/or modify
008 it under the terms of the GNU General Public License as published by
009 the Free Software Foundation; either version 2, or (at your option)
010 any later version.
011
012 GNU Classpath is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of
014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 General Public License for more details.
016
017 You should have received a copy of the GNU General Public License
018 along with GNU Classpath; see the file COPYING. If not, write to the
019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020 02110-1301 USA.
021
022 Linking this library statically or dynamically with other modules is
023 making a combined work based on this library. Thus, the terms and
024 conditions of the GNU General Public License cover the whole
025 combination.
026
027 As a special exception, the copyright holders of this library give you
028 permission to link this library with independent modules to produce an
029 executable, regardless of the license terms of these independent
030 modules, and to copy and distribute the resulting executable under
031 terms of your choice, provided that you also meet, for each linked
032 independent module, the terms and conditions of the license of that
033 module. An independent module is a module which is not derived from
034 or based on this library. If you modify this library, you may extend
035 this exception to your version of the library, but you are not
036 obligated to do so. If you do not wish to do so, delete this
037 exception statement from your version. */
038
039 package java.net;
040
041 import gnu.java.net.PlainSocketImpl;
042
043 import java.io.IOException;
044 import java.nio.channels.IllegalBlockingModeException;
045 import 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 */
065 public 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 }