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