Home | History | Annotate | Download | only in nio
      1 /* Licensed to the Apache Software Foundation (ASF) under one or more
      2  * contributor license agreements.  See the NOTICE file distributed with
      3  * this work for additional information regarding copyright ownership.
      4  * The ASF licenses this file to You under the Apache License, Version 2.0
      5  * (the "License"); you may not use this file except in compliance with
      6  * the License.  You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package java.nio;
     18 
     19 import android.system.ErrnoException;
     20 import java.io.Closeable;
     21 import java.io.FileDescriptor;
     22 import java.io.IOException;
     23 import java.nio.channels.Pipe;
     24 import java.nio.channels.SocketChannel;
     25 import java.nio.channels.spi.SelectorProvider;
     26 import libcore.io.IoUtils;
     27 import libcore.io.Libcore;
     28 import static android.system.OsConstants.*;
     29 
     30 /*
     31  * Implements {@link java.nio.channels.Pipe}.
     32  */
     33 final class PipeImpl extends Pipe {
     34     private final PipeSinkChannel sink;
     35     private final PipeSourceChannel source;
     36 
     37     public PipeImpl(SelectorProvider selectorProvider) throws IOException {
     38         try {
     39             FileDescriptor fd1 = new FileDescriptor();
     40             FileDescriptor fd2 = new FileDescriptor();
     41             Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd1, fd2);
     42 
     43             // It doesn't matter which file descriptor we use for which end;
     44             // they're guaranteed to be indistinguishable.
     45             this.sink = new PipeSinkChannel(selectorProvider, fd1);
     46             this.source = new PipeSourceChannel(selectorProvider, fd2);
     47         } catch (ErrnoException errnoException) {
     48             throw errnoException.rethrowAsIOException();
     49         }
     50     }
     51 
     52     @Override public SinkChannel sink() {
     53         return sink;
     54     }
     55 
     56     @Override public SourceChannel source() {
     57         return source;
     58     }
     59 
     60     private class PipeSourceChannel extends Pipe.SourceChannel implements FileDescriptorChannel {
     61         private final FileDescriptor fd;
     62         private final SocketChannel channel;
     63 
     64         private PipeSourceChannel(SelectorProvider selectorProvider, FileDescriptor fd) throws IOException {
     65             super(selectorProvider);
     66             this.fd = fd;
     67             this.channel = new SocketChannelImpl(selectorProvider, fd);
     68         }
     69 
     70         @Override protected void implCloseSelectableChannel() throws IOException {
     71             channel.close();
     72         }
     73 
     74         @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
     75             IoUtils.setBlocking(getFD(), blocking);
     76         }
     77 
     78         public int read(ByteBuffer buffer) throws IOException {
     79             return channel.read(buffer);
     80         }
     81 
     82         public long read(ByteBuffer[] buffers) throws IOException {
     83             return channel.read(buffers);
     84         }
     85 
     86         public long read(ByteBuffer[] buffers, int offset, int length) throws IOException {
     87             return channel.read(buffers, offset, length);
     88         }
     89 
     90         public FileDescriptor getFD() {
     91             return fd;
     92         }
     93     }
     94 
     95     private class PipeSinkChannel extends Pipe.SinkChannel implements FileDescriptorChannel {
     96         private final FileDescriptor fd;
     97         private final SocketChannel channel;
     98 
     99         private PipeSinkChannel(SelectorProvider selectorProvider, FileDescriptor fd) throws IOException {
    100             super(selectorProvider);
    101             this.fd = fd;
    102             this.channel = new SocketChannelImpl(selectorProvider, fd);
    103         }
    104 
    105         @Override protected void implCloseSelectableChannel() throws IOException {
    106             channel.close();
    107         }
    108 
    109         @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
    110             IoUtils.setBlocking(getFD(), blocking);
    111         }
    112 
    113         public int write(ByteBuffer buffer) throws IOException {
    114             return channel.write(buffer);
    115         }
    116 
    117         public long write(ByteBuffer[] buffers) throws IOException {
    118             return channel.write(buffers);
    119         }
    120 
    121         public long write(ByteBuffer[] buffers, int offset, int length) throws IOException {
    122             return channel.write(buffers, offset, length);
    123         }
    124 
    125         public FileDescriptor getFD() {
    126             return fd;
    127         }
    128     }
    129 }
    130