1 7 8 package java.net; 9 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.OutputStream ; 13 import java.io.InterruptedIOException ; 14 import java.io.FileDescriptor ; 15 import java.io.ByteArrayOutputStream ; 16 17 import sun.net.ConnectionResetException; 18 19 27 class PlainSocketImpl extends SocketImpl 28 { 29 30 int timeout; private int trafficClass; 33 34 private boolean shut_rd = false; 35 private boolean shut_wr = false; 36 37 private SocketInputStream socketInputStream = null; 38 39 40 private int fdUseCount = 0; 41 42 43 private Object fdLock = new Object (); 44 45 46 private boolean closePending = false; 47 48 49 private int CONNECTION_NOT_RESET = 0; 50 private int CONNECTION_RESET_PENDING = 1; 51 private int CONNECTION_RESET = 2; 52 private int resetState; 53 private Object resetLock = new Object (); 54 55 65 private FileDescriptor fd1; 66 71 private InetAddress anyLocalBoundAddr=null; 72 73 76 private int lastfd = -1; 77 78 81 static { 82 java.security.AccessController.doPrivileged( 83 new sun.security.action.LoadLibraryAction("net")); 84 initProto(); 85 } 86 87 90 PlainSocketImpl() { } 91 92 96 PlainSocketImpl(FileDescriptor fd) { 97 this.fd = fd; 98 } 99 100 104 protected synchronized void create(boolean stream) throws IOException { 105 fd = new FileDescriptor (); 106 fd1 = new FileDescriptor (); 107 socketCreate(stream); 108 if (socket != null) 109 socket.setCreated(); 110 if (serverSocket != null) 111 serverSocket.setCreated(); 112 } 113 114 120 protected void connect(String host, int port) 121 throws UnknownHostException , IOException 122 { 123 IOException pending = null; 124 try { 125 InetAddress address = InetAddress.getByName(host); 126 127 try { 128 connectToAddress(address, port, timeout); 129 return; 130 } catch (IOException e) { 131 pending = e; 132 } 133 } catch (UnknownHostException e) { 134 pending = e; 135 } 136 137 close(); 139 throw pending; 140 } 141 142 148 protected void connect(InetAddress address, int port) throws IOException { 149 this.port = port; 150 this.address = address; 151 152 try { 153 connectToAddress(address, port, timeout); 154 return; 155 } catch (IOException e) { 156 close(); 158 throw e; 159 } 160 } 161 162 172 protected void connect(SocketAddress address, int timeout) throws IOException { 173 if (address == null || !(address instanceof InetSocketAddress )) 174 throw new IllegalArgumentException ("unsupported address type"); 175 InetSocketAddress addr = (InetSocketAddress ) address; 176 if (addr.isUnresolved()) 177 throw new UnknownHostException (addr.getHostName()); 178 this.port = addr.getPort(); 179 this.address = addr.getAddress(); 180 181 try { 182 connectToAddress(this.address, port, timeout); 183 return; 184 } catch (IOException e) { 185 close(); 187 throw e; 188 } 189 } 190 191 private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { 192 if (address.isAnyLocalAddress()) { 193 doConnect(InetAddress.getLocalHost(), port, timeout); 194 } else { 195 doConnect(address, port, timeout); 196 } 197 } 198 199 public void setOption(int opt, Object val) throws SocketException { 200 if (isClosedOrPending()) { 201 throw new SocketException ("Socket Closed"); 202 } 203 boolean on = true; 204 switch (opt) { 205 209 case SO_LINGER: 210 if (val == null || (!(val instanceof Integer ) && !(val instanceof Boolean ))) 211 throw new SocketException ("Bad parameter for option"); 212 if (val instanceof Boolean ) { 213 214 on = false; 215 } 216 break; 217 case SO_TIMEOUT: 218 if (val == null || (!(val instanceof Integer ))) 219 throw new SocketException ("Bad parameter for SO_TIMEOUT"); 220 int tmp = ((Integer ) val).intValue(); 221 if (tmp < 0) 222 throw new IllegalArgumentException ("timeout < 0"); 223 timeout = tmp; 224 break; 225 case IP_TOS: 226 if (val == null || !(val instanceof Integer )) { 227 throw new SocketException ("bad argument for IP_TOS"); 228 } 229 trafficClass = ((Integer )val).intValue(); 230 break; 231 case SO_BINDADDR: 232 throw new SocketException ("Cannot re-bind socket"); 233 case TCP_NODELAY: 234 if (val == null || !(val instanceof Boolean )) 235 throw new SocketException ("bad parameter for TCP_NODELAY"); 236 on = ((Boolean )val).booleanValue(); 237 break; 238 case SO_SNDBUF: 239 case SO_RCVBUF: 240 if (val == null || !(val instanceof Integer ) || 241 !(((Integer )val).intValue() > 0)) { 242 throw new SocketException ("bad parameter for SO_SNDBUF " + 243 "or SO_RCVBUF"); 244 } 245 break; 246 case SO_KEEPALIVE: 247 if (val == null || !(val instanceof Boolean )) 248 throw new SocketException ("bad parameter for SO_KEEPALIVE"); 249 on = ((Boolean )val).booleanValue(); 250 break; 251 case SO_OOBINLINE: 252 if (val == null || !(val instanceof Boolean )) 253 throw new SocketException ("bad parameter for SO_OOBINLINE"); 254 on = ((Boolean )val).booleanValue(); 255 break; 256 case SO_REUSEADDR: 257 if (val == null || !(val instanceof Boolean )) 258 throw new SocketException ("bad parameter for SO_REUSEADDR"); 259 on = ((Boolean )val).booleanValue(); 260 break; 261 default: 262 throw new SocketException ("unrecognized TCP option: " + opt); 263 } 264 socketSetOption(opt, on, val); 265 } 266 public Object getOption(int opt) throws SocketException { 267 if (isClosedOrPending()) { 268 throw new SocketException ("Socket Closed"); 269 } 270 if (opt == SO_TIMEOUT) { 271 return new Integer (timeout); 272 } 273 int ret = 0; 274 281 282 switch (opt) { 283 case TCP_NODELAY: 284 ret = socketGetOption(opt, null); 285 return Boolean.valueOf(ret != -1); 286 case SO_OOBINLINE: 287 ret = socketGetOption(opt, null); 288 return Boolean.valueOf(ret != -1); 289 case SO_LINGER: 290 ret = socketGetOption(opt, null); 291 return (ret == -1) ? Boolean.FALSE: (Object )(new Integer (ret)); 292 case SO_REUSEADDR: 293 ret = socketGetOption(opt, null); 294 return Boolean.valueOf(ret != -1); 295 case SO_BINDADDR: 296 if (fd != null && fd1 != null ) { 297 298 return anyLocalBoundAddr; 299 } 300 InetAddressContainer in = new InetAddressContainer(); 301 ret = socketGetOption(opt, in); 302 return in.addr; 303 case SO_SNDBUF: 304 case SO_RCVBUF: 305 ret = socketGetOption(opt, null); 306 return new Integer (ret); 307 case IP_TOS: 308 ret = socketGetOption(opt, null); 309 if (ret == -1) { return new Integer (trafficClass); 311 } else { 312 return new Integer (ret); 313 } 314 case SO_KEEPALIVE: 315 ret = socketGetOption(opt, null); 316 return Boolean.valueOf(ret != -1); 317 default: 319 return null; 320 } 321 } 322 323 328 329 private synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { 330 try { 331 FileDescriptor fd = acquireFD(); 332 try { 333 socketConnect(address, port, timeout); 334 if (socket != null) { 339 socket.setBound(); 340 socket.setConnected(); 341 } 342 } finally { 343 releaseFD(); 344 } 345 } catch (IOException e) { 346 close(); 347 throw e; 348 } 349 } 350 351 356 protected synchronized void bind(InetAddress address, int lport) 357 throws IOException 358 { 359 socketBind(address, lport); 360 if (socket != null) 361 socket.setBound(); 362 if (serverSocket != null) 363 serverSocket.setBound(); 364 if (address.isAnyLocalAddress()) { 365 anyLocalBoundAddr = address; 366 } 367 } 368 369 373 protected synchronized void listen(int count) throws IOException { 374 socketListen(count); 375 } 376 377 381 protected synchronized void accept(SocketImpl s) throws IOException { 382 FileDescriptor fd = acquireFD(); 383 try { 384 socketAccept(s); 385 } finally { 386 releaseFD(); 387 } 388 } 389 390 393 protected synchronized InputStream getInputStream() throws IOException { 394 if (isClosedOrPending()) { 395 throw new IOException ("Socket Closed"); 396 } 397 if (shut_rd) { 398 throw new IOException ("Socket input is shutdown"); 399 } 400 if (socketInputStream == null) { 401 socketInputStream = new SocketInputStream (this); 402 } 403 return socketInputStream; 404 } 405 406 void setInputStream(SocketInputStream in) { 407 socketInputStream = in; 408 } 409 410 413 protected synchronized OutputStream getOutputStream() throws IOException { 414 if (isClosedOrPending()) { 415 throw new IOException ("Socket Closed"); 416 } 417 if (shut_wr) { 418 throw new IOException ("Socket output is shutdown"); 419 } 420 return new SocketOutputStream (this); 421 } 422 423 426 protected synchronized int available() throws IOException { 427 if (isClosedOrPending()) { 428 throw new IOException ("Stream closed."); 429 } 430 431 435 if (isConnectionReset()) { 436 return 0; 437 } 438 439 446 int n = 0; 447 try { 448 n = socketAvailable(); 449 if (n == 0 && isConnectionResetPending()) { 450 setConnectionReset(); 451 } 452 } catch (ConnectionResetException exc1) { 453 setConnectionResetPending(); 454 try { 455 n = socketAvailable(); 456 if (n == 0) { 457 setConnectionReset(); 458 } 459 } catch (ConnectionResetException exc2) { 460 } 461 } 462 return n; 463 } 464 465 468 protected void close() throws IOException { 469 synchronized(fdLock) { 470 if (fd != null || fd1 != null) { 471 if (fdUseCount == 0) { 472 if (closePending) { 473 return; 474 } 475 closePending = true; 476 484 try { 485 socketPreClose(); 486 } finally { 487 socketClose(); 488 } 489 fd = null; 490 fd1 = null; 491 return; 492 } else { 493 499 if (!closePending) { 500 closePending = true; 501 fdUseCount--; 502 socketPreClose(); 503 } 504 } 505 } 506 } 507 } 508 509 void reset() throws IOException { 510 if (fd != null || fd1 != null) { 511 socketClose(); 512 } 513 fd = null; 514 fd1 = null; 515 super.reset(); 516 } 517 518 519 522 protected void shutdownInput() throws IOException { 523 if (fd != null) { 524 socketShutdown(SHUT_RD); 525 if (socketInputStream != null) { 526 socketInputStream.setEOF(true); 527 } 528 shut_rd = true; 529 } 530 } 531 532 535 protected void shutdownOutput() throws IOException { 536 if (fd != null) { 537 socketShutdown(SHUT_WR); 538 shut_wr = true; 539 } 540 } 541 542 protected boolean supportsUrgentData () { 543 return true; 544 } 545 546 protected void sendUrgentData (int data) throws IOException { 547 if (fd == null) { 548 throw new IOException ("Socket Closed"); 549 } 550 socketSendUrgentData (data); 551 } 552 553 556 protected void finalize() throws IOException { 557 close(); 558 } 559 560 561 567 public final FileDescriptor acquireFD() { 568 synchronized (fdLock) { 569 fdUseCount++; 570 return fd; 571 } 572 } 573 574 579 public final void releaseFD() { 580 synchronized (fdLock) { 581 fdUseCount--; 582 if (fdUseCount == -1) { 583 if (fd != null) { 584 try { 585 socketClose(); 586 } catch (IOException e) { 587 } finally { 588 fd = null; 589 } 590 } 591 } 592 } 593 } 594 595 public boolean isConnectionReset() { 596 synchronized (resetLock) { 597 return (resetState == CONNECTION_RESET); 598 } 599 } 600 601 public boolean isConnectionResetPending() { 602 synchronized (resetLock) { 603 return (resetState == CONNECTION_RESET_PENDING); 604 } 605 } 606 607 public void setConnectionReset() { 608 synchronized (resetLock) { 609 resetState = CONNECTION_RESET; 610 } 611 } 612 613 public void setConnectionResetPending() { 614 synchronized (resetLock) { 615 if (resetState == CONNECTION_NOT_RESET) { 616 resetState = CONNECTION_RESET_PENDING; 617 } 618 } 619 620 } 621 622 625 public boolean isClosedOrPending() { 626 630 synchronized (fdLock) { 631 if (closePending || (fd == null && fd1 == null)) { 632 return true; 633 } else { 634 return false; 635 } 636 } 637 } 638 639 642 public int getTimeout() { 643 return timeout; 644 } 645 646 650 private void socketPreClose() throws IOException { 651 socketClose0(true); 652 } 653 654 657 private void socketClose() throws IOException { 658 socketClose0(false); 659 } 660 661 private native void socketCreate(boolean isServer) throws IOException ; 662 private native void socketConnect(InetAddress address, int port, int timeout) 663 throws IOException ; 664 private native void socketBind(InetAddress address, int port) 665 throws IOException ; 666 private native void socketListen(int count) 667 throws IOException ; 668 private native void socketAccept(SocketImpl s) 669 throws IOException ; 670 private native int socketAvailable() 671 throws IOException ; 672 private native void socketClose0(boolean useDeferredClose) 673 throws IOException ; 674 private native void socketShutdown(int howto) 675 throws IOException ; 676 private static native void initProto(); 677 private native void socketSetOption(int cmd, boolean on, Object value) 678 throws SocketException ; 679 private native int socketGetOption(int opt, Object iaContainerObj) throws SocketException ; 680 private native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException ; 681 private native void socketSendUrgentData(int data) 682 throws IOException ; 683 684 public final static int SHUT_RD = 0; 685 public final static int SHUT_WR = 1; 686 } 687 688 class InetAddressContainer { 689 InetAddress addr; 690 } 691 | Popular Tags |