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