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