1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.net; 28 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.io.OutputStream; 32 import java.io.FileDescriptor; 33 import java.util.Set; 34 35 /** 36 * The abstract class {@code SocketImpl} is a common superclass 37 * of all classes that actually implement sockets. It is used to 38 * create both client and server sockets. 39 * <p> 40 * A "plain" socket implements these methods exactly as 41 * described, without attempting to go through a firewall or proxy. 42 * 43 * @author unascribed 44 * @since 1.0 45 */ 46 public abstract class SocketImpl implements SocketOptions { 47 /** 48 * The actual Socket object. 49 */ 50 Socket socket = null; 51 ServerSocket serverSocket = null; 52 53 /** 54 * The file descriptor object for this socket. 55 */ 56 protected FileDescriptor fd; 57 58 /** 59 * The IP address of the remote end of this socket. 60 */ 61 protected InetAddress address; 62 63 /** 64 * The port number on the remote host to which this socket is connected. 65 */ 66 protected int port; 67 68 /** 69 * The local port number to which this socket is connected. 70 */ 71 protected int localport; 72 73 /** 74 * Creates either a stream or a datagram socket. 75 * 76 * @param stream if {@code true}, create a stream socket; 77 * otherwise, create a datagram socket. 78 * @exception IOException if an I/O error occurs while creating the 79 * socket. 80 */ create(boolean stream)81 protected abstract void create(boolean stream) throws IOException; 82 83 /** 84 * Connects this socket to the specified port on the named host. 85 * 86 * @param host the name of the remote host. 87 * @param port the port number. 88 * @exception IOException if an I/O error occurs when connecting to the 89 * remote host. 90 */ connect(String host, int port)91 protected abstract void connect(String host, int port) throws IOException; 92 93 /** 94 * Connects this socket to the specified port number on the specified host. 95 * 96 * @param address the IP address of the remote host. 97 * @param port the port number. 98 * @exception IOException if an I/O error occurs when attempting a 99 * connection. 100 */ connect(InetAddress address, int port)101 protected abstract void connect(InetAddress address, int port) throws IOException; 102 103 /** 104 * Connects this socket to the specified port number on the specified host. 105 * A timeout of zero is interpreted as an infinite timeout. The connection 106 * will then block until established or an error occurs. 107 * 108 * @param address the Socket address of the remote host. 109 * @param timeout the timeout value, in milliseconds, or zero for no timeout. 110 * @exception IOException if an I/O error occurs when attempting a 111 * connection. 112 * @since 1.4 113 */ connect(SocketAddress address, int timeout)114 protected abstract void connect(SocketAddress address, int timeout) throws IOException; 115 116 /** 117 * Binds this socket to the specified local IP address and port number. 118 * 119 * @param host an IP address that belongs to a local interface. 120 * @param port the port number. 121 * @exception IOException if an I/O error occurs when binding this socket. 122 */ bind(InetAddress host, int port)123 protected abstract void bind(InetAddress host, int port) throws IOException; 124 125 /** 126 * Sets the maximum queue length for incoming connection indications 127 * (a request to connect) to the {@code count} argument. If a 128 * connection indication arrives when the queue is full, the 129 * connection is refused. 130 * 131 * @param backlog the maximum length of the queue. 132 * @exception IOException if an I/O error occurs when creating the queue. 133 */ listen(int backlog)134 protected abstract void listen(int backlog) throws IOException; 135 136 /** 137 * Accepts a connection. 138 * 139 * @param s the accepted connection. 140 * @exception IOException if an I/O error occurs when accepting the 141 * connection. 142 */ accept(SocketImpl s)143 protected abstract void accept(SocketImpl s) throws IOException; 144 145 /** 146 * Returns an input stream for this socket. 147 * 148 * @return a stream for reading from this socket. 149 * @exception IOException if an I/O error occurs when creating the 150 * input stream. 151 */ getInputStream()152 protected abstract InputStream getInputStream() throws IOException; 153 154 /** 155 * Returns an output stream for this socket. 156 * 157 * @return an output stream for writing to this socket. 158 * @exception IOException if an I/O error occurs when creating the 159 * output stream. 160 */ getOutputStream()161 protected abstract OutputStream getOutputStream() throws IOException; 162 163 /** 164 * Returns the number of bytes that can be read from this socket 165 * without blocking. 166 * 167 * @return the number of bytes that can be read from this socket 168 * without blocking. 169 * @exception IOException if an I/O error occurs when determining the 170 * number of bytes available. 171 */ available()172 protected abstract int available() throws IOException; 173 174 /** 175 * Closes this socket. 176 * 177 * @exception IOException if an I/O error occurs when closing this socket. 178 */ close()179 protected abstract void close() throws IOException; 180 181 /** 182 * Places the input stream for this socket at "end of stream". 183 * Any data sent to this socket is acknowledged and then 184 * silently discarded. 185 * 186 * If you read from a socket input stream after invoking this method on the 187 * socket, the stream's {@code available} method will return 0, and its 188 * {@code read} methods will return {@code -1} (end of stream). 189 * 190 * @exception IOException if an I/O error occurs when shutting down this 191 * socket. 192 * @see java.net.Socket#shutdownOutput() 193 * @see java.net.Socket#close() 194 * @see java.net.Socket#setSoLinger(boolean, int) 195 * @since 1.3 196 */ shutdownInput()197 protected void shutdownInput() throws IOException { 198 throw new IOException("Method not implemented!"); 199 } 200 201 /** 202 * Disables the output stream for this socket. 203 * For a TCP socket, any previously written data will be sent 204 * followed by TCP's normal connection termination sequence. 205 * 206 * If you write to a socket output stream after invoking 207 * shutdownOutput() on the socket, the stream will throw 208 * an IOException. 209 * 210 * @exception IOException if an I/O error occurs when shutting down this 211 * socket. 212 * @see java.net.Socket#shutdownInput() 213 * @see java.net.Socket#close() 214 * @see java.net.Socket#setSoLinger(boolean, int) 215 * @since 1.3 216 */ shutdownOutput()217 protected void shutdownOutput() throws IOException { 218 throw new IOException("Method not implemented!"); 219 } 220 221 /** 222 * Returns the value of this socket's {@code fd} field. 223 * 224 * @return the value of this socket's {@code fd} field. 225 * @see java.net.SocketImpl#fd 226 */ getFileDescriptor()227 protected FileDescriptor getFileDescriptor() { 228 return fd; 229 } 230 231 // Android-added: getFD$() for testing. 232 /** 233 * Gets socket's underlying {@link FileDescriptor}. 234 * 235 * @hide used by java.nio tests 236 * 237 * @return socket's underlying {@link FileDescriptor}. 238 */ getFD$()239 public FileDescriptor getFD$() { 240 return fd; 241 } 242 243 /** 244 * Returns the value of this socket's {@code address} field. 245 * 246 * @return the value of this socket's {@code address} field. 247 * @see java.net.SocketImpl#address 248 */ getInetAddress()249 protected InetAddress getInetAddress() { 250 return address; 251 } 252 253 /** 254 * Returns the value of this socket's {@code port} field. 255 * 256 * @return the value of this socket's {@code port} field. 257 * @see java.net.SocketImpl#port 258 */ getPort()259 protected int getPort() { 260 return port; 261 } 262 263 /** 264 * Returns whether or not this SocketImpl supports sending 265 * urgent data. By default, false is returned 266 * unless the method is overridden in a sub-class 267 * 268 * @return true if urgent data supported 269 * @see java.net.SocketImpl#address 270 * @since 1.4 271 */ supportsUrgentData()272 protected boolean supportsUrgentData () { 273 return false; // must be overridden in sub-class 274 } 275 276 /** 277 * Send one byte of urgent data on the socket. 278 * The byte to be sent is the low eight bits of the parameter 279 * @param data The byte of data to send 280 * @exception IOException if there is an error 281 * sending the data. 282 * @since 1.4 283 */ sendUrgentData(int data)284 protected abstract void sendUrgentData (int data) throws IOException; 285 286 /** 287 * Returns the value of this socket's {@code localport} field. 288 * 289 * @return the value of this socket's {@code localport} field. 290 * @see java.net.SocketImpl#localport 291 */ getLocalPort()292 protected int getLocalPort() { 293 return localport; 294 } 295 setSocket(Socket soc)296 void setSocket(Socket soc) { 297 this.socket = soc; 298 } 299 getSocket()300 Socket getSocket() { 301 return socket; 302 } 303 setServerSocket(ServerSocket soc)304 void setServerSocket(ServerSocket soc) { 305 this.serverSocket = soc; 306 } 307 getServerSocket()308 ServerSocket getServerSocket() { 309 return serverSocket; 310 } 311 312 /** 313 * Returns the address and port of this socket as a {@code String}. 314 * 315 * @return a string representation of this socket. 316 */ toString()317 public String toString() { 318 return "Socket[addr=" + getInetAddress() + 319 ",port=" + getPort() + ",localport=" + getLocalPort() + "]"; 320 } 321 reset()322 void reset() throws IOException { 323 address = null; 324 port = 0; 325 localport = 0; 326 } 327 328 /** 329 * Sets performance preferences for this socket. 330 * 331 * <p> Sockets use the TCP/IP protocol by default. Some implementations 332 * may offer alternative protocols which have different performance 333 * characteristics than TCP/IP. This method allows the application to 334 * express its own preferences as to how these tradeoffs should be made 335 * when the implementation chooses from the available protocols. 336 * 337 * <p> Performance preferences are described by three integers 338 * whose values indicate the relative importance of short connection time, 339 * low latency, and high bandwidth. The absolute values of the integers 340 * are irrelevant; in order to choose a protocol the values are simply 341 * compared, with larger values indicating stronger preferences. Negative 342 * values represent a lower priority than positive values. If the 343 * application prefers short connection time over both low latency and high 344 * bandwidth, for example, then it could invoke this method with the values 345 * {@code (1, 0, 0)}. If the application prefers high bandwidth above low 346 * latency, and low latency above short connection time, then it could 347 * invoke this method with the values {@code (0, 1, 2)}. 348 * 349 * By default, this method does nothing, unless it is overridden in 350 * a sub-class. 351 * 352 * @param connectionTime 353 * An {@code int} expressing the relative importance of a short 354 * connection time 355 * 356 * @param latency 357 * An {@code int} expressing the relative importance of low 358 * latency 359 * 360 * @param bandwidth 361 * An {@code int} expressing the relative importance of high 362 * bandwidth 363 * 364 * @since 1.5 365 */ setPerformancePreferences(int connectionTime, int latency, int bandwidth)366 protected void setPerformancePreferences(int connectionTime, 367 int latency, 368 int bandwidth) 369 { 370 /* Not implemented yet */ 371 } 372 373 /** 374 * Called to set a socket option. 375 * 376 * @param <T> The type of the socket option value 377 * @param name The socket option 378 * 379 * @param value The value of the socket option. A value of {@code null} 380 * may be valid for some options. 381 * 382 * @throws UnsupportedOperationException if the SocketImpl does not 383 * support the option 384 * 385 * @throws IOException if an I/O error occurs, or if the socket is closed. 386 * 387 * @since 9 388 */ setOption(SocketOption<T> name, T value)389 protected <T> void setOption(SocketOption<T> name, T value) throws IOException { 390 if (name == StandardSocketOptions.SO_KEEPALIVE && 391 (getSocket() != null)) { 392 setOption(SocketOptions.SO_KEEPALIVE, value); 393 } else if (name == StandardSocketOptions.SO_SNDBUF && 394 (getSocket() != null)) { 395 setOption(SocketOptions.SO_SNDBUF, value); 396 } else if (name == StandardSocketOptions.SO_RCVBUF) { 397 setOption(SocketOptions.SO_RCVBUF, value); 398 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 399 setOption(SocketOptions.SO_REUSEADDR, value); 400 } else if (name == StandardSocketOptions.SO_REUSEPORT && 401 supportedOptions().contains(name)) { 402 setOption(SocketOptions.SO_REUSEPORT, value); 403 } else if (name == StandardSocketOptions.SO_LINGER && 404 (getSocket() != null)) { 405 setOption(SocketOptions.SO_LINGER, value); 406 } else if (name == StandardSocketOptions.IP_TOS) { 407 setOption(SocketOptions.IP_TOS, value); 408 } else if (name == StandardSocketOptions.TCP_NODELAY && 409 (getSocket() != null)) { 410 setOption(SocketOptions.TCP_NODELAY, value); 411 } else { 412 throw new UnsupportedOperationException("unsupported option"); 413 } 414 } 415 416 /** 417 * Called to get a socket option. 418 * 419 * @param <T> The type of the socket option value 420 * @param name The socket option 421 * 422 * @return the value of the named option 423 * 424 * @throws UnsupportedOperationException if the SocketImpl does not 425 * support the option. 426 * 427 * @throws IOException if an I/O error occurs, or if the socket is closed. 428 * 429 * @since 9 430 */ 431 @SuppressWarnings("unchecked") getOption(SocketOption<T> name)432 protected <T> T getOption(SocketOption<T> name) throws IOException { 433 if (name == StandardSocketOptions.SO_KEEPALIVE && 434 (getSocket() != null)) { 435 return (T)getOption(SocketOptions.SO_KEEPALIVE); 436 } else if (name == StandardSocketOptions.SO_SNDBUF && 437 (getSocket() != null)) { 438 return (T)getOption(SocketOptions.SO_SNDBUF); 439 } else if (name == StandardSocketOptions.SO_RCVBUF) { 440 return (T)getOption(SocketOptions.SO_RCVBUF); 441 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 442 return (T)getOption(SocketOptions.SO_REUSEADDR); 443 } else if (name == StandardSocketOptions.SO_REUSEPORT && 444 supportedOptions().contains(name)) { 445 return (T)getOption(SocketOptions.SO_REUSEPORT); 446 } else if (name == StandardSocketOptions.SO_LINGER && 447 (getSocket() != null)) { 448 return (T)getOption(SocketOptions.SO_LINGER); 449 } else if (name == StandardSocketOptions.IP_TOS) { 450 return (T)getOption(SocketOptions.IP_TOS); 451 } else if (name == StandardSocketOptions.TCP_NODELAY && 452 (getSocket() != null)) { 453 return (T)getOption(SocketOptions.TCP_NODELAY); 454 } else { 455 throw new UnsupportedOperationException("unsupported option"); 456 } 457 } 458 459 private static final Set<SocketOption<?>> socketOptions; 460 461 private static final Set<SocketOption<?>> serverSocketOptions; 462 463 static { 464 socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE, 465 StandardSocketOptions.SO_SNDBUF, 466 StandardSocketOptions.SO_RCVBUF, 467 StandardSocketOptions.SO_REUSEADDR, 468 StandardSocketOptions.SO_LINGER, 469 StandardSocketOptions.IP_TOS, 470 StandardSocketOptions.TCP_NODELAY); 471 472 serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF, 473 StandardSocketOptions.SO_REUSEADDR, 474 StandardSocketOptions.IP_TOS); 475 } 476 477 /** 478 * Returns a set of SocketOptions supported by this impl 479 * and by this impl's socket (Socket or ServerSocket) 480 * 481 * @return a Set of SocketOptions 482 * 483 * @since 9 484 */ supportedOptions()485 protected Set<SocketOption<?>> supportedOptions() { 486 if (getSocket() != null) { 487 return socketOptions; 488 } else { 489 return serverSocketOptions; 490 } 491 } 492 } 493