Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java
32288 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.lang.reflect.Constructor;28import java.io.FileDescriptor;29import java.io.IOException;30import java.net.InetAddress;31import java.net.InetSocketAddress;32import java.nio.channels.Channel;33import java.nio.channels.SocketChannel;34import java.nio.channels.ServerSocketChannel;35import java.nio.channels.DatagramChannel;36import java.nio.channels.spi.SelectorProvider;3738class InheritedChannel {3940// the "types" of socket returned by soType041private static final int UNKNOWN = -1;42private static final int SOCK_STREAM = 1;43private static final int SOCK_DGRAM = 2;4445// oflag values when opening a file46private static final int O_RDONLY = 0;47private static final int O_WRONLY = 1;48private static final int O_RDWR = 2;4950/*51* In order to "detach" the standard streams we dup them to /dev/null.52* In order to reduce the possibility of an error at close time we53* open /dev/null early - that way we know we won't run out of file54* descriptors at close time. This makes the close operation a55* simple dup2 operation for each of the standard streams.56*/57private static int devnull = -1;5859private static void detachIOStreams() {60try {61dup2(devnull, 0);62dup2(devnull, 1);63dup2(devnull, 2);64} catch (IOException ioe) {65// this shouldn't happen66throw new InternalError(ioe);67}68}6970/*71* Override the implCloseSelectableChannel for each channel type - this72* allows us to "detach" the standard streams after closing and ensures73* that the underlying socket really closes.74*/75public static class InheritedSocketChannelImpl extends SocketChannelImpl {7677InheritedSocketChannelImpl(SelectorProvider sp,78FileDescriptor fd,79InetSocketAddress remote)80throws IOException81{82super(sp, fd, remote);83}8485protected void implCloseSelectableChannel() throws IOException {86super.implCloseSelectableChannel();87detachIOStreams();88}89}9091public static class InheritedServerSocketChannelImpl extends92ServerSocketChannelImpl {9394InheritedServerSocketChannelImpl(SelectorProvider sp,95FileDescriptor fd)96throws IOException97{98super(sp, fd, true);99}100101protected void implCloseSelectableChannel() throws IOException {102super.implCloseSelectableChannel();103detachIOStreams();104}105106}107108public static class InheritedDatagramChannelImpl extends109DatagramChannelImpl {110111InheritedDatagramChannelImpl(SelectorProvider sp,112FileDescriptor fd)113throws IOException114{115super(sp, fd);116}117118protected void implCloseSelectableChannel() throws IOException {119super.implCloseSelectableChannel();120detachIOStreams();121}122}123124/*125* If there's a SecurityManager then check for the appropriate126* RuntimePermission.127*/128private static void checkAccess(Channel c) {129SecurityManager sm = System.getSecurityManager();130if (sm != null) {131sm.checkPermission(132new RuntimePermission("inheritedChannel")133);134}135}136137138/*139* If standard inherited channel is connected to a socket then return a Channel140* of the appropriate type based standard input.141*/142private static Channel createChannel() throws IOException {143144// dup the file descriptor - we do this so that for two reasons :-145// 1. Avoids any timing issues with FileDescriptor.in being closed146// or redirected while we create the channel.147// 2. Allows streams based on file descriptor 0 to co-exist with148// the channel (closing one doesn't impact the other)149150int fdVal = dup(0);151152// Examine the file descriptor - if it's not a socket then we don't153// create a channel so we release the file descriptor.154155int st;156st = soType0(fdVal);157if (st != SOCK_STREAM && st != SOCK_DGRAM) {158close0(fdVal);159return null;160}161162163// Next we create a FileDescriptor for the dup'ed file descriptor164// Have to use reflection and also make assumption on how FD165// is implemented.166167Class paramTypes[] = { int.class };168Constructor<?> ctr = Reflect.lookupConstructor("java.io.FileDescriptor",169paramTypes);170Object args[] = { new Integer(fdVal) };171FileDescriptor fd = (FileDescriptor)Reflect.invoke(ctr, args);172173174// Now create the channel. If the socket is a streams socket then175// we see if tthere is a peer (ie: connected). If so, then we176// create a SocketChannel, otherwise a ServerSocketChannel.177// If the socket is a datagram socket then create a DatagramChannel178179SelectorProvider provider = SelectorProvider.provider();180assert provider instanceof sun.nio.ch.SelectorProviderImpl;181182Channel c;183if (st == SOCK_STREAM) {184InetAddress ia = peerAddress0(fdVal);185if (ia == null) {186c = new InheritedServerSocketChannelImpl(provider, fd);187} else {188int port = peerPort0(fdVal);189assert port > 0;190InetSocketAddress isa = new InetSocketAddress(ia, port);191c = new InheritedSocketChannelImpl(provider, fd, isa);192}193} else {194c = new InheritedDatagramChannelImpl(provider, fd);195}196return c;197}198199private static boolean haveChannel = false;200private static Channel channel = null;201202/*203* Returns a Channel representing the inherited channel if the204* inherited channel is a stream connected to a network socket.205*/206public static synchronized Channel getChannel() throws IOException {207if (devnull < 0) {208devnull = open0("/dev/null", O_RDWR);209}210211// If we don't have the channel try to create it212if (!haveChannel) {213channel = createChannel();214haveChannel = true;215}216217// if there is a channel then do the security check before218// returning it.219if (channel != null) {220checkAccess(channel);221}222return channel;223}224225226// -- Native methods --227228private static native int dup(int fd) throws IOException;229private static native void dup2(int fd, int fd2) throws IOException;230private static native int open0(String path, int oflag) throws IOException;231private static native void close0(int fd) throws IOException;232private static native int soType0(int fd);233private static native InetAddress peerAddress0(int fd);234private static native int peerPort0(int fd);235236static {237IOUtil.load();238}239}240241242