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 import sun.net.PlatformSocketImpl;
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 /**
50 * Creates an instance of platform's SocketImpl
51 */
52 @SuppressWarnings("unchecked")
53 static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
58 * The file descriptor object for this socket.
59 */
60 protected FileDescriptor fd;
61
62 /**
63 * The IP address of the remote end of this socket.
64 */
65 protected InetAddress address;
66
67 /**
68 * The port number on the remote host to which this socket is connected.
69 */
70 protected int port;
71
72 /**
73 * The local port number to which this socket is connected.
74 */
75 protected int localport;
76
77 /**
78 * Whether this is a server or not.
79 */
80 final boolean isServer;
81
82
83 SocketImpl(boolean isServer) {
84 this.isServer = isServer;
85 }
86
87 /**
88 * Initialize a new instance of this class
89 */
90 public SocketImpl() {
91 this.isServer = false;
92 }
93
94 /**
95 * Creates either a stream or a datagram socket.
96 *
97 * @param stream if {@code true}, create a stream socket;
98 * otherwise, create a datagram socket.
99 * @exception IOException if an I/O error occurs while creating the
100 * socket.
101 */
102 protected abstract void create(boolean stream) throws IOException;
103
104 /**
105 * Connects this socket to the specified port on the named host.
106 *
107 * @param host the name of the remote host.
108 * @param port the port number.
109 * @exception IOException if an I/O error occurs when connecting to the
110 * remote host.
111 */
112 protected abstract void connect(String host, int port) throws IOException;
359 * @param latency
360 * An {@code int} expressing the relative importance of low
361 * latency
362 *
363 * @param bandwidth
364 * An {@code int} expressing the relative importance of high
365 * bandwidth
366 *
367 * @since 1.5
368 */
369 protected void setPerformancePreferences(int connectionTime,
370 int latency,
371 int bandwidth)
372 {
373 /* Not implemented yet */
374 }
375
376 /**
377 * Called to set a socket option.
378 *
379 * @param <T> The type of the socket option value
380 * @param name The socket option
381 *
382 * @param value The value of the socket option. A value of {@code null}
383 * may be valid for some options.
384 *
385 * @throws UnsupportedOperationException if the SocketImpl does not
386 * support the option
387 *
388 * @throws IOException if an I/O error occurs, or if the socket is closed.
389 *
390 * @since 9
391 */
392 protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
393 if (name == StandardSocketOptions.SO_KEEPALIVE && !isServer) {
394 setOption(SocketOptions.SO_KEEPALIVE, value);
395 } else if (name == StandardSocketOptions.SO_SNDBUF && !isServer) {
396 setOption(SocketOptions.SO_SNDBUF, value);
397 } else if (name == StandardSocketOptions.SO_RCVBUF) {
398 setOption(SocketOptions.SO_RCVBUF, value);
399 } else if (name == StandardSocketOptions.SO_REUSEADDR) {
400 setOption(SocketOptions.SO_REUSEADDR, value);
401 } else if (name == StandardSocketOptions.SO_REUSEPORT &&
402 supportedOptions().contains(name)) {
403 setOption(SocketOptions.SO_REUSEPORT, value);
404 } else if (name == StandardSocketOptions.SO_LINGER && !isServer) {
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 && !isServer) {
409 setOption(SocketOptions.TCP_NODELAY, value);
410 } else {
411 throw new UnsupportedOperationException("unsupported option");
412 }
413 }
414
415 /**
416 * Called to get a socket option.
417 *
418 * @param <T> The type of the socket option value
419 * @param name The socket option
420 *
421 * @return the value of the named option
422 *
423 * @throws UnsupportedOperationException if the SocketImpl does not
424 * support the option.
425 *
426 * @throws IOException if an I/O error occurs, or if the socket is closed.
427 *
428 * @since 9
429 */
430 @SuppressWarnings("unchecked")
431 protected <T> T getOption(SocketOption<T> name) throws IOException {
432 if (name == StandardSocketOptions.SO_KEEPALIVE && !isServer) {
433 return (T)getOption(SocketOptions.SO_KEEPALIVE);
434 } else if (name == StandardSocketOptions.SO_SNDBUF && !isServer) {
435 return (T)getOption(SocketOptions.SO_SNDBUF);
436 } else if (name == StandardSocketOptions.SO_RCVBUF) {
437 return (T)getOption(SocketOptions.SO_RCVBUF);
438 } else if (name == StandardSocketOptions.SO_REUSEADDR) {
439 return (T)getOption(SocketOptions.SO_REUSEADDR);
440 } else if (name == StandardSocketOptions.SO_REUSEPORT &&
441 supportedOptions().contains(name)) {
442 return (T)getOption(SocketOptions.SO_REUSEPORT);
443 } else if (name == StandardSocketOptions.SO_LINGER && !isServer) {
444 return (T)getOption(SocketOptions.SO_LINGER);
445 } else if (name == StandardSocketOptions.IP_TOS) {
446 return (T)getOption(SocketOptions.IP_TOS);
447 } else if (name == StandardSocketOptions.TCP_NODELAY && !isServer) {
448 return (T)getOption(SocketOptions.TCP_NODELAY);
449 } else {
450 throw new UnsupportedOperationException("unsupported option");
451 }
452 }
453
454 /**
455 * Attempts to copy socket options from this SocketImpl to a target SocketImpl.
456 * At this time, only the SO_TIMEOUT make sense to copy.
457 */
458 void copyOptionsTo(SocketImpl target) {
459 try {
460 Object timeout = getOption(SocketOptions.SO_TIMEOUT);
461 if (timeout instanceof Integer) {
462 target.setOption(SocketOptions.SO_TIMEOUT, timeout);
463 }
464 } catch (IOException ignore) { }
465 }
466
467 private static final Set<SocketOption<?>> socketOptions;
468
469 private static final Set<SocketOption<?>> serverSocketOptions;
470
471 static {
472 socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
473 StandardSocketOptions.SO_SNDBUF,
474 StandardSocketOptions.SO_RCVBUF,
475 StandardSocketOptions.SO_REUSEADDR,
476 StandardSocketOptions.SO_LINGER,
477 StandardSocketOptions.IP_TOS,
478 StandardSocketOptions.TCP_NODELAY);
479
480 serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
481 StandardSocketOptions.SO_REUSEADDR,
482 StandardSocketOptions.IP_TOS);
483 }
484
485 /**
486 * Returns a set of SocketOptions supported by this impl
487 * and by this impl's socket (Socket or ServerSocket)
488 *
489 * @return a Set of SocketOptions
490 *
491 * @since 9
492 */
493 protected Set<SocketOption<?>> supportedOptions() {
494 if (!isServer) {
495 return socketOptions;
496 } else {
497 return serverSocketOptions;
498 }
499 }
500 }
|
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 sun.net.PlatformSocketImpl;
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 /**
49 * Creates an instance of platform's SocketImpl
50 */
51 @SuppressWarnings("unchecked")
52 static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
57 * The file descriptor object for this socket.
58 */
59 protected FileDescriptor fd;
60
61 /**
62 * The IP address of the remote end of this socket.
63 */
64 protected InetAddress address;
65
66 /**
67 * The port number on the remote host to which this socket is connected.
68 */
69 protected int port;
70
71 /**
72 * The local port number to which this socket is connected.
73 */
74 protected int localport;
75
76 /**
77 * Initialize a new instance of this class
78 */
79 public SocketImpl() { }
80
81 /**
82 * Creates either a stream or a datagram socket.
83 *
84 * @param stream if {@code true}, create a stream socket;
85 * otherwise, create a datagram socket.
86 * @exception IOException if an I/O error occurs while creating the
87 * socket.
88 */
89 protected abstract void create(boolean stream) throws IOException;
90
91 /**
92 * Connects this socket to the specified port on the named host.
93 *
94 * @param host the name of the remote host.
95 * @param port the port number.
96 * @exception IOException if an I/O error occurs when connecting to the
97 * remote host.
98 */
99 protected abstract void connect(String host, int port) throws IOException;
346 * @param latency
347 * An {@code int} expressing the relative importance of low
348 * latency
349 *
350 * @param bandwidth
351 * An {@code int} expressing the relative importance of high
352 * bandwidth
353 *
354 * @since 1.5
355 */
356 protected void setPerformancePreferences(int connectionTime,
357 int latency,
358 int bandwidth)
359 {
360 /* Not implemented yet */
361 }
362
363 /**
364 * Called to set a socket option.
365 *
366 * @implSpec
367 * The default implementation of this method throws {@code
368 * UnsupportedOperationException}. Subclasses should override this method
369 * with an appropriate implementation.
370 *
371 * @param <T> The type of the socket option value
372 * @param name The socket option
373 * @param value The value of the socket option. A value of {@code null}
374 * may be valid for some options.
375 *
376 * @throws UnsupportedOperationException if the SocketImpl does not
377 * support the option
378 * @throws IllegalArgumentException if the value is not valid for
379 * the option
380 * @throws IOException if an I/O error occurs, or if the socket is closed
381 * @throws NullPointerException if name is {@code null}
382 *
383 * @since 9
384 */
385 protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
386 throw new UnsupportedOperationException("'" + name + "' not supported");
387 }
388
389 /**
390 * Called to get a socket option.
391 *
392 * @implSpec
393 * The default implementation of this method throws {@code
394 * UnsupportedOperationException}. Subclasses should override this method
395 * with an appropriate implementation.
396 *
397 * @param <T> The type of the socket option value
398 * @param name The socket option
399 * @return the value of the named option
400 *
401 * @throws UnsupportedOperationException if the SocketImpl does not
402 * support the option
403 * @throws IOException if an I/O error occurs, or if the socket is closed
404 * @throws NullPointerException if name is {@code null}
405 *
406 * @since 9
407 */
408 protected <T> T getOption(SocketOption<T> name) throws IOException {
409 throw new UnsupportedOperationException("'" + name + "' not supported");
410 }
411
412 /**
413 * Attempts to copy socket options from this SocketImpl to a target SocketImpl.
414 * At this time, only the SO_TIMEOUT make sense to copy.
415 */
416 void copyOptionsTo(SocketImpl target) {
417 try {
418 Object timeout = getOption(SocketOptions.SO_TIMEOUT);
419 if (timeout instanceof Integer) {
420 target.setOption(SocketOptions.SO_TIMEOUT, timeout);
421 }
422 } catch (IOException ignore) { }
423 }
424
425 /**
426 * Returns a set of SocketOptions supported by this impl
427 * and by this impl's socket (Socket or ServerSocket)
428 *
429 * @implSpec
430 * The default implementation of this method returns an empty set.
431 * Subclasses should override this method with an appropriate implementation.
432 *
433 * @return a Set of SocketOptions
434 *
435 * @since 9
436 */
437 protected Set<SocketOption<?>> supportedOptions() {
438 return Set.of();
439 }
440 }
|