56 class ServerSocketChannelImpl |
56 class ServerSocketChannelImpl |
57 extends ServerSocketChannel |
57 extends ServerSocketChannel |
58 implements SelChImpl |
58 implements SelChImpl |
59 { |
59 { |
60 // Used to make native close and configure calls |
60 // Used to make native close and configure calls |
61 private static NativeDispatcher nd; |
61 private static final NativeDispatcher nd = new SocketDispatcher(); |
62 |
62 |
63 // Our file descriptor |
63 // Our file descriptor |
64 private final FileDescriptor fd; |
64 private final FileDescriptor fd; |
65 private final int fdVal; |
65 private final int fdVal; |
66 |
66 |
95 // -- End of fields protected by stateLock |
95 // -- End of fields protected by stateLock |
96 |
96 |
97 |
97 |
98 ServerSocketChannelImpl(SelectorProvider sp) throws IOException { |
98 ServerSocketChannelImpl(SelectorProvider sp) throws IOException { |
99 super(sp); |
99 super(sp); |
100 this.fd = Net.serverSocket(true); |
100 this.fd = Net.serverSocket(true); |
101 this.fdVal = IOUtil.fdVal(fd); |
101 this.fdVal = IOUtil.fdVal(fd); |
102 } |
102 } |
103 |
103 |
104 ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound) |
104 ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound) |
105 throws IOException |
105 throws IOException |
259 } |
259 } |
260 } |
260 } |
261 |
261 |
262 @Override |
262 @Override |
263 public SocketChannel accept() throws IOException { |
263 public SocketChannel accept() throws IOException { |
|
264 int n = 0; |
|
265 FileDescriptor newfd = new FileDescriptor(); |
|
266 InetSocketAddress[] isaa = new InetSocketAddress[1]; |
|
267 |
264 acceptLock.lock(); |
268 acceptLock.lock(); |
265 try { |
269 try { |
266 int n = 0; |
|
267 FileDescriptor newfd = new FileDescriptor(); |
|
268 InetSocketAddress[] isaa = new InetSocketAddress[1]; |
|
269 |
|
270 boolean blocking = isBlocking(); |
270 boolean blocking = isBlocking(); |
271 try { |
271 try { |
272 begin(blocking); |
272 begin(blocking); |
273 do { |
273 do { |
274 n = accept(this.fd, newfd, isaa); |
274 n = Net.accept(this.fd, newfd, isaa); |
275 } while (n == IOStatus.INTERRUPTED && isOpen()); |
275 } while (n == IOStatus.INTERRUPTED && isOpen()); |
276 } finally { |
276 } finally { |
277 end(blocking, n > 0); |
277 end(blocking, n > 0); |
278 assert IOStatus.check(n); |
278 assert IOStatus.check(n); |
279 } |
279 } |
280 |
280 |
281 if (n < 1) |
281 } finally { |
282 return null; |
282 acceptLock.unlock(); |
283 |
283 } |
|
284 |
|
285 if (n < 1) |
|
286 return null; |
|
287 |
|
288 InetSocketAddress isa = isaa[0]; |
|
289 try { |
284 // newly accepted socket is initially in blocking mode |
290 // newly accepted socket is initially in blocking mode |
285 IOUtil.configureBlocking(newfd, true); |
291 IOUtil.configureBlocking(newfd, true); |
286 |
|
287 InetSocketAddress isa = isaa[0]; |
|
288 SocketChannel sc = new SocketChannelImpl(provider(), newfd, isa); |
|
289 |
292 |
290 // check permitted to accept connections from the remote address |
293 // check permitted to accept connections from the remote address |
291 SecurityManager sm = System.getSecurityManager(); |
294 SecurityManager sm = System.getSecurityManager(); |
292 if (sm != null) { |
295 if (sm != null) { |
293 try { |
296 sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort()); |
294 sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort()); |
297 } |
295 } catch (SecurityException x) { |
298 return new SocketChannelImpl(provider(), newfd, isa); |
296 sc.close(); |
299 } catch (Exception e) { |
297 throw x; |
300 nd.close(newfd); |
298 } |
301 throw e; |
299 } |
|
300 return sc; |
|
301 |
|
302 } finally { |
|
303 acceptLock.unlock(); |
|
304 } |
302 } |
305 } |
303 } |
306 |
304 |
307 @Override |
305 @Override |
308 protected void implConfigureBlocking(boolean block) throws IOException { |
306 protected void implConfigureBlocking(boolean block) throws IOException { |
506 } |
504 } |
507 } |
505 } |
508 sb.append(']'); |
506 sb.append(']'); |
509 return sb.toString(); |
507 return sb.toString(); |
510 } |
508 } |
511 |
|
512 /** |
|
513 * Accept a connection on a socket. |
|
514 * |
|
515 * @implNote Wrap native call to allow instrumentation. |
|
516 */ |
|
517 private int accept(FileDescriptor ssfd, |
|
518 FileDescriptor newfd, |
|
519 InetSocketAddress[] isaa) |
|
520 throws IOException |
|
521 { |
|
522 return accept0(ssfd, newfd, isaa); |
|
523 } |
|
524 |
|
525 // -- Native methods -- |
|
526 |
|
527 // Accepts a new connection, setting the given file descriptor to refer to |
|
528 // the new socket and setting isaa[0] to the socket's remote address. |
|
529 // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no |
|
530 // connections are pending) or IOStatus.INTERRUPTED. |
|
531 // |
|
532 private native int accept0(FileDescriptor ssfd, |
|
533 FileDescriptor newfd, |
|
534 InetSocketAddress[] isaa) |
|
535 throws IOException; |
|
536 |
|
537 private static native void initIDs(); |
|
538 |
|
539 static { |
|
540 IOUtil.load(); |
|
541 initIDs(); |
|
542 nd = new SocketDispatcher(); |
|
543 } |
|
544 |
|
545 } |
509 } |