14f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com/*
24f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * Copyright (C) 2014 The Android Open Source Project
34f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com *
44f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * Licensed under the Apache License, Version 2.0 (the "License");
54f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * you may not use this file except in compliance with the License.
64f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * You may obtain a copy of the License at
74f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com *
84f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com *      http://www.apache.org/licenses/LICENSE-2.0
94f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com *
104f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * Unless required by applicable law or agreed to in writing, software
114f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * distributed under the License is distributed on an "AS IS" BASIS,
124f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13721b7f267502e01728d1676cd69765ba28c68dc3vladimirv@gmail.com * See the License for the specific language governing permissions and
144f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com * limitations under the License.
154f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com */
164f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
174f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.compackage org.conscrypt;
184f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
194f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport java.io.IOException;
204f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.comimport java.io.InputStream;
21e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.comimport java.nio.ByteBuffer;
22e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com
23e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.compublic final class OpenSSLBIOSource {
244f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    private OpenSSLBIOInputStream source;
254f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
264f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    public static OpenSSLBIOSource wrap(ByteBuffer buffer) {
274f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        return new OpenSSLBIOSource(new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer)));
284f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    }
294f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
304f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    public OpenSSLBIOSource(OpenSSLBIOInputStream source) {
31e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com        this.source = source;
32e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com    }
33e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com
34e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com    public long getContext() {
35e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com        return source.getBioContext();
36e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com    }
37e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com
38e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com    public synchronized void release() {
39e37888d1534ce97db0afccf53d79b128b914a763daniel@transgaming.com        if (source != null) {
404f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            NativeCrypto.BIO_free_all(source.getBioContext());
414f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            source = null;
424f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        }
434f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    }
444f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
454f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    @Override
464f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    protected void finalize() throws Throwable {
474f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        try {
484f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            release();
494f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        } finally {
504f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            super.finalize();
514f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        }
524f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    }
534f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
544f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com    private static class ByteBufferInputStream extends InputStream {
554f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        private final ByteBuffer source;
564f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com
574f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        public ByteBufferInputStream(ByteBuffer source) {
584f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com            this.source = source;
59779aa2618c1333c034768f3a4ca7826a14753b60shannon.woods@transgaming.com        }
60779aa2618c1333c034768f3a4ca7826a14753b60shannon.woods@transgaming.com
614f39fd99568ce175f04b5ed72062bfed0fa41803daniel@transgaming.com        @Override
62        public int read() throws IOException {
63            if (source.remaining() > 0) {
64                return source.get();
65            } else {
66                return -1;
67            }
68        }
69
70        @Override
71        public int available() throws IOException {
72            return source.limit() - source.position();
73        }
74
75        @Override
76        public int read(byte[] buffer) throws IOException {
77            int originalPosition = source.position();
78            source.get(buffer);
79            return source.position() - originalPosition;
80        }
81
82        @Override
83        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
84            int toRead = Math.min(source.remaining(), byteCount);
85            int originalPosition = source.position();
86            source.get(buffer, byteOffset, toRead);
87            return source.position() - originalPosition;
88        }
89
90        @Override
91        public void reset() throws IOException {
92            source.reset();
93        }
94
95        @Override
96        public long skip(long byteCount) throws IOException {
97            int originalPosition = source.position();
98            source.position((int) (originalPosition + byteCount));
99            return source.position() - originalPosition;
100        }
101    }
102}
103