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.io.InputStream;
  30 import java.io.OutputStream;
  31 import java.io.FileDescriptor;
  32 import java.lang.reflect.Field;
  33 import java.net.Socket;
  34 import java.net.ServerSocket;
  35 import java.net.SocketImpl;
  36 import java.net.SocketOption;
  37 import java.net.SocketException;
  38 import java.net.UnknownHostException;
  39 import java.net.InetAddress;
  40 import java.net.SocketAddress;
  41 import java.net.InetSocketAddress;
  42 import java.net.StandardSocketOptions;
  43 import java.net.SocketOptions;
  44 import java.security.AccessController;
  45 import java.security.PrivilegedAction;
  46 import java.util.Set;
  47 import java.util.HashSet;
  48 import java.util.Collections;
  49 import jdk.internal.misc.JdkRdmaSocketImplAccess;
  50 import jdk.internal.misc.SharedSecrets;
  51 import sun.net.ConnectionResetException;
  52 import sun.net.ext.RdmaSocketOptions;
  53 
  54 public class RdmaSocketImpl extends SocketImpl
  55 {
  56     Socket socket = null;
  57     ServerSocket serverSocket = null;
  58 
  59     int timeout;   // timeout in millisec
  60 
  61     int trafficClass;
  62 
  63     InputStream socketInputStream;
  64     OutputStream socketOutputStream;
  65 
  66     private boolean shut_rd = false;
  67     private boolean shut_wr = false;
  68 
  69     /* number of threads using the FileDescriptor */
  70     protected int fdUseCount = 0;
  71 
  72     /* lock when increment/decrementing fdUseCount */
  73     protected final Object fdLock = new Object();
  74 
  75     /* indicates a close is pending on the file descriptor */
  76     protected boolean closePending = false;
  77 
  78     /* indicates connection reset state */
  79     private int CONNECTION_NOT_RESET = 0;
  80     private int CONNECTION_RESET_PENDING = 1;
  81     private int CONNECTION_RESET = 2;
  82     private int resetState;
  83     private final Object resetLock = new Object();
  84 
  85    /* whether this Socket is a stream (TCP) socket or not (UDP)
  86     */
  87     protected boolean stream;
  88 
  89     static final sun.net.ext.RdmaSocketOptions rdmaOptions =
  90             sun.net.ext.RdmaSocketOptions.getInstance();
  91 
  92     private static PlatformRdmaSocketImpl platformRdmaSocketImpl =
  93             PlatformRdmaSocketImpl.get();
  94 
  95     private static Field sCreateState;
  96     private static Field sBoundState;
  97     private static Field sConnectState;
  98     private static Field ssCreateState;
  99     private static Field ssBoundState;
 100     private static boolean socketStateSet;
 101     private static boolean serverSocketStateSet;
 102 
 103     static {
 104         SharedSecrets.setJdkRdmaSocketImplAccess(
 105                 new JdkRdmaSocketImplAccess() {
 106                     public void setSocket(SocketImpl si, Socket s) {
 107                         ((RdmaSocketImpl)si).setSocket(s);
 108                     }
 109                     public void setServerSocket(SocketImpl si,
 110                                                 ServerSocket ss) {
 111                         ((RdmaSocketImpl)si).setServerSocket(ss);
 112                     }
 113                 }
 114         );
 115     }
 116 
 117     boolean isRdmaAvailable() {
 118         return platformRdmaSocketImpl.isRdmaAvailable();
 119     }
 120 
 121     void setSocket(Socket soc) {
 122         this.socket = soc;
 123         try {
 124             if (!socketStateSet) {
 125                 sCreateState = Socket.class.getDeclaredField("created");
 126                 sCreateState.setAccessible(true);
 127                 sBoundState = Socket.class.getDeclaredField("bound");
 128                 sBoundState.setAccessible(true);
 129                 sConnectState= Socket.class.getDeclaredField("connected");
 130                 sConnectState.setAccessible(true);
 131                 sCreateState.setBoolean(socket, false);
 132                 sBoundState.setBoolean(socket, false);
 133                 sConnectState.setBoolean(socket, false);
 134             }
 135         } catch (NoSuchFieldException | IllegalAccessException e) {
 136             throw new Error(e);
 137         }
 138         socketStateSet = true;
 139     }
 140 
 141     Socket getSocket() {
 142         return socket;
 143     }
 144 
 145     void setServerSocket(ServerSocket soc) {
 146         this.serverSocket = soc;
 147         try {
 148             if (!serverSocketStateSet) {
 149                 ssCreateState = ServerSocket.class.getDeclaredField("created");
 150                 ssCreateState.setAccessible(true);
 151                 ssBoundState = ServerSocket.class.getDeclaredField("bound");
 152                 ssBoundState.setAccessible(true);
 153                 ssCreateState.setBoolean(serverSocket, false);
 154                 ssBoundState.setBoolean(serverSocket, false);
 155             }
 156         } catch (NoSuchFieldException | IllegalAccessException e) {
 157             throw new Error(e);
 158         }
 159         serverSocketStateSet = true;
 160     }
 161 
 162     ServerSocket getServerSocket() {
 163         return serverSocket;
 164     }
 165 
 166     private static final Set<SocketOption<?>> socketOptions;
 167 
 168     private static final Set<SocketOption<?>> serverSocketOptions;
 169 
 170     static {
 171         socketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
 172                                StandardSocketOptions.SO_RCVBUF,
 173                                StandardSocketOptions.SO_REUSEADDR,
 174                                StandardSocketOptions.TCP_NODELAY);
 175 
 176         serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
 177                                      StandardSocketOptions.SO_REUSEADDR);
 178     }
 179 
 180     @Override
 181     protected Set<SocketOption<?>> supportedOptions() {
 182         Set<SocketOption<?>> options = new HashSet<>();
 183         if (socket != null)
 184             options.addAll(socketOptions);
 185         else
 186             options.addAll(serverSocketOptions);
 187 
 188         if (isRdmaAvailable()) {
 189             RdmaSocketOptions rdmaOptions =
 190                     RdmaSocketOptions.getInstance();
 191             options.addAll(rdmaOptions.options());
 192         }
 193         options = Collections.unmodifiableSet(options);
 194         return options;
 195     }
 196 
 197     protected synchronized void create(boolean stream) throws IOException {
 198         this.stream = stream;
 199         if (stream) {
 200             fd = new FileDescriptor();
 201             platformRdmaSocketImpl.rdmaSocketCreate(true, this);
 202         }
 203         try {
 204             if (socket != null) {
 205                 sCreateState.setBoolean(socket, true);
 206             }
 207             if (serverSocket != null)
 208                 ssCreateState.setBoolean(serverSocket, true);
 209         } catch (IllegalAccessException e) {
 210             throw new AssertionError(e);
 211         }
 212     }
 213 
 214     protected void connect(String host, int port)
 215         throws UnknownHostException, IOException
 216     {
 217         boolean connected = false;
 218         try {
 219             InetAddress address = InetAddress.getByName(host);
 220             this.port = port;
 221             this.address = address;
 222 
 223             connectToAddress(address, port, timeout);
 224             connected = true;
 225         } finally {
 226             if (!connected) {
 227                 try {
 228                     close();
 229                 } catch (IOException ioe) {
 230                 }
 231             }
 232         }
 233     }
 234 
 235     protected void connect(InetAddress address, int port) throws IOException {
 236         this.port = port;
 237         this.address = address;
 238 
 239         try {
 240             connectToAddress(address, port, timeout);
 241             return;
 242         } catch (IOException e) {
 243             close();
 244             throw e;
 245         }
 246     }
 247 
 248     protected void connect(SocketAddress address, int timeout)
 249             throws IOException {
 250         boolean connected = false;
 251         try {
 252             if (address == null || !(address instanceof InetSocketAddress))
 253                 throw new IllegalArgumentException("unsupported address type");
 254             InetSocketAddress addr = (InetSocketAddress) address;
 255             if (addr.isUnresolved())
 256                 throw new UnknownHostException(addr.getHostName());
 257             this.port = addr.getPort();
 258             this.address = addr.getAddress();
 259 
 260             connectToAddress(this.address, port, timeout);
 261             connected = true;
 262         } finally {
 263             if (!connected) {
 264                 try {
 265                     close();
 266                 } catch (IOException ioe) {
 267                 }
 268             }
 269         }
 270     }
 271 
 272     private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
 273         if (address.isAnyLocalAddress()) {
 274             doConnect(InetAddress.getLocalHost(), port, timeout);
 275         } else {
 276             doConnect(address, port, timeout);
 277         }
 278     }
 279 
 280     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
 281         if (!rdmaOptions.isOptionSupported(name)) {
 282             int opt;
 283             if (name == StandardSocketOptions.SO_SNDBUF &&
 284                     socket != null) {
 285                 opt = SocketOptions.SO_SNDBUF;
 286             } else if (name == StandardSocketOptions.SO_RCVBUF) {
 287                 opt = SocketOptions.SO_RCVBUF;
 288             } else if (name == StandardSocketOptions.SO_REUSEADDR) {
 289                 opt = SocketOptions.SO_REUSEADDR;
 290             } else if (name == StandardSocketOptions.TCP_NODELAY &&
 291                     (socket != null)) {
 292                 opt = SocketOptions.TCP_NODELAY;
 293             } else {
 294                 throw new UnsupportedOperationException("unsupported option");
 295             }
 296             setOption(opt, value);
 297         } else {
 298             rdmaOptions.setOption(fd, name, value);
 299         }
 300     }
 301 
 302     @SuppressWarnings("unchecked")
 303     protected <T> T getOption(SocketOption<T> name) throws IOException {
 304         if (!rdmaOptions.isOptionSupported(name)) {
 305             int opt;
 306             if (name == StandardSocketOptions.SO_SNDBUF &&
 307                     (socket != null)) {
 308                 opt = SocketOptions.SO_SNDBUF;
 309             } else if (name == StandardSocketOptions.SO_RCVBUF) {
 310                 opt = SocketOptions.SO_RCVBUF;
 311             } else if (name == StandardSocketOptions.SO_REUSEADDR) {
 312                 opt = SocketOptions.SO_REUSEADDR;
 313             } else if (name == StandardSocketOptions.TCP_NODELAY &&
 314                     (socket != null)) {
 315                 opt = SocketOptions.TCP_NODELAY;
 316             } else {
 317                 throw new UnsupportedOperationException("unsupported option");
 318             }
 319             return (T) getOption(opt);
 320         } else {
 321             return (T) rdmaOptions.getOption(fd, name);
 322         }
 323     }
 324 
 325     public void setOption(int opt, Object val) throws SocketException {
 326         if (isClosedOrPending()) {
 327             throw new SocketException("Socket Closed");
 328         }
 329         boolean on = true;
 330         switch (opt) {
 331         case SO_TIMEOUT:
 332             if (val == null || (!(val instanceof Integer)))
 333                 throw new SocketException("Bad parameter for SO_TIMEOUT");
 334             int tmp = ((Integer) val).intValue();
 335             if (tmp < 0)
 336                 throw new IllegalArgumentException("timeout < 0");
 337             timeout = tmp;
 338             break;
 339         case SO_BINDADDR:
 340             throw new SocketException("Cannot re-bind socket");
 341         case TCP_NODELAY:
 342             if (val == null || !(val instanceof Boolean))
 343                 throw new SocketException("bad parameter for TCP_NODELAY");
 344             on = ((Boolean)val).booleanValue();
 345             break;
 346         case SO_SNDBUF:
 347         case SO_RCVBUF:
 348             int value = ((Integer)val).intValue();
 349             int maxValue = 1024 * 1024 * 1024 - 1;   //maximum value for the buffer
 350             if (val == null || !(val instanceof Integer) ||
 351                 !(value > 0)) {
 352                 throw new SocketException("bad parameter for SO_SNDBUF " +
 353                                           "or SO_RCVBUF");
 354             }
 355             if (value >= maxValue)
 356                 value = maxValue;
 357             break;
 358         case SO_REUSEADDR:
 359             if (val == null || !(val instanceof Boolean))
 360                 throw new SocketException("bad parameter for SO_REUSEADDR");
 361             on = ((Boolean)val).booleanValue();
 362             if (serverSocket != null && serverSocket.isBound())
 363                     throw new UnsupportedOperationException(
 364                             "RDMA server socket cannot set " +
 365                             "SO_REUSEADDR after bind.");
 366             if (socket != null && socket.isConnected())
 367                     throw new UnsupportedOperationException(
 368                             "RDMA socket cannot set " +
 369                             "SO_REUSEADDR after connect.");
 370             break;
 371         default:
 372             throw new SocketException("unrecognized TCP option: " + opt);
 373         }
 374         socketSetOption(opt, on, val);
 375     }
 376 
 377     public Object getOption(int opt) throws SocketException {
 378         if (isClosedOrPending()) {
 379             throw new SocketException("Socket Closed");
 380         }
 381         if (opt == SO_TIMEOUT) {
 382             return timeout;
 383         }
 384         int ret = 0;
 385 
 386         switch (opt) {
 387         case TCP_NODELAY:
 388             ret = platformRdmaSocketImpl.rdmaSocketGetOption(this, opt, null);
 389             return Boolean.valueOf(ret != -1);
 390         case SO_REUSEADDR:
 391             ret = platformRdmaSocketImpl.rdmaSocketGetOption(this, opt, null);
 392             return Boolean.valueOf(ret != -1);
 393         case SO_BINDADDR:
 394             RdmaInetAddressContainer in = new RdmaInetAddressContainer();
 395             ret = platformRdmaSocketImpl.rdmaSocketGetOption(this, opt, in);
 396             return in.addr;
 397         case SO_SNDBUF:
 398         case SO_RCVBUF:
 399             ret = platformRdmaSocketImpl.rdmaSocketGetOption(this, opt, null);
 400             return ret;
 401         default:
 402             return null;
 403         }
 404     }
 405 
 406     protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
 407         if (opt == SocketOptions.SO_REUSEPORT &&
 408             !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
 409             throw new UnsupportedOperationException("unsupported option");
 410         }
 411         try {
 412             platformRdmaSocketImpl.rdmaSocketSetOption(this, opt, b, val);
 413         } catch (SocketException se) {
 414             if (socket == null || !socket.isConnected())
 415                 throw se;
 416         }
 417     }
 418 
 419     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
 420         try {
 421             acquireFD();
 422             try {
 423                 platformRdmaSocketImpl.rdmaSocketConnect(this, address, port, timeout);
 424                 synchronized (fdLock) {
 425                     if (closePending) {
 426                         throw new SocketException ("Socket closed");
 427                     }
 428                 }
 429                 try {
 430                     if (socket != null) {
 431                         sBoundState.setBoolean(socket, true);
 432                         sConnectState.setBoolean(socket, true);
 433                     }
 434                 } catch (IllegalAccessException e) {
 435                     throw new AssertionError(e);
 436                 }
 437             } finally {
 438                 releaseFD();
 439             }
 440         } catch (IOException e) {
 441             close();
 442             throw e;
 443         }
 444     }
 445 
 446     protected synchronized void bind(InetAddress address, int lport)
 447         throws IOException
 448     {
 449         platformRdmaSocketImpl.rdmaSocketBind(this, address, lport);
 450         try {
 451             if (socket != null)
 452                 sBoundState.setBoolean(socket, true);
 453             if (serverSocket != null)
 454                 ssBoundState.setBoolean(serverSocket, true);
 455         } catch (IllegalAccessException e) {
 456             throw new AssertionError(e);
 457         }
 458     }
 459 
 460     protected synchronized void listen(int count) throws IOException {
 461         platformRdmaSocketImpl.rdmaSocketListen(this, count);
 462     }
 463 
 464     protected void accept(SocketImpl s) throws IOException {
 465         acquireFD();
 466         try {
 467             platformRdmaSocketImpl.rdmaSocketAccept(s, this);
 468         } finally {
 469             releaseFD();
 470         }
 471     }
 472 
 473     protected synchronized InputStream getInputStream() throws IOException {
 474         synchronized (fdLock) {
 475             if (isClosedOrPending())
 476                 throw new IOException("Socket Closed");
 477             if (shut_rd)
 478                 throw new IOException("Socket input is shutdown");
 479             if (socketInputStream == null)
 480                 socketInputStream = platformRdmaSocketImpl.getRdmaInputStream(this);
 481         }
 482         return socketInputStream;
 483     }
 484 
 485     protected synchronized OutputStream getOutputStream() throws IOException {
 486         synchronized (fdLock) {
 487             if (isClosedOrPending())
 488                 throw new IOException("Socket Closed");
 489             if (shut_wr)
 490                 throw new IOException("Socket output is shutdown");
 491             if (socketOutputStream == null)
 492                 socketOutputStream = platformRdmaSocketImpl.getRdmaOutputStream(this);
 493         }
 494         return socketOutputStream;
 495     }
 496 
 497     protected FileDescriptor getFileDescriptor() {
 498         return fd;
 499     }
 500 
 501     protected void setFileDescriptor(FileDescriptor fd) {
 502         this.fd = fd;
 503     }
 504 
 505     protected void setAddress(InetAddress address) {
 506         this.address = address;
 507     }
 508 
 509     void setPort(int port) {
 510         this.port = port;
 511     }
 512 
 513     void setLocalPort(int localport) {
 514         this.localport = localport;
 515     }
 516 
 517     protected synchronized int available() throws IOException {
 518         if (isClosedOrPending()) {
 519             throw new IOException("Stream closed.");
 520         }
 521 
 522         if (isConnectionReset() || shut_rd) {
 523             return 0;
 524         }
 525 
 526         int n = 0;
 527         try {
 528             n = platformRdmaSocketImpl.rdmaSocketAvailable(this);
 529             if (n == 0 && isConnectionResetPending()) {
 530                 setConnectionReset();
 531             }
 532         } catch (ConnectionResetException exc1) {
 533             setConnectionResetPending();
 534             try {
 535                 n = platformRdmaSocketImpl.rdmaSocketAvailable(this);
 536                 if (n == 0) {
 537                     setConnectionReset();
 538                 }
 539             } catch (ConnectionResetException exc2) {
 540             }
 541         }
 542         return n;
 543     }
 544 
 545     protected void close() throws IOException {
 546         synchronized(fdLock) {
 547             if (fd != null) {
 548                 if (fdUseCount == 0) {
 549                     if (closePending) {
 550                         return;
 551                     }
 552                     closePending = true;
 553                     try {
 554                         platformRdmaSocketImpl.rdmaSocketClose(true, this);
 555                     } finally {
 556                         platformRdmaSocketImpl.rdmaSocketClose(false, this);
 557                     }
 558                     fd = null;
 559                     return;
 560                 } else {
 561                     if (!closePending) {
 562                         closePending = true;
 563                         fdUseCount--;
 564                         platformRdmaSocketImpl.rdmaSocketClose(true, this);
 565                     }
 566                 }
 567             }
 568         }
 569     }
 570 
 571     void reset() throws IOException {
 572         if (fd != null) {
 573             platformRdmaSocketImpl.rdmaSocketClose(false, this);
 574         }
 575         fd = null;
 576         postReset();
 577     }
 578 
 579     void postReset() throws IOException {
 580         address = null;
 581         port = 0;
 582         localport = 0;
 583     }
 584 
 585     protected void shutdownInput() throws IOException {
 586       if (fd != null) {
 587           platformRdmaSocketImpl.rdmaSocketShutdownInput(SHUT_RD, this, socketInputStream);
 588           shut_rd = true;
 589       }
 590     }
 591 
 592     protected void shutdownOutput() throws IOException {
 593       if (fd != null) {
 594           platformRdmaSocketImpl.rdmaSocketShutdown(SHUT_WR, this);
 595           shut_wr = true;
 596       }
 597     }
 598 
 599     protected boolean supportsUrgentData () {
 600         return true;
 601     }
 602 
 603     protected void sendUrgentData (int data) throws IOException {
 604         if (fd == null) {
 605             throw new IOException("Socket Closed");
 606         }
 607         platformRdmaSocketImpl.rdmaSocketSendUrgentData(this, data);
 608     }
 609 
 610     FileDescriptor acquireFD() {
 611         synchronized (fdLock) {
 612             fdUseCount++;
 613             return fd;
 614         }
 615     }
 616 
 617     void releaseFD() {
 618         synchronized (fdLock) {
 619             fdUseCount--;
 620             if (fdUseCount == -1) {
 621                 if (fd != null) {
 622                     try {
 623                         platformRdmaSocketImpl.rdmaSocketClose(false, this);
 624                     } catch (IOException e) {
 625                     } finally {
 626                         fd = null;
 627                     }
 628                 }
 629             }
 630         }
 631     }
 632 
 633     public boolean isConnectionReset() {
 634         synchronized (resetLock) {
 635             return (resetState == CONNECTION_RESET);
 636         }
 637     }
 638 
 639     public boolean isConnectionResetPending() {
 640         synchronized (resetLock) {
 641             return (resetState == CONNECTION_RESET_PENDING);
 642         }
 643     }
 644 
 645     public void setConnectionReset() {
 646         synchronized (resetLock) {
 647             resetState = CONNECTION_RESET;
 648         }
 649     }
 650 
 651     public void setConnectionResetPending() {
 652         synchronized (resetLock) {
 653             if (resetState == CONNECTION_NOT_RESET) {
 654                 resetState = CONNECTION_RESET_PENDING;
 655             }
 656         }
 657 
 658     }
 659 
 660     public boolean isClosedOrPending() {
 661         synchronized (fdLock) {
 662             if (closePending || (fd == null)) {
 663                 return true;
 664             } else {
 665                 return false;
 666             }
 667         }
 668     }
 669 
 670     public int getTimeout() {
 671         return timeout;
 672     }
 673 
 674     protected InetAddress getInetAddress() {
 675         return address;
 676     }
 677 
 678     protected int getPort() {
 679         return port;
 680     }
 681 
 682     protected int getLocalPort() {
 683         return localport;
 684     }
 685 
 686     public static final int SHUT_RD = 0;
 687     public static final int SHUT_WR = 1;
 688 
 689     static class PlatformRdmaSocketImpl {
 690 
 691         @SuppressWarnings("unchecked")
 692         private static PlatformRdmaSocketImpl newInstance(String cn) {
 693             Class<PlatformRdmaSocketImpl> c;
 694             try {
 695                 c = (Class<PlatformRdmaSocketImpl>)Class.forName(cn);
 696                 return c.getConstructor(new Class<?>[] {}).newInstance();
 697             } catch (ReflectiveOperationException x) {
 698                 throw new AssertionError(x);
 699             }
 700         }
 701 
 702         private static PlatformRdmaSocketImpl create() {
 703             String osname = AccessController.doPrivileged(
 704                     new PrivilegedAction<String>() {
 705                         public String run() {
 706                             return System.getProperty("os.name");
 707                         }
 708                     });
 709             if ("Linux".equals(osname))
 710                 return newInstance("jdk.internal.net.rdma.LinuxRdmaSocketImpl");
 711             return new PlatformRdmaSocketImpl();
 712         }
 713 
 714         private static final PlatformRdmaSocketImpl instance = create();
 715 
 716         static PlatformRdmaSocketImpl get() {
 717             return instance;
 718         }
 719 
 720         boolean isRdmaAvailable() {
 721             return false;
 722         }
 723 
 724         InputStream getRdmaInputStream(RdmaSocketImpl impl) throws IOException {
 725             throw new UnsupportedOperationException("unsupported socket operation");
 726         }
 727 
 728         OutputStream getRdmaOutputStream(RdmaSocketImpl impl) throws IOException {
 729             throw new UnsupportedOperationException("unsupported socket operation");
 730         }
 731 
 732         void rdmaSocketClose(boolean useDeferredClose, RdmaSocketImpl impl) throws IOException {
 733             throw new UnsupportedOperationException("unsupported socket operation");
 734         }
 735 
 736         void rdmaSocketCreate(boolean isServer, RdmaSocketImpl impl) throws IOException {
 737             throw new UnsupportedOperationException("unsupported socket operation");
 738         }
 739 
 740         void rdmaSocketConnect(RdmaSocketImpl impl, InetAddress address, int port, int timeout)
 741             throws IOException {
 742             throw new UnsupportedOperationException("unsupported socket operation");
 743         }
 744 
 745         void rdmaSocketBind(RdmaSocketImpl impl, InetAddress address, int port)
 746             throws IOException {
 747             throw new UnsupportedOperationException("unsupported socket operation");
 748         }
 749 
 750         void rdmaSocketListen(RdmaSocketImpl impl, int count)
 751             throws IOException {
 752             throw new UnsupportedOperationException("unsupported socket operation");
 753         }
 754 
 755         void rdmaSocketAccept(SocketImpl s, RdmaSocketImpl impl)
 756             throws IOException {
 757             throw new UnsupportedOperationException("unsupported socket operation");
 758         }
 759 
 760         int rdmaSocketAvailable(RdmaSocketImpl impl)
 761             throws IOException {
 762             throw new UnsupportedOperationException("unsupported socket operation");
 763         }
 764 
 765         void rdmaSocketShutdown(int howto, RdmaSocketImpl impl)
 766             throws IOException {
 767             throw new UnsupportedOperationException("unsupported socket operation");
 768         }
 769 
 770         void rdmaSocketShutdownInput(int howto, RdmaSocketImpl impl,
 771                 InputStream socketInputStream) throws IOException {
 772             throw new UnsupportedOperationException("unsupported socket operation");
 773         }
 774 
 775         void rdmaSocketSetOption(RdmaSocketImpl impl, int cmd, boolean on, Object value)
 776             throws SocketException {
 777             throw new UnsupportedOperationException("unsupported socket operation");
 778         }
 779 
 780         int rdmaSocketGetOption(RdmaSocketImpl impl, int opt, Object iaContainerObj)
 781             throws SocketException {
 782             throw new UnsupportedOperationException("unsupported socket operation");
 783         }
 784 
 785         void rdmaSocketSendUrgentData(RdmaSocketImpl impl, int data)
 786             throws IOException {
 787             throw new UnsupportedOperationException("unsupported socket operation");
 788         }
 789     }
 790 }