1 2 /* 3 * Copyright (C) NGINX, Inc. 4 */ 5 6 #include <nxt_auto_config.h> 7 8 #include <nxt_unit.h> 9 #include <nxt_unit_request.h> 10 #include <jni.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 14 #include "nxt_jni.h" 15 #include "nxt_jni_Request.h" 16 #include "nxt_jni_URLClassLoader.h" 17 #include "nxt_jni_HeadersEnumeration.h" 18 #include "nxt_jni_HeaderNamesEnumeration.h" 19 20 21 static jstring JNICALL nxt_java_Request_getHeader(JNIEnv *env, jclass cls, 22 jlong req_ptr, jstring name, jint name_len); 23 static jobject JNICALL nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls, 24 jlong req_ptr); 25 static jobject JNICALL nxt_java_Request_getHeaders(JNIEnv *env, jclass cls, 26 jlong req_ptr, jstring name, jint name_len); 27 static jint JNICALL nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls, 28 jlong req_ptr, jstring name, jint name_len); 29 static jstring JNICALL nxt_java_Request_getMethod(JNIEnv *env, jclass cls, 30 jlong req_ptr); 31 static jstring JNICALL nxt_java_Request_getQueryString(JNIEnv *env, jclass cls, 32 jlong req_ptr); 33 static jstring JNICALL nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls, 34 jlong req_ptr); 35 static jlong JNICALL nxt_java_Request_getContentLength(JNIEnv *env, jclass cls, 36 jlong req_ptr); 37 static jstring JNICALL nxt_java_Request_getContentType(JNIEnv *env, jclass cls, 38 jlong req_ptr); 39 static jstring JNICALL nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, 40 jlong req_ptr); 41 static jstring JNICALL nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, 42 jlong req_ptr); 43 static jint JNICALL nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, 44 jlong req_ptr); 45 static jstring JNICALL nxt_java_Request_getProtocol(JNIEnv *env, jclass cls, 46 jlong req_ptr); 47 static jstring JNICALL nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls, 48 jlong req_ptr); 49 static jstring JNICALL nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls, 50 jlong req_ptr); 51 static jint JNICALL nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls, 52 jlong req_ptr); 53 static jstring JNICALL nxt_java_Request_getScheme(JNIEnv *env, jclass cls, 54 jlong req_ptr); 55 static jstring JNICALL nxt_java_Request_getServerName(JNIEnv *env, jclass cls, 56 jlong req_ptr); 57 static jint JNICALL nxt_java_Request_getServerPort(JNIEnv *env, jclass cls, 58 jlong req_ptr); 59 static void JNICALL nxt_java_Request_log(JNIEnv *env, jclass cls, 60 jlong req_info_ptr, jstring msg, jint msg_len); 61 static void JNICALL nxt_java_Request_trace(JNIEnv *env, jclass cls, 62 jlong req_info_ptr, jstring msg, jint msg_len); 63 static jobject JNICALL nxt_java_Request_getResponse(JNIEnv *env, jclass cls, 64 jlong req_info_ptr); 65 66 67 static jclass nxt_java_Request_class; 68 static jmethodID nxt_java_Request_ctor; 69 70 71 int 72 nxt_java_initRequest(JNIEnv *env, jobject cl) 73 { 74 int res; 75 jclass cls; 76 77 cls = nxt_java_loadClass(env, cl, "nginx.unit.Request"); 78 if (cls == NULL) { 79 return NXT_UNIT_ERROR; 80 } 81 82 nxt_java_Request_class = (*env)->NewGlobalRef(env, cls); 83 (*env)->DeleteLocalRef(env, cls); 84 cls = nxt_java_Request_class; 85 86 nxt_java_Request_ctor = (*env)->GetMethodID(env, cls, "<init>", "(Lnginx/unit/Context;JJ)V"); 87 if (nxt_java_Request_ctor == NULL) { 88 (*env)->DeleteGlobalRef(env, cls); 89 return NXT_UNIT_ERROR; 90 } 91 92 JNINativeMethod request_methods[] = { 93 { (char *) "getHeader", 94 (char *) "(JLjava/lang/String;I)Ljava/lang/String;", 95 nxt_java_Request_getHeader }, 96 97 { (char *) "getHeaderNames", 98 (char *) "(J)Ljava/util/Enumeration;", 99 nxt_java_Request_getHeaderNames }, 100 101 { (char *) "getHeaders", 102 (char *) "(JLjava/lang/String;I)Ljava/util/Enumeration;", 103 nxt_java_Request_getHeaders }, 104 105 { (char *) "getIntHeader", 106 (char *) "(JLjava/lang/String;I)I", 107 nxt_java_Request_getIntHeader }, 108 109 { (char *) "getMethod", 110 (char *) "(J)Ljava/lang/String;", 111 nxt_java_Request_getMethod }, 112 113 { (char *) "getQueryString", 114 (char *) "(J)Ljava/lang/String;", 115 nxt_java_Request_getQueryString }, 116 117 { (char *) "getRequestURI", 118 (char *) "(J)Ljava/lang/String;", 119 nxt_java_Request_getRequestURI }, 120 121 { (char *) "getContentLength", 122 (char *) "(J)J", 123 nxt_java_Request_getContentLength }, 124 125 { (char *) "getContentType", 126 (char *) "(J)Ljava/lang/String;", 127 nxt_java_Request_getContentType }, 128 129 { (char *) "getLocalAddr", 130 (char *) "(J)Ljava/lang/String;", 131 nxt_java_Request_getLocalAddr }, 132 133 { (char *) "getLocalName", 134 (char *) "(J)Ljava/lang/String;", 135 nxt_java_Request_getLocalName }, 136 137 { (char *) "getLocalPort", 138 (char *) "(J)I", 139 nxt_java_Request_getLocalPort }, 140 141 { (char *) "getProtocol", 142 (char *) "(J)Ljava/lang/String;", 143 nxt_java_Request_getProtocol }, 144 145 { (char *) "getRemoteAddr", 146 (char *) "(J)Ljava/lang/String;", 147 nxt_java_Request_getRemoteAddr }, 148 149 { (char *) "getRemoteHost", 150 (char *) "(J)Ljava/lang/String;", 151 nxt_java_Request_getRemoteHost }, 152 153 { (char *) "getRemotePort", 154 (char *) "(J)I", 155 nxt_java_Request_getRemotePort }, 156 157 { (char *) "getScheme", 158 (char *) "(J)Ljava/lang/String;", 159 nxt_java_Request_getScheme }, 160 161 { (char *) "getServerName", 162 (char *) "(J)Ljava/lang/String;", 163 nxt_java_Request_getServerName }, 164 165 { (char *) "getServerPort", 166 (char *) "(J)I", 167 nxt_java_Request_getServerPort }, 168 169 { (char *) "log", 170 (char *) "(JLjava/lang/String;I)V", 171 nxt_java_Request_log }, 172 173 { (char *) "trace", 174 (char *) "(JLjava/lang/String;I)V", 175 nxt_java_Request_trace }, 176 177 { (char *) "getResponse", 178 (char *) "(J)Lnginx/unit/Response;", 179 nxt_java_Request_getResponse }, 180 181 }; 182 183 res = (*env)->RegisterNatives(env, nxt_java_Request_class, 184 request_methods, 185 sizeof(request_methods) / sizeof(request_methods[0])); 186 187 nxt_unit_debug(NULL, "registered Request methods: %d", res); 188 189 if (res != 0) { 190 nxt_unit_warn(NULL, "registering natives for Request failed"); 191 goto failed; 192 } 193 194 res = nxt_java_initHeadersEnumeration(env, cl); 195 if (res != NXT_UNIT_OK) { 196 goto failed; 197 } 198 199 res = nxt_java_initHeaderNamesEnumeration(env, cl); 200 if (res != NXT_UNIT_OK) { 201 goto failed; 202 } 203 204 return NXT_UNIT_OK; 205 206 failed: 207 208 (*env)->DeleteGlobalRef(env, cls); 209 return NXT_UNIT_ERROR; 210 } 211 212 213 jobject 214 nxt_java_newRequest(JNIEnv *env, jobject ctx, nxt_unit_request_info_t *req) 215 { 216 return (*env)->NewObject(env, nxt_java_Request_class, 217 nxt_java_Request_ctor, ctx, nxt_ptr2jlong(req), 218 nxt_ptr2jlong(req->request)); 219 } 220 221 222 static jstring JNICALL 223 nxt_java_Request_getHeader(JNIEnv *env, jclass cls, jlong req_ptr, 224 jstring name, jint name_len) 225 { 226 const char *name_str; 227 nxt_unit_field_t *f; 228 nxt_unit_request_t *r; 229 230 name_str = (*env)->GetStringUTFChars(env, name, NULL); 231 if (name_str == NULL) { 232 return NULL; 233 } 234 235 r = nxt_jlong2ptr(req_ptr); 236 237 f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, 238 name_str, name_len); 239 240 (*env)->ReleaseStringUTFChars(env, name, name_str); 241 242 if (f == NULL) { 243 return NULL; 244 } 245 246 return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value)); 247 } 248 249 250 static jobject JNICALL 251 nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls, jlong req_ptr) 252 { 253 nxt_unit_request_t *r; 254 255 r = nxt_jlong2ptr(req_ptr); 256 257 return nxt_java_newHeaderNamesEnumeration(env, r->fields, r->fields_count); 258 } 259 260 261 static jobject JNICALL 262 nxt_java_Request_getHeaders(JNIEnv *env, jclass cls, jlong req_ptr, 263 jstring name, jint name_len) 264 { 265 const char *name_str; 266 nxt_unit_field_t *f; 267 nxt_unit_request_t *r; 268 269 name_str = (*env)->GetStringUTFChars(env, name, NULL); 270 if (name_str == NULL) { 271 return NULL; 272 } 273 274 r = nxt_jlong2ptr(req_ptr); 275 276 f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, 277 name_str, name_len); 278 279 (*env)->ReleaseStringUTFChars(env, name, name_str); 280 281 if (f == NULL) { 282 f = r->fields + r->fields_count; 283 } 284 285 return nxt_java_newHeadersEnumeration(env, r->fields, r->fields_count, 286 f - r->fields); 287 } 288 289 290 static jint JNICALL 291 nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls, jlong req_ptr, 292 jstring name, jint name_len) 293 { 294 jint res; 295 char *value, *end; 296 const char *name_str; 297 nxt_unit_field_t *f; 298 nxt_unit_request_t *r; 299 300 res = -1; 301 302 name_str = (*env)->GetStringUTFChars(env, name, NULL); 303 if (name_str == NULL) { 304 return res; 305 } 306 307 r = nxt_jlong2ptr(req_ptr); 308 309 f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, 310 name_str, name_len); 311 312 (*env)->ReleaseStringUTFChars(env, name, name_str); 313 314 if (f == NULL) { 315 return res; 316 } 317 318 value = nxt_unit_sptr_get(&f->value); 319 end = value + f->value_length; 320 321 res = strtol(value, &end, 10); 322 323 if (end < value + f->value_length) { 324 // TODO throw NumberFormatException.forInputString(value) 325 } 326 327 return res; 328 } 329 330 331 static jstring JNICALL 332 nxt_java_Request_getMethod(JNIEnv *env, jclass cls, jlong req_ptr) 333 { 334 nxt_unit_request_t *r; 335 336 r = nxt_jlong2ptr(req_ptr); 337 338 return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->method)); 339 } 340 341 342 static jstring JNICALL 343 nxt_java_Request_getQueryString(JNIEnv *env, jclass cls, jlong req_ptr) 344 { 345 char *query; 346 nxt_unit_request_t *r; 347 348 r = nxt_jlong2ptr(req_ptr); 349 350 if (r->query.offset != 0) { 351 query = nxt_unit_sptr_get(&r->query); 352 return (*env)->NewStringUTF(env, query); 353 } 354 355 return NULL; 356 } 357 358 359 static jstring JNICALL 360 nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls, jlong req_ptr) 361 { 362 char *target, *query; 363 nxt_unit_request_t *r; 364 365 r = nxt_jlong2ptr(req_ptr); 366 367 target = nxt_unit_sptr_get(&r->target); 368 369 if (r->query.offset != 0) { 370 query = nxt_unit_sptr_get(&r->query); 371 return nxt_java_newString(env, target, query - target - 1); 372 } 373 374 return (*env)->NewStringUTF(env, target); 375 } 376 377 378 static jlong JNICALL 379 nxt_java_Request_getContentLength(JNIEnv *env, jclass cls, jlong req_ptr) 380 { 381 nxt_unit_request_t *r; 382 383 r = nxt_jlong2ptr(req_ptr); 384 385 return r->content_length; 386 } 387 388 389 static jstring JNICALL 390 nxt_java_Request_getContentType(JNIEnv *env, jclass cls, jlong req_ptr) 391 { 392 nxt_unit_field_t *f; 393 nxt_unit_request_t *r; 394 395 r = nxt_jlong2ptr(req_ptr); 396 397 if (r->content_type_field != NXT_UNIT_NONE_FIELD) { 398 f = r->fields + r->content_type_field; 399 400 return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value)); 401 } 402 403 return NULL; 404 } 405 406 407 static jstring JNICALL 408 nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, jlong req_ptr) 409 { 410 nxt_unit_request_t *r; 411 412 r = nxt_jlong2ptr(req_ptr); 413 414 return nxt_java_newString(env, nxt_unit_sptr_get(&r->local), 415 r->local_length); 416 } 417 418 419 static jstring JNICALL 420 nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, jlong req_ptr) 421 { 422 char *local, *colon; 423 nxt_unit_request_t *r; 424 425 r = nxt_jlong2ptr(req_ptr); 426 427 local = nxt_unit_sptr_get(&r->local); 428 colon = memchr(local, ':', r->local_length); 429 430 if (colon == NULL) { 431 colon = local + r->local_length; 432 } 433 434 return nxt_java_newString(env, local, colon - local); 435 } 436 437 438 static jint JNICALL 439 nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, jlong req_ptr) 440 { 441 jint res; 442 char *local, *colon, tmp; 443 nxt_unit_request_t *r; 444 445 r = nxt_jlong2ptr(req_ptr); 446 447 local = nxt_unit_sptr_get(&r->local); 448 colon = memchr(local, ':', r->local_length); 449 450 if (colon == NULL) { 451 return 80; 452 } 453 454 tmp = local[r->local_length]; 455 456 local[r->local_length] = '\0'; 457 458 res = strtol(colon + 1, NULL, 10); 459 460 local[r->local_length] = tmp; 461 462 return res; 463 } 464 465 466 static jstring JNICALL 467 nxt_java_Request_getProtocol(JNIEnv *env, jclass cls, jlong req_ptr) 468 { 469 nxt_unit_request_t *r; 470 471 r = nxt_jlong2ptr(req_ptr); 472 473 return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->version)); 474 } 475 476 477 static jstring JNICALL 478 nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls, jlong req_ptr) 479 { 480 nxt_unit_request_t *r; 481 482 r = nxt_jlong2ptr(req_ptr); 483 484 return nxt_java_newString(env, nxt_unit_sptr_get(&r->remote), 485 r->remote_length); 486 } 487 488 489 static jstring JNICALL 490 nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls, jlong req_ptr) 491 { 492 char *remote, *colon; 493 nxt_unit_request_t *r; 494 495 r = nxt_jlong2ptr(req_ptr); 496 497 remote = nxt_unit_sptr_get(&r->remote); 498 colon = memchr(remote, ':', r->remote_length); 499 500 if (colon == NULL) { 501 colon = remote + r->remote_length; 502 } 503 504 return nxt_java_newString(env, remote, colon - remote); 505 } 506 507 508 static jint JNICALL 509 nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls, jlong req_ptr) 510 { 511 jint res; 512 char *remote, *colon, tmp; 513 nxt_unit_request_t *r; 514 515 r = nxt_jlong2ptr(req_ptr); 516 517 remote = nxt_unit_sptr_get(&r->remote); 518 colon = memchr(remote, ':', r->remote_length); 519 520 if (colon == NULL) { 521 return 80; 522 } 523 524 tmp = remote[r->remote_length]; 525 526 remote[r->remote_length] = '\0'; 527 528 res = strtol(colon + 1, NULL, 10); 529 530 remote[r->remote_length] = tmp; 531 532 return res; 533 } 534 535 536 static jstring JNICALL 537 nxt_java_Request_getScheme(JNIEnv *env, jclass cls, jlong req_ptr) 538 { 539 return (*env)->NewStringUTF(env, "http"); 540 } 541 542 543 static jstring JNICALL 544 nxt_java_Request_getServerName(JNIEnv *env, jclass cls, jlong req_ptr) 545 { 546 char *host, *colon; 547 nxt_unit_field_t *f; 548 nxt_unit_request_t *r; 549 550 r = nxt_jlong2ptr(req_ptr); 551 552 f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, 553 "Host", 4); 554 if (f != NULL) { 555 host = nxt_unit_sptr_get(&f->value); 556 557 colon = memchr(host, ':', f->value_length); 558 559 if (colon == NULL) { 560 colon = host + f->value_length; 561 } 562 563 return nxt_java_newString(env, host, colon - host); 564 } 565 566 return nxt_java_Request_getLocalName(env, cls, req_ptr); 567 } 568 569 570 static jint JNICALL 571 nxt_java_Request_getServerPort(JNIEnv *env, jclass cls, jlong req_ptr) 572 { 573 jint res; 574 char *host, *colon, tmp; 575 nxt_unit_field_t *f; 576 nxt_unit_request_t *r; 577 578 r = nxt_jlong2ptr(req_ptr); 579 580 f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, 581 "Host", 4); 582 if (f != NULL) { 583 host = nxt_unit_sptr_get(&f->value); 584 585 colon = memchr(host, ':', f->value_length); 586 587 if (colon == NULL) { 588 return 80; 589 } 590 591 tmp = host[f->value_length]; 592 593 host[f->value_length] = '\0'; 594 595 res = strtol(colon + 1, NULL, 10); 596 597 host[f->value_length] = tmp; 598 599 return res; 600 } 601 602 return nxt_java_Request_getLocalPort(env, cls, req_ptr); 603 } 604 605 606 static void JNICALL 607 nxt_java_Request_log(JNIEnv *env, jclass cls, jlong req_info_ptr, jstring msg, 608 jint msg_len) 609 { 610 const char *msg_str; 611 nxt_unit_request_info_t *req; 612 613 req = nxt_jlong2ptr(req_info_ptr); 614 615 msg_str = (*env)->GetStringUTFChars(env, msg, NULL); 616 if (msg_str == NULL) { 617 return; 618 } 619 620 nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); 621 622 (*env)->ReleaseStringUTFChars(env, msg, msg_str); 623 } 624 625 626 static void JNICALL 627 nxt_java_Request_trace(JNIEnv *env, jclass cls, jlong req_info_ptr, jstring msg, 628 jint msg_len) 629 { 630 #if (NXT_DEBUG) 631 const char *msg_str; 632 nxt_unit_request_info_t *req; 633 634 req = nxt_jlong2ptr(req_info_ptr); 635 636 msg_str = (*env)->GetStringUTFChars(env, msg, NULL); 637 if (msg_str == NULL) { 638 return; 639 } 640 641 nxt_unit_req_debug(req, "%.*s", msg_len, msg_str); 642 643 (*env)->ReleaseStringUTFChars(env, msg, msg_str); 644 #endif 645 } 646 647 648 static jobject JNICALL 649 nxt_java_Request_getResponse(JNIEnv *env, jclass cls, jlong req_info_ptr) 650 { 651 nxt_unit_request_info_t *req; 652 nxt_java_request_data_t *data; 653 654 req = nxt_jlong2ptr(req_info_ptr); 655 data = req->data; 656 657 return data->jresp; 658 } 659