1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership.
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License.  You may obtain a copy of the License at
7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17ae704b984c10a63883cc366e823d53902d6ac7a9Elliott Hughespackage java.nio;
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
195d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException;
2099a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughesimport java.io.Closeable;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.Pipe;
243218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughesimport java.nio.channels.SocketChannel;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.SelectorProvider;
2699a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughesimport libcore.io.IoUtils;
2741f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughesimport libcore.io.Libcore;
285d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
3199a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes * Implements {@link java.nio.channels.Pipe}.
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectfinal class PipeImpl extends Pipe {
3499a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes    private final PipeSinkChannel sink;
3599a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes    private final PipeSourceChannel source;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
373218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    public PipeImpl(SelectorProvider selectorProvider) throws IOException {
3841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        try {
393218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            FileDescriptor fd1 = new FileDescriptor();
403218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            FileDescriptor fd2 = new FileDescriptor();
413218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd1, fd2);
423218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes
433218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            // It doesn't matter which file descriptor we use for which end;
443218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            // they're guaranteed to be indistinguishable.
453218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            this.sink = new PipeSinkChannel(selectorProvider, fd1);
463218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            this.source = new PipeSourceChannel(selectorProvider, fd2);
4741f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        } catch (ErrnoException errnoException) {
4841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes            throw errnoException.rethrowAsIOException();
4941f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        }
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
5299a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes    @Override public SinkChannel sink() {
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sink;
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5699a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes    @Override public SourceChannel source() {
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return source;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
60d320e321d5567a4ac94b6e5874eda4b1f1189e13Elliott Hughes    private class PipeSourceChannel extends Pipe.SourceChannel implements FileDescriptorChannel {
6199a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        private final FileDescriptor fd;
623218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        private final SocketChannel channel;
6399a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes
643218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        private PipeSourceChannel(SelectorProvider selectorProvider, FileDescriptor fd) throws IOException {
653218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            super(selectorProvider);
6641f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes            this.fd = fd;
673218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            this.channel = new SocketChannelImpl(selectorProvider, fd);
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7099a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        @Override protected void implCloseSelectableChannel() throws IOException {
7199a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            channel.close();
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7499a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
75440ba565fa5384bc23255fbc412f7b97fcbdccd9Elliott Hughes            IoUtils.setBlocking(getFD(), blocking);
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read(ByteBuffer buffer) throws IOException {
7999a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return channel.read(buffer);
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public long read(ByteBuffer[] buffers) throws IOException {
8399a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return channel.read(buffers);
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
8699a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        public long read(ByteBuffer[] buffers, int offset, int length) throws IOException {
8799a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return channel.read(buffers, offset, length);
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public FileDescriptor getFD() {
9199a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return fd;
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
95d320e321d5567a4ac94b6e5874eda4b1f1189e13Elliott Hughes    private class PipeSinkChannel extends Pipe.SinkChannel implements FileDescriptorChannel {
9699a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        private final FileDescriptor fd;
973218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        private final SocketChannel channel;
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
993218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        private PipeSinkChannel(SelectorProvider selectorProvider, FileDescriptor fd) throws IOException {
1003218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            super(selectorProvider);
10141f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes            this.fd = fd;
1023218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes            this.channel = new SocketChannelImpl(selectorProvider, fd);
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10599a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        @Override protected void implCloseSelectableChannel() throws IOException {
10699a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            channel.close();
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10999a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
110440ba565fa5384bc23255fbc412f7b97fcbdccd9Elliott Hughes            IoUtils.setBlocking(getFD(), blocking);
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int write(ByteBuffer buffer) throws IOException {
11499a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return channel.write(buffer);
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public long write(ByteBuffer[] buffers) throws IOException {
11899a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return channel.write(buffers);
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
12199a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes        public long write(ByteBuffer[] buffers, int offset, int length) throws IOException {
12299a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return channel.write(buffers, offset, length);
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public FileDescriptor getFD() {
12699a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughes            return fd;
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
130