/* * Copyright (C) NGINX, Inc. */ #include #include #include #include #include "nxt_jni.h" #include "nxt_jni_InputStream.h" #include "nxt_jni_URLClassLoader.h" static jint JNICALL nxt_java_InputStream_readLine(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray b, jint off, jint len); static jboolean JNICALL nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, jlong req_info_ptr); static jint JNICALL nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, jlong req_info_ptr); static jint JNICALL nxt_java_InputStream_read(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray b, jint off, jint len); static jlong JNICALL nxt_java_InputStream_skip(JNIEnv *env, jclass cls, jlong req_info_ptr, jlong n); static jint JNICALL nxt_java_InputStream_available(JNIEnv *env, jclass cls, jlong req_info_ptr); static jclass nxt_java_InputStream_class; int nxt_java_initInputStream(JNIEnv *env, jobject cl) { int res; jclass cls; cls = nxt_java_loadClass(env, cl, "nginx.unit.InputStream"); if (cls == NULL) { return NXT_UNIT_ERROR; } nxt_java_InputStream_class = (*env)->NewGlobalRef(env, cls); (*env)->DeleteLocalRef(env, cls); JNINativeMethod is_methods[] = { { (char *) "readLine", (char *) "(J[BII)I", nxt_java_InputStream_readLine }, { (char *) "isFinished", (char *) "(J)Z", nxt_java_InputStream_isFinished }, { (char *) "read", (char *) "(J)I", nxt_java_InputStream_readByte }, { (char *) "read", (char *) "(J[BII)I", nxt_java_InputStream_read }, { (char *) "skip", (char *) "(JJ)J", nxt_java_InputStream_skip }, { (char *) "available", (char *) "(J)I", nxt_java_InputStream_available }, }; res = (*env)->RegisterNatives(env, nxt_java_InputStream_class, is_methods, sizeof(is_methods) / sizeof(is_methods[0])); nxt_unit_debug(NULL, "registered InputStream methods: %d", res); if (res != 0) { (*env)->DeleteGlobalRef(env, cls); return NXT_UNIT_ERROR; } return NXT_UNIT_OK; } static jint JNICALL nxt_java_InputStream_readLine(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray out, jint off, jint len) { uint8_t *data; ssize_t res; nxt_unit_request_info_t *req; req = nxt_jlong2ptr(req_info_ptr); data = (*env)->GetPrimitiveArrayCritical(env, out, NULL); res = nxt_unit_request_readline_size(req, len); if (res > 0) { res = nxt_unit_request_read(req, data + off, res); } nxt_unit_req_debug(req, "readLine '%.*s'", (int) res, (char *) data + off); (*env)->ReleasePrimitiveArrayCritical(env, out, data, 0); return res > 0 ? res : -1; } static jboolean JNICALL nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, jlong req_info_ptr) { nxt_unit_request_info_t *req; req = nxt_jlong2ptr(req_info_ptr); return req->content_length == 0; } static jint JNICALL nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, jlong req_info_ptr) { uint8_t b; ssize_t size; nxt_unit_request_info_t *req; req = nxt_jlong2ptr(req_info_ptr); size = nxt_unit_request_read(req, &b, 1); return size == 1 ? b : -1; } static jint JNICALL nxt_java_InputStream_read(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray b, jint off, jint len) { uint8_t *data; ssize_t res; nxt_unit_request_info_t *req; req = nxt_jlong2ptr(req_info_ptr); data = (*env)->GetPrimitiveArrayCritical(env, b, NULL); res = nxt_unit_request_read(req, data + off, len); nxt_unit_req_debug(req, "read '%.*s'", (int) res, (char *) data + off); (*env)->ReleasePrimitiveArrayCritical(env, b, data, 0); return res > 0 ? res : -1; } static jlong JNICALL nxt_java_InputStream_skip(JNIEnv *env, jclass cls, jlong req_info_ptr, jlong n) { size_t rest, b_size; nxt_unit_buf_t *buf; nxt_unit_request_info_t *req; req = nxt_jlong2ptr(req_info_ptr); rest = n; buf = req->content_buf; while (buf != NULL) { b_size = buf->end - buf->free; b_size = rest < b_size ? rest : b_size; buf->free += b_size; rest -= b_size; if (rest == 0) { if (buf->end == buf->free) { buf = nxt_unit_buf_next(buf); } break; } buf = nxt_unit_buf_next(buf); } n = n < (jlong) req->content_length ? n : (jlong) req->content_length; req->content_length -= n; return n; } static jint JNICALL nxt_java_InputStream_available(JNIEnv *env, jclass cls, jlong req_info_ptr) { nxt_unit_request_info_t *req; req = nxt_jlong2ptr(req_info_ptr); return req->content_length; }