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