xref: /aosp_15_r20/external/cronet/third_party/netty-tcnative/src/c/jnilib.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /*
2  * Copyright 2016 The Netty Project
3  *
4  * The Netty Project licenses this file to you under the Apache License,
5  * version 2.0 (the "License"); you may not use this file except in compliance
6  * with the License. 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 /* Licensed to the Apache Software Foundation (ASF) under one or more
17  * contributor license agreements.  See the NOTICE file distributed with
18  * this work for additional information regarding copyright ownership.
19  * The ASF licenses this file to You under the Apache License, Version 2.0
20  * (the "License"); you may not use this file except in compliance with
21  * the License.  You may obtain a copy of the License at
22  *
23  *     http://www.apache.org/licenses/LICENSE-2.0
24  *
25  * Unless required by applicable law or agreed to in writing, software
26  * distributed under the License is distributed on an "AS IS" BASIS,
27  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28  * See the License for the specific language governing permissions and
29  * limitations under the License.
30  */
31 
32 #include "tcn.h"
33 #include "apr_version.h"
34 #include "apr_atomic.h"
35 #include "apr_strings.h"
36 
37 #ifndef TCN_JNI_VERSION
38 #define TCN_JNI_VERSION JNI_VERSION_1_4
39 #endif
40 
41 apr_pool_t *tcn_global_pool = NULL;
42 static JavaVM     *tcn_global_vm = NULL;
43 
44 static jclass    jString_class;
45 static jmethodID jString_init;
46 static jmethodID jString_getBytes;
47 static jclass    byteArrayClass;
48 static jclass    keyMaterialClass;
49 static jfieldID  keyMaterialCertificateChainFieldId;
50 static jfieldID  keyMaterialPrivateKeyFieldId;
51 
52 /* Called by the JVM when APR_JAVA is loaded */
JNI_OnLoad_netty_tcnative(JavaVM * vm,void * reserved)53 JNIEXPORT jint JNICALL JNI_OnLoad_netty_tcnative(JavaVM *vm, void *reserved)
54 {
55     JNIEnv *env;
56     apr_version_t apv;
57     int apvn;
58 
59     UNREFERENCED(reserved);
60     if ((*vm)->GetEnv(vm, (void **)&env, TCN_JNI_VERSION)) {
61         return JNI_ERR;
62     }
63     tcn_global_vm = vm;
64 
65     /* Before doing anything else check if we have a valid
66      * APR version.
67      */
68     apr_version(&apv);
69     apvn = apv.major * 1000 + apv.minor * 100 + apv.patch;
70     if (apvn < 1201) {
71         tcn_Throw(env, "Unsupported APR version (%s)",
72                   apr_version_string());
73         return JNI_ERR;
74     }
75 
76 
77     /* Initialize global java.lang.String class */
78     TCN_LOAD_CLASS(env, jString_class, "java/lang/String", JNI_ERR);
79 
80     TCN_GET_METHOD(env, jString_class, jString_init,
81                    "<init>", "([B)V", JNI_ERR);
82     TCN_GET_METHOD(env, jString_class, jString_getBytes,
83                    "getBytes", "()[B", JNI_ERR);
84 
85     // Load the class which makes JNI references available in a static scope before loading any other classes.
86     if ((*env)->FindClass(env, "io/netty/internal/tcnative/NativeStaticallyReferencedJniMethods") == NULL) {
87         return JNI_ERR;
88     }
89 
90     TCN_LOAD_CLASS(env, byteArrayClass, "[B", JNI_ERR);
91     TCN_LOAD_CLASS(env, keyMaterialClass, "io/netty/internal/tcnative/CertificateRequestedCallback$KeyMaterial", JNI_ERR);
92 
93     TCN_GET_FIELD(env, keyMaterialClass, keyMaterialCertificateChainFieldId,
94                    "certificateChain", "J", JNI_ERR);
95     TCN_GET_FIELD(env, keyMaterialClass, keyMaterialPrivateKeyFieldId,
96                    "privateKey", "J", JNI_ERR);
97 
98     return TCN_JNI_VERSION;
99 }
100 
101 /* Called by the JVM when APR_JAVA is loaded */
JNI_OnLoad(JavaVM * vm,void * reserved)102 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
103 {
104   return JNI_OnLoad_netty_tcnative(vm, reserved);
105 }
106 
107 /* Called by the JVM before the APR_JAVA is unloaded */
JNI_OnUnload_netty_tcnative(JavaVM * vm,void * reserved)108 JNIEXPORT void JNICALL JNI_OnUnload_netty_tcnative(JavaVM *vm, void *reserved)
109 {
110     JNIEnv *env;
111 
112     UNREFERENCED(reserved);
113 
114     if ((*vm)->GetEnv(vm, (void **)&env, TCN_JNI_VERSION)) {
115         return;
116     }
117     if (tcn_global_pool) {
118         TCN_UNLOAD_CLASS(env, jString_class);
119         apr_terminate();
120     }
121 
122     TCN_UNLOAD_CLASS(env, byteArrayClass);
123     TCN_UNLOAD_CLASS(env, keyMaterialClass);
124 }
125 
126 /* Called by the JVM before the APR_JAVA is unloaded */
JNI_OnUnload(JavaVM * vm,void * reserved)127 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
128 {
129     JNI_OnUnload_netty_tcnative(vm, reserved);
130 }
131 
tcn_new_stringn(JNIEnv * env,const char * str,size_t l)132 jstring tcn_new_stringn(JNIEnv *env, const char *str, size_t l)
133 {
134     jstring result;
135     jbyteArray bytes = 0;
136 
137     if (!str)
138         return NULL;
139     if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
140         return NULL; /* out of memory error */
141     }
142     bytes = (*env)->NewByteArray(env, l);
143     if (bytes != NULL) {
144         (*env)->SetByteArrayRegion(env, bytes, 0, l, (jbyte *)str);
145         result = (*env)->NewObject(env, jString_class, jString_init, bytes);
146         (*env)->DeleteLocalRef(env, bytes);
147         return result;
148     } /* else fall through */
149     return NULL;
150 }
151 
tcn_new_string(JNIEnv * env,const char * str)152 jstring tcn_new_string(JNIEnv *env, const char *str)
153 {
154     if (!str)
155         return NULL;
156     else
157         return (*env)->NewStringUTF(env, str);
158 }
159 
TCN_IMPLEMENT_CALL(jboolean,Library,initialize0)160 TCN_IMPLEMENT_CALL(jboolean, Library, initialize0)(TCN_STDARGS)
161 {
162 
163     UNREFERENCED_STDARGS;
164     if (!tcn_global_pool) {
165         apr_initialize();
166         if (apr_pool_create(&tcn_global_pool, NULL) != APR_SUCCESS) {
167             return JNI_FALSE;
168         }
169         apr_atomic_init(tcn_global_pool);
170     }
171     return JNI_TRUE;
172 }
173 
TCN_IMPLEMENT_CALL(jint,Library,version)174 TCN_IMPLEMENT_CALL(jint, Library, version)(TCN_STDARGS, jint what)
175 {
176     apr_version_t apv;
177 
178     UNREFERENCED_STDARGS;
179     apr_version(&apv);
180 
181     switch (what) {
182         case 0x11:
183             return apv.major;
184         break;
185         case 0x12:
186             return apv.minor;
187         break;
188         case 0x13:
189             return apv.patch;
190         break;
191         case 0x14:
192             return apv.is_dev;
193         break;
194     }
195     return 0;
196 }
197 
TCN_IMPLEMENT_CALL(jstring,Library,aprVersionString)198 TCN_IMPLEMENT_CALL(jstring, Library, aprVersionString)(TCN_STDARGS)
199 {
200     UNREFERENCED(o);
201     return AJP_TO_JSTRING(apr_version_string());
202 }
203 
TCN_IMPLEMENT_CALL(jboolean,Library,has)204 TCN_IMPLEMENT_CALL(jboolean, Library, has)(TCN_STDARGS, jint what)
205 {
206     jboolean rv = JNI_FALSE;
207     UNREFERENCED_STDARGS;
208     switch (what) {
209         case 0:
210 #if APR_HAVE_IPV6
211             rv = JNI_TRUE;
212 #endif
213         break;
214         case 1:
215 #if APR_HAS_SHARED_MEMORY
216             rv = JNI_TRUE;
217 #endif
218         break;
219         case 2:
220 #if APR_HAS_THREADS
221             rv = JNI_TRUE;
222 #endif
223         break;
224         case 3:
225 #if APR_HAS_SENDFILE
226             rv = JNI_TRUE;
227 #endif
228         break;
229         case 4:
230 #if APR_HAS_MMAP
231             rv = JNI_TRUE;
232 #endif
233         break;
234         case 5:
235 #if APR_HAS_FORK
236             rv = JNI_TRUE;
237 #endif
238         break;
239         case 6:
240 #if APR_HAS_RANDOM
241             rv = JNI_TRUE;
242 #endif
243         break;
244         case 7:
245 #if APR_HAS_OTHER_CHILD
246             rv = JNI_TRUE;
247 #endif
248         break;
249         case 8:
250 #if APR_HAS_DSO
251             rv = JNI_TRUE;
252 #endif
253         break;
254         case 9:
255 #if APR_HAS_SO_ACCEPTFILTER
256             rv = JNI_TRUE;
257 #endif
258         break;
259         case 10:
260 #if APR_HAS_UNICODE_FS
261             rv = JNI_TRUE;
262 #endif
263         break;
264         case 11:
265 #if APR_HAS_PROC_INVOKED
266             rv = JNI_TRUE;
267 #endif
268         break;
269         case 12:
270 #if APR_HAS_USER
271             rv = JNI_TRUE;
272 #endif
273         break;
274         case 13:
275 #if APR_HAS_LARGE_FILES
276             rv = JNI_TRUE;
277 #endif
278         break;
279         case 14:
280 #if APR_HAS_XTHREAD_FILES
281             rv = JNI_TRUE;
282 #endif
283         break;
284         case 15:
285 #if APR_HAS_OS_UUID
286             rv = JNI_TRUE;
287 #endif
288         break;
289         case 16:
290 #if APR_IS_BIGENDIAN
291             rv = JNI_TRUE;
292 #endif
293         break;
294 
295         case 17:
296 #if APR_FILES_AS_SOCKETS
297             rv = JNI_TRUE;
298 #endif
299         break;
300         case 18:
301 #if APR_CHARSET_EBCDIC
302             rv = JNI_TRUE;
303 #endif
304         break;
305         case 19:
306 #if APR_TCP_NODELAY_INHERITED
307             rv = JNI_TRUE;
308 #endif
309         break;
310         case 20:
311 #if APR_O_NONBLOCK_INHERITED
312             rv = JNI_TRUE;
313 #endif
314         break;
315     }
316     return rv;
317 }
318 
tcn_get_string_class()319 jclass tcn_get_string_class()
320 {
321     return jString_class;
322 }
323 
tcn_get_byte_array_class()324 jclass tcn_get_byte_array_class()
325 {
326     return byteArrayClass;
327 }
328 
tcn_get_key_material_certificate_chain_field()329 jfieldID tcn_get_key_material_certificate_chain_field()
330 {
331     return keyMaterialCertificateChainFieldId;
332 }
333 
tcn_get_key_material_private_key_field()334 jfieldID tcn_get_key_material_private_key_field()
335 {
336     return keyMaterialPrivateKeyFieldId;
337 }
338 
tcn_get_java_env(JNIEnv ** env)339 jint tcn_get_java_env(JNIEnv **env)
340 {
341     if ((*tcn_global_vm)->GetEnv(tcn_global_vm, (void **)env,
342                                  TCN_JNI_VERSION)) {
343         return JNI_ERR;
344     }
345     return JNI_OK;
346 }
347