Frames | No Frames |
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: }