1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.net; 28 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.io.OutputStream; 32 import java.io.FileDescriptor; 33 34 import dalvik.annotation.optimization.ReachabilitySensitive; 35 import dalvik.system.BlockGuard; 36 import dalvik.system.CloseGuard; 37 import dalvik.system.SocketTagger; 38 import sun.net.ConnectionResetException; 39 import sun.net.NetHooks; 40 import sun.net.ResourceManager; 41 42 /** 43 * Default Socket Implementation. This implementation does 44 * not implement any security checks. 45 * Note this class should <b>NOT</b> be public. 46 * 47 * @author Steven B. Byrne 48 */ 49 abstract class AbstractPlainSocketImpl extends SocketImpl 50 { 51 /* instance variable for SO_TIMEOUT */ 52 int timeout; // timeout in millisec 53 // Android-removed: traffic class is set through socket. 54 // private int trafficClass; 55 56 private boolean shut_rd = false; 57 private boolean shut_wr = false; 58 59 private SocketInputStream socketInputStream = null; 60 private SocketOutputStream socketOutputStream = null; 61 62 /* number of threads using the FileDescriptor */ 63 protected int fdUseCount = 0; 64 65 /* lock when increment/decrementing fdUseCount */ 66 // Android-added: @ReachabilitySensitive. 67 // Marked mostly because it's used where fd is, and fd isn't declared here. 68 // This adds reachabilityFences where we would if fd were annotated. 69 @ReachabilitySensitive 70 protected final Object fdLock = new Object(); 71 72 /* indicates a close is pending on the file descriptor */ 73 protected boolean closePending = false; 74 75 /* indicates connection reset state */ 76 private int CONNECTION_NOT_RESET = 0; 77 private int CONNECTION_RESET_PENDING = 1; 78 private int CONNECTION_RESET = 2; 79 private int resetState; 80 private final Object resetLock = new Object(); 81 82 /* whether this Socket is a stream (TCP) socket or not (UDP) 83 */ 84 protected boolean stream; 85 86 // BEGIN Android-removed: Android doesn't need to load native net library. 87 /* 88 /** 89 * Load net library into runtime. 90 * 91 static { 92 java.security.AccessController.doPrivileged( 93 new java.security.PrivilegedAction<Void>() { 94 public Void run() { 95 System.loadLibrary("net"); 96 return null; 97 } 98 }); 99 } 100 */ 101 // END Android-removed: Android doesn't need to load native net library. 102 103 // Android-added: logs a warning if socket is not closed. 104 @ReachabilitySensitive 105 private final CloseGuard guard = CloseGuard.get(); 106 107 /** 108 * Creates a socket with a boolean that specifies whether this 109 * is a stream socket (true) or an unconnected UDP socket (false). 110 */ create(boolean stream)111 protected synchronized void create(boolean stream) throws IOException { 112 this.stream = stream; 113 if (!stream) { 114 ResourceManager.beforeUdpCreate(); 115 // Android-removed: socketCreate should set fd if it succeeds. 116 // fd = new FileDescriptor(); 117 try { 118 socketCreate(false); 119 } catch (IOException ioe) { 120 ResourceManager.afterUdpClose(); 121 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 122 // fd = null; 123 throw ioe; 124 } 125 } else { 126 // Android-removed: socketCreate should set fd if it succeeds. 127 // fd = new FileDescriptor(); 128 socketCreate(true); 129 } 130 if (socket != null) 131 socket.setCreated(); 132 if (serverSocket != null) 133 serverSocket.setCreated(); 134 135 // Android-added: CloseGuard. 136 if (fd != null && fd.valid()) { 137 guard.open("close"); 138 } 139 } 140 141 /** 142 * Creates a socket and connects it to the specified port on 143 * the specified host. 144 * @param host the specified host 145 * @param port the specified port 146 */ connect(String host, int port)147 protected void connect(String host, int port) 148 throws UnknownHostException, IOException 149 { 150 boolean connected = false; 151 try { 152 InetAddress address = InetAddress.getByName(host); 153 this.port = port; 154 this.address = address; 155 156 connectToAddress(address, port, timeout); 157 connected = true; 158 } finally { 159 if (!connected) { 160 try { 161 close(); 162 } catch (IOException ioe) { 163 /* Do nothing. If connect threw an exception then 164 it will be passed up the call stack */ 165 } 166 } 167 } 168 } 169 170 /** 171 * Creates a socket and connects it to the specified address on 172 * the specified port. 173 * @param address the address 174 * @param port the specified port 175 */ connect(InetAddress address, int port)176 protected void connect(InetAddress address, int port) throws IOException { 177 this.port = port; 178 this.address = address; 179 180 try { 181 connectToAddress(address, port, timeout); 182 return; 183 } catch (IOException e) { 184 // everything failed 185 close(); 186 throw e; 187 } 188 } 189 190 /** 191 * Creates a socket and connects it to the specified address on 192 * the specified port. 193 * @param address the address 194 * @param timeout the timeout value in milliseconds, or zero for no timeout. 195 * @throws IOException if connection fails 196 * @throws IllegalArgumentException if address is null or is a 197 * SocketAddress subclass not supported by this socket 198 * @since 1.4 199 */ connect(SocketAddress address, int timeout)200 protected void connect(SocketAddress address, int timeout) 201 throws IOException { 202 boolean connected = false; 203 try { 204 if (address == null || !(address instanceof InetSocketAddress)) 205 throw new IllegalArgumentException("unsupported address type"); 206 InetSocketAddress addr = (InetSocketAddress) address; 207 if (addr.isUnresolved()) 208 throw new UnknownHostException(addr.getHostName()); 209 this.port = addr.getPort(); 210 this.address = addr.getAddress(); 211 212 connectToAddress(this.address, port, timeout); 213 connected = true; 214 } finally { 215 if (!connected) { 216 try { 217 close(); 218 } catch (IOException ioe) { 219 /* Do nothing. If connect threw an exception then 220 it will be passed up the call stack */ 221 } 222 } 223 } 224 } 225 connectToAddress(InetAddress address, int port, int timeout)226 private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { 227 if (address.isAnyLocalAddress()) { 228 doConnect(InetAddress.getLocalHost(), port, timeout); 229 } else { 230 doConnect(address, port, timeout); 231 } 232 } 233 setOption(int opt, Object val)234 public void setOption(int opt, Object val) throws SocketException { 235 if (isClosedOrPending()) { 236 throw new SocketException("Socket Closed"); 237 } 238 // BEGIN Android-removed: Logic dealing with value type moved to socketSetOption. 239 /* 240 boolean on = true; 241 switch (opt) { 242 /* check type safety b4 going native. These should never 243 * fail, since only java.Socket* has access to 244 * PlainSocketImpl.setOption(). 245 * 246 case SO_LINGER: 247 if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean))) 248 throw new SocketException("Bad parameter for option"); 249 if (val instanceof Boolean) { 250 /* true only if disabling - enabling should be Integer * 251 on = false; 252 } 253 break; 254 case SO_TIMEOUT: 255 if (val == null || (!(val instanceof Integer))) 256 throw new SocketException("Bad parameter for SO_TIMEOUT"); 257 int tmp = ((Integer) val).intValue(); 258 if (tmp < 0) 259 throw new IllegalArgumentException("timeout < 0"); 260 timeout = tmp; 261 break; 262 case IP_TOS: 263 if (val == null || !(val instanceof Integer)) { 264 throw new SocketException("bad argument for IP_TOS"); 265 } 266 trafficClass = ((Integer)val).intValue(); 267 break; 268 case SO_BINDADDR: 269 throw new SocketException("Cannot re-bind socket"); 270 case TCP_NODELAY: 271 if (val == null || !(val instanceof Boolean)) 272 throw new SocketException("bad parameter for TCP_NODELAY"); 273 on = ((Boolean)val).booleanValue(); 274 break; 275 case SO_SNDBUF: 276 case SO_RCVBUF: 277 if (val == null || !(val instanceof Integer) || 278 !(((Integer)val).intValue() > 0)) { 279 throw new SocketException("bad parameter for SO_SNDBUF " + 280 "or SO_RCVBUF"); 281 } 282 break; 283 case SO_KEEPALIVE: 284 if (val == null || !(val instanceof Boolean)) 285 throw new SocketException("bad parameter for SO_KEEPALIVE"); 286 on = ((Boolean)val).booleanValue(); 287 break; 288 case SO_OOBINLINE: 289 if (val == null || !(val instanceof Boolean)) 290 throw new SocketException("bad parameter for SO_OOBINLINE"); 291 on = ((Boolean)val).booleanValue(); 292 break; 293 case SO_REUSEADDR: 294 if (val == null || !(val instanceof Boolean)) 295 throw new SocketException("bad parameter for SO_REUSEADDR"); 296 on = ((Boolean)val).booleanValue(); 297 break; 298 default: 299 throw new SocketException("unrecognized TCP option: " + opt); 300 } 301 socketSetOption(opt, on, val); 302 */ 303 // END Android-removed: Logic dealing with value type moved to socketSetOption. 304 // Android-added: Keep track of timeout value not handled by socketSetOption. 305 if (opt == SO_TIMEOUT) { 306 timeout = (Integer) val; 307 } 308 socketSetOption(opt, val); 309 } getOption(int opt)310 public Object getOption(int opt) throws SocketException { 311 if (isClosedOrPending()) { 312 throw new SocketException("Socket Closed"); 313 } 314 if (opt == SO_TIMEOUT) { 315 return new Integer(timeout); 316 } 317 // BEGIN Android-changed: Logic dealing with value type moved to socketGetOption. 318 /* 319 int ret = 0; 320 /* 321 * The native socketGetOption() knows about 3 options. 322 * The 32 bit value it returns will be interpreted according 323 * to what we're asking. A return of -1 means it understands 324 * the option but its turned off. It will raise a SocketException 325 * if "opt" isn't one it understands. 326 * 327 328 switch (opt) { 329 case TCP_NODELAY: 330 ret = socketGetOption(opt, null); 331 return Boolean.valueOf(ret != -1); 332 case SO_OOBINLINE: 333 ret = socketGetOption(opt, null); 334 return Boolean.valueOf(ret != -1); 335 case SO_LINGER: 336 ret = socketGetOption(opt, null); 337 return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret)); 338 case SO_REUSEADDR: 339 ret = socketGetOption(opt, null); 340 return Boolean.valueOf(ret != -1); 341 case SO_BINDADDR: 342 InetAddressContainer in = new InetAddressContainer(); 343 ret = socketGetOption(opt, in); 344 return in.addr; 345 case SO_SNDBUF: 346 case SO_RCVBUF: 347 ret = socketGetOption(opt, null); 348 return new Integer(ret); 349 case IP_TOS: 350 try { 351 ret = socketGetOption(opt, null); 352 if (ret == -1) { // ipv6 tos 353 return trafficClass; 354 } else { 355 return ret; 356 } 357 } catch (SocketException se) { 358 // TODO - should make better effort to read TOS or TCLASS 359 return trafficClass; // ipv6 tos 360 } 361 case SO_KEEPALIVE: 362 ret = socketGetOption(opt, null); 363 return Boolean.valueOf(ret != -1); 364 // should never get here 365 default: 366 return null; 367 } 368 */ 369 return socketGetOption(opt); 370 // END Android-changed: Logic dealing with value type moved to socketGetOption. 371 } 372 373 /** 374 * The workhorse of the connection operation. Tries several times to 375 * establish a connection to the given <host, port>. If unsuccessful, 376 * throws an IOException indicating what went wrong. 377 */ 378 doConnect(InetAddress address, int port, int timeout)379 synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { 380 synchronized (fdLock) { 381 if (!closePending && (socket == null || !socket.isBound())) { 382 NetHooks.beforeTcpConnect(fd, address, port); 383 } 384 } 385 try { 386 acquireFD(); 387 try { 388 // Android-added: BlockGuard. 389 BlockGuard.getThreadPolicy().onNetwork(); 390 socketConnect(address, port, timeout); 391 /* socket may have been closed during poll/select */ 392 synchronized (fdLock) { 393 if (closePending) { 394 throw new SocketException ("Socket closed"); 395 } 396 } 397 // If we have a ref. to the Socket, then sets the flags 398 // created, bound & connected to true. 399 // This is normally done in Socket.connect() but some 400 // subclasses of Socket may call impl.connect() directly! 401 if (socket != null) { 402 socket.setBound(); 403 socket.setConnected(); 404 } 405 } finally { 406 releaseFD(); 407 } 408 } catch (IOException e) { 409 close(); 410 throw e; 411 } 412 } 413 414 /** 415 * Binds the socket to the specified address of the specified local port. 416 * @param address the address 417 * @param lport the port 418 */ bind(InetAddress address, int lport)419 protected synchronized void bind(InetAddress address, int lport) 420 throws IOException 421 { 422 synchronized (fdLock) { 423 if (!closePending && (socket == null || !socket.isBound())) { 424 NetHooks.beforeTcpBind(fd, address, lport); 425 } 426 } 427 socketBind(address, lport); 428 if (socket != null) 429 socket.setBound(); 430 if (serverSocket != null) 431 serverSocket.setBound(); 432 } 433 434 /** 435 * Listens, for a specified amount of time, for connections. 436 * @param count the amount of time to listen for connections 437 */ listen(int count)438 protected synchronized void listen(int count) throws IOException { 439 socketListen(count); 440 } 441 442 /** 443 * Accepts connections. 444 * @param s the connection 445 */ accept(SocketImpl s)446 protected void accept(SocketImpl s) throws IOException { 447 acquireFD(); 448 try { 449 // Android-added: BlockGuard. 450 BlockGuard.getThreadPolicy().onNetwork(); 451 socketAccept(s); 452 } finally { 453 releaseFD(); 454 } 455 } 456 457 /** 458 * Gets an InputStream for this socket. 459 */ getInputStream()460 protected synchronized InputStream getInputStream() throws IOException { 461 synchronized (fdLock) { 462 if (isClosedOrPending()) 463 throw new IOException("Socket Closed"); 464 if (shut_rd) 465 throw new IOException("Socket input is shutdown"); 466 if (socketInputStream == null) 467 socketInputStream = new SocketInputStream(this); 468 } 469 return socketInputStream; 470 } 471 setInputStream(SocketInputStream in)472 void setInputStream(SocketInputStream in) { 473 socketInputStream = in; 474 } 475 476 /** 477 * Gets an OutputStream for this socket. 478 */ getOutputStream()479 protected synchronized OutputStream getOutputStream() throws IOException { 480 synchronized (fdLock) { 481 if (isClosedOrPending()) 482 throw new IOException("Socket Closed"); 483 if (shut_wr) 484 throw new IOException("Socket output is shutdown"); 485 if (socketOutputStream == null) 486 socketOutputStream = new SocketOutputStream(this); 487 } 488 return socketOutputStream; 489 } 490 491 // Android-removed: this.fd is maintained by the concrete implementation. 492 /* 493 void setFileDescriptor(FileDescriptor fd) { 494 this.fd = fd; 495 } 496 */ 497 setAddress(InetAddress address)498 void setAddress(InetAddress address) { 499 this.address = address; 500 } 501 setPort(int port)502 void setPort(int port) { 503 this.port = port; 504 } 505 setLocalPort(int localport)506 void setLocalPort(int localport) { 507 this.localport = localport; 508 } 509 510 /** 511 * Returns the number of bytes that can be read without blocking. 512 */ available()513 protected synchronized int available() throws IOException { 514 if (isClosedOrPending()) { 515 throw new IOException("Stream closed."); 516 } 517 518 /* 519 * If connection has been reset or shut down for input, then return 0 520 * to indicate there are no buffered bytes. 521 */ 522 if (isConnectionReset() || shut_rd) { 523 return 0; 524 } 525 526 /* 527 * If no bytes available and we were previously notified 528 * of a connection reset then we move to the reset state. 529 * 530 * If are notified of a connection reset then check 531 * again if there are bytes buffered on the socket. 532 */ 533 int n = 0; 534 try { 535 n = socketAvailable(); 536 if (n == 0 && isConnectionResetPending()) { 537 setConnectionReset(); 538 } 539 } catch (ConnectionResetException exc1) { 540 setConnectionResetPending(); 541 try { 542 n = socketAvailable(); 543 if (n == 0) { 544 setConnectionReset(); 545 } 546 } catch (ConnectionResetException exc2) { 547 } 548 } 549 return n; 550 } 551 552 /** 553 * Closes the socket. 554 */ close()555 protected void close() throws IOException { 556 synchronized(fdLock) { 557 if (fd != null && fd.valid()) { 558 if (!stream) { 559 ResourceManager.afterUdpClose(); 560 } 561 // Android-changed: Socket should be untagged before the preclose. 562 // After preclose, socket will dup2-ed to marker_fd, therefore, it won't describe 563 // the same file. If closingPending is true, then the socket has been preclosed. 564 // 565 // Also, close the CloseGuard when the #close is called. 566 if (!closePending) { 567 closePending = true; 568 guard.close(); 569 570 if (fdUseCount == 0) { 571 /* 572 * We close the FileDescriptor in two-steps - first the 573 * "pre-close" which closes the socket but doesn't 574 * release the underlying file descriptor. This operation 575 * may be lengthy due to untransmitted data and a long 576 * linger interval. Once the pre-close is done we do the 577 * actual socket to release the fd. 578 */ 579 try { 580 socketPreClose(); 581 } finally { 582 socketClose(); 583 } 584 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 585 // socketClose invalidates the fd by closing the fd. 586 // fd = null; 587 return; 588 } else { 589 /* 590 * If a thread has acquired the fd and a close 591 * isn't pending then use a deferred close. 592 * Also decrement fdUseCount to signal the last 593 * thread that releases the fd to close it. 594 */ 595 fdUseCount--; 596 socketPreClose(); 597 } 598 } 599 } 600 } 601 } 602 reset()603 void reset() throws IOException { 604 if (fd != null && fd.valid()) { 605 socketClose(); 606 // Android-changed: Notified the CloseGuard object as the fd has been released. 607 guard.close(); 608 } 609 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 610 // fd = null; 611 super.reset(); 612 } 613 614 615 /** 616 * Shutdown read-half of the socket connection; 617 */ shutdownInput()618 protected void shutdownInput() throws IOException { 619 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 620 if (fd != null && fd.valid()) { 621 socketShutdown(SHUT_RD); 622 if (socketInputStream != null) { 623 socketInputStream.setEOF(true); 624 } 625 shut_rd = true; 626 } 627 } 628 629 /** 630 * Shutdown write-half of the socket connection; 631 */ shutdownOutput()632 protected void shutdownOutput() throws IOException { 633 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 634 if (fd != null && fd.valid()) { 635 socketShutdown(SHUT_WR); 636 shut_wr = true; 637 } 638 } 639 supportsUrgentData()640 protected boolean supportsUrgentData () { 641 return true; 642 } 643 sendUrgentData(int data)644 protected void sendUrgentData (int data) throws IOException { 645 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 646 if (fd == null || !fd.valid()) { 647 throw new IOException("Socket Closed"); 648 } 649 socketSendUrgentData (data); 650 } 651 652 /** 653 * Cleans up if the user forgets to close it. 654 */ finalize()655 protected void finalize() throws IOException { 656 // Android-added: CloseGuard. 657 if (guard != null) { 658 guard.warnIfOpen(); 659 } 660 661 close(); 662 } 663 664 /* 665 * "Acquires" and returns the FileDescriptor for this impl 666 * 667 * A corresponding releaseFD is required to "release" the 668 * FileDescriptor. 669 */ acquireFD()670 FileDescriptor acquireFD() { 671 synchronized (fdLock) { 672 fdUseCount++; 673 return fd; 674 } 675 } 676 677 /* 678 * "Release" the FileDescriptor for this impl. 679 * 680 * If the use count goes to -1 then the socket is closed. 681 */ releaseFD()682 void releaseFD() { 683 synchronized (fdLock) { 684 fdUseCount--; 685 if (fdUseCount == -1) { 686 if (fd != null) { 687 try { 688 socketClose(); 689 } catch (IOException e) { 690 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 691 // socketClose invalidates the fd by closing the fd. 692 // } finally { 693 // fd = null; 694 } 695 } 696 } 697 } 698 } 699 isConnectionReset()700 public boolean isConnectionReset() { 701 synchronized (resetLock) { 702 return (resetState == CONNECTION_RESET); 703 } 704 } 705 isConnectionResetPending()706 public boolean isConnectionResetPending() { 707 synchronized (resetLock) { 708 return (resetState == CONNECTION_RESET_PENDING); 709 } 710 } 711 setConnectionReset()712 public void setConnectionReset() { 713 synchronized (resetLock) { 714 resetState = CONNECTION_RESET; 715 } 716 } 717 setConnectionResetPending()718 public void setConnectionResetPending() { 719 synchronized (resetLock) { 720 if (resetState == CONNECTION_NOT_RESET) { 721 resetState = CONNECTION_RESET_PENDING; 722 } 723 } 724 725 } 726 727 /* 728 * Return true if already closed or close is pending 729 */ isClosedOrPending()730 public boolean isClosedOrPending() { 731 /* 732 * Lock on fdLock to ensure that we wait if a 733 * close is in progress. 734 */ 735 synchronized (fdLock) { 736 // Android-changed: Closed sockets use an invalid fd, not null. b/26470377 737 if (closePending || (fd == null) || !fd.valid()) { 738 return true; 739 } else { 740 return false; 741 } 742 } 743 } 744 745 /* 746 * Return the current value of SO_TIMEOUT 747 */ getTimeout()748 public int getTimeout() { 749 return timeout; 750 } 751 752 /* 753 * "Pre-close" a socket by dup'ing the file descriptor - this enables 754 * the socket to be closed without releasing the file descriptor. 755 */ socketPreClose()756 private void socketPreClose() throws IOException { 757 socketClose0(true); 758 } 759 760 /* 761 * Close the socket (and release the file descriptor). 762 */ socketClose()763 protected void socketClose() throws IOException { 764 socketClose0(false); 765 } 766 socketCreate(boolean isServer)767 abstract void socketCreate(boolean isServer) throws IOException; socketConnect(InetAddress address, int port, int timeout)768 abstract void socketConnect(InetAddress address, int port, int timeout) 769 throws IOException; socketBind(InetAddress address, int port)770 abstract void socketBind(InetAddress address, int port) 771 throws IOException; socketListen(int count)772 abstract void socketListen(int count) 773 throws IOException; socketAccept(SocketImpl s)774 abstract void socketAccept(SocketImpl s) 775 throws IOException; socketAvailable()776 abstract int socketAvailable() 777 throws IOException; socketClose0(boolean useDeferredClose)778 abstract void socketClose0(boolean useDeferredClose) 779 throws IOException; socketShutdown(int howto)780 abstract void socketShutdown(int howto) 781 throws IOException; 782 783 // Android-changed: Method signature changes. 784 // socket{Get,Set}Option work directly with Object values. socketSetOption(int cmd, Object value)785 abstract void socketSetOption(int cmd, Object value) throws SocketException; socketGetOption(int opt)786 abstract Object socketGetOption(int opt) throws SocketException; 787 socketSendUrgentData(int data)788 abstract void socketSendUrgentData(int data) 789 throws IOException; 790 791 public final static int SHUT_RD = 0; 792 public final static int SHUT_WR = 1; 793 } 794