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*1489St.nateldemoura@f5.com #include "nxt_java_mounts.h" 30977Smax.romanov@gmail.com 311488St.nateldemoura@f5.com static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process, 32977Smax.romanov@gmail.com nxt_common_app_conf_t *conf); 331488St.nateldemoura@f5.com static nxt_int_t nxt_java_start(nxt_task_t *task, 341488St.nateldemoura@f5.com nxt_process_data_t *data); 35977Smax.romanov@gmail.com static void nxt_java_request_handler(nxt_unit_request_info_t *req); 361157Smax.romanov@nginx.com static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws); 371157Smax.romanov@nginx.com static void nxt_java_close_handler(nxt_unit_request_info_t *req); 38977Smax.romanov@gmail.com 39977Smax.romanov@gmail.com static uint32_t compat[] = { 40977Smax.romanov@gmail.com NXT_VERNUM, NXT_DEBUG, 41977Smax.romanov@gmail.com }; 42977Smax.romanov@gmail.com 43977Smax.romanov@gmail.com char *nxt_java_modules; 44977Smax.romanov@gmail.com 45977Smax.romanov@gmail.com 46977Smax.romanov@gmail.com #define NXT_STRING(x) _NXT_STRING(x) 47977Smax.romanov@gmail.com #define _NXT_STRING(x) #x 48977Smax.romanov@gmail.com 49977Smax.romanov@gmail.com NXT_EXPORT nxt_app_module_t nxt_app_module = { 50977Smax.romanov@gmail.com sizeof(compat), 51977Smax.romanov@gmail.com compat, 52977Smax.romanov@gmail.com nxt_string("java"), 53977Smax.romanov@gmail.com NXT_STRING(NXT_JAVA_VERSION), 54*1489St.nateldemoura@f5.com nxt_java_mounts, 55*1489St.nateldemoura@f5.com nxt_nitems(nxt_java_mounts), 561488St.nateldemoura@f5.com nxt_java_setup, 571488St.nateldemoura@f5.com nxt_java_start, 58977Smax.romanov@gmail.com }; 59977Smax.romanov@gmail.com 60977Smax.romanov@gmail.com typedef struct { 61977Smax.romanov@gmail.com JNIEnv *env; 62977Smax.romanov@gmail.com jobject ctx; 63977Smax.romanov@gmail.com } nxt_java_data_t; 64977Smax.romanov@gmail.com 65977Smax.romanov@gmail.com 66977Smax.romanov@gmail.com static nxt_int_t 671488St.nateldemoura@f5.com nxt_java_setup(nxt_task_t *task, nxt_process_t *process, 681488St.nateldemoura@f5.com nxt_common_app_conf_t *conf) 69977Smax.romanov@gmail.com { 70*1489St.nateldemoura@f5.com char *path, *relpath, *p, *rootfs; 71*1489St.nateldemoura@f5.com size_t jars_dir_len, rootfs_len; 72977Smax.romanov@gmail.com const char *unit_jars; 73977Smax.romanov@gmail.com 74*1489St.nateldemoura@f5.com rootfs = (char *) process->isolation.rootfs; 75*1489St.nateldemoura@f5.com rootfs_len = 0; 76*1489St.nateldemoura@f5.com 77977Smax.romanov@gmail.com unit_jars = conf->u.java.unit_jars; 78977Smax.romanov@gmail.com if (unit_jars == NULL) { 79*1489St.nateldemoura@f5.com if (rootfs != NULL) { 80*1489St.nateldemoura@f5.com unit_jars = "/"; 81*1489St.nateldemoura@f5.com } else { 82*1489St.nateldemoura@f5.com unit_jars = NXT_JARS; 83*1489St.nateldemoura@f5.com } 84977Smax.romanov@gmail.com } 85977Smax.romanov@gmail.com 86*1489St.nateldemoura@f5.com relpath = strdup(unit_jars); 87*1489St.nateldemoura@f5.com if (nxt_slow_path(relpath == NULL)) { 88977Smax.romanov@gmail.com return NXT_ERROR; 89977Smax.romanov@gmail.com } 90977Smax.romanov@gmail.com 91*1489St.nateldemoura@f5.com if (rootfs != NULL) { 92*1489St.nateldemoura@f5.com jars_dir_len = strlen(unit_jars); 93*1489St.nateldemoura@f5.com rootfs_len = strlen(rootfs); 94*1489St.nateldemoura@f5.com 95*1489St.nateldemoura@f5.com path = nxt_malloc(jars_dir_len + rootfs_len + 1); 96*1489St.nateldemoura@f5.com if (nxt_slow_path(path == NULL)) { 97*1489St.nateldemoura@f5.com free(relpath); 98*1489St.nateldemoura@f5.com return NXT_ERROR; 99*1489St.nateldemoura@f5.com } 100*1489St.nateldemoura@f5.com 101*1489St.nateldemoura@f5.com p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len); 102*1489St.nateldemoura@f5.com p = nxt_cpymem(p, relpath, jars_dir_len); 103*1489St.nateldemoura@f5.com *p = '\0'; 104*1489St.nateldemoura@f5.com 105*1489St.nateldemoura@f5.com free(relpath); 106*1489St.nateldemoura@f5.com 107*1489St.nateldemoura@f5.com } else { 108*1489St.nateldemoura@f5.com path = relpath; 109*1489St.nateldemoura@f5.com } 110*1489St.nateldemoura@f5.com 111*1489St.nateldemoura@f5.com nxt_java_modules = realpath(path, NULL); 112*1489St.nateldemoura@f5.com if (nxt_java_modules == NULL) { 113*1489St.nateldemoura@f5.com nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno); 114*1489St.nateldemoura@f5.com goto free; 115*1489St.nateldemoura@f5.com } 116*1489St.nateldemoura@f5.com 117*1489St.nateldemoura@f5.com if (rootfs != NULL && strlen(path) > rootfs_len) { 118*1489St.nateldemoura@f5.com nxt_java_modules = path + rootfs_len; 119*1489St.nateldemoura@f5.com } 120*1489St.nateldemoura@f5.com 121*1489St.nateldemoura@f5.com nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules); 122*1489St.nateldemoura@f5.com 123977Smax.romanov@gmail.com return NXT_OK; 124*1489St.nateldemoura@f5.com 125*1489St.nateldemoura@f5.com free: 126*1489St.nateldemoura@f5.com 127*1489St.nateldemoura@f5.com nxt_free(path); 128*1489St.nateldemoura@f5.com 129*1489St.nateldemoura@f5.com return NXT_ERROR; 130977Smax.romanov@gmail.com } 131977Smax.romanov@gmail.com 132977Smax.romanov@gmail.com 133977Smax.romanov@gmail.com static char ** 134977Smax.romanov@gmail.com nxt_java_module_jars(const char *jars[], int jar_count) 135977Smax.romanov@gmail.com { 136977Smax.romanov@gmail.com char **res, *jurl; 137*1489St.nateldemoura@f5.com uint8_t pathsep; 138977Smax.romanov@gmail.com nxt_int_t modules_len, jlen, i; 139977Smax.romanov@gmail.com const char **jar; 140977Smax.romanov@gmail.com 141977Smax.romanov@gmail.com res = nxt_malloc(jar_count * sizeof(char*)); 142977Smax.romanov@gmail.com if (res == NULL) { 143977Smax.romanov@gmail.com return NULL; 144977Smax.romanov@gmail.com } 145977Smax.romanov@gmail.com 146977Smax.romanov@gmail.com modules_len = nxt_strlen(nxt_java_modules); 147977Smax.romanov@gmail.com 148*1489St.nateldemoura@f5.com pathsep = nxt_java_modules[modules_len - 1] == '/'; 149*1489St.nateldemoura@f5.com 150977Smax.romanov@gmail.com for (i = 0, jar = jars; *jar != NULL; jar++) { 151*1489St.nateldemoura@f5.com jlen = nxt_length("file:") + modules_len 152*1489St.nateldemoura@f5.com + (!pathsep ? nxt_length("/") : 0) 153*1489St.nateldemoura@f5.com + nxt_strlen(*jar) + 1; 154*1489St.nateldemoura@f5.com 155977Smax.romanov@gmail.com jurl = nxt_malloc(jlen); 156977Smax.romanov@gmail.com if (jurl == NULL) { 157977Smax.romanov@gmail.com return NULL; 158977Smax.romanov@gmail.com } 159977Smax.romanov@gmail.com 160977Smax.romanov@gmail.com res[i++] = jurl; 161977Smax.romanov@gmail.com 162977Smax.romanov@gmail.com jurl = nxt_cpymem(jurl, "file:", nxt_length("file:")); 163977Smax.romanov@gmail.com jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len); 164*1489St.nateldemoura@f5.com 165*1489St.nateldemoura@f5.com if (!pathsep) { 166*1489St.nateldemoura@f5.com *jurl++ = '/'; 167*1489St.nateldemoura@f5.com } 168*1489St.nateldemoura@f5.com 169977Smax.romanov@gmail.com jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar)); 170977Smax.romanov@gmail.com *jurl++ = '\0'; 171977Smax.romanov@gmail.com } 172977Smax.romanov@gmail.com 173977Smax.romanov@gmail.com return res; 174977Smax.romanov@gmail.com } 175977Smax.romanov@gmail.com 176977Smax.romanov@gmail.com 177977Smax.romanov@gmail.com static nxt_int_t 1781488St.nateldemoura@f5.com nxt_java_start(nxt_task_t *task, nxt_process_data_t *data) 179977Smax.romanov@gmail.com { 1801488St.nateldemoura@f5.com jint rc; 1811488St.nateldemoura@f5.com char *opt, *real_path; 1821488St.nateldemoura@f5.com char **classpath_arr, **unit_jars, **system_jars; 1831488St.nateldemoura@f5.com JavaVM *jvm; 1841488St.nateldemoura@f5.com JNIEnv *env; 1851488St.nateldemoura@f5.com jobject cl, classpath; 1861488St.nateldemoura@f5.com nxt_str_t str; 1871488St.nateldemoura@f5.com nxt_int_t opt_len, real_path_len; 1881488St.nateldemoura@f5.com nxt_uint_t i, unit_jars_count, classpath_count; 1891488St.nateldemoura@f5.com nxt_uint_t system_jars_count; 1901488St.nateldemoura@f5.com JavaVMOption *jvm_opt; 1911488St.nateldemoura@f5.com JavaVMInitArgs jvm_args; 1921488St.nateldemoura@f5.com nxt_unit_ctx_t *ctx; 1931488St.nateldemoura@f5.com nxt_unit_init_t java_init; 1941488St.nateldemoura@f5.com nxt_java_data_t java_data; 1951488St.nateldemoura@f5.com nxt_conf_value_t *value; 1961488St.nateldemoura@f5.com nxt_java_app_conf_t *c; 1971488St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 198977Smax.romanov@gmail.com 199977Smax.romanov@gmail.com //setenv("ASAN_OPTIONS", "handle_segv=0", 1); 200977Smax.romanov@gmail.com 201977Smax.romanov@gmail.com jvm_args.version = JNI_VERSION_1_6; 202977Smax.romanov@gmail.com jvm_args.nOptions = 0; 203977Smax.romanov@gmail.com jvm_args.ignoreUnrecognized = 0; 204977Smax.romanov@gmail.com 2051488St.nateldemoura@f5.com app_conf = data->app; 2061488St.nateldemoura@f5.com c = &app_conf->u.java; 207977Smax.romanov@gmail.com 208977Smax.romanov@gmail.com if (c->options != NULL) { 209977Smax.romanov@gmail.com jvm_args.nOptions += nxt_conf_array_elements_count(c->options); 210977Smax.romanov@gmail.com } 211977Smax.romanov@gmail.com 212977Smax.romanov@gmail.com jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption)); 213977Smax.romanov@gmail.com if (jvm_opt == NULL) { 214977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate jvm_opt"); 215977Smax.romanov@gmail.com return NXT_ERROR; 216977Smax.romanov@gmail.com } 217977Smax.romanov@gmail.com 218977Smax.romanov@gmail.com jvm_args.options = jvm_opt; 219977Smax.romanov@gmail.com 220977Smax.romanov@gmail.com unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1; 221977Smax.romanov@gmail.com 222977Smax.romanov@gmail.com unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count); 223977Smax.romanov@gmail.com if (unit_jars == NULL) { 224977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate buffer for unit_jars array"); 225977Smax.romanov@gmail.com 226977Smax.romanov@gmail.com return NXT_ERROR; 227977Smax.romanov@gmail.com } 228977Smax.romanov@gmail.com 229977Smax.romanov@gmail.com system_jars_count = nxt_nitems(nxt_java_system_jars) - 1; 230977Smax.romanov@gmail.com 231977Smax.romanov@gmail.com system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count); 232977Smax.romanov@gmail.com if (system_jars == NULL) { 233977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate buffer for system_jars array"); 234977Smax.romanov@gmail.com 235977Smax.romanov@gmail.com return NXT_ERROR; 236977Smax.romanov@gmail.com } 237977Smax.romanov@gmail.com 238977Smax.romanov@gmail.com if (c->options != NULL) { 239977Smax.romanov@gmail.com 240977Smax.romanov@gmail.com for (i = 0; /* void */ ; i++) { 241977Smax.romanov@gmail.com value = nxt_conf_get_array_element(c->options, i); 242977Smax.romanov@gmail.com if (value == NULL) { 243977Smax.romanov@gmail.com break; 244977Smax.romanov@gmail.com } 245977Smax.romanov@gmail.com 246977Smax.romanov@gmail.com nxt_conf_get_string(value, &str); 247977Smax.romanov@gmail.com 248977Smax.romanov@gmail.com opt = nxt_malloc(str.length + 1); 249977Smax.romanov@gmail.com if (opt == NULL) { 250977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate jvm_opt"); 251977Smax.romanov@gmail.com return NXT_ERROR; 252977Smax.romanov@gmail.com } 253977Smax.romanov@gmail.com 254977Smax.romanov@gmail.com memcpy(opt, str.start, str.length); 255977Smax.romanov@gmail.com opt[str.length] = '\0'; 256977Smax.romanov@gmail.com 257977Smax.romanov@gmail.com jvm_opt[i].optionString = opt; 258977Smax.romanov@gmail.com } 259977Smax.romanov@gmail.com } 260977Smax.romanov@gmail.com 261977Smax.romanov@gmail.com if (c->classpath != NULL) { 262977Smax.romanov@gmail.com classpath_count = nxt_conf_array_elements_count(c->classpath); 263977Smax.romanov@gmail.com classpath_arr = nxt_malloc(classpath_count * sizeof(char *)); 264977Smax.romanov@gmail.com 265977Smax.romanov@gmail.com for (i = 0; /* void */ ; i++) { 266977Smax.romanov@gmail.com value = nxt_conf_get_array_element(c->classpath, i); 267977Smax.romanov@gmail.com if (value == NULL) { 268977Smax.romanov@gmail.com break; 269977Smax.romanov@gmail.com } 270977Smax.romanov@gmail.com 271977Smax.romanov@gmail.com nxt_conf_get_string(value, &str); 272977Smax.romanov@gmail.com 273977Smax.romanov@gmail.com opt_len = str.length + 1; 274977Smax.romanov@gmail.com 275977Smax.romanov@gmail.com char *sc = memchr(str.start, ':', str.length); 276977Smax.romanov@gmail.com if (sc == NULL && str.start[0] == '/') { 277977Smax.romanov@gmail.com opt_len += nxt_length("file:"); 278977Smax.romanov@gmail.com } 279977Smax.romanov@gmail.com 280977Smax.romanov@gmail.com opt = nxt_malloc(opt_len); 281977Smax.romanov@gmail.com if (opt == NULL) { 282977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate classpath"); 283977Smax.romanov@gmail.com return NXT_ERROR; 284977Smax.romanov@gmail.com } 285977Smax.romanov@gmail.com 286977Smax.romanov@gmail.com if (sc == NULL && str.start[0] != '/') { 287977Smax.romanov@gmail.com nxt_memcpy(opt, str.start, str.length); 288977Smax.romanov@gmail.com opt[str.length] = '\0'; 289977Smax.romanov@gmail.com 290977Smax.romanov@gmail.com real_path = realpath(opt, NULL); 291977Smax.romanov@gmail.com if (real_path == NULL) { 292977Smax.romanov@gmail.com nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno); 293977Smax.romanov@gmail.com return NXT_ERROR; 294977Smax.romanov@gmail.com } 295977Smax.romanov@gmail.com 296977Smax.romanov@gmail.com real_path_len = nxt_strlen(real_path); 297977Smax.romanov@gmail.com 298977Smax.romanov@gmail.com free(opt); 299977Smax.romanov@gmail.com 300977Smax.romanov@gmail.com opt_len = nxt_length("file:") + real_path_len + 1; 301977Smax.romanov@gmail.com 302977Smax.romanov@gmail.com opt = nxt_malloc(opt_len); 303977Smax.romanov@gmail.com if (opt == NULL) { 304977Smax.romanov@gmail.com nxt_alert(task, "failed to allocate classpath"); 305977Smax.romanov@gmail.com return NXT_ERROR; 306977Smax.romanov@gmail.com } 307977Smax.romanov@gmail.com 308977Smax.romanov@gmail.com } else { 309977Smax.romanov@gmail.com real_path = (char *) str.start; /* I love this cast! */ 310977Smax.romanov@gmail.com real_path_len = str.length; 311977Smax.romanov@gmail.com } 312977Smax.romanov@gmail.com 313977Smax.romanov@gmail.com classpath_arr[i] = opt; 314977Smax.romanov@gmail.com 315977Smax.romanov@gmail.com if (sc == NULL) { 316977Smax.romanov@gmail.com opt = nxt_cpymem(opt, "file:", nxt_length("file:")); 317977Smax.romanov@gmail.com } 318977Smax.romanov@gmail.com 319977Smax.romanov@gmail.com opt = nxt_cpymem(opt, real_path, real_path_len); 320977Smax.romanov@gmail.com *opt = '\0'; 321977Smax.romanov@gmail.com } 322977Smax.romanov@gmail.com 323977Smax.romanov@gmail.com } else { 324977Smax.romanov@gmail.com classpath_count = 0; 325977Smax.romanov@gmail.com classpath_arr = NULL; 326977Smax.romanov@gmail.com } 327977Smax.romanov@gmail.com 328977Smax.romanov@gmail.com rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args); 329977Smax.romanov@gmail.com if (rc != JNI_OK) { 330977Smax.romanov@gmail.com nxt_alert(task, "failed to create Java VM: %d", (int) rc); 331977Smax.romanov@gmail.com return NXT_ERROR; 332977Smax.romanov@gmail.com } 333977Smax.romanov@gmail.com 334977Smax.romanov@gmail.com rc = nxt_java_initThread(env); 335977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 336977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initThread() failed"); 337977Smax.romanov@gmail.com goto env_failed; 338977Smax.romanov@gmail.com } 339977Smax.romanov@gmail.com 340977Smax.romanov@gmail.com rc = nxt_java_initURLClassLoader(env); 341977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 342977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initURLClassLoader() failed"); 343977Smax.romanov@gmail.com goto env_failed; 344977Smax.romanov@gmail.com } 345977Smax.romanov@gmail.com 346977Smax.romanov@gmail.com cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars); 347977Smax.romanov@gmail.com if (cl == NULL) { 348977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_newURLClassLoader failed"); 349977Smax.romanov@gmail.com goto env_failed; 350977Smax.romanov@gmail.com } 351977Smax.romanov@gmail.com 352977Smax.romanov@gmail.com nxt_java_setContextClassLoader(env, cl); 353977Smax.romanov@gmail.com 354977Smax.romanov@gmail.com cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl); 355977Smax.romanov@gmail.com if (cl == NULL) { 356977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_newURLClassLoader_parent failed"); 357977Smax.romanov@gmail.com goto env_failed; 358977Smax.romanov@gmail.com } 359977Smax.romanov@gmail.com 360977Smax.romanov@gmail.com nxt_java_setContextClassLoader(env, cl); 361977Smax.romanov@gmail.com 362977Smax.romanov@gmail.com rc = nxt_java_initContext(env, cl); 363977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 364977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initContext() failed"); 365977Smax.romanov@gmail.com goto env_failed; 366977Smax.romanov@gmail.com } 367977Smax.romanov@gmail.com 368977Smax.romanov@gmail.com rc = nxt_java_initRequest(env, cl); 369977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 370977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initRequest() failed"); 371977Smax.romanov@gmail.com goto env_failed; 372977Smax.romanov@gmail.com } 373977Smax.romanov@gmail.com 374977Smax.romanov@gmail.com rc = nxt_java_initResponse(env, cl); 375977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 376977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initResponse() failed"); 377977Smax.romanov@gmail.com goto env_failed; 378977Smax.romanov@gmail.com } 379977Smax.romanov@gmail.com 380977Smax.romanov@gmail.com rc = nxt_java_initInputStream(env, cl); 381977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 382977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initInputStream() failed"); 383977Smax.romanov@gmail.com goto env_failed; 384977Smax.romanov@gmail.com } 385977Smax.romanov@gmail.com 386977Smax.romanov@gmail.com rc = nxt_java_initOutputStream(env, cl); 387977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 388977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_initOutputStream() failed"); 389977Smax.romanov@gmail.com goto env_failed; 390977Smax.romanov@gmail.com } 391977Smax.romanov@gmail.com 392977Smax.romanov@gmail.com nxt_java_jni_init(env); 393977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) { 394977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_jni_init() failed"); 395977Smax.romanov@gmail.com goto env_failed; 396977Smax.romanov@gmail.com } 397977Smax.romanov@gmail.com 398977Smax.romanov@gmail.com classpath = nxt_java_newURLs(env, classpath_count, classpath_arr); 399977Smax.romanov@gmail.com if (classpath == NULL) { 400977Smax.romanov@gmail.com nxt_alert(task, "nxt_java_newURLs failed"); 401977Smax.romanov@gmail.com goto env_failed; 402977Smax.romanov@gmail.com } 403977Smax.romanov@gmail.com 4041488St.nateldemoura@f5.com java_data.env = env; 4051488St.nateldemoura@f5.com java_data.ctx = nxt_java_startContext(env, c->webapp, classpath); 406977Smax.romanov@gmail.com 407977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 408977Smax.romanov@gmail.com nxt_alert(task, "Unhandled exception in application start"); 409977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 410977Smax.romanov@gmail.com return NXT_ERROR; 411977Smax.romanov@gmail.com } 412977Smax.romanov@gmail.com 413977Smax.romanov@gmail.com nxt_unit_default_init(task, &java_init); 414977Smax.romanov@gmail.com 415977Smax.romanov@gmail.com java_init.callbacks.request_handler = nxt_java_request_handler; 4161157Smax.romanov@nginx.com java_init.callbacks.websocket_handler = nxt_java_websocket_handler; 4171157Smax.romanov@nginx.com java_init.callbacks.close_handler = nxt_java_close_handler; 418977Smax.romanov@gmail.com java_init.request_data_size = sizeof(nxt_java_request_data_t); 4191488St.nateldemoura@f5.com java_init.data = &java_data; 4201488St.nateldemoura@f5.com java_init.shm_limit = app_conf->shm_limit; 421977Smax.romanov@gmail.com 422977Smax.romanov@gmail.com ctx = nxt_unit_init(&java_init); 423977Smax.romanov@gmail.com if (nxt_slow_path(ctx == NULL)) { 424977Smax.romanov@gmail.com nxt_alert(task, "nxt_unit_init() failed"); 425977Smax.romanov@gmail.com return NXT_ERROR; 426977Smax.romanov@gmail.com } 427977Smax.romanov@gmail.com 428977Smax.romanov@gmail.com rc = nxt_unit_run(ctx); 429977Smax.romanov@gmail.com if (nxt_slow_path(rc != NXT_UNIT_OK)) { 430977Smax.romanov@gmail.com /* TODO report error */ 431977Smax.romanov@gmail.com } 432977Smax.romanov@gmail.com 4331488St.nateldemoura@f5.com nxt_java_stopContext(env, java_data.ctx); 434977Smax.romanov@gmail.com 435977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 436977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 437977Smax.romanov@gmail.com } 438977Smax.romanov@gmail.com 4391157Smax.romanov@nginx.com nxt_unit_done(ctx); 4401157Smax.romanov@nginx.com 441977Smax.romanov@gmail.com (*jvm)->DestroyJavaVM(jvm); 442977Smax.romanov@gmail.com 443977Smax.romanov@gmail.com exit(0); 444977Smax.romanov@gmail.com 445977Smax.romanov@gmail.com return NXT_OK; 446977Smax.romanov@gmail.com 447977Smax.romanov@gmail.com env_failed: 448977Smax.romanov@gmail.com 449977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 450977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 451977Smax.romanov@gmail.com } 452977Smax.romanov@gmail.com 453977Smax.romanov@gmail.com return NXT_ERROR; 454977Smax.romanov@gmail.com } 455977Smax.romanov@gmail.com 456977Smax.romanov@gmail.com 457977Smax.romanov@gmail.com static void 458977Smax.romanov@gmail.com nxt_java_request_handler(nxt_unit_request_info_t *req) 459977Smax.romanov@gmail.com { 460977Smax.romanov@gmail.com JNIEnv *env; 461977Smax.romanov@gmail.com jobject jreq, jresp; 462977Smax.romanov@gmail.com nxt_java_data_t *java_data; 463977Smax.romanov@gmail.com nxt_java_request_data_t *data; 464977Smax.romanov@gmail.com 465977Smax.romanov@gmail.com java_data = req->unit->data; 466977Smax.romanov@gmail.com env = java_data->env; 467977Smax.romanov@gmail.com data = req->data; 468977Smax.romanov@gmail.com 469977Smax.romanov@gmail.com jreq = nxt_java_newRequest(env, java_data->ctx, req); 470977Smax.romanov@gmail.com if (jreq == NULL) { 471977Smax.romanov@gmail.com nxt_unit_req_alert(req, "failed to create Request instance"); 472977Smax.romanov@gmail.com 473977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 474977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 475977Smax.romanov@gmail.com (*env)->ExceptionClear(env); 476977Smax.romanov@gmail.com } 477977Smax.romanov@gmail.com 478977Smax.romanov@gmail.com nxt_unit_request_done(req, NXT_UNIT_ERROR); 479977Smax.romanov@gmail.com return; 480977Smax.romanov@gmail.com } 481977Smax.romanov@gmail.com 482977Smax.romanov@gmail.com jresp = nxt_java_newResponse(env, req); 483977Smax.romanov@gmail.com if (jresp == NULL) { 484977Smax.romanov@gmail.com nxt_unit_req_alert(req, "failed to create Response instance"); 485977Smax.romanov@gmail.com 486977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 487977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 488977Smax.romanov@gmail.com (*env)->ExceptionClear(env); 489977Smax.romanov@gmail.com } 490977Smax.romanov@gmail.com 491977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, jreq); 492977Smax.romanov@gmail.com 493977Smax.romanov@gmail.com nxt_unit_request_done(req, NXT_UNIT_ERROR); 494977Smax.romanov@gmail.com return; 495977Smax.romanov@gmail.com } 496977Smax.romanov@gmail.com 497977Smax.romanov@gmail.com data->header_size = 10 * 1024; 498977Smax.romanov@gmail.com data->buf_size = 32 * 1024; /* from Jetty */ 499977Smax.romanov@gmail.com data->jreq = jreq; 500977Smax.romanov@gmail.com data->jresp = jresp; 501977Smax.romanov@gmail.com data->buf = NULL; 502977Smax.romanov@gmail.com 503977Smax.romanov@gmail.com nxt_unit_request_group_dup_fields(req); 504977Smax.romanov@gmail.com 505977Smax.romanov@gmail.com nxt_java_service(env, java_data->ctx, jreq, jresp); 506977Smax.romanov@gmail.com 507977Smax.romanov@gmail.com if ((*env)->ExceptionCheck(env)) { 508977Smax.romanov@gmail.com (*env)->ExceptionDescribe(env); 509977Smax.romanov@gmail.com (*env)->ExceptionClear(env); 510977Smax.romanov@gmail.com } 511977Smax.romanov@gmail.com 512977Smax.romanov@gmail.com if (!nxt_unit_response_is_init(req)) { 513977Smax.romanov@gmail.com nxt_unit_response_init(req, 200, 0, 0); 514977Smax.romanov@gmail.com } 515977Smax.romanov@gmail.com 516977Smax.romanov@gmail.com if (!nxt_unit_response_is_sent(req)) { 517977Smax.romanov@gmail.com nxt_unit_response_send(req); 518977Smax.romanov@gmail.com } 519977Smax.romanov@gmail.com 520977Smax.romanov@gmail.com if (data->buf != NULL) { 521977Smax.romanov@gmail.com nxt_unit_buf_send(data->buf); 522977Smax.romanov@gmail.com 523977Smax.romanov@gmail.com data->buf = NULL; 524977Smax.romanov@gmail.com } 525977Smax.romanov@gmail.com 5261157Smax.romanov@nginx.com if (nxt_unit_response_is_websocket(req)) { 5271157Smax.romanov@nginx.com data->jreq = (*env)->NewGlobalRef(env, jreq); 5281157Smax.romanov@nginx.com data->jresp = (*env)->NewGlobalRef(env, jresp); 5291157Smax.romanov@nginx.com 5301157Smax.romanov@nginx.com } else { 5311157Smax.romanov@nginx.com nxt_unit_request_done(req, NXT_UNIT_OK); 5321157Smax.romanov@nginx.com } 5331157Smax.romanov@nginx.com 534977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, jresp); 535977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, jreq); 5361157Smax.romanov@nginx.com } 5371157Smax.romanov@nginx.com 5381157Smax.romanov@nginx.com 5391157Smax.romanov@nginx.com static void 5401157Smax.romanov@nginx.com nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws) 5411157Smax.romanov@nginx.com { 5421157Smax.romanov@nginx.com void *b; 5431157Smax.romanov@nginx.com JNIEnv *env; 5441157Smax.romanov@nginx.com jobject jbuf; 5451157Smax.romanov@nginx.com nxt_java_data_t *java_data; 5461157Smax.romanov@nginx.com nxt_java_request_data_t *data; 5471157Smax.romanov@nginx.com 5481157Smax.romanov@nginx.com java_data = ws->req->unit->data; 5491157Smax.romanov@nginx.com env = java_data->env; 5501157Smax.romanov@nginx.com data = ws->req->data; 5511157Smax.romanov@nginx.com 5521157Smax.romanov@nginx.com b = malloc(ws->payload_len); 5531157Smax.romanov@nginx.com if (b != NULL) { 5541157Smax.romanov@nginx.com nxt_unit_websocket_read(ws, b, ws->payload_len); 5551157Smax.romanov@nginx.com 5561157Smax.romanov@nginx.com jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len); 5571157Smax.romanov@nginx.com if (jbuf != NULL) { 5581157Smax.romanov@nginx.com nxt_java_Request_websocket(env, data->jreq, jbuf, 5591157Smax.romanov@nginx.com ws->header->opcode, ws->header->fin); 5601157Smax.romanov@nginx.com 5611157Smax.romanov@nginx.com if ((*env)->ExceptionCheck(env)) { 5621157Smax.romanov@nginx.com (*env)->ExceptionDescribe(env); 5631157Smax.romanov@nginx.com (*env)->ExceptionClear(env); 5641157Smax.romanov@nginx.com } 5651157Smax.romanov@nginx.com 5661157Smax.romanov@nginx.com (*env)->DeleteLocalRef(env, jbuf); 5671157Smax.romanov@nginx.com } 5681157Smax.romanov@nginx.com 5691157Smax.romanov@nginx.com free(b); 5701157Smax.romanov@nginx.com } 5711157Smax.romanov@nginx.com 5721157Smax.romanov@nginx.com nxt_unit_websocket_done(ws); 5731157Smax.romanov@nginx.com } 5741157Smax.romanov@nginx.com 5751157Smax.romanov@nginx.com 5761157Smax.romanov@nginx.com static void 5771157Smax.romanov@nginx.com nxt_java_close_handler(nxt_unit_request_info_t *req) 5781157Smax.romanov@nginx.com { 5791157Smax.romanov@nginx.com JNIEnv *env; 5801157Smax.romanov@nginx.com nxt_java_data_t *java_data; 5811157Smax.romanov@nginx.com nxt_java_request_data_t *data; 5821157Smax.romanov@nginx.com 5831157Smax.romanov@nginx.com java_data = req->unit->data; 5841157Smax.romanov@nginx.com env = java_data->env; 5851157Smax.romanov@nginx.com data = req->data; 5861157Smax.romanov@nginx.com 5871157Smax.romanov@nginx.com nxt_java_Request_close(env, data->jreq); 5881157Smax.romanov@nginx.com 5891157Smax.romanov@nginx.com (*env)->DeleteGlobalRef(env, data->jresp); 5901157Smax.romanov@nginx.com (*env)->DeleteGlobalRef(env, data->jreq); 591977Smax.romanov@gmail.com 592977Smax.romanov@gmail.com nxt_unit_request_done(req, NXT_UNIT_OK); 593977Smax.romanov@gmail.com } 594977Smax.romanov@gmail.com 595