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