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 rdma.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 class RdmaServerSocketAdaptor 43 extends ServerSocket 44 { 45 private final RdmaServerSocketChannelImpl ssc; 46 47 private volatile int timeout; 48 49 public static ServerSocket create(RdmaServerSocketChannelImpl ssc) { 50 try { 51 return new RdmaServerSocketAdaptor(ssc); 52 } catch (IOException x) { 53 throw new Error(x); 54 } 55 } 56 57 private RdmaServerSocketAdaptor(RdmaServerSocketChannelImpl ssc) throws IOException { 58 this.ssc = ssc; 59 } 60 61 public void bind(SocketAddress local) throws IOException { 62 bind(local, 50); 63 } 64 65 public void bind(SocketAddress local, int backlog) throws IOException { 66 if (local == null) 67 local = new InetSocketAddress(0); 68 try { 69 ssc.bind(local, backlog); 70 } catch (Exception x) { 71 RdmaNet.translateException(x); 72 } 73 } 74 75 public InetAddress getInetAddress() { 76 InetSocketAddress local = ssc.localAddress(); 77 if (local == null) { 78 return null; 79 } else { 80 return RdmaNet.getRevealedLocalAddress(local).getAddress(); 81 } 82 } 83 84 public int getLocalPort() { 85 InetSocketAddress local = ssc.localAddress(); 86 if (local == null) { 87 return -1; 88 } else { 89 return local.getPort(); 90 } 91 } 92 93 public Socket accept() throws IOException { 94 synchronized (ssc.blockingLock()) { 95 try { 96 if (!ssc.isBound()) 97 throw new NotYetBoundException(); 98 99 long to = this.timeout; 100 if (to == 0) { 101 // for compatibility reasons: accept connection if available 102 // when configured non-blocking 103 SocketChannel sc = ssc.accept(); 104 if (sc == null && !ssc.isBlocking()) 105 throw new IllegalBlockingModeException(); 106 return sc.socket(); 107 } 108 109 if (!ssc.isBlocking()) 110 throw new IllegalBlockingModeException(); 111 for (;;) { 112 long st = System.currentTimeMillis(); 113 if (ssc.pollAccept(to)) 114 return ssc.accept().socket(); 115 to -= System.currentTimeMillis() - st; 116 if (to <= 0) 117 throw new SocketTimeoutException(); 118 } 119 120 } catch (Exception x) { 121 RdmaNet.translateException(x); 122 assert false; 123 return null; // Never happens 124 } 125 } 126 } 127 128 public void close() throws IOException { 129 ssc.close(); 130 } 131 132 public ServerSocketChannel getChannel() { 133 return ssc; 134 } 135 136 public boolean isBound() { 137 return ssc.isBound(); 138 } 139 140 public boolean isClosed() { 141 return !ssc.isOpen(); 142 } 143 144 public void setSoTimeout(int timeout) throws SocketException { 145 this.timeout = timeout; 146 } 147 148 public int getSoTimeout() throws SocketException { 149 return timeout; 150 } 151 152 public void setReuseAddress(boolean on) throws SocketException { 153 try { 154 ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on); 155 } catch (IOException x) { 156 RdmaNet.translateToSocketException(x); 157 } 158 } 159 160 public boolean getReuseAddress() throws SocketException { 161 try { 162 return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue(); 163 } catch (IOException x) { 164 RdmaNet.translateToSocketException(x); 165 return false; // Never happens 166 } 167 } 168 169 public String toString() { 170 if (!isBound()) 171 return "RdmaServerSocket[unbound]"; 172 return "RdmaServerSocket[addr=" + getInetAddress() + 173 ",localport=" + getLocalPort() + "]"; 174 } 175 176 public void setReceiveBufferSize(int size) throws SocketException { 177 // size 0 valid for ServerSocketChannel, invalid for ServerSocket 178 if (size <= 0) 179 throw new IllegalArgumentException("size cannot be 0 or negative"); 180 try { 181 ssc.setOption(StandardSocketOptions.SO_RCVBUF, size); 182 } catch (IOException x) { 183 RdmaNet.translateToSocketException(x); 184 } 185 } 186 187 public int getReceiveBufferSize() throws SocketException { 188 try { 189 return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue(); 190 } catch (IOException x) { 191 RdmaNet.translateToSocketException(x); 192 return -1; // Never happens 193 } 194 } 195 }