1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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
17package org.conscrypt;
18
19import java.io.IOException;
20import java.io.InputStream;
21import java.nio.ByteBuffer;
22
23public final class OpenSSLBIOSource {
24    private OpenSSLBIOInputStream source;
25
26    public static OpenSSLBIOSource wrap(ByteBuffer buffer) {
27        return new OpenSSLBIOSource(
28            new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer), false));
29    }
30
31    public OpenSSLBIOSource(OpenSSLBIOInputStream source) {
32        this.source = source;
33    }
34
35    public long getContext() {
36        return source.getBioContext();
37    }
38
39    public synchronized void release() {
40        if (source != null) {
41            NativeCrypto.BIO_free_all(source.getBioContext());
42            source = null;
43        }
44    }
45
46    @Override
47    protected void finalize() throws Throwable {
48        try {
49            release();
50        } finally {
51            super.finalize();
52        }
53    }
54
55    private static class ByteBufferInputStream extends InputStream {
56        private final ByteBuffer source;
57
58        public ByteBufferInputStream(ByteBuffer source) {
59            this.source = source;
60        }
61
62        @Override
63        public int read() throws IOException {
64            if (source.remaining() > 0) {
65                return source.get();
66            } else {
67                return -1;
68            }
69        }
70
71        @Override
72        public int available() throws IOException {
73            return source.limit() - source.position();
74        }
75
76        @Override
77        public int read(byte[] buffer) throws IOException {
78            int originalPosition = source.position();
79            source.get(buffer);
80            return source.position() - originalPosition;
81        }
82
83        @Override
84        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
85            int toRead = Math.min(source.remaining(), byteCount);
86            int originalPosition = source.position();
87            source.get(buffer, byteOffset, toRead);
88            return source.position() - originalPosition;
89        }
90
91        @Override
92        public void reset() throws IOException {
93            source.reset();
94        }
95
96        @Override
97        public long skip(long byteCount) throws IOException {
98            int originalPosition = source.position();
99            source.position((int) (originalPosition + byteCount));
100            return source.position() - originalPosition;
101        }
102    }
103}
104