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.ServerSocket; 30 import java.net.Socket; 31 import java.net.SocketException; 32 import java.net.SocketOption; 33 import java.net.SocketOptions; 34 import java.net.StandardSocketOptions; 35 import java.util.HashMap; 36 import java.util.Map; 37 import java.util.Set; 38 import jdk.net.RdmaSocketOptions; 39 40 public class RdmaSocketProvider { 41 private static boolean rdmaLibInstalled = false; 42 private static boolean rdmaLibChecked = false; 43 44 static class RdmaClientSocketImpl extends RdmaSocketImpl { 45 46 @Override 47 protected <T> void setOption(SocketOption<T> name, T value) 48 throws IOException { 49 if(rdmaLibChecked && !rdmaLibInstalled) 50 throw new UnsupportedOperationException( 51 "librdmacm library is not installed!"); 52 53 rdmaLibChecked = true; 54 try { 55 if (!rdmaOptions.isOptionSupported(name)) { 56 int opt; 57 if (name == StandardSocketOptions.SO_SNDBUF) { 58 opt = SocketOptions.SO_SNDBUF; 59 } else if (name == StandardSocketOptions.SO_RCVBUF) { 60 opt = SocketOptions.SO_RCVBUF; 61 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 62 opt = SocketOptions.SO_REUSEADDR; 63 } else if (name == StandardSocketOptions.TCP_NODELAY) { 64 opt = SocketOptions.TCP_NODELAY; 65 } else { 66 throw new UnsupportedOperationException( 67 "unsupported option: " + name); 68 } 69 setOption(opt, value); 70 } else { 71 rdmaOptions.setOption(fd, name, value); 72 } 73 rdmaLibInstalled = true; 74 } catch (ExceptionInInitializerError e) { 75 rdmaLibInstalled = false; 76 throw new UnsupportedOperationException( 77 "librdmacm library is not installed!"); 78 } 79 } 80 81 @SuppressWarnings("unchecked") 82 @Override 83 protected <T> T getOption(SocketOption<T> name) throws IOException { 84 if(rdmaLibChecked && !rdmaLibInstalled) 85 throw new UnsupportedOperationException( 86 "librdmacm library is not installed!"); 87 88 rdmaLibChecked = true; 89 Object value; 90 try { 91 if (!rdmaOptions.isOptionSupported(name)) { 92 int opt; 93 if (name == StandardSocketOptions.SO_SNDBUF) { 94 opt = SocketOptions.SO_SNDBUF; 95 } else if (name == StandardSocketOptions.SO_RCVBUF) { 96 opt = SocketOptions.SO_RCVBUF; 97 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 98 opt = SocketOptions.SO_REUSEADDR; 99 } else if (name == StandardSocketOptions.TCP_NODELAY) { 100 opt = SocketOptions.TCP_NODELAY; 101 } else { 102 throw new UnsupportedOperationException( 103 "unsupported option: " + name); 104 } 105 value = getOption(opt); 106 } else { 107 value = rdmaOptions.getOption(fd, name); 108 } 109 rdmaLibInstalled = true; 110 return (T) value; 111 } catch (ExceptionInInitializerError e) { 112 rdmaLibInstalled = false; 113 throw new UnsupportedOperationException( 114 "librdmacm library is not installed!"); 115 } 116 } 117 } 118 119 static class RdmaServerSocketImpl extends RdmaSocketImpl { 120 121 @Override 122 protected <T> void setOption(SocketOption<T> name, T value) 123 throws IOException { 124 if(rdmaLibChecked && !rdmaLibInstalled) 125 throw new UnsupportedOperationException( 126 "librdmacm library is not installed!"); 127 128 rdmaLibChecked = true; 129 130 try { 131 if (!rdmaOptions.isOptionSupported(name)) { 132 int opt; 133 if (name == StandardSocketOptions.SO_RCVBUF) { 134 opt = SocketOptions.SO_RCVBUF; 135 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 136 opt = SocketOptions.SO_REUSEADDR; 137 } else { 138 throw new UnsupportedOperationException( 139 "unsupported option: " + name); 140 } 141 setOption(opt, value); 142 } else { 143 rdmaOptions.setOption(fd, name, value); 144 } 145 rdmaLibInstalled = true; 146 } catch (ExceptionInInitializerError e) { 147 rdmaLibInstalled = false; 148 throw new UnsupportedOperationException( 149 "librdmacm library is not installed!"); 150 } 151 } 152 153 @SuppressWarnings("unchecked") 154 @Override 155 protected <T> T getOption(SocketOption<T> name) throws IOException { 156 if(rdmaLibChecked && !rdmaLibInstalled) 157 throw new UnsupportedOperationException( 158 "librdmacm library is not installed!"); 159 160 rdmaLibChecked = true; 161 Object value; 162 try { 163 if (!rdmaOptions.isOptionSupported(name)) { 164 int opt; 165 if (name == StandardSocketOptions.SO_RCVBUF) { 166 opt = SocketOptions.SO_RCVBUF; 167 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 168 opt = SocketOptions.SO_REUSEADDR; 169 } else { 170 throw new UnsupportedOperationException( 171 "unsupported option: " + name); 172 } 173 rdmaLibInstalled = true; 174 value = getOption(opt); 175 } else { 176 rdmaLibInstalled = true; 177 value = rdmaOptions.getOption(fd, name); 178 } 179 rdmaLibInstalled = true; 180 return (T) value; 181 } catch (ExceptionInInitializerError e) { 182 rdmaLibInstalled = false; 183 throw new UnsupportedOperationException( 184 "librdmacm library is not installed!"); 185 } 186 } 187 } 188 189 public static Socket openSocket() throws IOException { 190 if(rdmaLibChecked && !rdmaLibInstalled) 191 throw new UnsupportedOperationException( 192 "librdmacm library is not installed!"); 193 194 rdmaLibChecked = true; 195 196 RdmaClientSocketImpl impl; 197 try { 198 impl = new RdmaClientSocketImpl(); 199 rdmaLibInstalled = true; 200 } catch (ExceptionInInitializerError e) { 201 rdmaLibInstalled = false; 202 throw new UnsupportedOperationException( 203 "librdmacm library is not installed!"); 204 } 205 Socket s = new Socket(impl) { 206 private final Set<SocketOption<?>> options = 207 Set.of(StandardSocketOptions.SO_SNDBUF, 208 StandardSocketOptions.SO_RCVBUF, 209 StandardSocketOptions.SO_REUSEADDR, 210 StandardSocketOptions.TCP_NODELAY, 211 RdmaSocketOptions.RDMA_SQSIZE, 212 RdmaSocketOptions.RDMA_RQSIZE, 213 RdmaSocketOptions.RDMA_INLINE); 214 215 @Override 216 public Set<SocketOption<?>> supportedOptions() { 217 return options; 218 } 219 }; 220 return s; 221 } 222 223 public static ServerSocket openServerSocket() throws IOException { 224 if(rdmaLibChecked && !rdmaLibInstalled) 225 throw new UnsupportedOperationException( 226 "librdmacm library is not installed!"); 227 228 rdmaLibChecked = true; 229 230 RdmaServerSocketImpl impl; 231 try { 232 impl = new RdmaServerSocketImpl(); 233 rdmaLibInstalled = true; 234 } catch (ExceptionInInitializerError e) { 235 rdmaLibInstalled = false; 236 throw new UnsupportedOperationException( 237 "librdmacm library is not installed!"); 238 } 239 ServerSocket ss = new ServerSocket(impl) { 240 private final Set<SocketOption<?>> options = 241 Set.of(StandardSocketOptions.SO_RCVBUF, 242 StandardSocketOptions.SO_REUSEADDR, 243 RdmaSocketOptions.RDMA_SQSIZE, 244 RdmaSocketOptions.RDMA_RQSIZE, 245 RdmaSocketOptions.RDMA_INLINE); 246 247 @Override 248 public Set<SocketOption<?>> supportedOptions() { 249 return options; 250 } 251 public Socket accept() throws IOException { 252 if (isClosed()) 253 throw new SocketException("Socket is closed"); 254 if (!isBound()) 255 throw new SocketException("Socket is not bound yet"); 256 257 Socket s = openSocket(); 258 implAccept(s); 259 return s; 260 } 261 }; 262 return ss; 263 } 264 265 private RdmaSocketProvider() {} 266 }