Home | History | Annotate | Download | only in conscrypt
      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 
     17 package org.conscrypt;
     18 
     19 import java.io.IOException;
     20 import java.io.InputStream;
     21 import java.nio.ByteBuffer;
     22 
     23 /**
     24  * Wrapped by a BoringSSL BIO to act as a source of bytes.
     25  */
     26 final class OpenSSLBIOSource {
     27     private OpenSSLBIOInputStream source;
     28 
     29     static OpenSSLBIOSource wrap(ByteBuffer buffer) {
     30         return new OpenSSLBIOSource(
     31             new OpenSSLBIOInputStream(new ByteBufferInputStream(buffer), false));
     32     }
     33 
     34     private OpenSSLBIOSource(OpenSSLBIOInputStream source) {
     35         this.source = source;
     36     }
     37 
     38     long getContext() {
     39         return source.getBioContext();
     40     }
     41 
     42     private synchronized void release() {
     43         if (source != null) {
     44             NativeCrypto.BIO_free_all(source.getBioContext());
     45             source = null;
     46         }
     47     }
     48 
     49     @Override
     50     protected void finalize() throws Throwable {
     51         try {
     52             release();
     53         } finally {
     54             super.finalize();
     55         }
     56     }
     57 
     58     private static class ByteBufferInputStream extends InputStream {
     59         private final ByteBuffer source;
     60 
     61         ByteBufferInputStream(ByteBuffer source) {
     62             this.source = source;
     63         }
     64 
     65         @Override
     66         public int read() throws IOException {
     67             if (source.remaining() > 0) {
     68                 return source.get();
     69             } else {
     70                 return -1;
     71             }
     72         }
     73 
     74         @Override
     75         public int available() throws IOException {
     76             return source.limit() - source.position();
     77         }
     78 
     79         @Override
     80         public int read(byte[] buffer) throws IOException {
     81             int originalPosition = source.position();
     82             source.get(buffer);
     83             return source.position() - originalPosition;
     84         }
     85 
     86         @Override
     87         public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
     88             int toRead = Math.min(source.remaining(), byteCount);
     89             int originalPosition = source.position();
     90             source.get(buffer, byteOffset, toRead);
     91             return source.position() - originalPosition;
     92         }
     93 
     94         @Override
     95         public void reset() throws IOException {
     96             source.reset();
     97         }
     98 
     99         @Override
    100         public long skip(long byteCount) throws IOException {
    101             long originalPosition = source.position();
    102             source.position((int) (originalPosition + byteCount));
    103             return source.position() - originalPosition;
    104         }
    105     }
    106 }
    107