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(new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer)));
28    }
29
30    public OpenSSLBIOSource(OpenSSLBIOInputStream source) {
31        this.source = source;
32    }
33
34    public long getContext() {
35        return source.getBioContext();
36    }
37
38    public synchronized void release() {
39        if (source != null) {
40            NativeCrypto.BIO_free_all(source.getBioContext());
41            source = null;
42        }
43    }
44
45    @Override
46    protected void finalize() throws Throwable {
47        try {
48            release();
49        } finally {
50            super.finalize();
51        }
52    }
53
54    private static class ByteBufferInputStream extends InputStream {
55        private final ByteBuffer source;
56
57        public ByteBufferInputStream(ByteBuffer source) {
58            this.source = source;
59        }
60
61        @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