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.net;
  27 
  28 import java.net.ProtocolFamily;
  29 import java.net.ServerSocket;
  30 import java.net.Socket;
  31 import java.net.SocketException;
  32 import java.net.SocketOption;
  33 import java.net.StandardSocketOptions;
  34 import java.nio.channels.Selector;
  35 import java.nio.channels.ServerSocketChannel;
  36 import java.nio.channels.SocketChannel;
  37 import java.nio.channels.spi.SelectorProvider;
  38 import java.io.IOException;
  39 import java.util.Collections;
  40 import java.util.HashMap;
  41 import java.util.HashSet;
  42 import java.util.Map;
  43 import java.util.Set;
  44 import jdk.internal.net.rdma.RdmaPollSelectorProvider;
  45 import jdk.internal.net.rdma.RdmaSocketProvider;
  46 
  47 /**
  48  * Factory methods for creating RDMA-based TCP sockets and channels.
  49  *
  50  * <p>The {@link #openSocket(ProtocolFamily family) openSocket} and {@link
  51  * #openServerSocket(ProtocolFamily family) openServerSocket} methods
  52  * create RDMA-based TCP sockets.
  53  * 
  54  * <p>The {@link #openSelector() openSelector}, {@link
  55  * #openSocketChannel(ProtocolFamily family) openSocketChannel}, and {@link
  56  * #openServerSocketChannel(ProtocolFamily family) openServerSocketChannel}
  57  * methods create selectors and selectable channels for use with RDMA sockets.
  58  * These objects are created by a {@link java.nio.channels.spi.SelectorProvider
  59  * SelectorProvider} that is not the default {@code SelectorProvider}.
  60  * Consequently, selectable channels to RDMA sockets may not be multiplexed
  61  * with selectable channels created by the default selector provider. The
  62  * selector provider does not support datagram channels and pipes.
  63  * The {@link java.nio.channels.spi.SelectorProvider#openDatagramChannel
  64  * openDatagramChannel} and
  65  * {@link java.nio.channels.spi.SelectorProvider#openPipe openPipe} methods
  66  * throw {@link java.lang.UnsupportedOperationException
  67  * UnsupportedOperationException}.
  68  * 
  69  * @since 12
  70  */
  71 public class RdmaSockets {
  72 
  73     private RdmaSockets() {}
  74 
  75     /**
  76      * Creates an unbound and unconnected RDMA socket.
  77      *
  78      * <p> A RDMA socket supports the same socket options that {@code
  79      * java.net.Socket} defines. In addition, it supports the socket options
  80      * specified by {@link RdmaSocketOptions}.
  81      *
  82      * <p> When binding the socket to a local address, or invoking connect
  83      * to connect the socket, the socket address specified to those methods
  84      * must correspond to the protocol family specified here.
  85      *
  86      * @param   family
  87      *          The protocol family
  88      *
  89      * @throws IOException
  90      *         If an I/O error occurs
  91      * @throws NullPointerException
  92      *         If name is null
  93      * @throws UnsupportedOperationException
  94      *         If RDMA sockets are not supported on this platform or if the
  95      *         specified protocol family is not supported. For example,
  96      *         suppose the parameter is specified as {@link
  97      *         java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
  98      *         but IPv6 is not enabled on the platform.
  99      */
 100     public static Socket openSocket(ProtocolFamily family) throws IOException {
 101         if(family == null)
 102             throw new NullPointerException("protocol family is null");
 103         return RdmaSocketProvider.openSocket(family);
 104     }
 105 
 106     /**
 107      * Creates an unbound RDMA server socket.
 108      *
 109      * <p> A RDMA socket supports the same socket options that {@code
 110      * java.net.ServerSocket} defines.
 111      *
 112      * <p> When binding the socket to an address, the socket address specified
 113      * to the bind method must correspond to the protocol family specified here.
 114      *
 115      * @param   family
 116      *          The protocol family
 117      *
 118      * @throws IOException
 119      *         If an I/O error occurs
 120      * @throws NullPointerException
 121      *         If name is null
 122      * @throws UnsupportedOperationException
 123      *         If RDMA sockets are not supported on this platform or if the
 124      *         specified protocol family is not supported. For example,
 125      *         suppose the parameter is specified as {@link
 126      *         java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
 127      *         but IPv6 is not enabled on the platform.
 128      */
 129     public static ServerSocket openServerSocket(ProtocolFamily family)
 130             throws IOException {
 131         if(family == null)
 132             throw new NullPointerException("protocol family is null");
 133         return RdmaSocketProvider.openServerSocket(family);
 134     }
 135 
 136     /**
 137      * Opens a socket channel to a RDMA socket. A newly created socket channel
 138      * is {@link SocketChannel#isOpen() open}, not yet bound to a {@link
 139      * SocketChannel#getLocalAddress() local address}, and not yet
 140      * {@link SocketChannel#isConnected() connected}.
 141      *
 142      * <p> A socket channel to a RDMA socket supports all of the socket options
 143      * specified by {@code SocketChannel}. In addition, it supports the
 144      * socket options specified by {@link RdmaSocketOptions}.
 145      *
 146      * <p> When binding the channel's socket to a local address, or invoking
 147      * connect to connect channel's socket, the socket address specified to
 148      * those methods must correspond to the protocol family specified here.
 149      *
 150      * @param   family
 151      *          The protocol family
 152      *
 153      * @throws IOException
 154      *         If an I/O error occurs
 155      * @throws NullPointerException
 156      *         If name is null
 157      * @throws UnsupportedOperationException
 158      *         If RDMA sockets are not supported on this platform or if the
 159      *         specified protocol family is not supported. For example,
 160      *         suppose the parameter is specified as {@link
 161      *         java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
 162      *         but IPv6 is not enabled on the platform.
 163      */
 164     public static SocketChannel openSocketChannel(ProtocolFamily family)
 165             throws IOException {
 166         if(family == null)
 167             throw new NullPointerException("protocol family is null");
 168         SelectorProvider provider = RdmaPollSelectorProvider.provider();
 169         return ((RdmaPollSelectorProvider)provider).openSocketChannel(family);
 170     }
 171 
 172     /**
 173      * Opens a server socket channel to a RDMA socket. A newly created socket
 174      * channel is {@link SocketChannel#isOpen() open} but not yet bound to a
 175      * {@link SocketChannel#getLocalAddress() local address}.
 176      *
 177      * <p> When binding the channel's socket to an address , the socket address
 178      * specified to the bind method must correspond to the protocol family
 179      * specified here.
 180      *
 181      * @param   family
 182      *          The protocol family
 183      *
 184      * @throws IOException
 185      *         If an I/O error occurs
 186      * @throws NullPointerException
 187      *         If name is null
 188      * @throws UnsupportedOperationException
 189      *         If RDMA sockets are not supported on this platform or if the
 190      *         specified protocol family is not supported. For example,
 191      *         suppose the parameter is specified as {@link
 192      *         java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
 193      *         but IPv6 is not enabled on the platform.
 194      */
 195     public static ServerSocketChannel openServerSocketChannel(
 196             ProtocolFamily family) throws IOException {
 197         if(family == null)
 198             throw new NullPointerException("protocol family is null");
 199         SelectorProvider provider = RdmaPollSelectorProvider.provider();
 200         return ((RdmaPollSelectorProvider)provider)
 201                 .openServerSocketChannel(family);
 202     }
 203  
 204     /**
 205      * Opens a selector to multiplex selectable channels to RDMA sockets.
 206      *
 207      * @throws IOException
 208      *         If an I/O error occurs
 209      * @throws UnsupportedOperationException
 210      *         If RDMA sockets are not supported on this platform
 211      */
 212     public static Selector openSelector() throws IOException {
 213         SelectorProvider provider = RdmaPollSelectorProvider.provider();
 214         return provider.openSelector();
 215     }
 216 }