1977Smax.romanov@gmail.com 2977Smax.romanov@gmail.com /* 3977Smax.romanov@gmail.com * Copyright (C) NGINX, Inc. 4977Smax.romanov@gmail.com */ 5977Smax.romanov@gmail.com 6977Smax.romanov@gmail.com 7977Smax.romanov@gmail.com #include <jni.h> 8977Smax.romanov@gmail.com 9977Smax.romanov@gmail.com #include <nxt_main.h> 10977Smax.romanov@gmail.com #include <nxt_runtime.h> 11977Smax.romanov@gmail.com #include <nxt_router.h> 12977Smax.romanov@gmail.com #include <nxt_unit.h> 13977Smax.romanov@gmail.com #include <nxt_unit_field.h> 14977Smax.romanov@gmail.com #include <nxt_unit_request.h> 15977Smax.romanov@gmail.com #include <nxt_unit_response.h> 161157Smax.romanov@nginx.com #include <nxt_unit_websocket.h> 17977Smax.romanov@gmail.com 18977Smax.romanov@gmail.com #include <java/nxt_jni.h> 19977Smax.romanov@gmail.com 20977Smax.romanov@gmail.com #include "java/nxt_jni_Thread.h" 21977Smax.romanov@gmail.com #include "java/nxt_jni_Context.h" 22977Smax.romanov@gmail.com #include "java/nxt_jni_Request.h" 23977Smax.romanov@gmail.com #include "java/nxt_jni_Response.h" 24977Smax.romanov@gmail.com #include "java/nxt_jni_InputStream.h" 25977Smax.romanov@gmail.com #include "java/nxt_jni_OutputStream.h" 26977Smax.romanov@gmail.com #include "java/nxt_jni_URLClassLoader.h" 27977Smax.romanov@gmail.com 28977Smax.romanov@gmail.com #include "nxt_jars.h" 29*1532St.nateldemoura@f5.com 30*1532St.nateldemoura@f5.com #include NXT_JAVA_MOUNTS_H 31977Smax.romanov@gmail.com 321488St.nateldemoura@f5.com static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process, 33977Smax.romanov@gmail.com nxt_common_app_conf_t *conf); 341488St.nateldemoura@f5.com static nxt_int_t nxt_java_start(nxt_task_t *task, 351488St.nateldemoura@f5.com nxt_process_data_t *data); 36977Smax.romanov@gmail.com static void nxt_java_request_handler(nxt_unit_request_info_t *req); 371157Smax.romanov@nginx.com static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws); 381157Smax.romanov@nginx.com static void nxt_java_close_handler(nxt_unit_request_info_t *req); 39977Smax.romanov@gmail.com 40977Smax.romanov@gmail.com static uint32_t compat[] = { 41977Smax.romanov@gmail.com NXT_VERNUM, NXT_DEBUG, 42977Smax.romanov@gmail.com }; 43977Smax.romanov@gmail.com 44977Smax.romanov@gmail.com char *nxt_java_modules; 45977Smax.romanov@gmail.com 46977Smax.romanov@gmail.com 47977Smax.romanov@gmail.com #define NXT_STRING(x) _NXT_STRING(x) 48977Smax.romanov@gmail.com #define _NXT_STRING(x) #x 49977Smax.romanov@gmail.com 50977Smax.romanov@gmail.com NXT_EXPORT nxt_app_module_t nxt_app_module = { 51977Smax.romanov@gmail.com sizeof(compat), 52977Smax.romanov@gmail.com compat, 53977Smax.romanov@gmail.com nxt_string("java"), 54977Smax.romanov@gmail.com NXT_STRING(NXT_JAVA_VERSION), 551489St.nateldemoura@f5.com nxt_java_mounts, 561489St.nateldemoura@f5.com nxt_nitems(nxt_java_mounts), 571488St.nateldemoura@f5.com nxt_java_setup, 581488St.nateldemoura@f5.com nxt_java_start, 59977Smax.romanov@gmail.com }; 60977Smax.romanov@gmail.com 61977Smax.romanov@gmail.com typedef struct { 62977Smax.romanov@gmail.com JNIEnv *env; 63977Smax.romanov@gmail.com jobject ctx; 64977Smax.romanov@gmail.com } nxt_java_data_t; 65977Smax.romanov@gmail.com 66977Smax.romanov@gmail.com 67977Smax.romanov@gmail.com static nxt_int_t 681488St.nateldemoura@f5.com nxt_java_setup(nxt_task_t *task, nxt_process_t *process, 691488St.nateldemoura@f5.com nxt_common_app_conf_t *conf) 70977Smax.romanov@gmail.com { 711489St.nateldemoura@f5.com char *path, *relpath, *p, *rootfs; 721489St.nateldemoura@f5.com size_t jars_dir_len, rootfs_len; 73977Smax.romanov@gmail.com const char *unit_jars; 74977Smax.romanov@gmail.com 751489St.nateldemoura@f5.com rootfs = (char *) process->isolation.rootfs; 761489St.nateldemoura@f5.com rootfs_len = 0; 771489St.nateldemoura@f5.com 78977Smax.romanov@gmail.com unit_jars = conf->u.java.unit_jars; 79977Smax.romanov@gmail.com if (unit_jars == NULL) { 801489St.nateldemoura@f5.com if (rootfs != NULL) { 811489St.nateldemoura@f5.com unit_jars = "/"; 821489St.nateldemoura@f5.com } else { 831489St.nateldemoura@f5.com unit_jars = NXT_JARS; 841489St.nateldemoura@f5.com } 85977Smax.romanov@gmail.com } 86977Smax.romanov@gmail.com 871489St.nateldemoura@f5.com relpath = strdup(unit_jars); 881489St.nateldemoura@f5.com if (nxt_slow_path(relpath == NULL)) { 89977Smax.romanov@gmail.com return NXT_ERROR; 90977Smax.romanov@gmail.com } 91977Smax.romanov@gmail.com 921489St.nateldemoura@f5.com if (rootfs != NULL) { 931489St.nateldemoura@f5.com jars_dir_len = strlen(unit_jars); 941489St.nateldemoura@f5.com rootfs_len = strlen(rootfs); 951489St.nateldemoura@f5.com 961489St.nateldemoura@f5.com path = nxt_malloc(jars_dir_len + rootfs_len + 1); 971489St.nateldemoura@f5.com if (nxt_slow_path(path == NULL)) { 981489St.nateldemoura@f5.com free(relpath); 991489St.nateldemoura@f5.com return NXT_ERROR; 1001489St.nateldemoura@f5.com } 1011489St.nateldemoura@f5.com 1021489St.nateldemoura@f5.com p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len); 1031489St.nateldemoura@f5.com p = nxt_cpymem(p, relpath, jars_dir_len); 1041489St.nateldemoura@f5.com *p = '\0'; 1051489St.nateldemoura@f5.com 1061489St.nateldemoura@f5.com free(relpath); 1071489St.nateldemoura@f5.com 1081489St.nateldemoura@f5.com } else { 1091489St.nateldemoura@f5.com path = relpath; 1101489St.nateldemoura@f5.com } 1111489St.nateldemoura@f5.com 1121489St.nateldemoura@f5.com nxt_java_modules = realpath(path, NULL); 1131489St.nateldemoura@f5.com if (nxt_java_modules == NULL) { 1141489St.nateldemoura@f5.com nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno); 1151489St.nateldemoura@f5.com goto free; 1161489St.nateldemoura@f5.com } 1171489St.nateldemoura@f5.com 1181489St.nateldemoura@f5.com if (rootfs != NULL && strlen(path) > rootfs_len) { 1191489St.nateldemoura@f5.com nxt_java_modules = path + rootfs_len; 1201489St.nateldemoura@f5.com } 1211489St.nateldemoura@f5.com 1221489St.nateldemoura@f5.com nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules); 1231489St.nateldemoura@f5.com 124977Smax.romanov@gmail.com return NXT_OK; 1251489St.nateldemoura@f5.com 1261489St.nateldemoura@f5.com free: 1271489St.nateldemoura@f5.com 1281489St.nateldemoura@f5.com nxt_free(path); 1291489St.nateldemoura@f5.com 1301489St.nateldemoura@f5.com return NXT_ERROR; 131977Smax.romanov@gmail.com } 132977Smax.romanov@gmail.com 133977Smax.romanov@gmail.com 134977Smax.romanov@gmail.com static char ** 135977Smax.romanov@gmail.com nxt_java_module_jars(const char *jars[], int jar_count) 136977Smax.romanov@gmail.com { 137977Smax.romanov@gmail.com char **res, *jurl; 1381489St.nateldemoura@f5.com uint8_t pathsep; 139977Smax.romanov@gmail.com nxt_int_t modules_len, jlen, i; 140977Smax.romanov@gmail.com const char **jar; 141977Smax.romanov@gmail.com 142977Smax.romanov@gmail.com res = nxt_malloc(jar_count * sizeof(char*)); 143977Smax.romanov@gmail.com if (res == NULL) { 144977Smax.romanov@gmail.com return NULL; 145977Smax.romanov@gmail.com } 146977Smax.romanov@gmail.com 147977Smax.romanov@gmail.com modules_len = nxt_strlen(nxt_java_modules); 148977Smax.romanov@gmail.com 1491489St.nateldemoura@f5.com pathsep = nxt_java_modules[modules_len - 1] == '/'; 1501489St.nateldemoura@f5.com 151977Smax.romanov@gmail.com for (i = 0, jar = jars; *jar != NULL; jar++) { 1521489St.nateldemoura@f5.com jlen = nxt_length("file:") + modules_len 1531489St.nateldemoura@f5.com + (!pathsep ? nxt_length("/") : 0) 1541489St.nateldemoura@f5.com + nxt_strlen(*jar) + 1; 1551489St.nateldemoura@f5.com 156977Smax.romanov@gmail.com jurl = nxt_malloc(jlen); 157977Smax.romanov@gmail.com if (jurl == NULL) { 158977Smax.romanov@gmail.com return NULL; 159977Smax.romanov@gmail.com } 160977Smax.romanov@gmail.com 161977Smax.romanov@gmail.com res[i++] = jurl; 162977Smax.romanov@gmail.com 163977Smax.romanov@gmail.com jurl = nxt_cpymem(jurl, "file:", nxt_length("file:")); 164977Smax.romanov@gmail.com jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len); 1651489St.nateldemoura@f5.com 1661489St.nateldemoura@f5.com if (!pathsep) { 1671489St.nateldemoura@f5.com *jurl++ = '/'; 1681489St.nateldemoura@f5.com } 1691489St.nateldemoura@f5.com 170977Smax.romanov@gmail.com jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar)); 171977Smax.romanov@gmail.com *jurl++ = '\0'; 172977Smax.romanov@gmail.com } 173977Smax.romanov@gmail.com 174977Smax.romanov@gmail.com return res; 175977Smax.romanov@gmail.com } 176977Smax.romanov@gmail.com 177977Smax.romanov@gmail.com 178977Smax.romanov@gmail.com static nxt_int_t 1791488St.nateldemoura@f5.com nxt_java_start(nxt_task_t *task, nxt_process_data_t *data) 180977Smax.romanov@gmail.com { 1811488St.nateldemoura@f5.com jint rc; 1821488St.nateldemoura@f5.com char *opt, *real_path; 1831488St.nateldemoura@f5.com char **classpath_arr, **unit_jars, **system_jars; 1841488St.nateldemoura@f5.com JavaVM *jvm; 1851488St.nateldemoura@f5.com JNIEnv *env; 1861488St.nateldemoura@f5.com jobject cl, classpath; 1871488St.nateldemoura@f5.com nxt_str_t str; 1881488St.nateldemoura@f5.com nxt_int_t opt_len, real_path_len; 1891488St.nateldemoura@f5.com nxt_uint_t i, unit_jars_count, classpath_count; 1901488St.nateldemoura@f5.com nxt_uint_t system_jars_count; 1911488St.nateldemoura@f5.com JavaVMOption *jvm_opt; 1921488St.nateldemoura@f5.com JavaVMInitArgs jvm_args; 1931488St.nateldemoura@f5.com nxt_unit_ctx_t *ctx; 1941488St.nateldemoura@f5.com nxt_unit_init_t java_init; 1951488St.nateldemoura@f5.com nxt_java_data_t java_data; 1961488St.nateldemoura@f5.com nxt_conf_value_t *value; 1971488St.nateldemoura@f5.com nxt_java_app_conf_t *c; 1981488St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 199977Smax.romanov@gmail.com 200977Smax.romanov@gmail.com //setenv("ASAN_OPTIONS", "handle_segv=0", 1); 201977Smax.romanov@gmail.com 202977Smax.romanov@gmail.com jvm_args.version = JNI_VERSION_1_6; 203977Smax.romanov@gmail.com jvm_args.nOptions = 0; 204977Smax.romanov@gmail.com jvm_args.ignoreUnrecognized = 0; 205977Smax.romanov@gmail.com 2061488St.nateldemoura@f5.com app_conf = data->app; 2071488St.nateldemoura@f5.com c = &app_conf->u.java; 208977Smax.romanov@gmail.com 209977Smax.romanov@gmail.com if (c->options != NULL) { 210977Smax.romanov@gmail.com jvm_args.nOptions += nxt_conf_array_elements_count(c->options); 211977Smax.romanov@gmail.com } 212977Smax.romanov@gmail.com 213977Smax.romanov@gmail.com jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption)); 214977Smax.romanov@gmail.com if (jvm_opt == NULL) { 215977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate jvm_opt"); 216977Smax.romanov@gmail.com return NXT_ERROR; 217977Smax.romanov@gmail.com } 218977Smax.romanov@gmail.com 219977Smax.romanov@gmail.com jvm_args.options = jvm_opt; 220977Smax.romanov@gmail.com 221977Smax.romanov@gmail.com unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1; 222977Smax.romanov@gmail.com 223977Smax.romanov@gmail.com unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count); 224977Smax.romanov@gmail.com if (unit_jars == NULL) { 225977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate buffer for unit_jars array"); 226977Smax.romanov@gmail.com 227977Smax.romanov@gmail.com return NXT_ERROR; 228977Smax.romanov@gmail.com } 229977Smax.romanov@gmail.com 230977Smax.romanov@gmail.com system_jars_count = nxt_nitems(nxt_java_system_jars) - 1; 231977Smax.romanov@gmail.com 232977Smax.romanov@gmail.com system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count); 233977Smax.romanov@gmail.com if (system_jars == NULL) { 234977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate buffer for system_jars array"); 235977Smax.romanov@gmail.com 236977Smax.romanov@gmail.com return NXT_ERROR; 237977Smax.romanov@gmail.com } 238977Smax.romanov@gmail.com 239977Smax.romanov@gmail.com if (c->options != NULL) { 240977Smax.romanov@gmail.com 241977Smax.romanov@gmail.com for (i = 0; /* void */ ; i++) { 242977Smax.romanov@gmail.com value = nxt_conf_get_array_element(c->options, i); 243977Smax.romanov@gmail.com if (value == NULL) { 244977Smax.romanov@gmail.com break; 245977Smax.romanov@gmail.com } 246977Smax.romanov@gmail.com 247977Smax.romanov@gmail.com nxt_conf_get_string(value, &str); 248977Smax.romanov@gmail.com 249977Smax.romanov@gmail.com opt = nxt_malloc(str.length + 1); 250977Smax.romanov@gmail.com if (opt == NULL) { 251977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate jvm_opt"); 252977Smax.romanov@gmail.com return NXT_ERROR; 253977Smax.romanov@gmail.com } 254977Smax.romanov@gmail.com 255977Smax.romanov@gmail.com memcpy(opt, str.start, str.length); 256977Smax.romanov@gmail.com opt[str.length] = '\0'; 257977Smax.romanov@gmail.com 258977Smax.romanov@gmail.com jvm_opt[i].optionString = opt; 259977Smax.romanov@gmail.com } 260977Smax.romanov@gmail.com } 261977Smax.romanov@gmail.com 262977Smax.romanov@gmail.com if (c->classpath != NULL) { 263977Smax.romanov@gmail.com classpath_count = nxt_conf_array_elements_count(c->classpath); 264977Smax.romanov@gmail.com classpath_arr = nxt_malloc(classpath_count * sizeof(char *)); 265977Smax.romanov@gmail.com 266977Smax.romanov@gmail.com for (i = 0; /* void */ ; i++) { 267977Smax.romanov@gmail.com value = nxt_conf_get_array_element(c->classpath, i); 268977Smax.romanov@gmail.com if (value == NULL) { 269977Smax.romanov@gmail.com break; 270977Smax.romanov@gmail.com } 271977Smax.romanov@gmail.com 272977Smax.romanov@gmail.com nxt_conf_get_string(value, &str); 273977Smax.romanov@gmail.com 274977Smax.romanov@gmail.com opt_len = str.length + 1; 275977Smax.romanov@gmail.com 276977Smax.romanov@gmail.com char *sc = memchr(str.start, ':', str.length); 277977Smax.romanov@gmail.com if (sc == NULL && str.start[0] == '/') { 278977Smax.romanov@gmail.com opt_len += nxt_length("file:"); 279977Smax.romanov@gmail.com } 280977Smax.romanov@gmail.com 281977Smax.romanov@gmail.com opt = nxt_malloc(opt_len); 282977Smax.romanov@gmail.com if (opt == NULL) { 283977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate classpath"); 284977Smax.romanov@gmail.com return NXT_ERROR; 285977Smax.romanov@gmail.com } 286977Smax.romanov@gmail.com 287977Smax.romanov@gmail.com if (sc == NULL && str.start[0] != '/') { 288977Smax.romanov@gmail.com nxt_memcpy(opt, str.start, str.length); 289977Smax.romanov@gmail.com opt[str.length] = '\0'; 290977Smax.romanov@gmail.com 291977Smax.romanov@gmail.com real_path = realpath(opt, NULL); 292977Smax.romanov@gmail.com if (real_path == NULL) { 293977Smax.romanov@gmail.com nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno); 294977Smax.romanov@gmail.com return NXT_ERROR; 295977Smax.romanov@gmail.com } 296977Smax.romanov@gmail.com 297977Smax.romanov@gmail.com real_path_len = nxt_strlen(real_path); 298977Smax.romanov@gmail.com 299977Smax.romanov@gmail.com free(opt); 300977Smax.romanov@gmail.com 301977Smax.romanov@gmail.com opt_len = nxt_length("file:") + real_path_len + 1; 302977Smax.romanov@gmail.com 303977Smax.romanov@gmail.com opt = nxt_malloc(opt_len); 304977Smax.romanov@gmail.com if (opt == NULL) { 305977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate classpath"); 306977Smax.romanov@gmail.com return NXT_ERROR; 307977Smax.romanov@gmail.com } 308977Smax.romanov@gmail.com 309977Smax.romanov@gmail.com } else { 310977Smax.romanov@gmail.com real_path = (char *) str.start; /* I love this cast! */ 311977Smax.romanov@gmail.com real_path_len = str.length; 312977Smax.romanov@gmail.com } 313977Smax.romanov@gmail.com 314977Smax.romanov@gmail.com classpath_arr[i] = opt; 315977Smax.romanov@gmail.com 316977Smax.romanov@gmail.com if (sc == NULL) { 317977Smax.romanov@gmail.com opt = nxt_cpymem(opt, "file:", nxt_length("file:")); 318977Smax.romanov@gmail.com } 319977Smax.romanov@gmail.com 320977Smax.romanov@gmail.com opt = nxt_cpymem(opt, real_path, real_path_len); 321977Smax.romanov@gmail.com *opt = '\0'; 322977Smax.romanov@gmail.com } 323977Smax.romanov@gmail.com 324977Smax.romanov@gmail.com } else { 325977Smax.romanov@gmail.com classpath_count = 0; 326977Smax.romanov@gmail.com classpath_arr = NULL; 327977Smax.romanov@gmail.com } 328977Smax.romanov@gmail.com 329977Smax.romanov@gmail.com rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args); 330977Smax.romanov@gmail.com if (rc != JNI_OK) { 331977Smax.romanov@gmail.com nxt_alert(task, "failed to create Java VM: %d", (int) rc); 332977Smax.romanov@gmail.com return NXT_ERROR; 333977Smax.romanov@gmail.com } 334977Smax.romanov@gmail.com 335977Smax.romanov@gmail.com rc = nxt_java_initThread(env); 336977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 337977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initThread() failed"); 338977Smax.romanov@gmail.com goto env_failed; 339977Smax.romanov@gmail.com } 340977Smax.romanov@gmail.com 341977Smax.romanov@gmail.com rc = nxt_java_initURLClassLoader(env); 342977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 343977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initURLClassLoader() failed"); 344977Smax.romanov@gmail.com goto env_failed; 345977Smax.romanov@gmail.com } 346977Smax.romanov@gmail.com 347977Smax.romanov@gmail.com cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars); 348977Smax.romanov@gmail.com if (cl == NULL) { 349977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_newURLClassLoader failed"); 350977Smax.romanov@gmail.com goto env_failed; 351977Smax.romanov@gmail.com } 352977Smax.romanov@gmail.com 353977Smax.romanov@gmail.com nxt_java_setContextClassLoader(env, cl); 354977Smax.romanov@gmail.com 355977Smax.romanov@gmail.com cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl); 356977Smax.romanov@gmail.com if (cl == NULL) { 357977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_newURLClassLoader_parent failed"); 358977Smax.romanov@gmail.com goto env_failed; 359977Smax.romanov@gmail.com } 360977Smax.romanov@gmail.com 361977Smax.romanov@gmail.com nxt_java_setContextClassLoader(env, cl); 362977Smax.romanov@gmail.com 363977Smax.romanov@gmail.com rc = nxt_java_initContext(env, cl); 364977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 365977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initContext() failed"); 366977Smax.romanov@gmail.com goto env_failed; 367977Smax.romanov@gmail.com } 368977Smax.romanov@gmail.com 369977Smax.romanov@gmail.com rc = nxt_java_initRequest(env, cl); 370977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 371977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initRequest() failed"); 372977Smax.romanov@gmail.com goto env_failed; 373977Smax.romanov@gmail.com } 374977Smax.romanov@gmail.com 375977Smax.romanov@gmail.com rc = nxt_java_initResponse(env, cl); 376977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 377977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initResponse() failed"); 378977Smax.romanov@gmail.com goto env_failed; 379977Smax.romanov@gmail.com } 380977Smax.romanov@gmail.com 381977Smax.romanov@gmail.com rc = nxt_java_initInputStream(env, cl); 382977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 383977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initInputStream() failed"); 384977Smax.romanov@gmail.com goto env_failed; 385977Smax.romanov@gmail.com } 386977Smax.romanov@gmail.com 387977Smax.romanov@gmail.com rc = nxt_java_initOutputStream(env, cl); 388977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 389977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initOutputStream() failed"); 390977Smax.romanov@gmail.com goto env_failed; 391977Smax.romanov@gmail.com } 392977Smax.romanov@gmail.com 393977Smax.romanov@gmail.com nxt_java_jni_init(env); 394977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 395977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_jni_init() failed"); 396977Smax.romanov@gmail.com goto env_failed; 397977Smax.romanov@gmail.com } 398977Smax.romanov@gmail.com 399977Smax.romanov@gmail.com classpath = nxt_java_newURLs(env, classpath_count, classpath_arr); 400977Smax.romanov@gmail.com if (classpath == NULL) { 401977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_newURLs failed"); 402977Smax.romanov@gmail.com goto env_failed; 403977Smax.romanov@gmail.com } 404977Smax.romanov@gmail.com 4051488St.nateldemoura@f5.com java_data.env = env; 4061488St.nateldemoura@f5.com java_data.ctx = nxt_java_startContext(env, c->webapp, classpath); 407977Smax.romanov@gmail.com 408977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 409977Smax.romanov@gmail.com nxt_alert(task, "Unhandled exception in application start"); 410977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 411977Smax.romanov@gmail.com return NXT_ERROR; 412977Smax.romanov@gmail.com } 413977Smax.romanov@gmail.com 414977Smax.romanov@gmail.com nxt_unit_default_init(task, &java_init); 415977Smax.romanov@gmail.com 416977Smax.romanov@gmail.com java_init.callbacks.request_handler = nxt_java_request_handler; 4171157Smax.romanov@nginx.com java_init.callbacks.websocket_handler = nxt_java_websocket_handler; 4181157Smax.romanov@nginx.com java_init.callbacks.close_handler = nxt_java_close_handler; 419977Smax.romanov@gmail.com java_init.request_data_size = sizeof(nxt_java_request_data_t); 4201488St.nateldemoura@f5.com java_init.data = &java_data; 4211488St.nateldemoura@f5.com java_init.shm_limit = app_conf->shm_limit; 422977Smax.romanov@gmail.com 423977Smax.romanov@gmail.com ctx = nxt_unit_init(&java_init); 424977Smax.romanov@gmail.com if (nxt_slow_path(ctx == NULL)) { 425977Smax.romanov@gmail.com nxt_alert(task, "nxt_unit_init() failed"); 426977Smax.romanov@gmail.com return NXT_ERROR; 427977Smax.romanov@gmail.com } 428977Smax.romanov@gmail.com 429977Smax.romanov@gmail.com rc = nxt_unit_run(ctx); 430977Smax.romanov@gmail.com if (nxt_slow_path(rc != NXT_UNIT_OK)) { 431977Smax.romanov@gmail.com /* TODO report error */ 432977Smax.romanov@gmail.com } 433977Smax.romanov@gmail.com 4341488St.nateldemoura@f5.com nxt_java_stopContext(env, java_data.ctx); 435977Smax.romanov@gmail.com 436977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 437977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 438977Smax.romanov@gmail.com } 439977Smax.romanov@gmail.com 4401157Smax.romanov@nginx.com nxt_unit_done(ctx); 4411157Smax.romanov@nginx.com 442977Smax.romanov@gmail.com (*jvm)->DestroyJavaVM(jvm); 443977Smax.romanov@gmail.com 444977Smax.romanov@gmail.com exit(0); 445977Smax.romanov@gmail.com 446977Smax.romanov@gmail.com return NXT_OK; 447977Smax.romanov@gmail.com 448977Smax.romanov@gmail.com env_failed: 449977Smax.romanov@gmail.com 450977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 451977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 452977Smax.romanov@gmail.com } 453977Smax.romanov@gmail.com 454977Smax.romanov@gmail.com return NXT_ERROR; 455977Smax.romanov@gmail.com } 456977Smax.romanov@gmail.com 457977Smax.romanov@gmail.com 458977Smax.romanov@gmail.com static void 459977Smax.romanov@gmail.com nxt_java_request_handler(nxt_unit_request_info_t *req) 460977Smax.romanov@gmail.com { 461977Smax.romanov@gmail.com JNIEnv *env; 462977Smax.romanov@gmail.com jobject jreq, jresp; 463977Smax.romanov@gmail.com nxt_java_data_t *java_data; 464977Smax.romanov@gmail.com nxt_java_request_data_t *data; 465977Smax.romanov@gmail.com 466977Smax.romanov@gmail.com java_data = req->unit->data; 467977Smax.romanov@gmail.com env = java_data->env; 468977Smax.romanov@gmail.com data = req->data; 469977Smax.romanov@gmail.com 470977Smax.romanov@gmail.com jreq = nxt_java_newRequest(env, java_data->ctx, req); 471977Smax.romanov@gmail.com if (jreq == NULL) { 472977Smax.romanov@gmail.com nxt_unit_req_alert(req, "failed to create Request instance"); 473977Smax.romanov@gmail.com 474977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 475977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 476977Smax.romanov@gmail.com (*env)->ExceptionClear(env); 477977Smax.romanov@gmail.com } 478977Smax.romanov@gmail.com 479977Smax.romanov@gmail.com nxt_unit_request_done(req, NXT_UNIT_ERROR); 480977Smax.romanov@gmail.com return; 481977Smax.romanov@gmail.com } 482977Smax.romanov@gmail.com 483977Smax.romanov@gmail.com jresp = nxt_java_newResponse(env, req); 484977Smax.romanov@gmail.com if (jresp == NULL) { 485977Smax.romanov@gmail.com nxt_unit_req_alert(req, "failed to create Response instance"); 486977Smax.romanov@gmail.com 487977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 488977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 489977Smax.romanov@gmail.com (*env)->ExceptionClear(env); 490977Smax.romanov@gmail.com } 491977Smax.romanov@gmail.com 492977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, jreq); 493977Smax.romanov@gmail.com 494977Smax.romanov@gmail.com nxt_unit_request_done(req, NXT_UNIT_ERROR); 495977Smax.romanov@gmail.com return; 496977Smax.romanov@gmail.com } 497977Smax.romanov@gmail.com 498977Smax.romanov@gmail.com data->header_size = 10 * 1024; 499977Smax.romanov@gmail.com data->buf_size = 32 * 1024; /* from Jetty */ 500977Smax.romanov@gmail.com data->jreq = jreq; 501977Smax.romanov@gmail.com data->jresp = jresp; 502977Smax.romanov@gmail.com data->buf = NULL; 503977Smax.romanov@gmail.com 504977Smax.romanov@gmail.com nxt_unit_request_group_dup_fields(req); 505977Smax.romanov@gmail.com 506977Smax.romanov@gmail.com nxt_java_service(env, java_data->ctx, jreq, jresp); 507977Smax.romanov@gmail.com 508977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 509977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 510977Smax.romanov@gmail.com (*env)->ExceptionClear(env); 511977Smax.romanov@gmail.com } 512977Smax.romanov@gmail.com 513977Smax.romanov@gmail.com if (!nxt_unit_response_is_init(req)) { 514977Smax.romanov@gmail.com nxt_unit_response_init(req, 200, 0, 0); 515977Smax.romanov@gmail.com } 516977Smax.romanov@gmail.com 517977Smax.romanov@gmail.com if (!nxt_unit_response_is_sent(req)) { 518977Smax.romanov@gmail.com nxt_unit_response_send(req); 519977Smax.romanov@gmail.com } 520977Smax.romanov@gmail.com 521977Smax.romanov@gmail.com if (data->buf != NULL) { 522977Smax.romanov@gmail.com nxt_unit_buf_send(data->buf); 523977Smax.romanov@gmail.com 524977Smax.romanov@gmail.com data->buf = NULL; 525977Smax.romanov@gmail.com } 526977Smax.romanov@gmail.com 5271157Smax.romanov@nginx.com if (nxt_unit_response_is_websocket(req)) { 5281157Smax.romanov@nginx.com data->jreq = (*env)->NewGlobalRef(env, jreq); 5291157Smax.romanov@nginx.com data->jresp = (*env)->NewGlobalRef(env, jresp); 5301157Smax.romanov@nginx.com 5311157Smax.romanov@nginx.com } else { 5321157Smax.romanov@nginx.com nxt_unit_request_done(req, NXT_UNIT_OK); 5331157Smax.romanov@nginx.com } 5341157Smax.romanov@nginx.com 535977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, jresp); 536977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, jreq); 5371157Smax.romanov@nginx.com } 5381157Smax.romanov@nginx.com 5391157Smax.romanov@nginx.com 5401157Smax.romanov@nginx.com static void 5411157Smax.romanov@nginx.com nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws) 5421157Smax.romanov@nginx.com { 5431157Smax.romanov@nginx.com void *b; 5441157Smax.romanov@nginx.com JNIEnv *env; 5451157Smax.romanov@nginx.com jobject jbuf; 5461157Smax.romanov@nginx.com nxt_java_data_t *java_data; 5471157Smax.romanov@nginx.com nxt_java_request_data_t *data; 5481157Smax.romanov@nginx.com 5491157Smax.romanov@nginx.com java_data = ws->req->unit->data; 5501157Smax.romanov@nginx.com env = java_data->env; 5511157Smax.romanov@nginx.com data = ws->req->data; 5521157Smax.romanov@nginx.com 5531157Smax.romanov@nginx.com b = malloc(ws->payload_len); 5541157Smax.romanov@nginx.com if (b != NULL) { 5551157Smax.romanov@nginx.com nxt_unit_websocket_read(ws, b, ws->payload_len); 5561157Smax.romanov@nginx.com 5571157Smax.romanov@nginx.com jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len); 5581157Smax.romanov@nginx.com if (jbuf != NULL) { 5591157Smax.romanov@nginx.com nxt_java_Request_websocket(env, data->jreq, jbuf, 5601157Smax.romanov@nginx.com ws->header->opcode, ws->header->fin); 5611157Smax.romanov@nginx.com 5621157Smax.romanov@nginx.com if ((*env)->ExceptionCheck(env)) { 5631157Smax.romanov@nginx.com (*env)->ExceptionDescribe(env); 5641157Smax.romanov@nginx.com (*env)->ExceptionClear(env); 5651157Smax.romanov@nginx.com } 5661157Smax.romanov@nginx.com 5671157Smax.romanov@nginx.com (*env)->DeleteLocalRef(env, jbuf); 5681157Smax.romanov@nginx.com } 5691157Smax.romanov@nginx.com 5701157Smax.romanov@nginx.com free(b); 5711157Smax.romanov@nginx.com } 5721157Smax.romanov@nginx.com 5731157Smax.romanov@nginx.com nxt_unit_websocket_done(ws); 5741157Smax.romanov@nginx.com } 5751157Smax.romanov@nginx.com 5761157Smax.romanov@nginx.com 5771157Smax.romanov@nginx.com static void 5781157Smax.romanov@nginx.com nxt_java_close_handler(nxt_unit_request_info_t *req) 5791157Smax.romanov@nginx.com { 5801157Smax.romanov@nginx.com JNIEnv *env; 5811157Smax.romanov@nginx.com nxt_java_data_t *java_data; 5821157Smax.romanov@nginx.com nxt_java_request_data_t *data; 5831157Smax.romanov@nginx.com 5841157Smax.romanov@nginx.com java_data = req->unit->data; 5851157Smax.romanov@nginx.com env = java_data->env; 5861157Smax.romanov@nginx.com data = req->data; 5871157Smax.romanov@nginx.com 5881157Smax.romanov@nginx.com nxt_java_Request_close(env, data->jreq); 5891157Smax.romanov@nginx.com 5901157Smax.romanov@nginx.com (*env)->DeleteGlobalRef(env, data->jresp); 5911157Smax.romanov@nginx.com (*env)->DeleteGlobalRef(env, data->jreq); 592977Smax.romanov@gmail.com 593977Smax.romanov@gmail.com nxt_unit_request_done(req, NXT_UNIT_OK); 594977Smax.romanov@gmail.com } 595977Smax.romanov@gmail.com 596