Source for gnu.java.net.PlainSocketImpl

   1: /* PlainSocketImpl.java -- Default socket implementation
   2:    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
   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: 
  40: package gnu.java.net;
  41: 
  42: import gnu.classpath.Configuration;
  43: 
  44: import java.io.IOException;
  45: import java.io.InputStream;
  46: import java.io.OutputStream;
  47: import java.net.InetAddress;
  48: import java.net.InetSocketAddress;
  49: import java.net.SocketAddress;
  50: import java.net.SocketException;
  51: import java.net.SocketImpl;
  52: import java.net.SocketOptions;
  53: 
  54: /**
  55:  * Written using on-line Java Platform 1.2 API Specification, as well
  56:  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
  57:  * Status:  Believed complete and correct.
  58:  */
  59: 
  60: /**
  61:  * Unless the application installs its own SocketImplFactory, this is the
  62:  * default socket implemetation that will be used.  It simply uses a
  63:  * combination of Java and native routines to implement standard BSD
  64:  * style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
  65:  *
  66:  * @author Per Bothner (bothner@cygnus.com)
  67:  * @author Nic Ferrier (nferrier@tapsellferrier.co.uk)
  68:  * @author Aaron M. Renn (arenn@urbanophile.com)
  69:  */
  70: public final class PlainSocketImpl extends SocketImpl
  71: {
  72:   // Static initializer to load native library.
  73:   static
  74:     {
  75:       if (Configuration.INIT_LOAD_LIBRARY)
  76:         {
  77:           System.loadLibrary("javanet");
  78:         }
  79:     }
  80:   
  81:   // These fields are mirrored for use in native code to avoid cpp conflicts
  82:   // when the #defines in system header files are the same as the public fields.
  83:   static final int _Jv_TCP_NODELAY_ = SocketOptions.TCP_NODELAY,
  84:                    _Jv_SO_BINDADDR_ = SocketOptions.SO_BINDADDR,
  85:                    _Jv_SO_REUSEADDR_ = SocketOptions.SO_REUSEADDR,
  86:                    _Jv_SO_BROADCAST_ = SocketOptions.SO_BROADCAST,
  87:                    _Jv_SO_OOBINLINE_ = SocketOptions.SO_OOBINLINE,
  88:                    _Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
  89:                    _Jv_IP_MULTICAST_IF2_ = SocketOptions.IP_MULTICAST_IF2,
  90:                    _Jv_IP_MULTICAST_LOOP_ = SocketOptions.IP_MULTICAST_LOOP,
  91:                    _Jv_IP_TOS_ = SocketOptions.IP_TOS,
  92:                    _Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
  93:                    _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
  94:                    _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
  95:                    _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF,
  96:                    _Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE;
  97: 
  98:   /**
  99:    * The OS file handle representing the socket.
 100:    * This is used for reads and writes to/from the socket and
 101:    * to close it.
 102:    *
 103:    * When the socket is closed this is reset to -1.
 104:    */
 105:   int native_fd = -1;
 106: 
 107:   // This value is set/read by setOption/getOption.
 108:   int timeout = 0;
 109:   
 110:   // localAddress cache
 111:   InetAddress localAddress;
 112: 
 113:   // Local address as an InetSocketAddress.
 114:   InetSocketAddress localSocketAddress;
 115: 
 116:   /**
 117:    * A cached copy of the in stream for reading from the socket.
 118:    */
 119:   private InputStream in;
 120: 
 121:   /**
 122:    * A cached copy of the out stream for writing to the socket.
 123:    */
 124:   private OutputStream out;
 125: 
 126:   /**
 127:    * Indicates whether a channel initiated whatever operation
 128:    * is being invoked on this socket.
 129:    */
 130:   private boolean inChannelOperation;
 131: 
 132:   /**
 133:    * Indicates whether we should ignore whether any associated
 134:    * channel is set to non-blocking mode. Certain operations
 135:    * throw an <code>IllegalBlockingModeException</code> if the
 136:    * associated channel is in non-blocking mode, <i>except</i>
 137:    * if the operation is invoked by the channel itself.
 138:    */
 139:   public final boolean isInChannelOperation()
 140:   {
 141:     return inChannelOperation;
 142:   }
 143:   
 144:   /**
 145:    * Sets our indicator of whether an I/O operation is being
 146:    * initiated by a channel.
 147:    */
 148:   public final void setInChannelOperation(boolean b)
 149:   {
 150:     inChannelOperation = b;
 151:   }
 152:  
 153:   /**
 154:    * Default do nothing constructor
 155:    */
 156:   public PlainSocketImpl()
 157:   {
 158:   }
 159:   
 160:   protected void finalize() throws Throwable
 161:   {
 162:     synchronized (this)
 163:       {
 164:     if (native_fd != -1)
 165:       try
 166:         {
 167:           close();
 168:         }
 169:       catch (IOException ex)
 170:         {
 171:         }
 172:       }
 173:     super.finalize();
 174:   }
 175: 
 176:   public int getNativeFD()
 177:   {
 178:     return native_fd;
 179:   }
 180: 
 181:   /**
 182:    * Sets the specified option on a socket to the passed in object.  For
 183:    * options that take an integer argument, the passed in object is an
 184:    * Integer.  The option_id parameter is one of the defined constants in
 185:    * this interface.
 186:    *
 187:    * @param option_id The identifier of the option
 188:    * @param val The value to set the option to
 189:    *
 190:    * @exception SocketException If an error occurs
 191:    */
 192:   public native void setOption(int optID, Object value) throws SocketException;
 193: 
 194:   /**
 195:    * Returns the current setting of the specified option.  The Object returned
 196:    * will be an Integer for options that have integer values.  The option_id
 197:    * is one of the defined constants in this interface.
 198:    *
 199:    * @param option_id The option identifier
 200:    *
 201:    * @return The current value of the option
 202:    *
 203:    * @exception SocketException If an error occurs
 204:    */
 205:   public native Object getOption(int optID) throws SocketException;
 206: 
 207:   /**
 208:    * Flushes the input stream and closes it. If you read from the input stream
 209:    * after calling this method a <code>IOException</code> will be thrown.
 210:    * 
 211:    * @throws IOException if an error occurs
 212:    */
 213:   public native void shutdownInput() throws IOException;
 214: 
 215:   /**
 216:    * Flushes the output stream and closes it. If you write to the output stream
 217:    * after calling this method a <code>IOException</code> will be thrown.
 218:    * 
 219:    * @throws IOException if an error occurs
 220:    */
 221:   public native void shutdownOutput() throws IOException;
 222: 
 223:   /**
 224:    * Creates a new socket that is not bound to any local address/port and
 225:    * is not connected to any remote address/port.  This will be created as
 226:    * a stream socket if the stream parameter is true, or a datagram socket
 227:    * if the stream parameter is false.
 228:    *
 229:    * @param stream true for a stream socket, false for a datagram socket
 230:    */
 231:   // FIXME: this is public for nio ... but this is just a hack
 232:   // until we upgrade to Classpath's nio.
 233:   public native void create(boolean stream) throws IOException;
 234: 
 235:   /**
 236:    * Connects to the remote hostname and port specified as arguments.
 237:    *
 238:    * @param hostname The remote hostname to connect to
 239:    * @param port The remote port to connect to
 240:    *
 241:    * @exception IOException If an error occurs
 242:    */
 243:   protected void connect(String host, int port) throws IOException
 244:   {
 245:     connect(InetAddress.getByName(host), port);
 246:   }
 247: 
 248:   /**
 249:    * Connects to the remote address and port specified as arguments.
 250:    *
 251:    * @param addr The remote address to connect to
 252:    * @param port The remote port to connect to
 253:    *
 254:    * @exception IOException If an error occurs
 255:    */
 256:   protected void connect(InetAddress host, int port) throws IOException
 257:   {
 258:     connect (new InetSocketAddress (host, port), 0);
 259:   }
 260: 
 261:   /**
 262:    * Connects to the remote socket address with a specified timeout.
 263:    *
 264:    * @param timeout The timeout to use for this connect, 0 means infinite.
 265:    *
 266:    * @exception IOException If an error occurs
 267:    */
 268:   protected native void connect(SocketAddress addr, int timeout) throws IOException;
 269: 
 270:   /**
 271:    * Binds to the specified port on the specified addr.  Note that this addr
 272:    * must represent a local IP address.  **** How bind to INADDR_ANY? ****
 273:    *
 274:    * @param addr The address to bind to
 275:    * @param port The port number to bind to
 276:    *
 277:    * @exception IOException If an error occurs
 278:    */
 279:   protected native void bind(InetAddress host, int port)
 280:     throws IOException;
 281: 
 282:   /**
 283:    * Starts listening for connections on a socket. The queuelen parameter
 284:    * is how many pending connections will queue up waiting to be serviced
 285:    * before being accept'ed.  If the queue of pending requests exceeds this
 286:    * number, additional connections will be refused.
 287:    *
 288:    * @param queuelen The length of the pending connection queue
 289:    * 
 290:    * @exception IOException If an error occurs
 291:    */
 292:   protected native void listen(int queuelen)
 293:     throws IOException;
 294: 
 295:   /**
 296:    * Accepts a new connection on this socket and returns in in the 
 297:    * passed in SocketImpl.
 298:    *
 299:    * @param impl The SocketImpl object to accept this connection.
 300:    */
 301:   protected void accept(SocketImpl impl)
 302:     throws IOException
 303:   {
 304:     accept((PlainSocketImpl) impl);
 305:   }
 306: 
 307:   private native void accept(PlainSocketImpl impl)
 308:     throws IOException;
 309: 
 310:   /**
 311:    * Returns the number of bytes that the caller can read from this socket
 312:    * without blocking. 
 313:    *
 314:    * @return The number of readable bytes before blocking
 315:    *
 316:    * @exception IOException If an error occurs
 317:    */
 318:   protected native int available() throws IOException;
 319: 
 320:   /**
 321:    * Closes the socket.  This will cause any InputStream or OutputStream
 322:    * objects for this Socket to be closed as well.
 323:    * <p>
 324:    * Note that if the SO_LINGER option is set on this socket, then the
 325:    * operation could block.
 326:    *
 327:    * @exception IOException If an error occurs
 328:    */
 329:   protected native void close() throws IOException;
 330: 
 331:   protected native void sendUrgentData(int data) throws IOException;
 332: 
 333:   public synchronized InetSocketAddress getLocalAddress()
 334:   {
 335:     if (localSocketAddress == null)
 336:       {
 337:     try
 338:       {
 339:         localSocketAddress
 340:           = new InetSocketAddress ((InetAddress) getOption(SocketOptions.SO_BINDADDR),
 341:                        localport == -1 ? 0 : localport);
 342:       }
 343:     catch (SocketException _)
 344:       {
 345:         return null;
 346:       }
 347:       }
 348:     return localSocketAddress;
 349:   }
 350: 
 351:   /**
 352:    * Returns an InputStream object for reading from this socket.  This will
 353:    * be an instance of SocketInputStream.
 354:    *
 355:    * @return An input stream attached to the socket.
 356:    *
 357:    * @exception IOException If an error occurs
 358:    */
 359:   protected synchronized InputStream getInputStream() throws IOException
 360:   {
 361:     if (in == null)
 362:       in = new SocketInputStream();
 363:     
 364:     return in;
 365:   }
 366: 
 367:   /**
 368:    * Returns an OutputStream object for writing to this socket.  This will
 369:    * be an instance of SocketOutputStream.
 370:    *
 371:    * @return An output stream attached to the socket.
 372:    *
 373:    * @exception IOException If an error occurs
 374:    */
 375:   protected synchronized OutputStream getOutputStream() throws IOException
 376:   {
 377:     if (out == null)
 378:       out = new SocketOutputStream();
 379:     
 380:     return out;
 381:   }
 382: 
 383:   /**
 384:    * This class contains an implementation of <code>InputStream</code> for 
 385:    * sockets.  It in an internal only class used by <code>PlainSocketImpl</code>.
 386:    *
 387:    * @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
 388:    */
 389:   final class SocketInputStream
 390:     extends InputStream
 391:   {
 392:     /**
 393:      * Returns the number of bytes available to be read before blocking
 394:      */
 395:     public int available() throws IOException
 396:     {
 397:       return PlainSocketImpl.this.available();
 398:     }
 399: 
 400:     /**
 401:      * This method not only closes the stream, it closes the underlying socket
 402:      * (and thus any connection) and invalidates any other Input/Output streams
 403:      * for the underlying impl object
 404:      */
 405:     public void close() throws IOException
 406:     {
 407:       PlainSocketImpl.this.close();
 408:     }
 409: 
 410:     /**
 411:      * Reads the next byte of data and returns it as an int.  
 412:      *
 413:      * @return The byte read (as an int) or -1 if end of stream);
 414:      *
 415:      * @exception IOException If an error occurs.
 416:      */
 417:     public native int read() throws IOException;
 418: 
 419:     /**
 420:      * Reads up to len bytes of data into the caller supplied buffer starting
 421:      * at offset bytes from the start of the buffer
 422:      *
 423:      * @param buf The buffer
 424:      * @param offset Offset into the buffer to start reading from
 425:      * @param len The number of bytes to read
 426:      *
 427:      * @return The number of bytes actually read or -1 if end of stream
 428:      *
 429:      * @exception IOException If an error occurs.
 430:      */
 431:     public native int read(byte[] buf, int offset, int len) throws IOException;
 432:   }
 433: 
 434:   /**
 435:    * This class is used internally by <code>PlainSocketImpl</code> to be the 
 436:    * <code>OutputStream</code> subclass returned by its 
 437:    * <code>getOutputStream method</code>.  It expects only to  be used in that
 438:    * context.
 439:    *
 440:    * @author Nic Ferrier  <nferrier@tapsellferrier.co.uk>
 441:    */
 442:   final class SocketOutputStream
 443:     extends OutputStream
 444:   {
 445:     /**
 446:      * This method closes the stream and the underlying socket connection. This
 447:      * action also effectively closes any other InputStream or OutputStream
 448:      * object associated with the connection.
 449:      *
 450:      * @exception IOException If an error occurs
 451:      */
 452:     public void close() throws IOException
 453:     {
 454:       PlainSocketImpl.this.close();
 455:     }
 456: 
 457:     /**
 458:      * Writes a byte (passed in as an int) to the given output stream
 459:      * 
 460:      * @param b The byte to write
 461:      *
 462:      * @exception IOException If an error occurs
 463:      */
 464:     public native void write(int b) throws IOException;
 465: 
 466:     /**
 467:      * Writes len number of bytes from the array buf to the stream starting
 468:      * at offset bytes into the buffer.
 469:      *
 470:      * @param buf The buffer
 471:      * @param offset Offset into the buffer to start writing from
 472:      * @param len The number of bytes to write
 473:      *
 474:      * @exception IOException If an error occurs.
 475:      */
 476:     public native void write(byte[] buf, int offset, int len) throws IOException;
 477:   }
 478: }