1 /* 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. 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 sun.nio.ch; 27 28 import java.io.IOException; 29 import java.net.InetAddress; 30 import java.net.InetSocketAddress; 31 import java.net.ServerSocket; 32 import java.net.Socket; 33 import java.net.SocketAddress; 34 import java.net.SocketException; 35 import java.net.SocketOption; 36 import java.net.StandardSocketOptions; 37 import java.nio.channels.IllegalBlockingModeException; 38 import java.nio.channels.ServerSocketChannel; 39 import java.nio.channels.SocketChannel; 40 import java.security.AccessController; 41 import java.security.PrivilegedActionException; 42 import java.security.PrivilegedExceptionAction; 43 import java.util.Set; 44 45 import static java.util.concurrent.TimeUnit.MILLISECONDS; 46 47 48 // Make a server-socket channel look like a server socket. 49 // 50 // The methods in this class are defined in exactly the same order as in 51 // java.net.ServerSocket so as to simplify tracking future changes to that 52 // class. 53 // 54 55 class ServerSocketAdaptor // package-private 56 extends ServerSocket 57 { 58 // The channel being adapted 59 private final InetServerSocketChannelImpl ssc; 60 61 // Timeout "option" value for accepts 62 private volatile int timeout; 63 64 static ServerSocket create(InetServerSocketChannelImpl ssc) { 65 PrivilegedExceptionAction<ServerSocket> pa = () -> new ServerSocketAdaptor(ssc); 66 try { 67 return AccessController.doPrivileged(pa); 68 } catch (PrivilegedActionException pae) { 69 throw new InternalError("Should not reach here", pae); 70 } 71 } 72 73 private ServerSocketAdaptor(InetServerSocketChannelImpl ssc) { 74 super(DummySocketImpl.create()); 75 this.ssc = ssc; 76 } 77 78 @Override 79 public void bind(SocketAddress local) throws IOException { 80 bind(local, 50); 81 } 82 83 @Override 84 public void bind(SocketAddress local, int backlog) throws IOException { 85 if (local == null) 86 local = new InetSocketAddress(0); 87 try { 88 ssc.bind(local, backlog); 89 } catch (Exception x) { 90 Net.translateException(x); 91 } 92 } 93 94 @Override 95 public InetAddress getInetAddress() { 96 InetSocketAddress local = ssc.localAddress(); 97 if (local == null) { 98 return null; 99 } else { 100 return Net.getRevealedLocalAddress(local).getAddress(); 101 } 102 } 103 104 @Override 105 public int getLocalPort() { 106 InetSocketAddress local = ssc.localAddress(); 107 if (local == null) { 108 return -1; 109 } else { 110 return local.getPort(); 111 } 112 } 113 114 @Override 115 public Socket accept() throws IOException { 116 SocketChannel sc = null; 117 try { 118 int timeout = this.timeout; 119 if (timeout > 0) { 120 long nanos = MILLISECONDS.toNanos(timeout); 121 sc = ssc.blockingAccept(nanos); 122 } else { 123 // accept connection if possible when non-blocking (to preserve 124 // long standing behavior) 125 sc = ssc.accept(); 126 if (sc == null) { 127 throw new IllegalBlockingModeException(); 128 } 129 } 130 } catch (Exception e) { 131 Net.translateException(e); 132 } 133 return sc.socket(); 134 } 135 136 @Override 137 public void close() throws IOException { 138 ssc.close(); 139 } 140 141 @Override 142 public ServerSocketChannel getChannel() { 143 return ssc; 144 } 145 146 @Override 147 public boolean isBound() { 148 return ssc.isBound(); 149 } 150 151 @Override 152 public boolean isClosed() { 153 return !ssc.isOpen(); 154 } 155 156 @Override 157 public void setSoTimeout(int timeout) throws SocketException { 158 if (!ssc.isOpen()) 159 throw new SocketException("Socket is closed"); 160 if (timeout < 0) 161 throw new IllegalArgumentException("timeout < 0"); 162 this.timeout = timeout; 163 } 164 165 @Override 166 public int getSoTimeout() throws SocketException { 167 if (!ssc.isOpen()) 168 throw new SocketException("Socket is closed"); 169 return timeout; 170 } 171 172 @Override 173 public void setReuseAddress(boolean on) throws SocketException { 174 try { 175 ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on); 176 } catch (IOException x) { 177 Net.translateToSocketException(x); 178 } 179 } 180 181 @Override 182 public boolean getReuseAddress() throws SocketException { 183 try { 184 return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue(); 185 } catch (IOException x) { 186 Net.translateToSocketException(x); 187 return false; // Never happens 188 } 189 } 190 191 @Override 192 public String toString() { 193 if (!isBound()) 194 return "ServerSocket[unbound]"; 195 return "ServerSocket[addr=" + getInetAddress() + 196 ",localport=" + getLocalPort() + "]"; 197 } 198 199 @Override 200 public void setReceiveBufferSize(int size) throws SocketException { 201 // size 0 valid for ServerSocketChannel, invalid for ServerSocket 202 if (size <= 0) 203 throw new IllegalArgumentException("size cannot be 0 or negative"); 204 try { 205 ssc.setOption(StandardSocketOptions.SO_RCVBUF, size); 206 } catch (IOException x) { 207 Net.translateToSocketException(x); 208 } 209 } 210 211 @Override 212 public int getReceiveBufferSize() throws SocketException { 213 try { 214 return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue(); 215 } catch (IOException x) { 216 Net.translateToSocketException(x); 217 return -1; // Never happens 218 } 219 } 220 221 @Override 222 public <T> ServerSocket setOption(SocketOption<T> name, T value) throws IOException { 223 ssc.setOption(name, value); 224 return this; 225 } 226 227 @Override 228 public <T> T getOption(SocketOption<T> name) throws IOException { 229 return ssc.getOption(name); 230 } 231 232 @Override 233 public Set<SocketOption<?>> supportedOptions() { 234 return ssc.supportedOptions(); 235 } 236 }