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