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 42 43 // Make a server-socket channel look like a server socket. 44 // 45 // The methods in this class are defined in exactly the same order as in 46 // java.net.ServerSocket so as to simplify tracking future changes to that 47 // class. 48 // 49 50 class ServerSocketAdaptor // package-private 51 extends ServerSocket 52 { 53 // The channel being adapted 54 private final ServerSocketChannelImpl ssc; 55 56 // Timeout "option" value for accepts 57 private volatile int timeout; 58 59 public static ServerSocket create(ServerSocketChannelImpl ssc) { 60 try { 61 return new ServerSocketAdaptor(ssc); 62 } catch (IOException x) { 63 throw new Error(x); 64 } 65 } 66 67 // ## super will create a useless impl 68 private ServerSocketAdaptor(ServerSocketChannelImpl ssc) throws IOException { 69 this.ssc = ssc; 70 } 71 72 public void bind(SocketAddress local) throws IOException { 73 bind(local, 50); 74 } 75 76 public void bind(SocketAddress local, int backlog) throws IOException { 77 if (local == null) 78 local = new InetSocketAddress(0); 79 try { 80 ssc.bind(local, backlog); 81 } catch (Exception x) { 82 Net.translateException(x); 83 } 84 } 85 86 public InetAddress getInetAddress() { 87 InetSocketAddress local = ssc.localAddress(); 88 if (local == null) { 89 return null; 90 } else { 91 return Net.getRevealedLocalAddress(local).getAddress(); 92 } 93 } 94 95 public int getLocalPort() { 96 InetSocketAddress local = ssc.localAddress(); 97 if (local == null) { 98 return -1; 99 } else { 100 return local.getPort(); 101 } 102 } 103 104 public Socket accept() throws IOException { 105 synchronized (ssc.blockingLock()) { 106 try { 107 if (!ssc.isBound()) 108 throw new NotYetBoundException(); 109 110 long to = this.timeout; 111 if (to == 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 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 } 136 } 137 } 138 139 public void close() throws IOException { 140 ssc.close(); 141 } 142 143 public ServerSocketChannel getChannel() { 144 return ssc; 145 } 146 147 public boolean isBound() { 148 return ssc.isBound(); 149 } 150 151 public boolean isClosed() { 152 return !ssc.isOpen(); 153 } 154 155 public void setSoTimeout(int timeout) throws SocketException { 156 this.timeout = timeout; 157 } 158 159 public int getSoTimeout() throws SocketException { 160 return timeout; 161 } 162 163 public void setReuseAddress(boolean on) throws SocketException { 164 try { 165 ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on); 166 } catch (IOException x) { 167 Net.translateToSocketException(x); 168 } 169 } 170 171 public boolean getReuseAddress() throws SocketException { 172 try { 173 return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue(); 174 } catch (IOException x) { 175 Net.translateToSocketException(x); 176 return false; // Never happens 177 } 178 } 179 180 public String toString() { 181 if (!isBound()) 182 return "ServerSocket[unbound]"; 183 return "ServerSocket[addr=" + getInetAddress() + 184 ",localport=" + getLocalPort() + "]"; 185 } 186 187 public void setReceiveBufferSize(int size) throws SocketException { 188 // size 0 valid for ServerSocketChannel, invalid for ServerSocket 189 if (size <= 0) 190 throw new IllegalArgumentException("size cannot be 0 or negative"); 191 try { 192 ssc.setOption(StandardSocketOptions.SO_RCVBUF, size); 193 } catch (IOException x) { 194 Net.translateToSocketException(x); 195 } 196 } 197 198 public int getReceiveBufferSize() throws SocketException { 199 try { 200 return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue(); 201 } catch (IOException x) { 202 Net.translateToSocketException(x); 203 return -1; // Never happens 204 } 205 } 206 }