src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java
changeset 54620 13b67c1420b8
parent 49001 ce06058197a4
child 58614 29624901d8bc
equal deleted inserted replaced
54619:b43cc3b9ef40 54620:13b67c1420b8
     1 /*
     1 /*
     2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    30 import java.net.InetSocketAddress;
    30 import java.net.InetSocketAddress;
    31 import java.net.ServerSocket;
    31 import java.net.ServerSocket;
    32 import java.net.Socket;
    32 import java.net.Socket;
    33 import java.net.SocketAddress;
    33 import java.net.SocketAddress;
    34 import java.net.SocketException;
    34 import java.net.SocketException;
    35 import java.net.SocketTimeoutException;
    35 import java.net.SocketOption;
    36 import java.net.StandardSocketOptions;
    36 import java.net.StandardSocketOptions;
    37 import java.nio.channels.IllegalBlockingModeException;
    37 import java.nio.channels.IllegalBlockingModeException;
    38 import java.nio.channels.NotYetBoundException;
       
    39 import java.nio.channels.ServerSocketChannel;
    38 import java.nio.channels.ServerSocketChannel;
    40 import java.nio.channels.SocketChannel;
    39 import java.nio.channels.SocketChannel;
       
    40 import java.util.Set;
       
    41 
       
    42 import static java.util.concurrent.TimeUnit.MILLISECONDS;
    41 
    43 
    42 
    44 
    43 // Make a server-socket channel look like a server socket.
    45 // Make a server-socket channel look like a server socket.
    44 //
    46 //
    45 // The methods in this class are defined in exactly the same order as in
    47 // The methods in this class are defined in exactly the same order as in
    54     private final ServerSocketChannelImpl ssc;
    56     private final ServerSocketChannelImpl ssc;
    55 
    57 
    56     // Timeout "option" value for accepts
    58     // Timeout "option" value for accepts
    57     private volatile int timeout;
    59     private volatile int timeout;
    58 
    60 
    59     public static ServerSocket create(ServerSocketChannelImpl ssc) {
    61     static ServerSocket create(ServerSocketChannelImpl ssc) {
    60         try {
    62         return new ServerSocketAdaptor(ssc);
    61             return new ServerSocketAdaptor(ssc);
    63     }
    62         } catch (IOException x) {
    64 
    63             throw new Error(x);
    65     private ServerSocketAdaptor(ServerSocketChannelImpl ssc) {
    64         }
    66         super(DummySocketImpl.create());
    65     }
       
    66 
       
    67     // ## super will create a useless impl
       
    68     private ServerSocketAdaptor(ServerSocketChannelImpl ssc) throws IOException {
       
    69         this.ssc = ssc;
    67         this.ssc = ssc;
    70     }
    68     }
    71 
    69 
       
    70     @Override
    72     public void bind(SocketAddress local) throws IOException {
    71     public void bind(SocketAddress local) throws IOException {
    73         bind(local, 50);
    72         bind(local, 50);
    74     }
    73     }
    75 
    74 
       
    75     @Override
    76     public void bind(SocketAddress local, int backlog) throws IOException {
    76     public void bind(SocketAddress local, int backlog) throws IOException {
    77         if (local == null)
    77         if (local == null)
    78             local = new InetSocketAddress(0);
    78             local = new InetSocketAddress(0);
    79         try {
    79         try {
    80             ssc.bind(local, backlog);
    80             ssc.bind(local, backlog);
    81         } catch (Exception x) {
    81         } catch (Exception x) {
    82             Net.translateException(x);
    82             Net.translateException(x);
    83         }
    83         }
    84     }
    84     }
    85 
    85 
       
    86     @Override
    86     public InetAddress getInetAddress() {
    87     public InetAddress getInetAddress() {
    87         InetSocketAddress local = ssc.localAddress();
    88         InetSocketAddress local = ssc.localAddress();
    88         if (local == null) {
    89         if (local == null) {
    89             return null;
    90             return null;
    90         } else {
    91         } else {
    91             return Net.getRevealedLocalAddress(local).getAddress();
    92             return Net.getRevealedLocalAddress(local).getAddress();
    92         }
    93         }
    93     }
    94     }
    94 
    95 
       
    96     @Override
    95     public int getLocalPort() {
    97     public int getLocalPort() {
    96         InetSocketAddress local = ssc.localAddress();
    98         InetSocketAddress local = ssc.localAddress();
    97         if (local == null) {
    99         if (local == null) {
    98             return -1;
   100             return -1;
    99         } else {
   101         } else {
   100             return local.getPort();
   102             return local.getPort();
   101         }
   103         }
   102     }
   104     }
   103 
   105 
       
   106     @Override
   104     public Socket accept() throws IOException {
   107     public Socket accept() throws IOException {
   105         synchronized (ssc.blockingLock()) {
   108         SocketChannel sc = null;
   106             try {
   109         try {
   107                 if (!ssc.isBound())
   110             int timeout = this.timeout;
   108                     throw new NotYetBoundException();
   111             if (timeout > 0) {
   109 
   112                 long nanos = MILLISECONDS.toNanos(timeout);
   110                 long to = this.timeout;
   113                 sc = ssc.blockingAccept(nanos);
   111                 if (to == 0) {
   114             } else {
   112                     // for compatibility reasons: accept connection if available
   115                 // accept connection if possible when non-blocking (to preserve
   113                     // when configured non-blocking
   116                 // long standing behavior)
   114                     SocketChannel sc = ssc.accept();
   117                 sc = ssc.accept();
   115                     if (sc == null && !ssc.isBlocking())
   118                 if (sc == null) {
   116                         throw new IllegalBlockingModeException();
   119                     throw new IllegalBlockingModeException();
   117                     return sc.socket();
       
   118                 }
   120                 }
   119 
       
   120                 if (!ssc.isBlocking())
       
   121                     throw new IllegalBlockingModeException();
       
   122                 for (;;) {
       
   123                     long st = System.currentTimeMillis();
       
   124                     if (ssc.pollAccept(to))
       
   125                         return ssc.accept().socket();
       
   126                     to -= System.currentTimeMillis() - st;
       
   127                     if (to <= 0)
       
   128                         throw new SocketTimeoutException();
       
   129                 }
       
   130 
       
   131             } catch (Exception x) {
       
   132                 Net.translateException(x);
       
   133                 assert false;
       
   134                 return null;            // Never happens
       
   135             }
   121             }
   136         }
   122         } catch (Exception e) {
   137     }
   123             Net.translateException(e);
   138 
   124         }
       
   125         return sc.socket();
       
   126     }
       
   127 
       
   128     @Override
   139     public void close() throws IOException {
   129     public void close() throws IOException {
   140         ssc.close();
   130         ssc.close();
   141     }
   131     }
   142 
   132 
       
   133     @Override
   143     public ServerSocketChannel getChannel() {
   134     public ServerSocketChannel getChannel() {
   144         return ssc;
   135         return ssc;
   145     }
   136     }
   146 
   137 
       
   138     @Override
   147     public boolean isBound() {
   139     public boolean isBound() {
   148         return ssc.isBound();
   140         return ssc.isBound();
   149     }
   141     }
   150 
   142 
       
   143     @Override
   151     public boolean isClosed() {
   144     public boolean isClosed() {
   152         return !ssc.isOpen();
   145         return !ssc.isOpen();
   153     }
   146     }
   154 
   147 
       
   148     @Override
   155     public void setSoTimeout(int timeout) throws SocketException {
   149     public void setSoTimeout(int timeout) throws SocketException {
       
   150         if (!ssc.isOpen())
       
   151             throw new SocketException("Socket is closed");
       
   152         if (timeout < 0)
       
   153             throw new IllegalArgumentException("timeout < 0");
   156         this.timeout = timeout;
   154         this.timeout = timeout;
   157     }
   155     }
   158 
   156 
       
   157     @Override
   159     public int getSoTimeout() throws SocketException {
   158     public int getSoTimeout() throws SocketException {
       
   159         if (!ssc.isOpen())
       
   160             throw new SocketException("Socket is closed");
   160         return timeout;
   161         return timeout;
   161     }
   162     }
   162 
   163 
       
   164     @Override
   163     public void setReuseAddress(boolean on) throws SocketException {
   165     public void setReuseAddress(boolean on) throws SocketException {
   164         try {
   166         try {
   165             ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on);
   167             ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on);
   166         } catch (IOException x) {
   168         } catch (IOException x) {
   167             Net.translateToSocketException(x);
   169             Net.translateToSocketException(x);
   168         }
   170         }
   169     }
   171     }
   170 
   172 
       
   173     @Override
   171     public boolean getReuseAddress() throws SocketException {
   174     public boolean getReuseAddress() throws SocketException {
   172         try {
   175         try {
   173             return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue();
   176             return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue();
   174         } catch (IOException x) {
   177         } catch (IOException x) {
   175             Net.translateToSocketException(x);
   178             Net.translateToSocketException(x);
   176             return false;       // Never happens
   179             return false;       // Never happens
   177         }
   180         }
   178     }
   181     }
   179 
   182 
       
   183     @Override
   180     public String toString() {
   184     public String toString() {
   181         if (!isBound())
   185         if (!isBound())
   182             return "ServerSocket[unbound]";
   186             return "ServerSocket[unbound]";
   183         return "ServerSocket[addr=" + getInetAddress() +
   187         return "ServerSocket[addr=" + getInetAddress() +
   184                ",localport=" + getLocalPort()  + "]";
   188                ",localport=" + getLocalPort()  + "]";
   185     }
   189     }
   186 
   190 
       
   191     @Override
   187     public void setReceiveBufferSize(int size) throws SocketException {
   192     public void setReceiveBufferSize(int size) throws SocketException {
   188         // size 0 valid for ServerSocketChannel, invalid for ServerSocket
   193         // size 0 valid for ServerSocketChannel, invalid for ServerSocket
   189         if (size <= 0)
   194         if (size <= 0)
   190             throw new IllegalArgumentException("size cannot be 0 or negative");
   195             throw new IllegalArgumentException("size cannot be 0 or negative");
   191         try {
   196         try {
   193         } catch (IOException x) {
   198         } catch (IOException x) {
   194             Net.translateToSocketException(x);
   199             Net.translateToSocketException(x);
   195         }
   200         }
   196     }
   201     }
   197 
   202 
       
   203     @Override
   198     public int getReceiveBufferSize() throws SocketException {
   204     public int getReceiveBufferSize() throws SocketException {
   199         try {
   205         try {
   200             return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue();
   206             return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue();
   201         } catch (IOException x) {
   207         } catch (IOException x) {
   202             Net.translateToSocketException(x);
   208             Net.translateToSocketException(x);
   203             return -1;          // Never happens
   209             return -1;          // Never happens
   204         }
   210         }
   205     }
   211     }
       
   212 
       
   213     @Override
       
   214     public <T> ServerSocket setOption(SocketOption<T> name, T value) throws IOException {
       
   215         ssc.setOption(name, value);
       
   216         return this;
       
   217     }
       
   218 
       
   219     @Override
       
   220     public <T> T getOption(SocketOption<T> name) throws IOException {
       
   221         return ssc.getOption(name);
       
   222     }
       
   223 
       
   224     @Override
       
   225     public Set<SocketOption<?>> supportedOptions() {
       
   226         return ssc.supportedOptions();
       
   227     }
   206 }
   228 }