xref: /unit/src/java/nxt_jni_InputStream.c (revision 1436:44ccce64ddf9)
1 
2 /*
3  * Copyright (C) NGINX, Inc.
4  */
5 
6 #include <nxt_auto_config.h>
7 
8 #include <jni.h>
9 #include <nxt_unit.h>
10 #include <string.h>
11 
12 #include "nxt_jni.h"
13 #include "nxt_jni_InputStream.h"
14 #include "nxt_jni_URLClassLoader.h"
15 
16 
17 static jint JNICALL nxt_java_InputStream_readLine(JNIEnv *env, jclass cls,
18     jlong req_info_ptr, jarray b, jint off, jint len);
19 static jboolean JNICALL nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls,
20     jlong req_info_ptr);
21 static jint JNICALL nxt_java_InputStream_readByte(JNIEnv *env, jclass cls,
22     jlong req_info_ptr);
23 static jint JNICALL nxt_java_InputStream_read(JNIEnv *env, jclass cls,
24     jlong req_info_ptr, jarray b, jint off, jint len);
25 static jlong JNICALL nxt_java_InputStream_skip(JNIEnv *env, jclass cls,
26     jlong req_info_ptr, jlong n);
27 static jint JNICALL nxt_java_InputStream_available(JNIEnv *env, jclass cls,
28     jlong req_info_ptr);
29 
30 
31 static jclass  nxt_java_InputStream_class;
32 
33 
34 int
nxt_java_initInputStream(JNIEnv * env,jobject cl)35 nxt_java_initInputStream(JNIEnv *env, jobject cl)
36 {
37     int     res;
38     jclass  cls;
39 
40     cls = nxt_java_loadClass(env, cl, "nginx.unit.InputStream");
41     if (cls == NULL) {
42         return NXT_UNIT_ERROR;
43     }
44 
45     nxt_java_InputStream_class = (*env)->NewGlobalRef(env, cls);
46     (*env)->DeleteLocalRef(env, cls);
47 
48     JNINativeMethod is_methods[] = {
49         { (char *) "readLine",
50           (char *) "(J[BII)I",
51           nxt_java_InputStream_readLine },
52 
53         { (char *) "isFinished",
54           (char *) "(J)Z",
55           nxt_java_InputStream_isFinished },
56 
57         { (char *) "read",
58           (char *) "(J)I",
59           nxt_java_InputStream_readByte },
60 
61         { (char *) "read",
62           (char *) "(J[BII)I",
63           nxt_java_InputStream_read },
64 
65         { (char *) "skip",
66           (char *) "(JJ)J",
67           nxt_java_InputStream_skip },
68 
69         { (char *) "available",
70           (char *) "(J)I",
71           nxt_java_InputStream_available },
72     };
73 
74     res = (*env)->RegisterNatives(env, nxt_java_InputStream_class,
75                                   is_methods,
76                                   sizeof(is_methods) / sizeof(is_methods[0]));
77 
78     nxt_unit_debug(NULL, "registered InputStream methods: %d", res);
79 
80     if (res != 0) {
81         (*env)->DeleteGlobalRef(env, cls);
82         return NXT_UNIT_ERROR;
83     }
84 
85     return NXT_UNIT_OK;
86 }
87 
88 
89 static jint JNICALL
nxt_java_InputStream_readLine(JNIEnv * env,jclass cls,jlong req_info_ptr,jarray out,jint off,jint len)90 nxt_java_InputStream_readLine(JNIEnv *env, jclass cls,
91     jlong req_info_ptr, jarray out, jint off, jint len)
92 {
93     uint8_t                  *data;
94     ssize_t                  res;
95     nxt_unit_request_info_t  *req;
96 
97     req = nxt_jlong2ptr(req_info_ptr);
98 
99     data = (*env)->GetPrimitiveArrayCritical(env, out, NULL);
100 
101     res = nxt_unit_request_readline_size(req, len);
102 
103     if (res > 0) {
104         res = nxt_unit_request_read(req, data + off, res);
105     }
106 
107     nxt_unit_req_debug(req, "readLine '%.*s'", (int) res, (char *) data + off);
108 
109     (*env)->ReleasePrimitiveArrayCritical(env, out, data, 0);
110 
111     return res > 0 ? res : -1;
112 }
113 
114 
115 static jboolean JNICALL
nxt_java_InputStream_isFinished(JNIEnv * env,jclass cls,jlong req_info_ptr)116 nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, jlong req_info_ptr)
117 {
118     nxt_unit_request_info_t  *req;
119 
120     req = nxt_jlong2ptr(req_info_ptr);
121 
122     return req->content_length == 0;
123 }
124 
125 
126 static jint JNICALL
nxt_java_InputStream_readByte(JNIEnv * env,jclass cls,jlong req_info_ptr)127 nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, jlong req_info_ptr)
128 {
129     uint8_t                  b;
130     ssize_t                  size;
131     nxt_unit_request_info_t  *req;
132 
133     req = nxt_jlong2ptr(req_info_ptr);
134 
135     size = nxt_unit_request_read(req, &b, 1);
136 
137     return size == 1 ? b : -1;
138 }
139 
140 
141 static jint JNICALL
nxt_java_InputStream_read(JNIEnv * env,jclass cls,jlong req_info_ptr,jarray b,jint off,jint len)142 nxt_java_InputStream_read(JNIEnv *env, jclass cls, jlong req_info_ptr,
143     jarray b, jint off, jint len)
144 {
145     uint8_t                  *data;
146     ssize_t                  res;
147     nxt_unit_request_info_t  *req;
148 
149     req = nxt_jlong2ptr(req_info_ptr);
150 
151     data = (*env)->GetPrimitiveArrayCritical(env, b, NULL);
152 
153     res = nxt_unit_request_read(req, data + off, len);
154 
155     nxt_unit_req_debug(req, "read '%.*s'", (int) res, (char *) data + off);
156 
157     (*env)->ReleasePrimitiveArrayCritical(env, b, data, 0);
158 
159     return res > 0 ? res : -1;
160 }
161 
162 
163 static jlong JNICALL
nxt_java_InputStream_skip(JNIEnv * env,jclass cls,jlong req_info_ptr,jlong n)164 nxt_java_InputStream_skip(JNIEnv *env, jclass cls, jlong req_info_ptr, jlong n)
165 {
166     size_t                   rest, b_size;
167     nxt_unit_buf_t           *buf;
168     nxt_unit_request_info_t  *req;
169 
170     req = nxt_jlong2ptr(req_info_ptr);
171 
172     rest = n;
173 
174     buf = req->content_buf;
175 
176     while (buf != NULL) {
177         b_size = buf->end - buf->free;
178         b_size = rest < b_size ? rest : b_size;
179 
180         buf->free += b_size;
181         rest -= b_size;
182 
183         if (rest == 0) {
184             if (buf->end == buf->free) {
185                 buf = nxt_unit_buf_next(buf);
186             }
187 
188             break;
189         }
190 
191         buf = nxt_unit_buf_next(buf);
192     }
193 
194     n = n < (jlong) req->content_length ? n : (jlong) req->content_length;
195 
196     req->content_length -= n;
197 
198     return n;
199 }
200 
201 
202 static jint JNICALL
nxt_java_InputStream_available(JNIEnv * env,jclass cls,jlong req_info_ptr)203 nxt_java_InputStream_available(JNIEnv *env, jclass cls, jlong req_info_ptr)
204 {
205     nxt_unit_request_info_t  *req;
206 
207     req = nxt_jlong2ptr(req_info_ptr);
208 
209     return req->content_length;
210 }
211