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 }