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 */ isInChannelOperation()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 */ setInChannelOperation(boolean b)148 public final void setInChannelOperation(boolean b) 149 { 150 inChannelOperation = b; 151 } 152 153 /** 154 * Default do nothing constructor 155 */ PlainSocketImpl()156 public PlainSocketImpl() 157 { 158 } 159 finalize()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 getNativeFD()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 */ setOption(int optID, Object value)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 */ getOption(int optID)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 */ shutdownInput()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 */ shutdownOutput()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. create(boolean stream)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 */ connect(String host, int port)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 */ connect(InetAddress host, int port)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 */ connect(SocketAddress addr, int timeout)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 */ bind(InetAddress host, int port)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 */ listen(int queuelen)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 */ accept(SocketImpl impl)301 protected void accept(SocketImpl impl) 302 throws IOException 303 { 304 accept((PlainSocketImpl) impl); 305 } 306 accept(PlainSocketImpl impl)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 */ available()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 */ close()329 protected native void close() throws IOException; 330 sendUrgentData(int data)331 protected native void sendUrgentData(int data) throws IOException; 332 getLocalAddress()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 */ getInputStream()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 */ getOutputStream()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 */ available()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 */ close()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 */ read()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 */ read(byte[] buf, int offset, int len)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 */ close()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 */ write(int b)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 */ write(byte[] buf, int offset, int len)476 public native void write(byte[] buf, int offset, int len) throws IOException; 477 } 478 } 479