OLD | NEW |
| 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 */ |
1 /* Licensed to the Apache Software Foundation (ASF) under one or more | 16 /* Licensed to the Apache Software Foundation (ASF) under one or more |
2 * contributor license agreements. See the NOTICE file distributed with | 17 * contributor license agreements. See the NOTICE file distributed with |
3 * this work for additional information regarding copyright ownership. | 18 * this work for additional information regarding copyright ownership. |
4 * The ASF licenses this file to You under the Apache License, Version 2.0 | 19 * The ASF licenses this file to You under the Apache License, Version 2.0 |
5 * (the "License"); you may not use this file except in compliance with | 20 * (the "License"); you may not use this file except in compliance with |
6 * the License. You may obtain a copy of the License at | 21 * the License. You may obtain a copy of the License at |
7 * | 22 * |
8 * http://www.apache.org/licenses/LICENSE-2.0 | 23 * http://www.apache.org/licenses/LICENSE-2.0 |
9 * | 24 * |
10 * Unless required by applicable law or agreed to in writing, software | 25 * Unless required by applicable law or agreed to in writing, software |
11 * distributed under the License is distributed on an "AS IS" BASIS, | 26 * distributed under the License is distributed on an "AS IS" BASIS, |
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 27 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 * See the License for the specific language governing permissions and | 28 * See the License for the specific language governing permissions and |
14 * limitations under the License. | 29 * limitations under the License. |
15 */ | 30 */ |
16 | 31 |
17 /* | |
18 * | |
19 * @author Mladen Turk | |
20 * @version $Id: jnilib.c 1666217 2015-03-12 15:03:31Z rjung $ | |
21 */ | |
22 | |
23 #include "tcn.h" | 32 #include "tcn.h" |
24 #include "apr_version.h" | 33 #include "apr_version.h" |
25 #include "apr_file_io.h" | |
26 #include "apr_mmap.h" | |
27 #include "apr_atomic.h" | 34 #include "apr_atomic.h" |
| 35 #include "apr_strings.h" |
28 | 36 |
29 #include "tcn_version.h" | 37 #ifndef TCN_JNI_VERSION |
30 | 38 #define TCN_JNI_VERSION JNI_VERSION_1_4 |
31 #ifdef TCN_DO_STATISTICS | |
32 extern void sp_poll_dump_statistics(); | |
33 extern void sp_network_dump_statistics(); | |
34 extern void ssl_network_dump_statistics(); | |
35 #endif | 39 #endif |
36 | 40 |
37 apr_pool_t *tcn_global_pool = NULL; | 41 apr_pool_t *tcn_global_pool = NULL; |
38 static JavaVM *tcn_global_vm = NULL; | 42 static JavaVM *tcn_global_vm = NULL; |
39 | 43 |
40 static jclass jString_class; | 44 static jclass jString_class; |
41 static jclass jFinfo_class; | |
42 static jclass jAinfo_class; | |
43 static jmethodID jString_init; | 45 static jmethodID jString_init; |
44 static jmethodID jString_getBytes; | 46 static jmethodID jString_getBytes; |
45 | 47 static jclass byteArrayClass; |
46 int tcn_parent_pid = 0; | 48 static jclass keyMaterialClass; |
| 49 static jfieldID keyMaterialCertificateChainFieldId; |
| 50 static jfieldID keyMaterialPrivateKeyFieldId; |
47 | 51 |
48 /* Called by the JVM when APR_JAVA is loaded */ | 52 /* Called by the JVM when APR_JAVA is loaded */ |
49 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) | 53 JNIEXPORT jint JNICALL JNI_OnLoad_netty_tcnative(JavaVM *vm, void *reserved) |
50 { | 54 { |
51 JNIEnv *env; | 55 JNIEnv *env; |
52 apr_version_t apv; | 56 apr_version_t apv; |
53 int apvn; | 57 int apvn; |
54 | 58 |
55 UNREFERENCED(reserved); | 59 UNREFERENCED(reserved); |
56 if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4)) { | 60 if ((*vm)->GetEnv(vm, (void **)&env, TCN_JNI_VERSION)) { |
57 return JNI_ERR; | 61 return JNI_ERR; |
58 } | 62 } |
59 tcn_global_vm = vm; | 63 tcn_global_vm = vm; |
60 | 64 |
61 /* Before doing anything else check if we have a valid | 65 /* Before doing anything else check if we have a valid |
62 * APR version. | 66 * APR version. |
63 */ | 67 */ |
64 apr_version(&apv); | 68 apr_version(&apv); |
65 apvn = apv.major * 1000 + apv.minor * 100 + apv.patch; | 69 apvn = apv.major * 1000 + apv.minor * 100 + apv.patch; |
66 if (apvn < 1201) { | 70 if (apvn < 1201) { |
67 tcn_Throw(env, "Unupported APR version (%s)", | 71 tcn_Throw(env, "Unsupported APR version (%s)", |
68 apr_version_string()); | 72 apr_version_string()); |
69 return JNI_ERR; | 73 return JNI_ERR; |
70 } | 74 } |
71 | 75 |
72 | 76 |
73 /* Initialize global java.lang.String class */ | 77 /* Initialize global java.lang.String class */ |
74 TCN_LOAD_CLASS(env, jString_class, "java/lang/String", JNI_ERR); | 78 TCN_LOAD_CLASS(env, jString_class, "java/lang/String", JNI_ERR); |
75 TCN_LOAD_CLASS(env, jFinfo_class, TCN_FINFO_CLASS, JNI_ERR); | |
76 TCN_LOAD_CLASS(env, jAinfo_class, TCN_AINFO_CLASS, JNI_ERR); | |
77 | 79 |
78 TCN_GET_METHOD(env, jString_class, jString_init, | 80 TCN_GET_METHOD(env, jString_class, jString_init, |
79 "<init>", "([B)V", JNI_ERR); | 81 "<init>", "([B)V", JNI_ERR); |
80 TCN_GET_METHOD(env, jString_class, jString_getBytes, | 82 TCN_GET_METHOD(env, jString_class, jString_getBytes, |
81 "getBytes", "()[B", JNI_ERR); | 83 "getBytes", "()[B", JNI_ERR); |
82 | 84 |
83 if(tcn_load_finfo_class(env, jFinfo_class) != APR_SUCCESS) | 85 // Load the class which makes JNI references available in a static scope bef
ore loading any other classes. |
| 86 if ((*env)->FindClass(env, "io/netty/internal/tcnative/NativeStaticallyRefer
encedJniMethods") == NULL) { |
84 return JNI_ERR; | 87 return JNI_ERR; |
85 if(tcn_load_ainfo_class(env, jAinfo_class) != APR_SUCCESS) | |
86 return JNI_ERR; | |
87 #ifdef WIN32 | |
88 { | |
89 char *ppid = getenv(TCN_PARENT_IDE); | |
90 if (ppid) | |
91 tcn_parent_pid = atoi(ppid); | |
92 } | 88 } |
93 #else | |
94 tcn_parent_pid = getppid(); | |
95 #endif | |
96 | 89 |
97 return JNI_VERSION_1_4; | 90 TCN_LOAD_CLASS(env, byteArrayClass, "[B", JNI_ERR); |
| 91 TCN_LOAD_CLASS(env, keyMaterialClass, "io/netty/internal/tcnative/Certificat
eRequestedCallback$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; |
98 } | 99 } |
99 | 100 |
| 101 /* Called by the JVM when APR_JAVA is loaded */ |
| 102 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) |
| 103 { |
| 104 return JNI_OnLoad_netty_tcnative(vm, reserved); |
| 105 } |
100 | 106 |
101 /* Called by the JVM before the APR_JAVA is unloaded */ | 107 /* Called by the JVM before the APR_JAVA is unloaded */ |
102 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) | 108 JNIEXPORT void JNICALL JNI_OnUnload_netty_tcnative(JavaVM *vm, void *reserved) |
103 { | 109 { |
104 JNIEnv *env; | 110 JNIEnv *env; |
105 | 111 |
106 UNREFERENCED(reserved); | 112 UNREFERENCED(reserved); |
107 | 113 |
108 if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2)) { | 114 if ((*vm)->GetEnv(vm, (void **)&env, TCN_JNI_VERSION)) { |
109 return; | 115 return; |
110 } | 116 } |
111 if (tcn_global_pool) { | 117 if (tcn_global_pool) { |
112 TCN_UNLOAD_CLASS(env, jString_class); | 118 TCN_UNLOAD_CLASS(env, jString_class); |
113 TCN_UNLOAD_CLASS(env, jFinfo_class); | |
114 TCN_UNLOAD_CLASS(env, jAinfo_class); | |
115 apr_terminate(); | 119 apr_terminate(); |
116 } | 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 */ |
| 127 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) |
| 128 { |
| 129 JNI_OnUnload_netty_tcnative(vm, reserved); |
117 } | 130 } |
118 | 131 |
119 jstring tcn_new_stringn(JNIEnv *env, const char *str, size_t l) | 132 jstring tcn_new_stringn(JNIEnv *env, const char *str, size_t l) |
120 { | 133 { |
121 jstring result; | 134 jstring result; |
122 jbyteArray bytes = 0; | 135 jbyteArray bytes = 0; |
123 | 136 |
124 if (!str) | 137 if (!str) |
125 return NULL; | 138 return NULL; |
126 if ((*env)->EnsureLocalCapacity(env, 2) < 0) { | 139 if ((*env)->EnsureLocalCapacity(env, 2) < 0) { |
127 return NULL; /* out of memory error */ | 140 return NULL; /* out of memory error */ |
128 } | 141 } |
129 bytes = (*env)->NewByteArray(env, l); | 142 bytes = (*env)->NewByteArray(env, l); |
130 if (bytes != NULL) { | 143 if (bytes != NULL) { |
131 (*env)->SetByteArrayRegion(env, bytes, 0, l, (jbyte *)str); | 144 (*env)->SetByteArrayRegion(env, bytes, 0, l, (jbyte *)str); |
132 result = (*env)->NewObject(env, jString_class, jString_init, bytes); | 145 result = (*env)->NewObject(env, jString_class, jString_init, bytes); |
133 (*env)->DeleteLocalRef(env, bytes); | 146 (*env)->DeleteLocalRef(env, bytes); |
134 return result; | 147 return result; |
135 } /* else fall through */ | 148 } /* else fall through */ |
136 return NULL; | 149 return NULL; |
137 } | 150 } |
138 | 151 |
139 jbyteArray tcn_new_arrayb(JNIEnv *env, const unsigned char *data, size_t len) | |
140 { | |
141 jbyteArray bytes = (*env)->NewByteArray(env, (jsize)len); | |
142 if (bytes != NULL) { | |
143 (*env)->SetByteArrayRegion(env, bytes, 0, (jint)len, (jbyte *)data); | |
144 } | |
145 return bytes; | |
146 } | |
147 | |
148 jobjectArray tcn_new_arrays(JNIEnv *env, size_t len) | |
149 { | |
150 return (*env)->NewObjectArray(env, (jsize)len, jString_class, NULL); | |
151 } | |
152 | |
153 jstring tcn_new_string(JNIEnv *env, const char *str) | 152 jstring tcn_new_string(JNIEnv *env, const char *str) |
154 { | 153 { |
155 if (!str) | 154 if (!str) |
156 return NULL; | 155 return NULL; |
157 else | 156 else |
158 return (*env)->NewStringUTF(env, str); | 157 return (*env)->NewStringUTF(env, str); |
159 } | 158 } |
160 | 159 |
161 char *tcn_get_string(JNIEnv *env, jstring jstr) | 160 TCN_IMPLEMENT_CALL(jboolean, Library, initialize0)(TCN_STDARGS) |
162 { | |
163 jbyteArray bytes = NULL; | |
164 jthrowable exc; | |
165 char *result = NULL; | |
166 | |
167 if ((*env)->EnsureLocalCapacity(env, 2) < 0) { | |
168 return NULL; /* out of memory error */ | |
169 } | |
170 bytes = (*env)->CallObjectMethod(env, jstr, jString_getBytes); | |
171 exc = (*env)->ExceptionOccurred(env); | |
172 if (!exc) { | |
173 jint len = (*env)->GetArrayLength(env, bytes); | |
174 result = (char *)malloc(len + 1); | |
175 if (result == NULL) { | |
176 TCN_THROW_OS_ERROR(env); | |
177 (*env)->DeleteLocalRef(env, bytes); | |
178 return 0; | |
179 } | |
180 (*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *)result); | |
181 result[len] = '\0'; /* NULL-terminate */ | |
182 } | |
183 else { | |
184 (*env)->DeleteLocalRef(env, exc); | |
185 } | |
186 (*env)->DeleteLocalRef(env, bytes); | |
187 | |
188 return result; | |
189 } | |
190 | |
191 char *tcn_strdup(JNIEnv *env, jstring jstr) | |
192 { | |
193 char *result = NULL; | |
194 const char *cjstr; | |
195 | |
196 cjstr = (const char *)((*env)->GetStringUTFChars(env, jstr, 0)); | |
197 if (cjstr) { | |
198 result = strdup(cjstr); | |
199 (*env)->ReleaseStringUTFChars(env, jstr, cjstr); | |
200 } | |
201 return result; | |
202 } | |
203 | |
204 char *tcn_pstrdup(JNIEnv *env, jstring jstr, apr_pool_t *pool) | |
205 { | |
206 char *result = NULL; | |
207 const char *cjstr; | |
208 | |
209 cjstr = (const char *)((*env)->GetStringUTFChars(env, jstr, 0)); | |
210 if (cjstr) { | |
211 result = apr_pstrdup(pool, cjstr); | |
212 (*env)->ReleaseStringUTFChars(env, jstr, cjstr); | |
213 } | |
214 return result; | |
215 } | |
216 | |
217 TCN_IMPLEMENT_CALL(jboolean, Library, initialize)(TCN_STDARGS) | |
218 { | 161 { |
219 | 162 |
220 UNREFERENCED_STDARGS; | 163 UNREFERENCED_STDARGS; |
221 if (!tcn_global_pool) { | 164 if (!tcn_global_pool) { |
222 apr_initialize(); | 165 apr_initialize(); |
223 if (apr_pool_create(&tcn_global_pool, NULL) != APR_SUCCESS) { | 166 if (apr_pool_create(&tcn_global_pool, NULL) != APR_SUCCESS) { |
224 return JNI_FALSE; | 167 return JNI_FALSE; |
225 } | 168 } |
226 apr_atomic_init(tcn_global_pool); | 169 apr_atomic_init(tcn_global_pool); |
227 } | 170 } |
228 return JNI_TRUE; | 171 return JNI_TRUE; |
229 } | 172 } |
230 | 173 |
231 TCN_IMPLEMENT_CALL(void, Library, terminate)(TCN_STDARGS) | |
232 { | |
233 | |
234 UNREFERENCED_STDARGS; | |
235 if (tcn_global_pool) { | |
236 apr_pool_t *p = tcn_global_pool; | |
237 tcn_global_pool = NULL; | |
238 #ifdef TCN_DO_STATISTICS | |
239 fprintf(stderr, "APR Statistical data ....\n"); | |
240 #endif | |
241 apr_pool_destroy(p); | |
242 #ifdef TCN_DO_STATISTICS | |
243 sp_poll_dump_statistics(); | |
244 sp_network_dump_statistics(); | |
245 ssl_network_dump_statistics(); | |
246 fprintf(stderr, "APR Terminated\n"); | |
247 #endif | |
248 apr_terminate(); | |
249 } | |
250 } | |
251 | |
252 TCN_IMPLEMENT_CALL(jlong, Library, globalPool)(TCN_STDARGS) | |
253 { | |
254 UNREFERENCED_STDARGS; | |
255 return P2J(tcn_global_pool); | |
256 } | |
257 | |
258 TCN_IMPLEMENT_CALL(jint, Library, version)(TCN_STDARGS, jint what) | 174 TCN_IMPLEMENT_CALL(jint, Library, version)(TCN_STDARGS, jint what) |
259 { | 175 { |
260 apr_version_t apv; | 176 apr_version_t apv; |
261 | 177 |
262 UNREFERENCED_STDARGS; | 178 UNREFERENCED_STDARGS; |
263 apr_version(&apv); | 179 apr_version(&apv); |
264 | 180 |
265 switch (what) { | 181 switch (what) { |
266 case 0x01: | |
267 return TCN_MAJOR_VERSION; | |
268 break; | |
269 case 0x02: | |
270 return TCN_MINOR_VERSION; | |
271 break; | |
272 case 0x03: | |
273 return TCN_PATCH_VERSION; | |
274 break; | |
275 case 0x04: | |
276 return TCN_IS_DEV_VERSION; | |
277 break; | |
278 case 0x11: | 182 case 0x11: |
279 return apv.major; | 183 return apv.major; |
280 break; | 184 break; |
281 case 0x12: | 185 case 0x12: |
282 return apv.minor; | 186 return apv.minor; |
283 break; | 187 break; |
284 case 0x13: | 188 case 0x13: |
285 return apv.patch; | 189 return apv.patch; |
286 break; | 190 break; |
287 case 0x14: | 191 case 0x14: |
288 return apv.is_dev; | 192 return apv.is_dev; |
289 break; | 193 break; |
290 } | 194 } |
291 return 0; | 195 return 0; |
292 } | 196 } |
293 | 197 |
294 TCN_IMPLEMENT_CALL(jstring, Library, versionString)(TCN_STDARGS) | |
295 { | |
296 UNREFERENCED(o); | |
297 return AJP_TO_JSTRING(TCN_VERSION_STRING); | |
298 } | |
299 | |
300 TCN_IMPLEMENT_CALL(jstring, Library, aprVersionString)(TCN_STDARGS) | 198 TCN_IMPLEMENT_CALL(jstring, Library, aprVersionString)(TCN_STDARGS) |
301 { | 199 { |
302 UNREFERENCED(o); | 200 UNREFERENCED(o); |
303 return AJP_TO_JSTRING(apr_version_string()); | 201 return AJP_TO_JSTRING(apr_version_string()); |
304 } | 202 } |
305 | 203 |
306 TCN_IMPLEMENT_CALL(jboolean, Library, has)(TCN_STDARGS, jint what) | 204 TCN_IMPLEMENT_CALL(jboolean, Library, has)(TCN_STDARGS, jint what) |
307 { | 205 { |
308 jboolean rv = JNI_FALSE; | 206 jboolean rv = JNI_FALSE; |
309 UNREFERENCED_STDARGS; | 207 UNREFERENCED_STDARGS; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 break; | 309 break; |
412 case 20: | 310 case 20: |
413 #if APR_O_NONBLOCK_INHERITED | 311 #if APR_O_NONBLOCK_INHERITED |
414 rv = JNI_TRUE; | 312 rv = JNI_TRUE; |
415 #endif | 313 #endif |
416 break; | 314 break; |
417 } | 315 } |
418 return rv; | 316 return rv; |
419 } | 317 } |
420 | 318 |
421 TCN_IMPLEMENT_CALL(jint, Library, size)(TCN_STDARGS, jint what) | |
422 { | |
423 | |
424 UNREFERENCED_STDARGS; | |
425 | |
426 switch (what) { | |
427 case 1: | |
428 return APR_SIZEOF_VOIDP; | |
429 break; | |
430 case 2: | |
431 return APR_PATH_MAX; | |
432 break; | |
433 case 3: | |
434 return APRMAXHOSTLEN; | |
435 break; | |
436 case 4: | |
437 return APR_MAX_IOVEC_SIZE; | |
438 break; | |
439 case 5: | |
440 return APR_MAX_SECS_TO_LINGER; | |
441 break; | |
442 case 6: | |
443 return APR_MMAP_THRESHOLD; | |
444 break; | |
445 case 7: | |
446 return APR_MMAP_LIMIT; | |
447 break; | |
448 | |
449 } | |
450 return 0; | |
451 } | |
452 | |
453 apr_pool_t *tcn_get_global_pool() | |
454 { | |
455 if (!tcn_global_pool) { | |
456 if (apr_pool_create(&tcn_global_pool, NULL) != APR_SUCCESS) { | |
457 return NULL; | |
458 } | |
459 apr_atomic_init(tcn_global_pool); | |
460 } | |
461 return tcn_global_pool; | |
462 } | |
463 | |
464 jclass tcn_get_string_class() | 319 jclass tcn_get_string_class() |
465 { | 320 { |
466 return jString_class; | 321 return jString_class; |
467 } | 322 } |
468 | 323 |
469 JavaVM * tcn_get_java_vm() | 324 jclass tcn_get_byte_array_class() |
470 { | 325 { |
471 return tcn_global_vm; | 326 return byteArrayClass; |
| 327 } |
| 328 |
| 329 jfieldID tcn_get_key_material_certificate_chain_field() |
| 330 { |
| 331 return keyMaterialCertificateChainFieldId; |
| 332 } |
| 333 |
| 334 jfieldID tcn_get_key_material_private_key_field() |
| 335 { |
| 336 return keyMaterialPrivateKeyFieldId; |
472 } | 337 } |
473 | 338 |
474 jint tcn_get_java_env(JNIEnv **env) | 339 jint tcn_get_java_env(JNIEnv **env) |
475 { | 340 { |
476 if ((*tcn_global_vm)->GetEnv(tcn_global_vm, (void **)env, | 341 if ((*tcn_global_vm)->GetEnv(tcn_global_vm, (void **)env, |
477 JNI_VERSION_1_4)) { | 342 TCN_JNI_VERSION)) { |
478 return JNI_ERR; | 343 return JNI_ERR; |
479 } | 344 } |
480 return JNI_OK; | 345 return JNI_OK; |
481 } | 346 } |
OLD | NEW |