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.ProtocolFamily; 30 import java.net.ServerSocket; 31 import java.net.Socket; 32 import java.net.SocketException; 33 import java.net.SocketImpl; 34 import java.net.SocketOption; 35 import java.net.SocketOptions; 36 import java.net.StandardSocketOptions; 37 import java.util.HashMap; 38 import java.util.Map; 39 import java.util.Set; 40 import jdk.net.RdmaSocketOptions; 41 42 public class RdmaSocketProvider { 43 44 static class RdmaClientSocketImpl extends RdmaSocketImpl { 45 46 private final Set<SocketOption<?>> options = 47 Set.of(StandardSocketOptions.SO_SNDBUF, 48 StandardSocketOptions.SO_RCVBUF, 49 StandardSocketOptions.SO_REUSEADDR, 50 StandardSocketOptions.TCP_NODELAY, 51 RdmaSocketOptions.RDMA_SQSIZE, 52 RdmaSocketOptions.RDMA_RQSIZE, 53 RdmaSocketOptions.RDMA_INLINE); 54 55 RdmaClientSocketImpl(ProtocolFamily family) { 56 super(family); 57 } 58 59 @Override 60 public Set<SocketOption<?>> supportedOptions() { 61 return options; 62 } 63 64 @Override 65 protected <T> void setOption(SocketOption<T> name, T value) 66 throws IOException { 67 if (!rdmaOptions.isOptionSupported(name)) { 68 int opt; 69 if (name == StandardSocketOptions.SO_SNDBUF) { 70 opt = SocketOptions.SO_SNDBUF; 71 } else if (name == StandardSocketOptions.SO_RCVBUF) { 72 opt = SocketOptions.SO_RCVBUF; 73 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 74 opt = SocketOptions.SO_REUSEADDR; 75 } else if (name == StandardSocketOptions.TCP_NODELAY) { 76 opt = SocketOptions.TCP_NODELAY; 77 } else { 78 throw new UnsupportedOperationException( 79 "unsupported option: " + name); 80 } 81 setOption(opt, value); 82 } else { 83 rdmaOptions.setOption(fd, name, value); 84 } 85 } 86 87 @SuppressWarnings("unchecked") 88 @Override 89 protected <T> T getOption(SocketOption<T> name) throws IOException { 90 Object value; 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 return (T) value; 110 } 111 } 112 113 static class RdmaServerSocketImpl extends RdmaSocketImpl { 114 private final Set<SocketOption<?>> options = 115 Set.of(StandardSocketOptions.SO_RCVBUF, 116 StandardSocketOptions.SO_REUSEADDR, 117 RdmaSocketOptions.RDMA_SQSIZE, 118 RdmaSocketOptions.RDMA_RQSIZE, 119 RdmaSocketOptions.RDMA_INLINE); 120 121 RdmaServerSocketImpl(ProtocolFamily family) { 122 super(family); 123 } 124 125 @Override 126 public Set<SocketOption<?>> supportedOptions() { 127 return options; 128 } 129 130 @Override 131 protected <T> void setOption(SocketOption<T> name, T value) 132 throws IOException { 133 if (!rdmaOptions.isOptionSupported(name)) { 134 int opt; 135 if (name == StandardSocketOptions.SO_RCVBUF) { 136 opt = SocketOptions.SO_RCVBUF; 137 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 138 opt = SocketOptions.SO_REUSEADDR; 139 } else { 140 throw new UnsupportedOperationException( 141 "unsupported option: " + name); 142 } 143 setOption(opt, value); 144 } else { 145 rdmaOptions.setOption(fd, name, value); 146 } 147 } 148 149 @SuppressWarnings("unchecked") 150 @Override 151 protected <T> T getOption(SocketOption<T> name) throws IOException { 152 Object value; 153 if (!rdmaOptions.isOptionSupported(name)) { 154 int opt; 155 if (name == StandardSocketOptions.SO_RCVBUF) { 156 opt = SocketOptions.SO_RCVBUF; 157 } else if (name == StandardSocketOptions.SO_REUSEADDR) { 158 opt = SocketOptions.SO_REUSEADDR; 159 } else { 160 throw new UnsupportedOperationException( 161 "unsupported option: " + name); 162 } 163 value = getOption(opt); 164 } else { 165 value = rdmaOptions.getOption(fd, name); 166 } 167 return (T) value; 168 } 169 } 170 171 public static Socket openSocket(ProtocolFamily family) throws IOException { 172 return new Socket(new RdmaClientSocketImpl(family)) { }; 173 } 174 175 public static ServerSocket openServerSocket(ProtocolFamily family) 176 throws IOException { 177 return new ServerSocket(new RdmaServerSocketImpl(family)) { 178 public Socket accept() throws IOException { 179 if (isClosed()) 180 throw new SocketException("Socket is closed"); 181 if (!isBound()) 182 throw new SocketException("Socket is not bound yet"); 183 184 Socket s = openSocket(family); 185 implAccept(s); 186 return s; 187 } 188 }; 189 } 190 191 private RdmaSocketProvider() {} 192 }