1 /* 2 * Copyright (c) 2000, 2018, 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.SocketTimeoutException; 36 import java.net.StandardSocketOptions; 37 import java.nio.channels.IllegalBlockingModeException; 38 import java.nio.channels.NotYetBoundException; 39 import java.nio.channels.ServerSocketChannel; 40 import java.nio.channels.SocketChannel; 41 import java.security.AccessController; 42 import java.security.PrivilegedActionException; 43 import java.security.PrivilegedExceptionAction; 44 45 // Make a server-socket channel look like a server socket. 46 // 47 // The methods in this class are defined in exactly the same order as in 48 // java.net.ServerSocket so as to simplify tracking future changes to that 49 // class. 50 // 51 52 class ServerSocketAdaptor // package-private 53 extends ServerSocket 54 { 55 // The channel being adapted 56 private final ServerSocketChannelImpl ssc; 57 58 // Timeout "option" value for accepts 59 private volatile int timeout; 60 61 public static ServerSocket create(ServerSocketChannelImpl ssc) { 62 PrivilegedExceptionAction<ServerSocket> pa = () -> new ServerSocketAdaptor(ssc); 63 try { 64 return AccessController.doPrivileged(pa); 65 } catch (PrivilegedActionException pae) { 66 throw new InternalError("Should not reach here", pae); 67 } 68 } 69 70 // ## super will create a useless impl 71 private ServerSocketAdaptor(ServerSocketChannelImpl ssc) throws IOException { 72 this.ssc = ssc; 73 } 74 75 public void bind(SocketAddress local) throws IOException { 76 bind(local, 50); 77 } 78 79 public void bind(SocketAddress local, int backlog) throws IOException { 80 if (local == null) 81 local = new InetSocketAddress(0); 82 try { 83 ssc.bind(local, backlog); 84 } catch (Exception x) { 85 Net.translateException(x); 86 } 87 } 88 89 public InetAddress getInetAddress() { 90 InetSocketAddress local = ssc.localAddress(); 91 if (local == null) { 92 return null; 93 } else { 94 return Net.getRevealedLocalAddress(local).getAddress(); 95 } 96 } 97 98 public int getLocalPort() { 99 InetSocketAddress local = ssc.localAddress(); 100 if (local == null) { 101 return -1; 102 } else { 103 return local.getPort(); 104 } 105 } 106 107 public Socket accept() throws IOException { 108 synchronized (ssc.blockingLock()) { 109 try { 110 if (!ssc.isBound()) 111 throw new NotYetBoundException(); 112 113 long to = this.timeout; 114 if (to == 0) { 115 // for compatibility reasons: accept connection if available 116 // when configured non-blocking 117 SocketChannel sc = ssc.accept(); 118 if (sc == null && !ssc.isBlocking()) 119 throw new IllegalBlockingModeException(); 120 return sc.socket(); 121 } 122 123 if (!ssc.isBlocking()) 124 throw new IllegalBlockingModeException(); 125 for (;;) { 126 long st = System.currentTimeMillis(); 127 if (ssc.pollAccept(to)) 128 return ssc.accept().socket(); 129 to -= System.currentTimeMillis() - st; 130 if (to <= 0) 131 throw new SocketTimeoutException(); 132 } 133 134 } catch (Exception x) { 135 Net.translateException(x); 136 assert false; 137 return null; // Never happens 138 } 139 } 140 } 141 142 public void close() throws IOException { 143 ssc.close(); 144 } 145 146 public ServerSocketChannel getChannel() { 147 return ssc; 148 } 149 150 public boolean isBound() { 151 return ssc.isBound(); 152 } 153 154 public boolean isClosed() { 155 return !ssc.isOpen(); 156 } 157 158 public void setSoTimeout(int timeout) throws SocketException { 159 this.timeout = timeout; 160 } 161 162 public int getSoTimeout() throws SocketException { 163 return timeout; 164 } 165 166 public void setReuseAddress(boolean on) throws SocketException { 167 try { 168 ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on); 169 } catch (IOException x) { 170 Net.translateToSocketException(x); 171 } 172 } 173 174 public boolean getReuseAddress() throws SocketException { 175 try { 176 return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue(); 177 } catch (IOException x) { 178 Net.translateToSocketException(x); 179 return false; // Never happens 180 } 181 } 182 183 public String toString() { 184 if (!isBound()) 185 return "ServerSocket[unbound]"; 186 return "ServerSocket[addr=" + getInetAddress() + 187 ",localport=" + getLocalPort() + "]"; 188 } 189 190 public void setReceiveBufferSize(int size) throws SocketException { 191 // size 0 valid for ServerSocketChannel, invalid for ServerSocket 192 if (size <= 0) 193 throw new IllegalArgumentException("size cannot be 0 or negative"); 194 try { 195 ssc.setOption(StandardSocketOptions.SO_RCVBUF, size); 196 } catch (IOException x) { 197 Net.translateToSocketException(x); 198 } 199 } 200 201 public int getReceiveBufferSize() throws SocketException { 202 try { 203 return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue(); 204 } catch (IOException x) { 205 Net.translateToSocketException(x); 206 return -1; // Never happens 207 } 208 } 209 }