387 * 388 * @throws AsynchronousCloseException if the channel was closed asynchronously 389 */ 390 private void endRead(boolean blocking, boolean completed) 391 throws AsynchronousCloseException 392 { 393 if (blocking) { 394 synchronized (stateLock) { 395 readerThread = 0; 396 if (state == ST_CLOSING) { 397 tryFinishClose(); 398 } 399 } 400 // remove hook for Thread.interrupt 401 end(completed); 402 } 403 } 404 405 private SocketAddress sender; // Set by receive0 (## ugh) 406 407 @Override 408 public SocketAddress receive(ByteBuffer dst) throws IOException { 409 if (dst.isReadOnly()) 410 throw new IllegalArgumentException("Read-only buffer"); 411 412 readLock.lock(); 413 try { 414 boolean blocking = isBlocking(); 415 int n = 0; 416 ByteBuffer bb = null; 417 try { 418 SocketAddress remote = beginRead(blocking, false); 419 boolean connected = (remote != null); 420 SecurityManager sm = System.getSecurityManager(); 421 if (connected || (sm == null)) { 422 // connected or no security manager 423 n = receive(fd, dst, connected); 424 if (blocking) { 425 while (IOStatus.okayToRetry(n) && isOpen()) { 426 park(Net.POLLIN); 427 n = receive(fd, dst, connected); 428 } 429 } else if (n == IOStatus.UNAVAILABLE) { 430 return null; 431 } 432 } else { 433 // Cannot receive into user's buffer when running with a 434 // security manager and not connected 435 bb = Util.getTemporaryDirectBuffer(dst.remaining()); 436 for (;;) { 437 n = receive(fd, bb, connected); 438 if (blocking) { 439 while (IOStatus.okayToRetry(n) && isOpen()) { 440 park(Net.POLLIN); 441 n = receive(fd, bb, connected); 442 } 443 } else if (n == IOStatus.UNAVAILABLE) { 444 return null; 445 } 446 InetSocketAddress isa = (InetSocketAddress)sender; 447 try { 448 sm.checkAccept(isa.getAddress().getHostAddress(), 449 isa.getPort()); 450 } catch (SecurityException se) { 451 // Ignore packet 452 bb.clear(); 453 n = 0; 454 continue; 455 } 456 bb.flip(); 457 dst.put(bb); 458 break; 459 } 460 } 461 assert sender != null; 462 return sender; 463 } finally { 464 if (bb != null) 465 Util.releaseTemporaryDirectBuffer(bb); 466 endRead(blocking, n > 0); 467 assert IOStatus.check(n); 468 } 469 } finally { 470 readLock.unlock(); 471 } 472 } 473 474 private int receive(FileDescriptor fd, ByteBuffer dst, boolean connected) 475 throws IOException 476 { 477 int pos = dst.position(); 478 int lim = dst.limit(); 479 assert (pos <= lim); 480 int rem = (pos <= lim ? lim - pos : 0); 481 if (dst instanceof DirectBuffer && rem > 0) 482 return receiveIntoNativeBuffer(fd, dst, rem, pos, connected); 483 484 // Substitute a native buffer. If the supplied buffer is empty 485 // we must instead use a nonempty buffer, otherwise the call 486 // will not block waiting for a datagram on some platforms. | 387 * 388 * @throws AsynchronousCloseException if the channel was closed asynchronously 389 */ 390 private void endRead(boolean blocking, boolean completed) 391 throws AsynchronousCloseException 392 { 393 if (blocking) { 394 synchronized (stateLock) { 395 readerThread = 0; 396 if (state == ST_CLOSING) { 397 tryFinishClose(); 398 } 399 } 400 // remove hook for Thread.interrupt 401 end(completed); 402 } 403 } 404 405 private SocketAddress sender; // Set by receive0 (## ugh) 406 407 private static final int INITIAL = -100; // some unambiguous negative value 408 409 @Override 410 public SocketAddress receive(ByteBuffer dst) throws IOException { 411 if (dst.isReadOnly()) 412 throw new IllegalArgumentException("Read-only buffer"); 413 414 readLock.lock(); 415 try { 416 boolean blocking = isBlocking(); 417 int n = INITIAL; 418 ByteBuffer bb = null; 419 try { 420 SocketAddress remote = beginRead(blocking, false); 421 boolean connected = (remote != null); 422 SecurityManager sm = System.getSecurityManager(); 423 if (connected || (sm == null)) { 424 // connected or no security manager 425 n = receive(fd, dst, connected); 426 if (blocking) { 427 while (IOStatus.okayToRetry(n) && isOpen()) { 428 park(Net.POLLIN); 429 n = receive(fd, dst, connected); 430 } 431 } else if (n == IOStatus.UNAVAILABLE) { 432 return null; 433 } 434 } else { 435 // Cannot receive into user's buffer when running with a 436 // security manager and not connected 437 bb = Util.getTemporaryDirectBuffer(dst.remaining()); 438 for (;;) { 439 n = receive(fd, bb, connected); 440 if (blocking) { 441 while (IOStatus.okayToRetry(n) && isOpen()) { 442 park(Net.POLLIN); 443 n = receive(fd, bb, connected); 444 } 445 } else if (n == IOStatus.UNAVAILABLE) { 446 return null; 447 } 448 InetSocketAddress isa = (InetSocketAddress)sender; 449 try { 450 sm.checkAccept(isa.getAddress().getHostAddress(), 451 isa.getPort()); 452 } catch (SecurityException se) { 453 // Ignore packet 454 bb.clear(); 455 n = INITIAL; 456 continue; 457 } 458 bb.flip(); 459 dst.put(bb); 460 break; 461 } 462 } 463 assert sender != null; 464 return sender; 465 } finally { 466 if (bb != null) 467 Util.releaseTemporaryDirectBuffer(bb); 468 endRead(blocking, n >= 0); 469 assert IOStatus.check(n); 470 } 471 } finally { 472 readLock.unlock(); 473 } 474 } 475 476 private int receive(FileDescriptor fd, ByteBuffer dst, boolean connected) 477 throws IOException 478 { 479 int pos = dst.position(); 480 int lim = dst.limit(); 481 assert (pos <= lim); 482 int rem = (pos <= lim ? lim - pos : 0); 483 if (dst instanceof DirectBuffer && rem > 0) 484 return receiveIntoNativeBuffer(fd, dst, rem, pos, connected); 485 486 // Substitute a native buffer. If the supplied buffer is empty 487 // we must instead use a nonempty buffer, otherwise the call 488 // will not block waiting for a datagram on some platforms. |