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.ClosedChannelException; 38 import java.nio.channels.IllegalBlockingModeException; 39 import java.nio.channels.NotYetBoundException; 40 import java.nio.channels.ServerSocketChannel; 41 import java.nio.channels.SocketChannel; 42 43 44 // Make a server-socket channel look like a server socket. 45 // 46 // The methods in this class are defined in exactly the same order as in 47 // java.net.ServerSocket so as to simplify tracking future changes to that 48 // class. 49 // 50 51 class ServerSocketAdaptor // package-private 52 extends ServerSocket 53 { 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 try { 63 return new ServerSocketAdaptor(ssc); 64 } catch (IOException x) { 65 throw new Error(x); 66 } 67 } 68 69 // ## super will create a useless impl 70 private ServerSocketAdaptor(ServerSocketChannelImpl ssc) 71 throws IOException 72 { 73 this.ssc = ssc; 74 } 75 76 77 public void bind(SocketAddress local) throws IOException { 78 bind(local, 50); 79 } 80 81 public void bind(SocketAddress local, int backlog) throws IOException { 82 if (local == null) 83 local = new InetSocketAddress(0); 84 try { 85 ssc.bind(local, backlog); 86 } catch (Exception x) { 87 Net.translateException(x); 88 } 89 } 90 91 public InetAddress getInetAddress() { 92 if (!ssc.isBound()) 93 return null; 94 return Net.getRevealedLocalAddress(ssc.localAddress()).getAddress(); 95 96 } 97 98 public int getLocalPort() { 99 if (!ssc.isBound()) 100 return -1; 101 return Net.asInetSocketAddress(ssc.localAddress()).getPort(); 102 } 103 104 105 public Socket accept() throws IOException { 106 synchronized (ssc.blockingLock()) { 107 try { 108 if (!ssc.isBound()) 109 throw new NotYetBoundException(); 110 111 if (timeout == 0) { 112 // for compatibility reasons: accept connection if available 113 // when configured non-blocking 114 SocketChannel sc = ssc.accept(); 115 if (sc == null && !ssc.isBlocking()) 116 throw new IllegalBlockingModeException(); 117 return sc.socket(); 118 } 119 120 if (!ssc.isBlocking()) 121 throw new IllegalBlockingModeException(); 122 ssc.configureBlocking(false); 123 try { 124 SocketChannel sc; 125 if ((sc = ssc.accept()) != null) 126 return sc.socket(); 127 long to = timeout; 128 for (;;) { 129 if (!ssc.isOpen()) 130 throw new ClosedChannelException(); 131 long st = System.currentTimeMillis(); 132 int result = ssc.poll(Net.POLLIN, to); 133 if (result > 0 && ((sc = ssc.accept()) != null)) 134 return sc.socket(); 135 to -= System.currentTimeMillis() - st; 136 if (to <= 0) 137 throw new SocketTimeoutException(); 138 } 139 } finally { 140 try { 141 ssc.configureBlocking(true); 142 } catch (ClosedChannelException e) { } 143 } 144 } catch (Exception x) { 145 Net.translateException(x); 146 assert false; 147 return null; // Never happens 148 } 149 } 150 } 151 152 public void close() throws IOException { 153 ssc.close(); 154 } 155 156 public ServerSocketChannel getChannel() { 157 return ssc; 158 } 159 160 public boolean isBound() { 161 return ssc.isBound(); 162 } 163 164 public boolean isClosed() { 165 return !ssc.isOpen(); 166 } 167 168 public void setSoTimeout(int timeout) throws SocketException { 169 this.timeout = timeout; 170 } 171 172 public int getSoTimeout() throws SocketException { 173 return timeout; 174 } 175 176 public void setReuseAddress(boolean on) throws SocketException { 177 try { 178 ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on); 179 } catch (IOException x) { 180 Net.translateToSocketException(x); 181 } 182 } 183 184 public boolean getReuseAddress() throws SocketException { 185 try { 186 return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue(); 187 } catch (IOException x) { 188 Net.translateToSocketException(x); 189 return false; // Never happens 190 } 191 } 192 193 public String toString() { 194 if (!isBound()) 195 return "ServerSocket[unbound]"; 196 return "ServerSocket[addr=" + getInetAddress() + 197 ",localport=" + getLocalPort() + "]"; 198 } 199 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 public int getReceiveBufferSize() throws SocketException { 212 try { 213 return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue(); 214 } catch (IOException x) { 215 Net.translateToSocketException(x); 216 return -1; // Never happens 217 } 218 } 219 220 }