• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #ifndef CONSCRYPT_BIOINPUTSTREAM_H_
18 #define CONSCRYPT_BIOINPUTSTREAM_H_
19 
20 #include <jni.h>
21 #include <openssl/ssl.h>
22 
23 #include "BioStream.h"
24 
25 namespace conscrypt {
26 
27 class BioInputStream : public BioStream {
28 public:
BioInputStream(jobject stream,bool isFinite)29     BioInputStream(jobject stream, bool isFinite) : BioStream(stream), isFinite_(isFinite) {}
30 
read(char * buf,int len)31     int read(char *buf, int len) {
32         return read_internal(buf, len, JniConstants::inputStream_readMethod);
33     }
34 
gets(char * buf,int len)35     int gets(char *buf, int len) {
36         if (len > PEM_LINE_LENGTH) {
37             len = PEM_LINE_LENGTH;
38         }
39 
40         int read = read_internal(buf, len - 1, JniConstants::openSslInputStream_readLineMethod);
41         buf[read] = '\0';
42         JNI_TRACE("BIO::gets \"%s\"", buf);
43         return read;
44     }
45 
isFinite()46     bool isFinite() const {
47         return isFinite_;
48     }
49 
50 private:
51     const bool isFinite_;
52 
read_internal(char * buf,int len,jmethodID method)53     int read_internal(char *buf, int len, jmethodID method) {
54         JNIEnv *env = JniConstants::getJNIEnv();
55         if (env == nullptr) {
56             JNI_TRACE("BioInputStream::read could not get JNIEnv");
57             return -1;
58         }
59 
60         if (env->ExceptionCheck()) {
61             JNI_TRACE("BioInputStream::read called with pending exception");
62             return -1;
63         }
64 
65         ScopedLocalRef<jbyteArray> javaBytes(env, env->NewByteArray(len));
66         if (javaBytes.get() == nullptr) {
67             JNI_TRACE("BioInputStream::read failed call to NewByteArray");
68             return -1;
69         }
70 
71         jint read = env->CallIntMethod(getStream(), method, javaBytes.get());
72         if (env->ExceptionCheck()) {
73             JNI_TRACE("BioInputStream::read failed call to InputStream#read");
74             return -1;
75         }
76 
77         /* Java uses -1 to indicate EOF condition. */
78         if (read == -1) {
79             setEof(true);
80             read = 0;
81         } else if (read > 0) {
82             env->GetByteArrayRegion(javaBytes.get(), 0, read, reinterpret_cast<jbyte *>(buf));
83         }
84 
85         return read;
86     }
87 
88 public:
89     /** Length of PEM-encoded line (64) plus CR plus NUL */
90     static const int PEM_LINE_LENGTH = 66;
91 };
92 
93 }  // namespace conscrypt
94 
95 #endif  // CONSCRYPT_BIOINPUTSTREAM_H_
96