Source for gnu.java.net.PlainSocketImpl

   1: /* PlainSocketImpl.java -- Default socket implementation
   2:    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
   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:   /**
 114:    * A cached copy of the in stream for reading from the socket.
 115:    */
 116:   private InputStream in;
 117: 
 118:   /**
 119:    * A cached copy of the out stream for writing to the socket.
 120:    */
 121:   private OutputStream out;
 122: 
 123:   /**
 124:    * Indicates whether a channel initiated whatever operation
 125:    * is being invoked on this socket.
 126:    */
 127:   private boolean inChannelOperation;
 128: 
 129:   /**
 130:    * Indicates whether we should ignore whether any associated
 131:    * channel is set to non-blocking mode. Certain operations
 132:    * throw an <code>IllegalBlockingModeException</code> if the
 133:    * associated channel is in non-blocking mode, <i>except</i>
 134:    * if the operation is invoked by the channel itself.
 135:    */
 136:   public final boolean isInChannelOperation()
 137:   {
 138:     return inChannelOperation;
 139:   }
 140:   
 141:   /**
 142:    * Sets our indicator of whether an I/O operation is being
 143:    * initiated by a channel.
 144:    */
 145:   public final void setInChannelOperation(boolean b)
 146:   {
 147:     inChannelOperation = b;
 148:   }
 149:  
 150:   /**
 151:    * Default do nothing constructor
 152:    */
 153:   public PlainSocketImpl()
 154:   {
 155:   }
 156:   
 157:   protected void finalize() throws Throwable
 158:   {
 159:     synchronized (this)
 160:       {
 161:     if (native_fd != -1)
 162:       try
 163:         {
 164:           close();
 165:         }
 166:       catch (IOException ex)
 167:         {
 168:         }
 169:       }
 170:     super.finalize();
 171:   }
 172: 
 173:   public int getNativeFD()
 174:   {
 175:     return native_fd;
 176:   }
 177: 
 178:   /**
 179:    * Sets the specified option on a socket to the passed in object.  For
 180:    * options that take an integer argument, the passed in object is an
 181:    * Integer.  The option_id parameter is one of the defined constants in
 182:    * this interface.
 183:    *
 184:    * @param option_id The identifier of the option
 185:    * @param val The value to set the option to
 186:    *
 187:    * @exception SocketException If an error occurs
 188:    */
 189:   public native void setOption(int optID, Object value) throws SocketException;
 190: 
 191:   /**
 192:    * Returns the current setting of the specified option.  The Object returned
 193:    * will be an Integer for options that have integer values.  The option_id
 194:    * is one of the defined constants in this interface.
 195:    *
 196:    * @param option_id The option identifier
 197:    *
 198:    * @return The current value of the option
 199:    *
 200:    * @exception SocketException If an error occurs
 201:    */
 202:   public native Object getOption(int optID) throws SocketException;
 203: 
 204:   /**
 205:    * Flushes the input stream and closes it. If you read from the input stream
 206:    * after calling this method a <code>IOException</code> will be thrown.
 207:    * 
 208:    * @throws IOException if an error occurs
 209:    */
 210:   public native void shutdownInput() throws IOException;
 211: 
 212:   /**
 213:    * Flushes the output stream and closes it. If you write to the output stream
 214:    * after calling this method a <code>IOException</code> will be thrown.
 215:    * 
 216:    * @throws IOException if an error occurs
 217:    */
 218:   public native void shutdownOutput() throws IOException;
 219: 
 220:   /**
 221:    * Creates a new socket that is not bound to any local address/port and
 222:    * is not connected to any remote address/port.  This will be created as
 223:    * a stream socket if the stream parameter is true, or a datagram socket
 224:    * if the stream parameter is false.
 225:    *
 226:    * @param stream true for a stream socket, false for a datagram socket
 227:    */
 228:   protected native void create(boolean stream) throws IOException;
 229: 
 230:   /**
 231:    * Connects to the remote hostname and port specified as arguments.
 232:    *
 233:    * @param hostname The remote hostname to connect to
 234:    * @param port The remote port to connect to
 235:    *
 236:    * @exception IOException If an error occurs
 237:    */
 238:   protected void connect(String host, int port) throws IOException
 239:   {
 240:     connect(InetAddress.getByName(host), port);
 241:   }
 242: 
 243:   /**
 244:    * Connects to the remote address and port specified as arguments.
 245:    *
 246:    * @param addr The remote address to connect to
 247:    * @param port The remote port to connect to
 248:    *
 249:    * @exception IOException If an error occurs
 250:    */
 251:   protected void connect(InetAddress host, int port) throws IOException
 252:   {
 253:     connect (new InetSocketAddress (host, port), 0);
 254:   }
 255: 
 256:   /**
 257:    * Connects to the remote socket address with a specified timeout.
 258:    *
 259:    * @param timeout The timeout to use for this connect, 0 means infinite.
 260:    *
 261:    * @exception IOException If an error occurs
 262:    */
 263:   protected native void connect(SocketAddress addr, int timeout) throws IOException;
 264: 
 265:   /**
 266:    * Binds to the specified port on the specified addr.  Note that this addr
 267:    * must represent a local IP address.  **** How bind to INADDR_ANY? ****
 268:    *
 269:    * @param addr The address to bind to
 270:    * @param port The port number to bind to
 271:    *
 272:    * @exception IOException If an error occurs
 273:    */
 274:   protected native void bind(InetAddress host, int port)
 275:     throws IOException;
 276: 
 277:   /**
 278:    * Starts listening for connections on a socket. The queuelen parameter
 279:    * is how many pending connections will queue up waiting to be serviced
 280:    * before being accept'ed.  If the queue of pending requests exceeds this
 281:    * number, additional connections will be refused.
 282:    *
 283:    * @param queuelen The length of the pending connection queue
 284:    * 
 285:    * @exception IOException If an error occurs
 286:    */
 287:   protected native void listen(int queuelen)
 288:     throws IOException;
 289: 
 290:   /**
 291:    * Accepts a new connection on this socket and returns in in the 
 292:    * passed in SocketImpl.
 293:    *
 294:    * @param impl The SocketImpl object to accept this connection.
 295:    */
 296:   protected void accept(SocketImpl impl)
 297:     throws IOException
 298:   {
 299:     accept((PlainSocketImpl) impl);
 300:   }
 301: 
 302:   private native void accept(PlainSocketImpl impl)
 303:     throws IOException;
 304: 
 305:   /**
 306:    * Returns the number of bytes that the caller can read from this socket
 307:    * without blocking. 
 308:    *
 309:    * @return The number of readable bytes before blocking
 310:    *
 311:    * @exception IOException If an error occurs
 312:    */
 313:   protected native int available() throws IOException;
 314: 
 315:   /**
 316:    * Closes the socket.  This will cause any InputStream or OutputStream
 317:    * objects for this Socket to be closed as well.
 318:    * <p>
 319:    * Note that if the SO_LINGER option is set on this socket, then the
 320:    * operation could block.
 321:    *
 322:    * @exception IOException If an error occurs
 323:    */
 324:   protected native void close() throws IOException;
 325: 
 326:   protected native void sendUrgentData(int data) throws IOException;
 327: 
 328:   /**
 329:    * Returns an InputStream object for reading from this socket.  This will
 330:    * be an instance of SocketInputStream.
 331:    *
 332:    * @return An input stream attached to the socket.
 333:    *
 334:    * @exception IOException If an error occurs
 335:    */
 336:   protected synchronized InputStream getInputStream() throws IOException
 337:   {
 338:     if (in == null)
 339:       in = new SocketInputStream();
 340:     
 341:     return in;
 342:   }
 343: 
 344:   /**
 345:    * Returns an OutputStream object for writing to this socket.  This will
 346:    * be an instance of SocketOutputStream.
 347:    *
 348:    * @return An output stream attached to the socket.
 349:    *
 350:    * @exception IOException If an error occurs
 351:    */
 352:   protected synchronized OutputStream getOutputStream() throws IOException
 353:   {
 354:     if (out == null)
 355:       out = new SocketOutputStream();
 356:     
 357:     return out;
 358:   }
 359: 
 360:   /**
 361:    * This class contains an implementation of <code>InputStream</code> for 
 362:    * sockets.  It in an internal only class used by <code>PlainSocketImpl</code>.
 363:    *
 364:    * @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
 365:    */
 366:   final class SocketInputStream
 367:     extends InputStream
 368:   {
 369:     /**
 370:      * Returns the number of bytes available to be read before blocking
 371:      */
 372:     public int available() throws IOException
 373:     {
 374:       return PlainSocketImpl.this.available();
 375:     }
 376: 
 377:     /**
 378:      * This method not only closes the stream, it closes the underlying socket
 379:      * (and thus any connection) and invalidates any other Input/Output streams
 380:      * for the underlying impl object
 381:      */
 382:     public void close() throws IOException
 383:     {
 384:       PlainSocketImpl.this.close();
 385:     }
 386: 
 387:     /**
 388:      * Reads the next byte of data and returns it as an int.  
 389:      *
 390:      * @return The byte read (as an int) or -1 if end of stream);
 391:      *
 392:      * @exception IOException If an error occurs.
 393:      */
 394:     public native int read() throws IOException;
 395: 
 396:     /**
 397:      * Reads up to len bytes of data into the caller supplied buffer starting
 398:      * at offset bytes from the start of the buffer
 399:      *
 400:      * @param buf The buffer
 401:      * @param offset Offset into the buffer to start reading from
 402:      * @param len The number of bytes to read
 403:      *
 404:      * @return The number of bytes actually read or -1 if end of stream
 405:      *
 406:      * @exception IOException If an error occurs.
 407:      */
 408:     public native int read(byte[] buf, int offset, int len) throws IOException;
 409:   }
 410: 
 411:   /**
 412:    * This class is used internally by <code>PlainSocketImpl</code> to be the 
 413:    * <code>OutputStream</code> subclass returned by its 
 414:    * <code>getOutputStream method</code>.  It expects only to  be used in that
 415:    * context.
 416:    *
 417:    * @author Nic Ferrier  <nferrier@tapsellferrier.co.uk>
 418:    */
 419:   final class SocketOutputStream
 420:     extends OutputStream
 421:   {
 422:     /**
 423:      * This method closes the stream and the underlying socket connection. This
 424:      * action also effectively closes any other InputStream or OutputStream
 425:      * object associated with the connection.
 426:      *
 427:      * @exception IOException If an error occurs
 428:      */
 429:     public void close() throws IOException
 430:     {
 431:       PlainSocketImpl.this.close();
 432:     }
 433: 
 434:     /**
 435:      * Writes a byte (passed in as an int) to the given output stream
 436:      * 
 437:      * @param b The byte to write
 438:      *
 439:      * @exception IOException If an error occurs
 440:      */
 441:     public native void write(int b) throws IOException;
 442: 
 443:     /**
 444:      * Writes len number of bytes from the array buf to the stream starting
 445:      * at offset bytes into the buffer.
 446:      *
 447:      * @param buf The buffer
 448:      * @param offset Offset into the buffer to start writing from
 449:      * @param len The number of bytes to write
 450:      *
 451:      * @exception IOException If an error occurs.
 452:      */
 453:     public native void write(byte[] buf, int offset, int len) throws IOException;
 454:   }
 455: }